diff options
-rw-r--r-- | Changelog-Trunk.txt | 5 | ||||
-rw-r--r-- | conf/log_athena.conf | 4 | ||||
-rw-r--r-- | db/abra_db.txt | 2 | ||||
-rw-r--r-- | db/mob_db.txt | 2 | ||||
-rw-r--r-- | db/skill_db.txt | 12 | ||||
-rw-r--r-- | src/common/strlib.c | 80 | ||||
-rw-r--r-- | src/common/strlib.h | 4 | ||||
-rw-r--r-- | src/map/atcommand.c | 32 | ||||
-rw-r--r-- | src/map/mob.c | 17 | ||||
-rw-r--r-- | src/map/pc.c | 166 | ||||
-rw-r--r-- | src/map/quest.c | 2 | ||||
-rw-r--r-- | src/map/skill.c | 175 | ||||
-rw-r--r-- | src/map/skill.h | 5 | ||||
-rw-r--r-- | src/map/status.c | 2 |
14 files changed, 227 insertions, 281 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index 4c79831af..9eaec89a1 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -4,6 +4,11 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. 2008/04/15 + * Corrected some invalid syntax in skill_db.txt (wrong usage of commas) + * Renamed BA_FROSTJOKE to BA_FROSTJOKER (aegis server-side name) + * Implemented a generic framework for parsing delimited db files + - allows specifying min/max column ranges and max number of rows to read + * Cleaned up pc.c a bit [ultramage] * Updated item_db.sql to latest [Toms] 2008/04/14 * Fixed a possible crash in char_sql. (since r12575, later modified in r12590). [FlavioJS] diff --git a/conf/log_athena.conf b/conf/log_athena.conf index ccad43221..b75f1b363 100644 --- a/conf/log_athena.conf +++ b/conf/log_athena.conf @@ -54,7 +54,7 @@ refine_items_log: 5 // Log Items whith min drop rate <= rare_items_log // 1 = 0.01%, 100 = 1% drop chance, etc rare_items_log: 100 -// don't log it if the current item price < price_items_log +// don't log it if the current item buy price < price_items_log price_items_log: 1000 // don't log it if the current item amount < amount_items_log amount_items_log: 100 @@ -121,7 +121,7 @@ log_chat_db: chatlog // Dead Branch Log File log_branch_file: log/branchlog.log -// Drops & Pickups Log File +// Drops & Pickups Log File log_pick_file: log/picklog.log // Zeny Log File diff --git a/db/abra_db.txt b/db/abra_db.txt index 8cd2a90e3..788a7243b 100644 --- a/db/abra_db.txt +++ b/db/abra_db.txt @@ -60,7 +60,7 @@ //49,Improve Dodge,1,0 50,Steal,2,5000 51,Hiding,2,5000 -52,Envenom,1,5000, +52,Envenom,1,5000 53,Detoxify,1,5000 54,Resurrection,1,5000 diff --git a/db/mob_db.txt b/db/mob_db.txt index 2994cd8d4..99f00556c 100644 --- a/db/mob_db.txt +++ b/db/mob_db.txt @@ -6,7 +6,7 @@ 1001,SCORPION,Scorpion,Scorpion,24,1109,0,287,176,1,80,135,30,0,1,24,24,5,52,5,10,12,0,4,23,0x3195,200,1564,864,576,0,0,0,0,0,0,0,0,990,70,904,5500,757,57,943,210,7041,100,508,200,625,20,0,0,0,0,4068,1 1002,PORING,Poring,Poring,1,50,0,2,1,1,7,10,0,5,1,1,1,0,6,30,10,12,1,3,21,0x83,400,1872,672,480,0,0,0,0,0,0,0,0,909,7000,1202,100,938,400,512,1000,713,1500,512,150,619,20,0,0,0,0,4001,1 -//1003,TESTEGG,Test Egg,Test Egg,2,100000,0,10,10,0,3,9,99,0,1,99,1,1,1,1,10,12,0,4,22,0,512,0,512,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +1003,TESTEGG,Test Egg,Test Egg,2,100000,0,10,10,0,3,9,99,0,1,99,1,1,1,1,10,12,0,4,22,0,512,0,512,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 1004,HORNET,Hornet,Hornet,8,169,0,19,15,1,22,27,5,5,6,20,8,10,17,5,10,12,0,4,24,0x1189,150,1292,792,216,0,0,0,0,0,0,0,0,992,80,939,9000,909,3500,1208,15,511,350,518,150,0,0,0,0,0,0,4019,1 1005,FARMILIAR,Familiar,Familiar,8,155,0,28,15,1,20,28,0,0,1,12,8,5,28,0,10,12,0,2,27,0x3885,150,1276,576,384,0,0,0,0,0,0,0,0,913,5500,1105,20,2209,15,601,50,514,100,507,700,645,50,0,0,0,0,4020,1 //1006,THIEF_BUG_LARVA,Thief Bug Larva,Thief Bug Larva,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,1,651,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 diff --git a/db/skill_db.txt b/db/skill_db.txt index 5e96cfcc7..b95f29813 100644 --- a/db/skill_db.txt +++ b/db/skill_db.txt @@ -468,24 +468,24 @@ 424,0,0,0,0,0,0,5,0,no,0,0,0,weapon,0, TK_POWER,Kihop 425,0,6,4,2:4:1:3:8:7:6,0x1,0,7,1,no,0,0,0,weapon,0, TK_SEVENWIND,Mild Wind 426,0,6,4,0,0x1,0,5,1,no,0,0,0,weapon,0, TK_HIGHJUMP,Taekwon Jump -427,0,6,4,0,0x1,0,3,1,yes,0,0,0,magic,0, SG_FEEL,Feeling the Sun, Moon and Stars +427,0,6,4,0,0x1,0,3,1,yes,0,0,0,magic,0, SG_FEEL,Feeling the Sun Moon and Stars 428,1,6,4,-1,0x42,1,3,1,yes,0,0,0,weapon,2, SG_SUN_WARM,Warmth of the Sun 429,1,6,4,-1,0x42,1,3,1,yes,0,0,0,weapon,2, SG_MOON_WARM,Warmth of the Moon 430,1,6,4,-1,0x42,1,3,1,yes,0,0,0,weapon,2, SG_STAR_WARM,Warmth of the Stars 431,0,0,4,0,0x1,0,4,1,yes,0,0,0,magic,0, SG_SUN_COMFORT,Comfort of the Sun 432,0,0,4,0,0x1,0,4,1,yes,0,0,0,magic,0, SG_MOON_COMFORT,Comfort of the Moon 433,0,0,4,0,0x1,0,4,1,yes,0,0,0,magic,0, SG_STAR_COMFORT,Comfort of the Stars -434,10,6,1,0,0x1,0,3,1,yes,0,0,0,magic,0, SG_HATE,Hatred of the Sun, Moon and Stars +434,10,6,1,0,0x1,0,3,1,yes,0,0,0,magic,0, SG_HATE,Hatred of the Sun Moon and Stars 435,0,0,0,0,0,0,3,0,no,0,0,0,none,0, SG_SUN_ANGER,Anger of the Sun 436,0,0,0,0,0,0,3,0,no,0,0,0,none,0, SG_MOON_ANGER,Anger of the Moon 437,0,0,0,0,0,0,3,0,no,0,0,0,none,0, SG_STAR_ANGER,Anger of the Stars 438,0,0,0,0,0,0,5,0,no,0,0,0,none,0, SG_SUN_BLESS,Blessing of the Sun 439,0,0,0,0,0,0,5,0,no,0,0,0,none,0, SG_MOON_BLESS,Blessing of the Moon 440,0,0,0,0,0,0,5,0,no,0,0,0,none,0, SG_STAR_BLESS,Blessing of the Stars -441,0,0,0,0,0,0,10,0,no,0,0,0,none,0, SG_DEVIL,Demon of the Sun, Moon and Stars -442,0,0,0,0,0,0,3,0,no,0,0,0,none,0, SG_FRIEND,Friend of the Sun, Moon and Stars -443,0,0,0,0,0,0,10,0,no,0,0,0,none,0, SG_KNOWLEDGE,Knowledge of the Sun, Moon and Stars -444,0,6,4,0,0x1,0,1,1,no,0,0,0,misc,0, SG_FUSION,Union of the Sun, Moon and Stars +441,0,0,0,0,0,0,10,0,no,0,0,0,none,0, SG_DEVIL,Demon of the Sun Moon and Stars +442,0,0,0,0,0,0,3,0,no,0,0,0,none,0, SG_FRIEND,Friend of the Sun Moon and Stars +443,0,0,0,0,0,0,10,0,no,0,0,0,none,0, SG_KNOWLEDGE,Knowledge of the Sun Moon and Stars +444,0,6,4,0,0x1,0,1,1,no,0,0,0,misc,0, SG_FUSION,Union of the Sun Moon and Stars 445,9,6,16,0,0x1,0,5,1,yes,0,0x200,0,magic,0, SL_ALCHEMIST,Spirit of the Alchemist 446,9,6,16,0,0x1,0,1,1,yes,0,0xC08,0,none,0, AM_BERSERKPITCHER,Aid Berserk Potion 447,9,6,16,0,0x1,0,5,1,yes,0,0x200,0,magic,0, SL_MONK,Spirit of the Monk diff --git a/src/common/strlib.c b/src/common/strlib.c index ffc6f8a32..0f440ff54 100644 --- a/src/common/strlib.c +++ b/src/common/strlib.c @@ -786,6 +786,86 @@ size_t sv_unescape_c(char* out_dest, const char* src, size_t len) return j; } +/// Opens and parses a file containing delim-separated columns, feeding them to the specified callback function row by row. +/// Tracks the progress of the operation (current line number, number of successfully processed rows). +/// Returns 'true' if it was able to process the specified file, or 'false' if it could not be read. +/// +/// @param directory Directory +/// @param filename File to process +/// @param delim Field delimiter +/// @param mincols Minimum number of columns of a valid row +/// @param maxcols Maximum number of columns of a valid row +/// @param parseproc User-supplied row processing function +/// @return true on success, false if file could not be opened +bool sv_readdb(const char* directory, const char* filename, char delim, int mincols, int maxcols, int maxrows, bool (*parseproc)(char* fields[], int columns, int current)) +{ + FILE* fp; + int lines = 0; + int entries = 0; + char* fields[64]; // room for 63 fields ([0] is reserved) + int columns; + char path[1024], line[1024]; + + if( maxcols > ARRAYLENGTH(fields)-1 ) + { + ShowError("sv_readdb: Insufficient column storage in parser for file \"%s\" (want %d, have only %d). Increase the capacity in the source code please.\n", path, maxcols, ARRAYLENGTH(fields)-1); + return false; + } + + // open file + snprintf(path, sizeof(path), "%s/%s", directory, filename); + fp = fopen(path, "r"); + if( fp == NULL ) + { + ShowError("sv_readdb: can't read %s\n", path); + return false; + } + + // process rows one by one + while( fgets(line, sizeof(line), fp) ) + { + lines++; + if( line[0] == '/' && line[1] == '/' ) + continue; + //TODO: strip trailing // comment + //TODO: strip trailing whitespace + if( line[0] == '\0' || line[0] == '\n' ) + continue; + + columns = sv_split(line, strlen(line), 0, delim, fields, ARRAYLENGTH(fields), SV_NOESCAPE_NOTERMINATE); + + if( columns < mincols ) + { + ShowError("sv_readdb: Insufficient columns in line %d of \"%s\" (found %d, need at least %d).\n", lines, path, columns, mincols); + continue; // not enough columns + } + if( columns > maxcols ) + { + ShowError("sv_readdb: Too many columns in line %d of \"%s\" (found %d, maximum is %d).\n", lines, path, columns, maxcols ); + continue; // too many columns + } + if( entries == maxrows ) + { + ShowError("sv_readdb: Reached the maximum allowed number of entries (%d) when parsing file \"%s\".\n", maxrows, path); + break; + } + + // parse this row + if( !parseproc(fields+1, columns, entries) ) + { + ShowError("sv_readdb: Could not process contents of line %d of \"%s\".\n", lines, path); + continue; // invalid row contents + } + + // success! + entries++; + } + + fclose(fp); + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", entries, path); + + return true; +} ///////////////////////////////////////////////////////////////////// diff --git a/src/common/strlib.h b/src/common/strlib.h index d4b514089..3c4075902 100644 --- a/src/common/strlib.h +++ b/src/common/strlib.h @@ -91,6 +91,10 @@ size_t sv_escape_c(char* out_dest, const char* src, size_t len, const char* esca /// out_dest should be len+1 in size and can be the same buffer as src. size_t sv_unescape_c(char* out_dest, const char* src, size_t len); +/// Opens and parses a file containing delim-separated columns, feeding them to the specified callback function row by row. +/// Tracks the progress of the operation (current line number, number of successfully processed rows). +/// Returns 'true' if it was able to process the specified file, or 'false' if it could not be read. +bool sv_readdb(const char* directory, const char* filename, char delim, int mincols, int maxcols, int maxrows, bool (*parseproc)(char* fields[], int columns, int current)); /// StringBuf - dynamic string diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 3a9f987cb..abb9c61d3 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -5674,8 +5674,8 @@ int atcommand_displayskill(const int fd, struct map_session_data* sd, const char int atcommand_skilltree(const int fd, struct map_session_data* sd, const char* command, const char* message) { struct map_session_data *pl_sd = NULL; - int skillnum, skillidx = -1; - int meets = 1, j, c=0; + int skillnum; + int meets, j, c=0; char target[NAME_LENGTH], *tbl; struct skill_tree_entry *ent; nullpo_retr(-1, sd); @@ -5696,37 +5696,33 @@ int atcommand_skilltree(const int fd, struct map_session_data* sd, const char* c tbl = job_name(c); - sprintf(atcmd_output, "Player is using %s skill tree (%d basic points)", - tbl, pc_checkskill(pl_sd, 1)); + sprintf(atcmd_output, "Player is using %s skill tree (%d basic points)", tbl, pc_checkskill(pl_sd, 1)); clif_displaymessage(fd, atcmd_output); - for (j = 0; skill_tree[c][j].id != 0; j++) { - if (skill_tree[c][j].id == skillnum) { - skillidx = j; - break; - } - } - - if (skillidx == -1) { + ARR_FIND( 0, MAX_SKILL_TREE, j, skill_tree[c][j].id == 0 || skill_tree[c][j].id == skillnum ); + if( j == MAX_SKILL_TREE || skill_tree[c][j].id == 0 ) + { sprintf(atcmd_output, "I do not believe the player can use that skill"); clif_displaymessage(fd, atcmd_output); return 0; } - ent = &skill_tree[c][skillidx]; + ent = &skill_tree[c][j]; + meets = 1; for(j=0;j<5;j++) + { if( ent->need[j].id && pc_checkskill(sd,ent->need[j].id) < ent->need[j].lv) { sprintf(atcmd_output, "player requires level %d of skill %s", ent->need[j].lv, skill_db[ent->need[j].id].desc); clif_displaymessage(fd, atcmd_output); meets = 0; } - - if (meets == 1) { - sprintf(atcmd_output, "I believe the player meets all the requirements for that skill"); - clif_displaymessage(fd, atcmd_output); - } + } + if (meets == 1) { + sprintf(atcmd_output, "I believe the player meets all the requirements for that skill"); + clif_displaymessage(fd, atcmd_output); + } return 0; } diff --git a/src/map/mob.c b/src/map/mob.c index 3c5beca7b..bb81a779d 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -3409,22 +3409,7 @@ int mob_clone_spawn(struct map_session_data *sd, int m, int x, int y, const char if (duration) //Auto Delete after a while. md->deletetimer = add_timer (gettick() + duration, mob_timer_delete, md->bl.id, 0); } -#if 0 - //I am playing with this for packet-research purposes, enable it if you want, but don't remove it :X [Skotlex] - //Guardian data - if (sd->status.guild_id) { - struct guild* g = guild_search(sd->status.guild_id); - md->guardian_data = aCalloc(1, sizeof(struct guardian_data)); - md->guardian_data->castle = NULL; - md->guardian_data->number = MAX_GUARDIANS; - md->guardian_data->guild_id = sd->status.guild_id; - if (g) - { - md->guardian_data->emblem_id = g->emblem_id; - memcpy(md->guardian_data->guild_name, g->name, NAME_LENGTH); - } - } -#endif + mob_spawn(md); return md->bl.id; diff --git a/src/map/pc.c b/src/map/pc.c index 5fc764cb1..400799e61 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -19,6 +19,7 @@ #include "intif.h" #include "itemdb.h" #include "log.h" +#include "mail.h" #include "map.h" #include "path.h" #include "mercenary.h" // merc_is_hom_active() @@ -34,10 +35,6 @@ #include "pc.h" #include "quest.h" -#ifndef TXT_ONLY // mail system [Valaris] -#include "mail.h" -#endif - #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -494,23 +491,19 @@ int pc_setequipindex(struct map_session_data *sd) for(j=0;j<EQI_MAX;j++) if(sd->status.inventory[i].equip & equip_pos[j]) sd->equip_index[j] = i; - if(sd->status.inventory[i].equip & EQP_HAND_R) { + + if(sd->status.inventory[i].equip & EQP_HAND_R) + { if(sd->inventory_data[i]) sd->weapontype1 = sd->inventory_data[i]->look; else sd->weapontype1 = 0; } - if(sd->status.inventory[i].equip & EQP_HAND_L) { - if(sd->inventory_data[i]) { - if(sd->inventory_data[i]->type == 4) { - if(sd->status.inventory[i].equip == EQP_HAND_L) - sd->weapontype2 = sd->inventory_data[i]->look; - else - sd->weapontype2 = 0; - } - else - sd->weapontype2 = 0; - } + + if( sd->status.inventory[i].equip & EQP_HAND_L ) + { + if( sd->inventory_data[i] && sd->inventory_data[i]->type == 4 ) + sd->weapontype2 = sd->inventory_data[i]->look; else sd->weapontype2 = 0; } @@ -521,7 +514,8 @@ int pc_setequipindex(struct map_session_data *sd) return 0; } -static int pc_isAllowedCardOn(struct map_session_data *sd,int s,int eqindex,int flag) { +static int pc_isAllowedCardOn(struct map_session_data *sd,int s,int eqindex,int flag) +{ int i; struct item *item = &sd->status.inventory[eqindex]; struct item_data *data; @@ -529,14 +523,8 @@ static int pc_isAllowedCardOn(struct map_session_data *sd,int s,int eqindex,int if (itemdb_isspecial(item->card[0])) return 1; - for (i=0;i<s;i++) { - if (item->card[i] && - (data = itemdb_exists(item->card[i])) && - data->flag.no_equip&flag - ) - return 0; - } - return 1; + ARR_FIND( 0, s, i, item->card[i] && (data = itemdb_exists(item->card[i])) != NULL && data->flag.no_equip&flag ); + return( i < s ) ? 0 : 1; } bool pc_isequipped(struct map_session_data *sd, int nameid) @@ -3283,32 +3271,34 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun return 1; i=MAX_CART; - if(itemdb_isstackable2(data)){ - for(i=0;i<MAX_CART;i++){ - if(sd->status.cart[i].nameid==item_data->nameid && - sd->status.cart[i].card[0] == item_data->card[0] && sd->status.cart[i].card[1] == item_data->card[1] && - sd->status.cart[i].card[2] == item_data->card[2] && sd->status.cart[i].card[3] == item_data->card[3]){ - if(sd->status.cart[i].amount+amount > MAX_AMOUNT) - return 1; - sd->status.cart[i].amount+=amount; - clif_cart_additem(sd,i,amount,0); - break; - } - } + if(itemdb_isstackable2(data)) + { + ARR_FIND( 0, MAX_CART, i, + sd->status.cart[i].nameid == item_data->nameid && + sd->status.cart[i].card[0] == item_data->card[0] && sd->status.cart[i].card[1] == item_data->card[1] && + sd->status.cart[i].card[2] == item_data->card[2] && sd->status.cart[i].card[3] == item_data->card[3] ); + }; + + if( i < MAX_CART ) + {// item already in cart, stack it + if(sd->status.cart[i].amount+amount > MAX_AMOUNT) + return 1; // no room + + sd->status.cart[i].amount+=amount; + clif_cart_additem(sd,i,amount,0); } - if(i >= MAX_CART){ - for(i=0;i<MAX_CART;i++){ - if(sd->status.cart[i].nameid==0){ - memcpy(&sd->status.cart[i],item_data,sizeof(sd->status.cart[0])); - sd->status.cart[i].amount=amount; - sd->cart_num++; - clif_cart_additem(sd,i,amount,0); - break; - } - } - if(i >= MAX_CART) - return 1; + else + {// item not stackable or not present, add it + ARR_FIND( 0, MAX_CART, i, sd->status.cart[i].nameid == 0 ); + if( i == MAX_CART ) + return 1; // no room + + memcpy(&sd->status.cart[i],item_data,sizeof(sd->status.cart[0])); + sd->status.cart[i].amount=amount; + sd->cart_num++; + clif_cart_additem(sd,i,amount,0); } + sd->cart_weight += w; clif_updatestatus(sd,SP_CARTINFO); @@ -3343,7 +3333,8 @@ int pc_cart_delitem(struct map_session_data *sd,int n,int amount,int type) /*========================================== * カ?トへアイテム移動 *------------------------------------------*/ -int pc_putitemtocart(struct map_session_data *sd,int idx,int amount) { +int pc_putitemtocart(struct map_session_data *sd,int idx,int amount) +{ struct item *item_data; nullpo_retr(0, sd); @@ -5078,32 +5069,6 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) } } - // PK/Karma system code (not enabled yet) [celest] - /* - if(sd->status.karma > 0) { - int eq_num=0,eq_n[MAX_INVENTORY]; - memset(eq_n,0,sizeof(eq_n)); - for(i=0;i<MAX_INVENTORY;i++){ - int k; - for(k=0;k<MAX_INVENTORY;k++){ - if(eq_n[k] <= 0){ - eq_n[k]=i; - break; - } - } - eq_num++; - } - if(eq_num > 0){ - int n = eq_n[rand()%eq_num]; - if(rand()%10000 < sd->status.karma){ - if(sd->status.inventory[n].equip) - pc_unequipitem(sd,n,0); - pc_dropitem(sd,n,1); - } - } - } - */ - if(battle_config.bone_drop==2 || (battle_config.bone_drop==1 && map[sd->bl.m].flag.pvp)) { @@ -5182,7 +5147,8 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) } } - if(map[sd->bl.m].flag.pvp_nightmaredrop){ // Moved this outside so it works when PVP isn't enabled and during pk mode [Ancyker] + if(map[sd->bl.m].flag.pvp_nightmaredrop) + { // Moved this outside so it works when PVP isn't enabled and during pk mode [Ancyker] for(j=0;j<MAX_DROP_PER_MAP;j++){ int id = map[sd->bl.m].drop_list[j].drop_id; int type = map[sd->bl.m].drop_list[j].drop_type; @@ -5196,13 +5162,12 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) int k; if( (type == 1 && !sd->status.inventory[i].equip) || (type == 2 && sd->status.inventory[i].equip) - || type == 3){ - for(k=0;k<MAX_INVENTORY;k++){ - if(eq_n[k] <= 0){ - eq_n[k]=i; - break; - } - } + || type == 3) + { + ARR_FIND( 0, MAX_INVENTORY, k, eq_n[k] <= 0 ); + if( k < MAX_INVENTORY ) + eq_n[k] = i; + eq_num++; } } @@ -6848,16 +6813,6 @@ int pc_divorce(struct map_session_data *sd) *------------------------------------------*/ struct map_session_data *pc_get_partner(struct map_session_data *sd) { - //struct map_session_data *p_sd = NULL; - //char *nick; - //if(sd == NULL || !pc_ismarried(sd)) - // return NULL; - //nick=map_charid2nick(sd->status.partner_id); - //if (nick==NULL) - // return NULL; - //if((p_sd=map_nick2sd(nick)) == NULL ) - // return NULL; - if (sd && pc_ismarried(sd)) // charid2sd returns NULL if not found return map_charid2sd(sd->status.partner_id); @@ -7302,18 +7257,15 @@ int pc_split_atoui(char* str, unsigned int* val, char sep, int max) return i; } -// -// 初期化物 -// /*========================================== - * 設定ファイル?み?む - * exp.txt 必要??値 - * job_db1.txt 重量,hp,sp,攻?速度 - * job_db2.txt job能力値ボ?ナス - * skill_tree.txt 各職?のスキルツリ? - * attr_fix.txt ?性修正テ?ブル - * size_fix.txt サイズ補正テ?ブル - * refine_db.txt 精?デ?タテ?ブル + * DB reading. + * exp.txt - required experience values + * job_db1.txt - weight, hp, sp, aspd + * job_db2.txt - job level stat bonuses + * skill_tree.txt - skill tree for every class + * attr_fix.txt - elemental adjustment table + * size_fix.txt - size adjustment table for weapons + * refine_db.txt - refining data table *------------------------------------------*/ int pc_readdb(void) { @@ -7436,8 +7388,8 @@ int pc_readdb(void) continue; idx = pc_class2idx(idx); k = atoi(split[1]); //This is to avoid adding two lines for the same skill. [Skotlex] - for(j = 0; j < MAX_SKILL_TREE && skill_tree[idx][j].id && skill_tree[idx][j].id != k; j++); - if (j == MAX_SKILL_TREE) + ARR_FIND( 0, MAX_SKILL_TREE, j, skill_tree[idx][j].id == 0 || skill_tree[idx][j].id == k ); + if( j == MAX_SKILL_TREE ) { ShowWarning("Unable to load skill %d into job %d's tree. Maximum number of skills per class has been reached.\n", k, atoi(split[0])); continue; diff --git a/src/map/quest.c b/src/map/quest.c index 51082532f..b822b67ca 100644 --- a/src/map/quest.c +++ b/src/map/quest.c @@ -172,7 +172,7 @@ int quest_update_objective(TBL_PC * sd, int quest_id, int objective_num, const c ARR_FIND(0, MAX_QUEST, i, sd->quest_log[i].quest_id == quest_id); //Quest not found - if(i != MAX_QUEST) + if(i == MAX_QUEST) return -1; memcpy(&sd->quest_log[i].objectives[objective_num].name, name, NAME_LENGTH); diff --git a/src/map/skill.c b/src/map/skill.c index 1a2c24855..6ede18445 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -147,11 +147,14 @@ int skill_get_unit_layout_type( int id ,int lv ){ skill_get (skill_db[id].unit_l int skill_tree_get_max(int id, int b_class) { - int i, skillid; + int i; b_class = pc_class2idx(b_class); - for(i=0;(skillid=skill_tree[b_class][i].id)>0;i++) - if (id == skillid) return skill_tree[b_class][i].max; - return skill_get_max (id); + + ARR_FIND( 0, MAX_SKILL_TREE, i, skill_tree[b_class][i].id == 0 || skill_tree[b_class][i].id == id ); + if( i < MAX_SKILL_TREE && skill_tree[b_class][i].id == id ) + return skill_tree[b_class][i].max; + else + return skill_get_max(id); } int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag ); @@ -616,7 +619,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int sc_start(bl,SC_BLIND,(10+3*skilllv),skilllv,skill_get_time2(skillid,skilllv)); break; - case BA_FROSTJOKE: + case BA_FROSTJOKER: sc_start(bl,SC_FREEZE,(15+5*skilllv),skilllv,skill_get_time2(skillid,skilllv)); break; @@ -2057,7 +2060,7 @@ static int skill_timerskill (int tid, unsigned int tick, int id, int data) unit_warp(target, -1, x, y, 3); } break; - case BA_FROSTJOKE: + case BA_FROSTJOKER: case DC_SCREAM: range= skill_get_splash(skl->skill_id, skl->skill_lv); map_foreachinarea(skill_frostjoke_scream,skl->map,skl->x-range,skl->y-range, @@ -3787,7 +3790,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in } break; - case BA_FROSTJOKE: + case BA_FROSTJOKER: case DC_SCREAM: clif_skill_nodamage(src,bl,skillid,skilllv,1); skill_addtimerskill(src,tick+2000,bl->id,src->x,src->y,skillid,skilllv,0,flag); @@ -10726,77 +10729,13 @@ void skill_init_unit_layout (void) * skill_db.txt * skill_require_db.txt * skill_cast_db.txt + * skill_castnodex_db.txt + * skill_nocast_db.txt * skill_unit_db.txt * produce_db.txt * create_arrow_db.txt * abra_db.txt - * skill_castnodex_db.txt - * skill_nocast_db.txt *------------------------------------------*/ -/// Opens and parses a CSV file into columns, feeding them to the specified callback function row by row. -/// Tracks the progress of the operation (file position, number of successfully processed rows). -/// Returns 'true' if it was able to process the specified file, or 'false' if it could not be read. -static bool skill_read_csvdb( const char* directory, const char* filename, int mincolumns, bool (*parseproc)(char* split[], int columns, int current) ) -{ - FILE* fp; - int lines = 0; - int entries = 0; - char path[1024], line[1024]; - - // open file - snprintf(path, sizeof(path), "%s/%s", directory, filename); - fp = fopen(path,"r"); - if( fp == NULL ) - { - ShowError("skill_read_db: can't read %s\n", path); - return false; - } - - // process rows one by one - while( fgets(line, sizeof(line), fp) ) - { - char* split[50]; - int columns; - - lines++; - if( line[0] == '/' && line[1] == '/' ) - continue; - //TODO: strip trailing // comment - //TODO: strip trailing whitespace - if( line[0] == '\0' || line[0] == '\n' ) - continue; - - memset(split,0,sizeof(split)); - columns = skill_split_str(line,split,ARRAYLENGTH(split)); - if( columns < 2 ) // FIXME: assumes db has at least 2 mandatory columns - continue; // empty line - if( columns < mincolumns ) - { - ShowError("skill_read_csvdb: Insufficient columns in line %d of \"%s\" (found %d, need at least %d).\n", lines, path, columns, mincolumns); - continue; // not enough columns - } - if( columns > ARRAYLENGTH(split) ) - { - ShowError("skill_read_csvdb: Too many columns in line %d of \"%s\" (found %d, capacity %d). Increase the capacity in the source code please.\n", lines, path, columns, ARRAYLENGTH(split) ); - continue; // source code problem - } - - // parse this row - if( !parseproc(split, columns, entries) ) - { - ShowError("skill_read_csvdb: Could not process contents of line %d of \"%s\".\n", lines, path); - continue; // invalid row contents? - } - - // success! - entries++; - } - - fclose(fp); - ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", entries, path); - - return true; -} static bool skill_parse_row_skilldb(char* split[], int columns, int current) {// id,range,hit,inf,element,nk,splash,max,list_num,castcancel,cast_defence_rate,inf2,maxcount,skill_type,blow_count,name,description @@ -10938,6 +10877,32 @@ static bool skill_parse_row_castdb(char* split[], int columns, int current) return true; } +static bool skill_parse_row_castnodexdb(char* split[], int columns, int current) +{// Skill id,Cast,Delay (optional) + int i = atoi(split[0]); + i = skill_get_index(i); + if( !i ) // invalid skill id + return false; + + skill_split_atoi(split[1],skill_db[i].castnodex); + if( split[2] ) // optional column + skill_split_atoi(split[2],skill_db[i].delaynodex); + + return true; +} + +static bool skill_parse_row_nocastdb(char* split[], int columns, int current) +{// SkillID,Flag + int i = atoi(split[0]); + i = skill_get_index(i); + if( !i ) // invalid skill id + return false; + + skill_db[i].nocast |= atoi(split[1]); + + return true; +} + static bool skill_parse_row_unitdb(char* split[], int columns, int current) {// ID,unit ID,unit ID 2,layout,range,interval,target,flag int i = atoi(split[0]); @@ -10985,8 +10950,6 @@ static bool skill_parse_row_producedb(char* split[], int columns, int current) int i = atoi(split[0]); if( !i ) return false; - if( current == MAX_SKILL_PRODUCE_DB ) - return false; skill_produce_db[current].nameid = i; skill_produce_db[current].itemlv = atoi(split[1]); @@ -10999,9 +10962,6 @@ static bool skill_parse_row_producedb(char* split[], int columns, int current) skill_produce_db[current].mat_amount[y] = atoi(split[x+1]); } - if( current == MAX_SKILL_PRODUCE_DB-1 ) - ShowWarning("Reached the max number of produce_db entries (%d), consider raising the value of MAX_SKILL_PRODUCE_DB and recompile.\n", MAX_SKILL_PRODUCE_DB); - return true; } @@ -11012,19 +10972,15 @@ static bool skill_parse_row_createarrowdb(char* split[], int columns, int curren int i = atoi(split[0]); if( !i ) return false; - if( current == MAX_SKILL_ARROW_DB ) - return false; skill_arrow_db[current].nameid = i; - for( x = 1, y = 0; x+1 < columns && split[x] && split[x+1] && y < 5; x += 2, y++ ) + for( x = 1, y = 0; x+1 < columns && split[x] && split[x+1] && y < MAX_ARROW_RESOURCE; x += 2, y++ ) { skill_arrow_db[current].cre_id[y] = atoi(split[x]); skill_arrow_db[current].cre_amount[y] = atoi(split[x+1]); } - //TODO?: add capacity warning here - return true; } @@ -11042,45 +10998,14 @@ static bool skill_parse_row_abradb(char* split[], int columns, int current) return false; } - if( current == MAX_SKILL_ABRA_DB ) - return false; - skill_abra_db[current].skillid = i; skill_abra_db[current].req_lv = atoi(split[2]); skill_abra_db[current].per = atoi(split[3]); - //TODO?: add capacity warning here - return true; } -static bool skill_parse_row_castnodexdb(char* split[], int columns, int current) -{// Skill id,Cast,Delay (optional) - int i = atoi(split[0]); - i = skill_get_index(i); - if( !i ) // invalid skill id - return false; - - skill_split_atoi(split[1],skill_db[i].castnodex); - if( split[2] ) // optional column - skill_split_atoi(split[2],skill_db[i].delaynodex); - - return true; -} - -static bool skill_parse_row_nocastdb(char* split[], int columns, int current) -{// SkillID,Flag - int i = atoi(split[0]); - i = skill_get_index(i); - if( !i ) // invalid skill id - return false; - - skill_db[i].nocast |= atoi(split[1]); - - return true; -} - -int skill_readdb(void) +static void skill_readdb(void) { // init skill db structures memset(skill_db,0,sizeof(skill_db)); @@ -11089,20 +11014,18 @@ int skill_readdb(void) memset(skill_abra_db,0,sizeof(skill_abra_db)); // load skill databases - skill_read_csvdb(db_path, "skill_db.txt", 17, skill_parse_row_skilldb); safestrncpy(skill_db[0].name, "UNKNOWN_SKILL", sizeof(skill_db[0].name)); safestrncpy(skill_db[0].desc, "Unknown Skill", sizeof(skill_db[0].desc)); - skill_read_csvdb(db_path, "skill_require_db.txt", 17, skill_parse_row_requiredb); - skill_read_csvdb(db_path, "skill_cast_db.txt", 6, skill_parse_row_castdb); - skill_read_csvdb(db_path, "skill_unit_db.txt", 8, skill_parse_row_unitdb); + sv_readdb(db_path, "skill_db.txt" , ',', 17, 17, MAX_SKILL_DB, skill_parse_row_skilldb); + sv_readdb(db_path, "skill_require_db.txt" , ',', 32, 32, MAX_SKILL_DB, skill_parse_row_requiredb); + sv_readdb(db_path, "skill_cast_db.txt" , ',', 6, 6, MAX_SKILL_DB, skill_parse_row_castdb); + sv_readdb(db_path, "skill_castnodex_db.txt", ',', 2, 3, MAX_SKILL_DB, skill_parse_row_castnodexdb); + sv_readdb(db_path, "skill_nocast_db.txt" , ',', 2, 2, MAX_SKILL_DB, skill_parse_row_nocastdb); + sv_readdb(db_path, "skill_unit_db.txt" , ',', 8, 8, MAX_SKILL_DB, skill_parse_row_unitdb); skill_init_unit_layout(); - skill_read_csvdb(db_path, "produce_db.txt", 4, skill_parse_row_producedb); - skill_read_csvdb(db_path, "create_arrow_db.txt", 1+2, skill_parse_row_createarrowdb); - skill_read_csvdb(db_path, "abra_db.txt", 4, skill_parse_row_abradb); - skill_read_csvdb(db_path, "skill_castnodex_db.txt", 2, skill_parse_row_castnodexdb); - skill_read_csvdb(db_path, "skill_nocast_db.txt", 2, skill_parse_row_nocastdb); - - return 0; + sv_readdb(db_path, "produce_db.txt" , ',', 4, 4+2*MAX_PRODUCE_RESOURCE, MAX_SKILL_PRODUCE_DB, skill_parse_row_producedb); + sv_readdb(db_path, "create_arrow_db.txt" , ',', 1+2, 1+2*MAX_ARROW_RESOURCE, MAX_SKILL_ARROW_DB, skill_parse_row_createarrowdb); + sv_readdb(db_path, "abra_db.txt" , ',', 4, 4, MAX_SKILL_ABRA_DB, skill_parse_row_abradb); } void skill_reload (void) diff --git a/src/map/skill.h b/src/map/skill.h index 70ebefe89..864eb4a97 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -16,6 +16,7 @@ struct status_change_entry; #define MAX_SKILL_PRODUCE_DB 150 #define MAX_PRODUCE_RESOURCE 12 #define MAX_SKILL_ARROW_DB 150 +#define MAX_ARROW_RESOURCE 5 #define MAX_SKILL_ABRA_DB 350 #define MAX_SKILL_LEVEL 100 @@ -186,7 +187,7 @@ extern struct s_skill_produce_db skill_produce_db[MAX_SKILL_PRODUCE_DB]; // 矢作成デ?タベ?ス struct s_skill_arrow_db { int nameid, trigger; - int cre_id[5],cre_amount[5]; + int cre_id[MAX_ARROW_RESOURCE],cre_amount[MAX_ARROW_RESOURCE]; }; extern struct s_skill_arrow_db skill_arrow_db[MAX_SKILL_ARROW_DB]; @@ -685,7 +686,7 @@ enum s_skill { BA_MUSICALLESSON, BA_MUSICALSTRIKE, BA_DISSONANCE, - BA_FROSTJOKE, + BA_FROSTJOKER, BA_WHISTLE, BA_ASSASSINCROSS, BA_POEMBRAGI, diff --git a/src/map/status.c b/src/map/status.c index 046e13b2a..b362a15cd 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -260,7 +260,7 @@ void initChangeTables(void) add_sc( BD_ROKISWEIL , SC_ROKISWEIL ); add_sc( BD_INTOABYSS , SC_INTOABYSS ); set_sc( BD_SIEGFRIED , SC_SIEGFRIED , SI_BLANK , SCB_PC ); - add_sc( BA_FROSTJOKE , SC_FREEZE ); + add_sc( BA_FROSTJOKER , SC_FREEZE ); set_sc( BA_WHISTLE , SC_WHISTLE , SI_BLANK , SCB_FLEE|SCB_FLEE2 ); set_sc( BA_ASSASSINCROSS , SC_ASSNCROS , SI_BLANK , SCB_ASPD ); add_sc( BA_POEMBRAGI , SC_POEMBRAGI ); |