summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog-Trunk.txt5
-rw-r--r--conf/log_athena.conf4
-rw-r--r--db/abra_db.txt2
-rw-r--r--db/mob_db.txt2
-rw-r--r--db/skill_db.txt12
-rw-r--r--src/common/strlib.c80
-rw-r--r--src/common/strlib.h4
-rw-r--r--src/map/atcommand.c32
-rw-r--r--src/map/mob.c17
-rw-r--r--src/map/pc.c166
-rw-r--r--src/map/quest.c2
-rw-r--r--src/map/skill.c175
-rw-r--r--src/map/skill.h5
-rw-r--r--src/map/status.c2
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 );