Merge pull request #279 from rathena/revert-264-cleanup/skill_db

Revert rathena/rathena#264 -- Skill DB clean up
- Reverted until further issues in the main pull request are resolved.
This commit is contained in:
Aleos 2015-02-10 09:45:50 -05:00
commit fe3fccee73
31 changed files with 1016 additions and 1302 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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.";

View File

@ -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 {

View File

@ -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;

View File

@ -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;i<MAX_SKILL;i++)
if ((p->skill[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;
}

View File

@ -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 {

View File

@ -32,7 +32,6 @@
#include "trade.h"
#include "mapreg.h"
#include "quest.h"
#include "pc.h"
#include <stdlib.h>
#include <math.h>
@ -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

View File

@ -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, },

View File

@ -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;

View File

@ -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 <skill id>.W <type>.L <level>.W <sp cost>.W <attack range>.W <skill name>.24B <upgradable>.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 <skill id>.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 <skill id>.W <level>.W <sp cost>.W <attack range>.W <upgradable>.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 <skill id>.W <type>.L <level>.W <sp cost>.W <attack range>.W <upgradable>.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;

View File

@ -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);

View File

@ -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<ARRAYLENGTH(filename); i++){
sv_readdb(db_path, filename[i], ',', 26, 26, -1, &read_elementaldb_sub, i);
}
@ -826,8 +825,7 @@ void read_elementaldb(void) {
* ElementalID,SkillID,SkillLevel,ReqMode
*/
static bool read_elemental_skilldb_sub(char* str[], int columns, int current) {
uint16 class_ = atoi(str[0]), skill_id, skill_lv, skillmode;
uint8 i;
uint16 class_ = atoi(str[0]), i, skill_id, skill_lv, skillmode;
struct s_elemental_db *db;
ARR_FIND(0, MAX_ELEMENTAL_CLASS, i, class_ == elemental_db[i].class_);
@ -837,8 +835,8 @@ static bool read_elemental_skilldb_sub(char* str[], int columns, int current) {
}
skill_id = atoi(str[1]);
if( !SKILL_CHK_ELEM(skill_id) ) {
ShowError("read_elemental_skilldb_sub: Invalid Elemental skill '%d'.\n", skill_id);
if( skill_id < EL_SKILLBASE || skill_id >= EL_SKILLBASE + MAX_ELEMENTALSKILL ) {
ShowError("read_elemental_skilldb_sub: Skill out of range, line %d.\n", current);
return false;
}

View File

@ -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) {// <skill id>,<max lv>,<req id1>,<req lv1>,<req id2>,<req lv2>,<req id3>,<req lv3>,<req id4>,<req lv4>,<req id5>,<req lv5>
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;i<MAX_GUILD_SKILL_REQUIRE;i++)
@ -1268,41 +1257,37 @@ int guild_getexp(struct map_session_data *sd,int exp) {
/*====================================================
* Ask to increase guildskill skill_id
*---------------------------------------------------*/
void guild_skillup(TBL_PC* sd, uint16 skill_id) {
int guild_skillup(TBL_PC* sd, uint16 skill_id) {
struct guild* g;
short idx = guild_skill_get_index(skill_id);
short max = 0;
int idx = skill_id - GD_SKILLBASE;
int max = guild_skill_get_max(skill_id);
nullpo_retv(sd);
nullpo_ret(sd);
if (idx == -1)
return;
if( sd->status.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;i<g->max_member;i++)
if((sd=g->member[i].sd)!=NULL)
clif_guild_skillinfo(sd);
return 0;

View File

@ -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);

View File

@ -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)
{// <hom class>,<skill id>,<max level>[,<job level>],<req id1>,<req lv1>,<req id2>,<req lv2>,<req id3>,<req lv3>,<req id4>,<req lv4>,<req id5>,<req lv5>,<intimacy lv req>
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;
}

View File

@ -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);

View File

@ -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_AMMO_TYPE)-1)
///Item combo struct
struct item_combo
{

View File

@ -59,20 +59,6 @@ struct view_data * mercenary_get_viewdata(int class_){
return &mercenary_db[i].vd;
}
/**
* Get mercenary skill index for mercenary skill tree
* @param skill_id
* @return Index in skill_tree or -1
**/
short mercenary_skill_get_index(uint16 skill_id) {
if (!SKILL_CHK_MERC(skill_id))
return -1;
skill_id -= MC_SKILLBASE;
if (skill_id >= 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<ARRAYLENGTH(filename); i++){
@ -554,9 +542,7 @@ void mercenary_readdb(void) {
static bool mercenary_read_skilldb_sub(char* str[], int columns, int current)
{// <merc id>,<skill id>,<skill level>
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<ARRAYLENGTH(filename); i++){
sv_readdb(db_path, filename[i], ',', 3, 3, -1, &mercenary_read_skilldb_sub, i);
}

View File

@ -71,7 +71,6 @@ void mercenary_set_calls(struct mercenary_data *md, int value);
void mercenary_kills(struct mercenary_data *md);
int mercenary_checkskill(struct mercenary_data *md, uint16 skill_id);
short mercenary_skill_get_index(uint16 skill_id);
/**
* atcommand.c required

View File

@ -3492,9 +3492,8 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons
//Go Backwards to give better priority to advanced skills.
for (i=0,j = MAX_SKILL_TREE-1;j>=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);

View File

@ -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 )
{

View File

@ -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<MAX_SKILL;i++){
uint8 skill_lv;
if( (skill_lv = pc_checkskill(sd,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;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) {
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;i<MAX_SKILL;i++){
switch( i ) {
case SG_DEVIL:
case MO_TRIPLEATTACK:
case RG_SNATCHER:
continue;
default:
if( !(skill_get_inf2(i)&(INF2_NPC_SKILL|INF2_GUILD_SKILL)) )
if ( ( sd->status.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
*------------------------------------------*/

View File

@ -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<<MAX_WEAPON_TYPE)-1)
enum ammo_type {
A_ARROW = 1,
A_DAGGER, //2
@ -916,15 +914,7 @@ void pc_bonus2(struct map_session_data *sd, int type, int type2, int val);
void pc_bonus3(struct map_session_data *sd, int type, int type2, int type3, int val);
void pc_bonus4(struct map_session_data *sd, int type, int type2, int type3, int type4, int val);
void pc_bonus5(struct map_session_data *sd, int type, int type2, int type3, int type4, int type5, int val);
enum e_addskill_type {
ADDSKILL_PERMANENT = 0, ///< Permanent skill. Remove the skill if level is 0
ADDSKILL_TEMP = 1, ///< Temporary skill. If player learned the skill and the given level is higher, level will be replaced and learned level will be palced in skill flag. `flag = learned + SKILL_FLAG_REPLACED_LV_0; learned_level = level;`
ADDSKILL_TEMP_ADDLEVEL = 2, ///< Like PCSKILL_TEMP, except the level will be stacked. `learned_level += level`. The flag is used to store original learned level
ADDSKILL_PERMANENT_GRANTED = 3, ///< Grant permanent skill, ignore skill tree and learned level
};
bool pc_skill(struct map_session_data *sd, uint16 skill_id, int level, enum e_addskill_type type);
int pc_skill(struct map_session_data *sd, int id, int level, int flag);
int pc_insert_card(struct map_session_data *sd,int idx_card,int idx_equip);
@ -951,7 +941,7 @@ int pc_need_status_point(struct map_session_data *,int,int);
int pc_maxparameterincrease(struct map_session_data*,int);
bool pc_statusup(struct map_session_data*,int,int);
int pc_statusup2(struct map_session_data*,int,int);
void pc_skillup(struct map_session_data*,uint16 skill_id);
int pc_skillup(struct map_session_data*,uint16 skill_id);
int pc_allskillup(struct map_session_data*);
int pc_resetlvl(struct map_session_data*,int type);
int pc_resetstate(struct map_session_data*);
@ -1036,12 +1026,12 @@ int pc_mapid2jobid(unsigned short class_, int sex); // Skotlex
const char * job_name(int class_);
struct skill_tree_entry {
uint16 id;
uint8 max;
uint8 joblv;
short id;
unsigned char max;
unsigned char joblv;
struct {
uint16 id;
uint8 lv;
short id;
unsigned char lv;
} need[MAX_PC_SKILL_REQUIRE];
}; // Celest
extern struct skill_tree_entry skill_tree[CLASS_COUNT][MAX_SKILL_TREE];
@ -1144,8 +1134,6 @@ bool pc_is_same_equip_index(enum equip_index eqi, short *equip_index, short inde
int pc_autotrade_timer(int tid, unsigned int tick, int id, intptr_t data);
void pc_validate_skill(struct map_session_data *sd);
#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
int pc_level_penalty_mod(struct map_session_data *sd, int mob_level, uint32 mob_class, int type);
#endif

View File

@ -8604,25 +8604,53 @@ BUILDIN_FUNC(skill)
{
int id;
int level;
int flag = ADDSKILL_TEMP;
int flag = 1;
TBL_PC* sd;
struct script_data *data;
const char* command = script_getfuncname(st);
sd = script_rid2sd(st);
if( sd == NULL )
return 0;// no player attached, report source
if (strcmpi(command, "addtoskill") == 0)
flag = ADDSKILL_TEMP_ADDLEVEL;
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, (enum e_addskill_type)flag);
pc_skill(sd, id, level, flag);
return SCRIPT_CMD_SUCCESS;
}
/// Changes the level of a player skill.
/// like skill, but <flag> defaults to 2
///
/// addtoskill <skill id>,<amount>,<flag>
/// addtoskill <skill id>,<amount>
/// addtoskill "<skill name>",<amount>,<flag>
/// addtoskill "<skill name>",<amount>
///
/// @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"),

File diff suppressed because it is too large Load Diff

View File

@ -13,14 +13,14 @@ struct skill_unit;
struct skill_unit_group;
struct status_change_entry;
#define MAX_SKILL_DB MAX_SKILL /// Max Skill DB
#define MAX_SKILL_PRODUCE_DB 270 /// Max Produce DB
#define MAX_PRODUCE_RESOURCE 12 /// Max Produce requirements
#define MAX_SKILL_ARROW_DB 150 /// Max Arrow Creation DB
#define MAX_ARROW_RESULT 5 /// Max Arrow results/created
#define MAX_SKILL_ABRA_DB 160 /// Max Skill list of Abracadabra DB
#define MAX_SKILL_IMPROVISE_DB 30 /// Max Skill for Improvise
#define MAX_SKILL_LEVEL 10 /// Max Skill Level (for skill_db storage)
#define MAX_MOBSKILL_LEVEL 100 /// Max monster skill level (on skill usage)
#define MAX_SKILL_LEVEL 100 /// Max Skill Level
#define MAX_SKILL_CRIMSON_MARKER 3 /// Max Crimson Marker targets (RL_C_MARKER)
#define SKILL_NAME_LENGTH 31 /// Max Skill Name length
#define SKILL_DESC_LENGTH 31 /// Max Skill Desc length
@ -111,116 +111,80 @@ enum e_skill_display {
#define MAX_SKILL_ITEM_REQUIRE 10 /// Maximum required items
#define MAX_SKILL_STATUS_REQUIRE 3 /// Maximum required statuses
#define MAX_SKILL_EQUIP_REQUIRE 10 /// Maximum required equipped item
/// Single skill requirement. !TODO: Cleanup the variable types
struct skill_condition {
int16 hp; ///< HP cost
int16 mhp; ///< Max HP to trigger
int16 sp; /// SP cost
int16 hp_rate; /// HP cost (%)
int16 sp_rate; /// SP cost (%)
uint32 zeny; /// Zeny cost
uint32 weapon; /// Weapon type. Combined bitmask of enum weapon_type (1<<weapon)
uint16 ammo; /// Ammo type. Combine bitmask of enum ammo_type (1<<ammo)
int8 ammo_qty; /// Amount of ammo
uint8 state; /// State/condition. @see enum e_require_state
int8 spiritball; /// Spiritball cost
uint16 itemid[MAX_SKILL_ITEM_REQUIRE]; /// Required item
uint16 amount[MAX_SKILL_ITEM_REQUIRE]; /// Amount of item
uint16 *eqItem; /// List of equipped item
enum sc_type *status; /// List of Status required (SC)
uint8 status_count, /// Count of SC
eqItem_count; /// Count of equipped item
int hp, /// HP cost
mhp, /// Max HP to trigger
sp, /// SP cost
hp_rate, /// HP cost (%)
sp_rate, /// SP cost (%)
ammo, /// Ammo type
ammo_qty, /// Amount of ammo
weapon, /// Weapon type
zeny, /// Zeny cost
state, /// State/condition
spiritball, /// Spiritball cost
itemid[MAX_SKILL_ITEM_REQUIRE], /// Required item
amount[MAX_SKILL_ITEM_REQUIRE]; /// Amount of item
uint16 *eqItem; /// List of equipped item
enum sc_type *status; /// List of Status required (SC)
uint8 status_count, /// Count of SC
eqItem_count; /// Count of equipped item
};
/// Skill requirement structure. !TODO: Cleanup the variable types that use array [MAX_SKILL_LEVEL]
struct s_skill_require {
int hp[MAX_SKILL_LEVEL]; ///< HP cost
int mhp[MAX_SKILL_LEVEL]; ///< Max HP to trigger
int sp[MAX_SKILL_LEVEL]; /// SP cost
int hp_rate[MAX_SKILL_LEVEL]; /// HP cost (%)
int sp_rate[MAX_SKILL_LEVEL]; /// SP cost (%)
int zeny[MAX_SKILL_LEVEL]; /// Zeny cost
uint32 weapon; /// Weapon type. Combined bitmask of enum weapon_type (1<<weapon)
uint16 ammo; /// Ammo type. Combine bitmask of enum ammo_type (1<<ammo)
int ammo_qty[MAX_SKILL_LEVEL]; /// Amount of ammo
uint8 state; /// State/condition. @see enum e_require_state
int spiritball[MAX_SKILL_LEVEL]; /// Spiritball cost
int itemid[MAX_SKILL_ITEM_REQUIRE]; /// Required item
int amount[MAX_SKILL_ITEM_REQUIRE]; /// Amount of item
uint16 *eqItem; /// List of equipped item
enum sc_type *status; /// List of Status required (SC)
uint8 status_count, /// Count of SC
eqItem_count; /// Count of equipped item
int hp[MAX_SKILL_LEVEL], /// HP cost
mhp[MAX_SKILL_LEVEL], /// Max HP to trigger
sp[MAX_SKILL_LEVEL], /// SP cost
hp_rate[MAX_SKILL_LEVEL], /// HP cost (%)
sp_rate[MAX_SKILL_LEVEL], /// SP cost (%)
zeny[MAX_SKILL_LEVEL], /// Zeny cost
weapon, /// Weapon type
ammo, /// Ammo type
ammo_qty[MAX_SKILL_LEVEL], /// Amount of ammo
state, /// State/condition
spiritball[MAX_SKILL_LEVEL], /// Spiritball cost
itemid[MAX_SKILL_ITEM_REQUIRE], /// Required item
amount[MAX_SKILL_ITEM_REQUIRE]; /// Amount of item
uint16 *eqItem; /// List of equipped item
enum sc_type *status; /// List of Status required (SC)
uint8 status_count, /// Count of SC
eqItem_count; /// Count of equipped item
};
/// Database skills. !TODO: Cleanup the variable types that use array [MAX_SKILL_LEVEL]
/// Database skills
struct s_skill_db {
// skill_db.txt
uint16 nameid; ///< Skill ID
char name[SKILL_NAME_LENGTH]; ///< AEGIS_Name
char desc[SKILL_DESC_LENGTH]; ///< English Name
int range[MAX_SKILL_LEVEL]; ///< Range
int8 hit; ///< Hit type
uint8 inf; ///< Inf: 0- passive, 1- enemy, 2- place, 4- self, 16- friend, 32- trap
int element[MAX_SKILL_LEVEL]; ///< Element
uint8 nk; ///< Damage properties
int splash[MAX_SKILL_LEVEL]; ///< Splash effect
uint8 max; ///< Max level
int num[MAX_SKILL_LEVEL]; ///< Number of hit
bool castcancel; ///< Cancel cast when being hit
int16 cast_def_rate; ///< Def rate during cast a skill
uint16 skill_type; ///< Skill type
int blewcount[MAX_SKILL_LEVEL]; ///< Blew count
uint32 inf2; ///<
uint32 inf3; ///<
int maxcount[MAX_SKILL_LEVEL]; ///< Max number skill can be casted in same map
// skill_castnodex_db.txt
uint8 castnodex; ///< 1 - Not affected by dex, 2 - Not affected by SC, 4 - Not affected by item
uint8 delaynodex; ///< 1 - Not affected by dex, 2 - Not affected by SC, 4 - Not affected by item
// skill_nocast_db.txt
uint32 nocast; ///< Skill cannot be casted at this zone
// skill_unit_db.txt
uint16 unit_id[2]; ///< Unit ID. @see enum s_skill_unit_id
int unit_layout_type[MAX_SKILL_LEVEL]; ///< Layout type. -1 is special layout, others are square with lenght*width: (val*2+1)^2
int unit_range[MAX_SKILL_LEVEL]; ///< Unit cell effect range
int16 unit_interval; ///< Interval
uint32 unit_target; ///< Unit target. @see enum e_battle_check_target
uint32 unit_flag; ///< Unit flags. @see enum e_skill_unit_flag
// skill_cast_db.txt
int cast[MAX_SKILL_LEVEL]; ///< Variable casttime
char name[SKILL_NAME_LENGTH];
char desc[SKILL_DESC_LENGTH];
int range[MAX_SKILL_LEVEL],hit,inf,element[MAX_SKILL_LEVEL],nk,splash[MAX_SKILL_LEVEL],max;
int num[MAX_SKILL_LEVEL];
int cast[MAX_SKILL_LEVEL],walkdelay[MAX_SKILL_LEVEL],delay[MAX_SKILL_LEVEL];
#ifdef RENEWAL_CAST
int fixed_cast[MAX_SKILL_LEVEL]; ///< If -1 means 20% than 'cast'
int fixed_cast[MAX_SKILL_LEVEL];
#endif
int walkdelay[MAX_SKILL_LEVEL]; ///< Delay to walk after casting
int delay[MAX_SKILL_LEVEL]; ///< Global delay (delay before reusing all skills)
int cooldown[MAX_SKILL_LEVEL]; ///< Cooldown (delay before reusing same skill)
int upkeep_time[MAX_SKILL_LEVEL]; ///< Duration
int upkeep_time2[MAX_SKILL_LEVEL]; ///< Duration2
// skill_require_db.txt
struct s_skill_require require; ///< Skill requirement
// skill_nonearnpc_db.txt
int upkeep_time[MAX_SKILL_LEVEL],upkeep_time2[MAX_SKILL_LEVEL],cooldown[MAX_SKILL_LEVEL];
int castcancel,cast_def_rate;
int inf2,maxcount[MAX_SKILL_LEVEL],skill_type,inf3;
int blewcount[MAX_SKILL_LEVEL];
struct s_skill_require require;
int castnodex[MAX_SKILL_LEVEL], delaynodex[MAX_SKILL_LEVEL];
int32 nocast;
int unit_id[2];
int unit_layout_type[MAX_SKILL_LEVEL];
int unit_range[MAX_SKILL_LEVEL];
int unit_interval;
int unit_target;
int unit_flag;
uint8 unit_nonearnpc_range; //additional range for UF_NONEARNPC or INF2_NO_NEARNPC [Cydh]
uint8 unit_nonearnpc_type; //type of NPC [Cydh]
// skill_damage_db.txt
#ifdef ADJUST_SKILL_DAMAGE
struct s_skill_damage damage;
#endif
// skill_copyable_db.txt
struct s_copyable { // [Cydh]
uint8 option;
uint16 joballowed, req_opt;
} copyable;
};
extern struct s_skill_db **skill_db;
extern struct s_skill_db skill_db[MAX_SKILL_DB];
#define MAX_SKILL_UNIT_LAYOUT 52
#define MAX_SKILL_UNIT_LAYOUT2 17
@ -297,7 +261,7 @@ struct skill_unit_group_tickset {
};
enum e_skill_unit_flag {
enum {
UF_DEFNOTENEMY = 0x00001, // If 'defunit_not_enemy' is set, the target is changed to 'friend'
UF_NOREITERATION = 0x00002, // Spell cannot be stacked
UF_NOFOOTSET = 0x00004, // Spell cannot be cast near/on targets
@ -357,9 +321,7 @@ const char* skill_get_desc( uint16 skill_id ); // [Skotlex]
int skill_tree_get_max( uint16 skill_id, int b_class ); // Celest
// Accessor to the skills database
int skill_get_index_( uint16 skill_id, bool check_db );
#define skill_get_index(skill_id) skill_get_index_((skill_id),false) /// Get skill index from skill_id (common usage on source)
#define skill_get_index2(skill_id) skill_get_index_((skill_id),true) /// Get skill index from skill_id (used when reading skill_db files)
int skill_get_index( uint16 skill_id );
int skill_get_type( uint16 skill_id );
int skill_get_hit( uint16 skill_id );
int skill_get_inf( uint16 skill_id );
@ -375,7 +337,7 @@ int skill_get_delay( uint16 skill_id ,uint16 skill_lv );
int skill_get_walkdelay( uint16 skill_id ,uint16 skill_lv );
int skill_get_time( uint16 skill_id ,uint16 skill_lv );
int skill_get_time2( uint16 skill_id ,uint16 skill_lv );
int skill_get_castnodex( uint16 skill_id );
int skill_get_castnodex( uint16 skill_id ,uint16 skill_lv );
int skill_get_castdef( uint16 skill_id );
int skill_get_nocast( uint16 skill_id );
int skill_get_unit_id(uint16 skill_id,int flag);
@ -405,9 +367,6 @@ int skill_get_itemid( uint16 skill_id, int idx );
int skill_get_itemqty( uint16 skill_id, int idx );
int skill_name2id(const char* name);
uint16 skill_idx2id(uint16 idx);
uint16 SKILL_MAX_DB(void);
int skill_isammotype(struct map_session_data *sd, unsigned short skill_id);
int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data);
@ -1856,7 +1815,7 @@ enum e_skill {
};
/// The client view ids for land skills.
enum s_skill_unit_id {
enum {
UNT_SAFETYWALL = 0x7e,
UNT_FIREWALL,
UNT_WARP_WAITING,
@ -2096,9 +2055,4 @@ enum e_skill_damage_caster {
/// Variable name of copied skill level by Reproduce
#define SKILL_VAR_REPRODUCE_LV "REPRODUCE_SKILL_LV"
#define SKILL_CHK_HOMUN(skill_id) ( (skill_id) >= 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_ */

View File

@ -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;

View File

@ -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