diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/char/int_guild.c | 451 | ||||
-rw-r--r-- | src/char_sql/int_guild.c | 210 | ||||
-rw-r--r-- | src/char_sql/int_homun.c | 18 | ||||
-rw-r--r-- | src/common/mmo.h | 7 | ||||
-rw-r--r-- | src/common/showmsg.c | 2 | ||||
-rw-r--r-- | src/map/battle.c | 4 | ||||
-rw-r--r-- | src/map/chrif.c | 10 | ||||
-rw-r--r-- | src/map/clif.c | 32 | ||||
-rw-r--r-- | src/map/guild.c | 133 | ||||
-rw-r--r-- | src/map/guild.h | 3 | ||||
-rw-r--r-- | src/map/intif.c | 5 | ||||
-rw-r--r-- | src/map/irc.c | 2 | ||||
-rw-r--r-- | src/map/npc.c | 105 | ||||
-rw-r--r-- | src/map/npc.h | 4 | ||||
-rw-r--r-- | src/map/status.c | 2 | ||||
-rw-r--r-- | src/map/status.h | 2 |
16 files changed, 488 insertions, 502 deletions
diff --git a/src/char/int_guild.c b/src/char/int_guild.c index 6332d33b7..706b1b3d9 100644 --- a/src/char/int_guild.c +++ b/src/char/int_guild.c @@ -31,23 +31,24 @@ static unsigned int guild_exp[100]; int mapif_parse_GuildLeave(int fd, int guild_id, int account_id, int char_id, int flag, const char *mes); int mapif_guild_broken(int guild_id, int flag); -int guild_check_empty(struct guild *g); +bool guild_check_empty(struct guild *g); int guild_calcinfo(struct guild *g); int mapif_guild_basicinfochanged(int guild_id, int type, const void *data, int len); int mapif_guild_info(int fd, struct guild *g); int guild_break_sub(DBKey key, void *data, va_list ap); -// ギルドデータの文字列への変換 -int inter_guild_tostr(char *str, struct guild *g) { +/// serializes the guild data structure into the provided string +int inter_guild_tostr(char* str, struct guild* g) +{ int i, c, len; - // 基本データ + // save guild base info len = sprintf(str, "%d\t%s\t%s\t%d,%d,%u,%d,%d\t%s#\t%s#\t", - g->guild_id, g->name, g->master, - g->guild_lv, g->max_member, g->exp, g->skill_point, g->castle_id, - g->mes1, g->mes2); - // メンバー - for(i = 0; i < g->max_member; i++) { + g->guild_id, g->name, g->master, g->guild_lv, g->max_member, g->exp, g->skill_point, 0, g->mes1, g->mes2); + + // save guild member info + for(i = 0; i < g->max_member; i++) + { struct guild_member *m = &g->member[i]; len += sprintf(str + len, "%d,%d,%d,%d,%d,%d,%d,%u,%d,%d\t%s\t", m->account_id, m->char_id, @@ -55,18 +56,21 @@ int inter_guild_tostr(char *str, struct guild *g) { m->class_, m->lv, m->exp, m->exp_payper, m->position, ((m->account_id > 0) ? m->name : "-")); } - // 役職 + + // save guild position info for(i = 0; i < MAX_GUILDPOSITION; i++) { struct guild_position *p = &g->position[i]; len += sprintf(str + len, "%d,%d\t%s#\t", p->mode, p->exp_mode, p->name); } - // エンブレム + + // save guild emblem len += sprintf(str + len, "%d,%d,", g->emblem_len, g->emblem_id); for(i = 0; i < g->emblem_len; i++) { len += sprintf(str + len, "%02x", (unsigned char)(g->emblem_data[i])); } len += sprintf(str + len, "$\t"); - // 同盟リスト + + // save guild alliance info c = 0; for(i = 0; i < MAX_GUILDALLIANCE; i++) if (g->alliance[i].guild_id > 0) @@ -77,7 +81,8 @@ int inter_guild_tostr(char *str, struct guild *g) { if (a->guild_id > 0) len += sprintf(str + len, "%d,%d\t%s\t", a->guild_id, a->opposition, a->name); } - // 追放リスト + + // save guild expulsion info c = 0; for(i = 0; i < MAX_GUILDEXPULSION; i++) if (g->expulsion[i].account_id > 0) @@ -87,10 +92,10 @@ int inter_guild_tostr(char *str, struct guild *g) { struct guild_expulsion *e = &g->expulsion[i]; if (e->account_id > 0) len += sprintf(str + len, "%d,%d,%d,%d\t%s\t%s\t%s#\t", - e->account_id, e->rsv1, e->rsv2, e->rsv3, - e->name, e->acc, e->mes ); + e->account_id, 0, 0, 0, e->name, "#", e->mes ); } - // ギルドスキル + + // save guild skill info for(i = 0; i < MAX_GUILDSKILL; i++) { len += sprintf(str + len, "%d,%d ", g->skill[i].id, g->skill[i].lv); } @@ -99,154 +104,206 @@ int inter_guild_tostr(char *str, struct guild *g) { return 0; } #endif //TXT_SQL_CONVERT -// ギルドデータの文字列からの変換 -int inter_guild_fromstr(char *str, struct guild *g) { - int i, j, c; - unsigned int exp; - int tmp_int[16]; - char tmp_str[4][256]; - char tmp_str2[4096]; + +/// parses the guild data string into a guild data structure +int inter_guild_fromstr(char* str, struct guild* g) +{ + int i, c; char *pstr; - // 基本データ memset(g, 0, sizeof(struct guild)); - if (sscanf(str, "%d\t%[^\t]\t%[^\t]\t%d,%d,%u,%d,%d\t%[^\t]\t%[^\t]\t", &tmp_int[0], - tmp_str[0], tmp_str[1], - &tmp_int[1], &tmp_int[2], &exp, &tmp_int[4], &tmp_int[5], - tmp_str[2], tmp_str[3]) < 8) - return 1; - g->guild_id = tmp_int[0]; - g->guild_lv = tmp_int[1]; - g->max_member = tmp_int[2]; - g->exp = exp; - g->skill_point = tmp_int[4]; -#ifndef TXT_SQL_CONVERT - g->castle_id = tmp_int[5]; -#endif - memcpy(g->name, tmp_str[0], NAME_LENGTH); - memcpy(g->master, tmp_str[1], NAME_LENGTH); - memcpy(g->mes1, tmp_str[2], 60); - memcpy(g->mes2, tmp_str[3], 120); - g->mes1[strlen(g->mes1)-1] = 0; - g->mes2[strlen(g->mes2)-1] = 0; - - for(j = 0; j < 6 && str != NULL; j++) // 位置スキップ - str = strchr(str + 1, '\t'); -// printf("GuildBaseInfo OK\n"); - - // メンバー - for(i = 0; i < g->max_member; i++) { - struct guild_member *m = &g->member[i]; - if (sscanf(str + 1, "%d,%d,%d,%d,%d,%d,%d,%u,%d,%d\t%[^\t]\t", - &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3], &tmp_int[4], - &tmp_int[5], &tmp_int[6], &exp, &tmp_int[8], &tmp_int[9], - tmp_str[0]) < 11) + {// load guild base info + int guildid; + char name[256]; // only 24 used + char master[256]; // only 24 used + int guildlv; + int max_member; + unsigned int exp; + int skpoint; + char mes1[256]; // only 60 used + char mes2[256]; // only 120 used + int len; + + if( sscanf(str, "%d\t%[^\t]\t%[^\t]\t%d,%d,%u,%d,%*d\t%[^\t]\t%[^\t]\t%n", + &guildid, name, master, &guildlv, &max_member, &exp, &skpoint, mes1, mes2, &len) < 9 ) return 1; - m->account_id = tmp_int[0]; - m->char_id = tmp_int[1]; - m->hair = tmp_int[2]; - m->hair_color = tmp_int[3]; - m->gender = tmp_int[4]; - m->class_ = tmp_int[5]; - m->lv = tmp_int[6]; - m->exp = exp; - m->exp_payper = tmp_int[8]; - m->position = tmp_int[9]; - memcpy(m->name, tmp_str[0], NAME_LENGTH); - - for(j = 0; j < 2 && str != NULL; j++) // 位置スキップ - str = strchr(str + 1, '\t'); + + // remove '#' + mes1[strlen(mes1)-1] = '\0'; + mes2[strlen(mes2)-1] = '\0'; + + g->guild_id = guildid; + g->guild_lv = guildlv; + g->max_member = max_member; + g->exp = exp; + g->skill_point = skpoint; + safestrncpy(g->name, name, sizeof(g->name)); + safestrncpy(g->master, master, sizeof(g->master)); + safestrncpy(g->mes1, mes1, sizeof(g->mes1)); + safestrncpy(g->mes2, mes2, sizeof(g->mes2)); + + str+= len; } -// printf("GuildMemberInfo OK\n"); - // 役職 - i = 0; - while (sscanf(str+1, "%d,%d%n", &tmp_int[0], &tmp_int[1], &j) == 2 && str[1+j] == '\t') { - struct guild_position *p = &g->position[i]; - if (sscanf(str+1, "%d,%d\t%[^\t]\t", &tmp_int[0], &tmp_int[1], tmp_str[0]) < 3) - return 1; - p->mode = tmp_int[0]; - p->exp_mode = tmp_int[1]; - tmp_str[0][strlen(tmp_str[0])-1] = 0; - memcpy(p->name, tmp_str[0], NAME_LENGTH); - for(j = 0; j < 2 && str != NULL; j++) // 位置スキップ - str = strchr(str+1, '\t'); - i++; + {// load guild member info + int accountid; + int charid; + int hair, hair_color, gender; + int class_, lv; + unsigned int exp; + int exp_payper; + int position; + char name[256]; // only 24 used + int len; + int i; + + for( i = 0; i < g->max_member; i++ ) + { + struct guild_member* m = &g->member[i]; + if (sscanf(str, "%d,%d,%d,%d,%d,%d,%d,%u,%d,%d\t%[^\t]\t%n", + &accountid, &charid, &hair, &hair_color, &gender, + &class_, &lv, &exp, &exp_payper, &position, + name, &len) < 11) + return 1; + + m->account_id = accountid; + m->char_id = charid; + m->hair = hair; + m->hair_color = hair_color; + m->gender = gender; + m->class_ = class_; + m->lv = lv; + m->exp = exp; + m->exp_payper = exp_payper; + m->position = position; + safestrncpy(m->name, name, NAME_LENGTH); + + str+= len; + } } -// printf("GuildPositionInfo OK\n"); - // エンブレム - tmp_int[1] = 0; - if (sscanf(str + 1, "%d,%d,%[^\t]\t", &tmp_int[0], &tmp_int[1], tmp_str2)< 3 && - sscanf(str + 1, "%d,%[^\t]\t", &tmp_int[0], tmp_str2) < 2) - return 1; - g->emblem_len = tmp_int[0]; - g->emblem_id = tmp_int[1]; - for(i = 0, pstr = tmp_str2; i < g->emblem_len; i++, pstr += 2) { - int c1 = pstr[0], c2 = pstr[1], x1 = 0, x2 = 0; - if (c1 >= '0' && c1 <= '9') x1 = c1 - '0'; - if (c1 >= 'a' && c1 <= 'f') x1 = c1 - 'a' + 10; - if (c1 >= 'A' && c1 <= 'F') x1 = c1 - 'A' + 10; - if (c2 >= '0' && c2 <= '9') x2 = c2 - '0'; - if (c2 >= 'a' && c2 <= 'f') x2 = c2 - 'a' + 10; - if (c2 >= 'A' && c2 <= 'F') x2 = c2 - 'A' + 10; - g->emblem_data[i] = (x1<<4) | x2; + + {// load guild position info + int mode, exp_mode; + char name[256]; // only 24 used + int len; + int i = 0; + int j; + + while (sscanf(str, "%d,%d%n", &mode, &exp_mode, &j) == 2 && str[j] == '\t') + { + struct guild_position *p = &g->position[i]; + if (sscanf(str, "%d,%d\t%[^\t]\t%n", &mode, &exp_mode, name, &len) < 3) + return 1; + + p->mode = mode; + p->exp_mode = exp_mode; + name[strlen(name)-1] = 0; + safestrncpy(p->name, name, NAME_LENGTH); + + i++; + str+= len; + } } -// printf("GuildEmblemInfo OK\n"); - str=strchr(str + 1, '\t'); // 位置スキップ - // 同盟リスト - if (sscanf(str + 1, "%d\t", &c) < 1) - return 1; - str = strchr(str + 1, '\t'); // 位置スキップ - for(i = 0; i < c; i++) { - struct guild_alliance *a = &g->alliance[i]; - if (sscanf(str + 1, "%d,%d\t%[^\t]\t", &tmp_int[0], &tmp_int[1], tmp_str[0]) < 3) + {// load guild emblem + int emblemlen; + int emblemid; + char emblem[4096]; + int len; + + emblemid = 0; + if( sscanf(str, "%d,%d,%[^\t]\t%n", &emblemlen, &emblemid, emblem, &len) < 3 ) + if( sscanf(str, "%d,%[^\t]\t%n", &emblemlen, emblem, &len) < 2 ) //! pre-svn format return 1; - a->guild_id = tmp_int[0]; - a->opposition = tmp_int[1]; - memcpy(a->name, tmp_str[0], NAME_LENGTH); - for(j = 0; j < 2 && str != NULL; j++) // 位置スキップ - str = strchr(str + 1, '\t'); + g->emblem_len = emblemlen; + g->emblem_id = emblemid; + for(i = 0, pstr = emblem; i < g->emblem_len; i++, pstr += 2) { + int c1 = pstr[0], c2 = pstr[1], x1 = 0, x2 = 0; + if (c1 >= '0' && c1 <= '9') x1 = c1 - '0'; + if (c1 >= 'a' && c1 <= 'f') x1 = c1 - 'a' + 10; + if (c1 >= 'A' && c1 <= 'F') x1 = c1 - 'A' + 10; + if (c2 >= '0' && c2 <= '9') x2 = c2 - '0'; + if (c2 >= 'a' && c2 <= 'f') x2 = c2 - 'a' + 10; + if (c2 >= 'A' && c2 <= 'F') x2 = c2 - 'A' + 10; + g->emblem_data[i] = (x1<<4) | x2; + } + + str+= len; } -// printf("GuildAllianceInfo OK\n"); - // 追放リスト - if (sscanf(str+1, "%d\t", &c) < 1) - return 1; - str = strchr(str + 1, '\t'); // 位置スキップ - for(i = 0; i < c; i++) { - struct guild_expulsion *e = &g->expulsion[i]; - if (sscanf(str + 1, "%d,%d,%d,%d\t%[^\t]\t%[^\t]\t%[^\t]\t", - &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3], - tmp_str[0], tmp_str[1], tmp_str[2]) < 6) + + {// load guild alliance info + int guildid; + int opposition; + char name[256]; // only 24 used + int len; + + if (sscanf(str, "%d\t%n", &c, &len) < 1) return 1; - e->account_id = tmp_int[0]; - e->rsv1 = tmp_int[1]; - e->rsv2 = tmp_int[2]; - e->rsv3 = tmp_int[3]; - memcpy(e->name, tmp_str[0], NAME_LENGTH); - memcpy(e->acc, tmp_str[1], 24); - tmp_str[2][strlen(tmp_str[2])-1] = 0; - memcpy(e->mes, tmp_str[2], 40); - - for(j = 0; j < 4 && str != NULL; j++) // 位置スキップ - str = strchr(str + 1, '\t'); + str+= len; + + for(i = 0; i < c; i++) + { + struct guild_alliance* a = &g->alliance[i]; + if (sscanf(str, "%d,%d\t%[^\t]\t%n", &guildid, &opposition, name, &len) < 3) + return 1; + + a->guild_id = guildid; + a->opposition = opposition; + safestrncpy(a->name, name, NAME_LENGTH); + + str+= len; + } } -// printf("GuildExpulsionInfo OK\n"); - // ギルドスキル - for(i = 0; i < MAX_GUILDSKILL; i++) { - if (sscanf(str+1,"%d,%d ", &tmp_int[0], &tmp_int[1]) < 2) - break; - g->skill[i].id = tmp_int[0]; - g->skill[i].lv = tmp_int[1]; - str = strchr(str + 1, ' '); + + {// load guild expulsion info + int accountid; + char name[256]; // only 24 used + char message[256]; // only 40 used + int len; + int i; + + if (sscanf(str, "%d\t%n", &c, &len) < 1) + return 1; + str+= len; + + for(i = 0; i < c; i++) + { + struct guild_expulsion *e = &g->expulsion[i]; + if (sscanf(str, "%d,%*d,%*d,%*d\t%[^\t]\t%*[^\t]\t%[^\t]\t%n", &accountid, name, message, &len) < 3) + return 1; + + e->account_id = accountid; + safestrncpy(e->name, name, sizeof(e->name)); + message[strlen(message)-1] = 0; // remove '#' + safestrncpy(e->mes, message, sizeof(e->mes)); + + str+= len; + } + } + + {// load guild skill info + int skillid; + int skilllv; + int len; + int i; + + for(i = 0; i < MAX_GUILDSKILL; i++) + { + if (sscanf(str, "%d,%d %n", &skillid, &skilllv, &len) < 2) + break; + g->skill[i].id = skillid; + g->skill[i].lv = skilllv; + + str+= len; + } + str = strchr(str, '\t'); } - str = strchr(str + 1, '\t'); -// printf("GuildSkillInfo OK\n"); return 0; } + #ifndef TXT_SQL_CONVERT // ギルド城データの文字列への変換 int inter_guildcastle_tostr(char *str, struct guild_castle *gc) { @@ -500,7 +557,6 @@ int inter_guild_save() { guild_db->foreach(guild_db, inter_guild_save_sub, fp); // fprintf(fp, "%d\t%%newid%%\n", guild_newid); lock_fclose(fp, guild_txt, &lock); -// printf("int_guild: %s saved.\n", guild_txt); if ((fp = lock_fopen(castle_txt,&lock)) == NULL) { ShowError("int_guild: can't write [%s] !!! data is lost !!!\n", castle_txt); @@ -532,20 +588,19 @@ struct guild* search_guildname(char *str) { } // ギルドが空かどうかチェック -int guild_check_empty(struct guild *g) { +static bool guild_check_empty(struct guild *g) +{ int i; + ARR_FIND( 0, g->max_member, i, g->member[i].account_id > 0 ); + if( i < g->max_member) + return false; // not empty - for(i = 0; i < g->max_member; i++) { - if (g->member[i].account_id > 0) { - return 0; - } - } - // 誰もいないので解散 + // 誰もいないので解散 guild_db->foreach(guild_db, guild_break_sub, g->guild_id); inter_guild_storage_delete(g->guild_id); mapif_guild_broken(g->guild_id, 0); idb_remove(guild_db, g->guild_id); - return 1; + return true; } unsigned int guild_nextexp (int level) @@ -1023,46 +1078,48 @@ int mapif_parse_GuildAddMember(int fd, int guild_id, struct guild_member *m) { return 0; } -// ギルド脱退/追放要求 -int mapif_parse_GuildLeave(int fd, int guild_id, int account_id, int char_id, int flag, const char *mes) { - struct guild *g = NULL; +// Delete member from guild +int mapif_parse_GuildLeave(int fd, int guild_id, int account_id, int char_id, int flag, const char *mes) +{ int i, j; - g = idb_get(guild_db, guild_id); - if (g != NULL) { - for(i = 0; i < MAX_GUILD; i++) { - if (g->member[i].account_id == account_id && g->member[i].char_id == char_id) { -// printf("%d %d\n", i, (int)(&g->member[i])); -// printf("%d %s\n", i, g->member[i].name); - - if (flag) { // 追放の場合追放リストに入れる - for(j = 0; j < MAX_GUILDEXPULSION; j++) { - if (g->expulsion[j].account_id == 0) - break; - } - if (j == MAX_GUILDEXPULSION) { // 一杯なので古いのを消す - for(j = 0; j < MAX_GUILDEXPULSION - 1; j++) - g->expulsion[j] = g->expulsion[j+1]; - j = MAX_GUILDEXPULSION - 1; - } - g->expulsion[j].account_id = account_id; - strncpy(g->expulsion[j].acc, "dummy", NAME_LENGTH); - memcpy(g->expulsion[j].name, g->member[i].name, NAME_LENGTH); - memcpy(g->expulsion[j].mes, mes, 40); - } - - mapif_guild_leaved(guild_id, account_id, char_id, flag, g->member[i].name, mes); -// printf("%d %d\n", i, (int)(&g->member[i])); -// printf("%d %s\n", i, (&g->member[i])->name); - memset(&g->member[i], 0, sizeof(struct guild_member)); + struct guild* g = idb_get(guild_db, guild_id); + if( g == NULL ) + { + //TODO + return 0; + } - if (guild_check_empty(g) == 0) - mapif_guild_info(-1,g);// まだ人がいるのでデータ送信 + // Find the member + ARR_FIND( 0, g->max_member, i, g->member[i].account_id == account_id && g->member[i].char_id == char_id ); + if( i == g->max_member ) + { + //TODO + return 0; + } - return 0; - } + if( flag ) + { // 追放の場合追放リストに入れる + ARR_FIND( 0, MAX_GUILDEXPULSION, j, g->expulsion[j].account_id == 0 ); + if (j == MAX_GUILDEXPULSION) + { // 一杯なので古いのを消す + for(j = 0; j < MAX_GUILDEXPULSION - 1; j++) + g->expulsion[j] = g->expulsion[j+1]; + j = MAX_GUILDEXPULSION - 1; } + // Save the expulsion entry + g->expulsion[j].account_id = account_id; + safestrncpy(g->expulsion[j].name, g->member[i].name, NAME_LENGTH); + safestrncpy(g->expulsion[j].mes, mes, 40); } + + mapif_guild_leaved(guild_id, account_id, char_id, flag, g->member[i].name, mes); + + memset(&g->member[i], 0, sizeof(struct guild_member)); + + if (guild_check_empty(g) == 0) + mapif_guild_info(-1,g);// まだ人がいるのでデータ送信 + return 0; } @@ -1408,12 +1465,13 @@ int mapif_parse_GuildCastleDataLoad(int fd, int castle_id, int index) { return 0; } -int mapif_parse_GuildCastleDataSave(int fd, int castle_id, int index, int value) { +int mapif_parse_GuildCastleDataSave(int fd, int castle_id, int index, int value) +{ struct guild_castle *gc= idb_get(castle_db, castle_id); - if (gc == NULL) { + if (gc == NULL) return mapif_guild_castle_datasave(castle_id, index, value); - } + switch(index) { case 1: if (gc->guild_id != value) { @@ -1494,7 +1552,8 @@ int mapif_parse_GuildMasterChange(int fd, int guild_id, const char* name, int le // ・パケット長データはinter.cにセットしておくこと // ・パケット長チェックや、RFIFOSKIPは呼び出し元で行われるので行ってはならない // ・エラーなら0(false)、そうでないなら1(true)をかえさなければならない -int inter_guild_parse_frommap(int fd) { +int inter_guild_parse_frommap(int fd) +{ RFIFOHEAD(fd); switch(RFIFOW(fd,0)) { case 0x3030: mapif_parse_CreateGuild(fd, RFIFOL(fd,4), (char*)RFIFOP(fd,8), (struct guild_member *)RFIFOP(fd,32)); break; @@ -1522,13 +1581,15 @@ int inter_guild_parse_frommap(int fd) { return 1; } -// マップサーバーの接続時処理 -int inter_guild_mapif_init(int fd) { +// processes a mapserver connection event +int inter_guild_mapif_init(int fd) +{ return mapif_guild_castle_alldataload(fd); } // サーバーから脱退要求(キャラ削除用) -int inter_guild_leave(int guild_id, int account_id, int char_id) { +int inter_guild_leave(int guild_id, int account_id, int char_id) +{ return mapif_parse_GuildLeave(-1, guild_id, account_id, char_id, 0, "** Character Deleted **"); } #endif //TXT_SQL_CONVERT diff --git a/src/char_sql/int_guild.c b/src/char_sql/int_guild.c index 8b8c517f2..3ac50e56c 100644 --- a/src/char_sql/int_guild.c +++ b/src/char_sql/int_guild.c @@ -1,13 +1,13 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#include "../common/mmo.h" #include "../common/cbasetypes.h" -#include "../common/strlib.h" -#include "../common/showmsg.h" -#include "../common/db.h" +#include "../common/mmo.h" #include "../common/malloc.h" #include "../common/socket.h" +#include "../common/db.h" +#include "../common/showmsg.h" +#include "../common/strlib.h" #include "../common/timer.h" #include "char.h" #include "inter.h" @@ -40,7 +40,7 @@ static unsigned int guild_exp[100]; int mapif_parse_GuildLeave(int fd,int guild_id,int account_id,int char_id,int flag,const char *mes); int mapif_guild_broken(int guild_id,int flag); -int guild_check_empty(struct guild *g); +bool guild_check_empty(struct guild *g); int guild_calcinfo(struct guild *g); int mapif_guild_basicinfochanged(int guild_id,int type,const void *data,int len); int mapif_guild_info(int fd,struct guild *g); @@ -105,10 +105,10 @@ int inter_guild_tosql(struct guild *g,int flag) // GS_LEVEL `guild_lv`,`max_member`,`exp`,`next_exp`,`skill_point` // GS_BASIC `name`,`master`,`char_id` - // GS_MEMBER `guild_member` (`guild_id`,`account_id`,`char_id`,`hair`,`hair_color`,`gender`,`class`,`lv`,`exp`,`exp_payper`,`online`,`position`,`rsv1`,`rsv2`,`name`) + // GS_MEMBER `guild_member` (`guild_id`,`account_id`,`char_id`,`hair`,`hair_color`,`gender`,`class`,`lv`,`exp`,`exp_payper`,`online`,`position`,`name`) // GS_POSITION `guild_position` (`guild_id`,`position`,`name`,`mode`,`exp_mode`) // GS_ALLIANCE `guild_alliance` (`guild_id`,`opposition`,`alliance_id`,`name`) - // GS_EXPULSION `guild_expulsion` (`guild_id`,`name`,`mes`,`acc`,`account_id`,`rsv1`,`rsv2`,`rsv3`) + // GS_EXPULSION `guild_expulsion` (`guild_id`,`account_id`,`name`,`mes`) // GS_SKILL `guild_skill` (`guild_id`,`id`,`lv`) // temporary storage for str convertion. They must be twice the size of the @@ -327,15 +327,11 @@ int inter_guild_tosql(struct guild *g,int flag) struct guild_expulsion *e=&g->expulsion[i]; if(e->account_id>0){ char esc_mes[sizeof(e->mes)*2+1]; - char esc_acc[sizeof(e->acc)*2+1]; Sql_EscapeStringLen(sql_handle, esc_name, e->name, strnlen(e->name, NAME_LENGTH)); Sql_EscapeStringLen(sql_handle, esc_mes, e->mes, strnlen(e->mes, sizeof(e->mes))); - Sql_EscapeStringLen(sql_handle, esc_acc, e->acc, strnlen(e->acc, sizeof(e->acc))); - if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`name`,`mes`,`acc`,`account_id`,`rsv1`,`rsv2`,`rsv3`) " - "VALUES ('%d','%s','%s','%s','%d','%d','%d','%d')", - guild_expulsion_db, g->guild_id, - esc_name, esc_mes, esc_acc, e->account_id, e->rsv1, e->rsv2 ,e->rsv3) ) + if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`account_id`,`name`,`mes`) " + "VALUES ('%d','%d','%s','%s')", guild_expulsion_db, g->guild_id, e->account_id, esc_name, esc_mes) ) Sql_ShowDebug(sql_handle); } } @@ -392,11 +388,11 @@ struct guild * inter_guild_fromsql(int guild_id) CREATE(g, struct guild, 1); g->guild_id = guild_id; - Sql_GetData(sql_handle, 0, &data, &len); memcpy(g->name, data, min(len, NAME_LENGTH)); - Sql_GetData(sql_handle, 1, &data, &len); memcpy(g->master, data, min(len, NAME_LENGTH)); - Sql_GetData(sql_handle, 2, &data, NULL); g->guild_lv = atoi(data); - Sql_GetData(sql_handle, 3, &data, NULL); g->connect_member = atoi(data); - Sql_GetData(sql_handle, 4, &data, NULL); g->max_member = atoi(data); + Sql_GetData(sql_handle, 0, &data, &len); memcpy(g->name, data, min(len, NAME_LENGTH)); + Sql_GetData(sql_handle, 1, &data, &len); memcpy(g->master, data, min(len, NAME_LENGTH)); + Sql_GetData(sql_handle, 2, &data, NULL); g->guild_lv = atoi(data); + Sql_GetData(sql_handle, 3, &data, NULL); g->connect_member = atoi(data); + Sql_GetData(sql_handle, 4, &data, NULL); g->max_member = atoi(data); if( g->max_member > MAX_GUILD ) { // Fix reduction of MAX_GUILD [PoW] ShowWarning("Guild %d:%s specifies higher capacity (%d) than MAX_GUILD (%d)\n", guild_id, g->name, g->max_member, MAX_GUILD); @@ -433,9 +429,9 @@ struct guild * inter_guild_fromsql(int guild_id) ++data; } - //printf("- Read guild_member %d from sql \n",guild_id); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id`,`account_id`,`char_id`,`hair`,`hair_color`,`gender`,`class`,`lv`,`exp`,`exp_payper`,`online`,`position`,`rsv1`,`rsv2`,`name` " - "FROM `%s` WHERE `guild_id`='%d' ORDER BY `position`", guild_member_db, guild_id) ) + // load guild member info + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`char_id`,`hair`,`hair_color`,`gender`,`class`,`lv`,`exp`,`exp_payper`,`online`,`position`,`name` " + "FROM `%s` WHERE `guild_id`='%d' ORDER BY `position`", guild_member_db, guild_id) ) { Sql_ShowDebug(sql_handle); aFree(g); @@ -445,29 +441,25 @@ struct guild * inter_guild_fromsql(int guild_id) { struct guild_member* m = &g->member[i]; - Sql_GetData(sql_handle, 1, &data, NULL); m->account_id = atoi(data); - Sql_GetData(sql_handle, 2, &data, NULL); m->char_id = atoi(data); - Sql_GetData(sql_handle, 3, &data, NULL); m->hair = atoi(data); - Sql_GetData(sql_handle, 4, &data, NULL); m->hair_color = atoi(data); - Sql_GetData(sql_handle, 5, &data, NULL); m->gender = atoi(data); - Sql_GetData(sql_handle, 6, &data, NULL); m->class_ = atoi(data); - Sql_GetData(sql_handle, 7, &data, NULL); m->lv = atoi(data); - Sql_GetData(sql_handle, 8, &data, NULL); m->exp = (unsigned int)strtoul(data, NULL, 10); - Sql_GetData(sql_handle, 9, &data, NULL); m->exp_payper = (unsigned int)atoi(data); - Sql_GetData(sql_handle, 10, &data, NULL); m->online = atoi(data); - Sql_GetData(sql_handle, 11, &data, NULL); m->position = atoi(data); + Sql_GetData(sql_handle, 0, &data, NULL); m->account_id = atoi(data); + Sql_GetData(sql_handle, 1, &data, NULL); m->char_id = atoi(data); + Sql_GetData(sql_handle, 2, &data, NULL); m->hair = atoi(data); + Sql_GetData(sql_handle, 3, &data, NULL); m->hair_color = atoi(data); + Sql_GetData(sql_handle, 4, &data, NULL); m->gender = atoi(data); + Sql_GetData(sql_handle, 5, &data, NULL); m->class_ = atoi(data); + Sql_GetData(sql_handle, 6, &data, NULL); m->lv = atoi(data); + Sql_GetData(sql_handle, 7, &data, NULL); m->exp = (unsigned int)strtoul(data, NULL, 10); + Sql_GetData(sql_handle, 8, &data, NULL); m->exp_payper = (unsigned int)atoi(data); + Sql_GetData(sql_handle, 9, &data, NULL); m->online = atoi(data); + Sql_GetData(sql_handle, 10, &data, NULL); m->position = atoi(data); if( m->position >= MAX_GUILDPOSITION ) // Fix reduction of MAX_GUILDPOSITION [PoW] m->position = MAX_GUILDPOSITION - 1; - //## TODO what about the rsv fields? - // rsv1 (12) - // rsv2 (13) - // name - Sql_GetData(sql_handle, 14, &data, &len); memcpy(m->name, data, min(len, NAME_LENGTH)); + Sql_GetData(sql_handle, 11, &data, &len); memcpy(m->name, data, min(len, NAME_LENGTH)); m->modified = GS_MEMBER_UNMODIFIED; } //printf("- Read guild_position %d from sql \n",guild_id); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id`,`position`,`name`,`mode`,`exp_mode` FROM `%s` WHERE `guild_id`='%d'", guild_position_db, guild_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `position`,`name`,`mode`,`exp_mode` FROM `%s` WHERE `guild_id`='%d'", guild_position_db, guild_id) ) { Sql_ShowDebug(sql_handle); aFree(g); @@ -478,18 +470,18 @@ struct guild * inter_guild_fromsql(int guild_id) int position; struct guild_position* p; - Sql_GetData(sql_handle, 1, &data, NULL); position = atoi(data); + Sql_GetData(sql_handle, 0, &data, NULL); position = atoi(data); if( position < 0 || position >= MAX_GUILDPOSITION ) continue;// invalid position p = &g->position[position]; - Sql_GetData(sql_handle, 2, &data, &len); memcpy(p->name, data, min(len, NAME_LENGTH)); - Sql_GetData(sql_handle, 3, &data, NULL); p->mode = atoi(data); - Sql_GetData(sql_handle, 4, &data, NULL); p->exp_mode = atoi(data); + Sql_GetData(sql_handle, 1, &data, &len); memcpy(p->name, data, min(len, NAME_LENGTH)); + Sql_GetData(sql_handle, 2, &data, NULL); p->mode = atoi(data); + Sql_GetData(sql_handle, 3, &data, NULL); p->exp_mode = atoi(data); p->modified = GS_POSITION_UNMODIFIED; } //printf("- Read guild_alliance %d from sql \n",guild_id); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id`,`opposition`,`alliance_id`,`name` FROM `%s` WHERE `guild_id`='%d'", guild_alliance_db, guild_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `opposition`,`alliance_id`,`name` FROM `%s` WHERE `guild_id`='%d'", guild_alliance_db, guild_id) ) { Sql_ShowDebug(sql_handle); aFree(g); @@ -499,13 +491,13 @@ struct guild * inter_guild_fromsql(int guild_id) { struct guild_alliance* a = &g->alliance[i]; - Sql_GetData(sql_handle, 1, &data, NULL); a->opposition = atoi(data); - Sql_GetData(sql_handle, 2, &data, NULL); a->guild_id = atoi(data); - Sql_GetData(sql_handle, 3, &data, &len); memcpy(a->name, data, min(len, NAME_LENGTH)); + Sql_GetData(sql_handle, 0, &data, NULL); a->opposition = atoi(data); + Sql_GetData(sql_handle, 1, &data, NULL); a->guild_id = atoi(data); + Sql_GetData(sql_handle, 2, &data, &len); memcpy(a->name, data, min(len, NAME_LENGTH)); } //printf("- Read guild_expulsion %d from sql \n",guild_id); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id`,`name`,`mes`,`acc`,`account_id`,`rsv1`,`rsv2`,`rsv3` FROM `%s` WHERE `guild_id`='%d'", guild_expulsion_db, guild_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name`,`mes` FROM `%s` WHERE `guild_id`='%d'", guild_expulsion_db, guild_id) ) { Sql_ShowDebug(sql_handle); aFree(g); @@ -515,17 +507,13 @@ struct guild * inter_guild_fromsql(int guild_id) { struct guild_expulsion *e = &g->expulsion[i]; + Sql_GetData(sql_handle, 0, &data, NULL); e->account_id = atoi(data); Sql_GetData(sql_handle, 1, &data, &len); memcpy(e->name, data, min(len, NAME_LENGTH)); Sql_GetData(sql_handle, 2, &data, &len); memcpy(e->mes, data, min(len, sizeof(e->mes))); - Sql_GetData(sql_handle, 3, &data, &len); memcpy(e->acc, data, min(len, sizeof(e->acc))); - Sql_GetData(sql_handle, 4, &data, NULL); e->account_id = atoi(data); - Sql_GetData(sql_handle, 5, &data, NULL); e->rsv1 = atoi(data); - Sql_GetData(sql_handle, 6, &data, NULL); e->rsv2 = atoi(data); - Sql_GetData(sql_handle, 7, &data, NULL); e->rsv3 = atoi(data); } //printf("- Read guild_skill %d from sql \n",guild_id); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id`,`id`,`lv` FROM `%s` WHERE `guild_id`='%d' ORDER BY `id`", guild_skill_db, guild_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `id`,`lv` FROM `%s` WHERE `guild_id`='%d' ORDER BY `id`", guild_skill_db, guild_id) ) { Sql_ShowDebug(sql_handle); aFree(g); @@ -540,14 +528,10 @@ struct guild * inter_guild_fromsql(int guild_id) while( SQL_SUCCESS == Sql_NextRow(sql_handle) ) { int id; - // id - Sql_GetData(sql_handle, 1, &data, NULL); - id = atoi(data) - GD_SKILLBASE; + Sql_GetData(sql_handle, 0, &data, NULL); id = atoi(data) - GD_SKILLBASE; if( id < 0 && id >= MAX_GUILDSKILL ) continue;// invalid guild skill - // lv - Sql_GetData(sql_handle, 2, &data, NULL); - g->skill[id].lv = atoi(data); + Sql_GetData(sql_handle, 1, &data, NULL); g->skill[id].lv = atoi(data); } Sql_FreeResult(sql_handle); @@ -853,17 +837,16 @@ int search_guildname(char *str) } // Check if guild is empty -int guild_check_empty(struct guild *g) +static bool guild_check_empty(struct guild *g) { int i; - for(i=0;i<g->max_member;i++){ - if(g->member[i].account_id>0){ - return 0; - } - } + ARR_FIND( 0, g->max_member, i, g->member[i].account_id > 0 ); + if( i < g->max_member) + return false; // not empty + //Let the calling function handle the guild removal in case they need //to do something else with it before freeing the data. [Skotlex] - return 1; + return true; } unsigned int guild_nextexp(int level) @@ -1385,60 +1368,57 @@ int mapif_parse_GuildAddMember(int fd,int guild_id,struct guild_member *m) } // Delete member from guild -int mapif_parse_GuildLeave(int fd,int guild_id,int account_id,int char_id,int flag,const char *mes) +int mapif_parse_GuildLeave(int fd, int guild_id, int account_id, int char_id, int flag, const char *mes) { - struct guild * g = inter_guild_fromsql(guild_id); - - if(g){ - int i; - // Find the member - for(i=0;i<g->max_member;i++){ - if( g->member[i].account_id==account_id && g->member[i].char_id==char_id) - { - if(flag) - { - // Write expulsion reason - int j; - // Find an empty slot - for(j=0;j<MAX_GUILDEXPULSION;j++){ - if(g->expulsion[j].account_id==0) - break; - } - // Expulsion list is full, flush the oldest one - if(j==MAX_GUILDEXPULSION){ - for(j=0;j<MAX_GUILDEXPULSION-1;j++) - g->expulsion[j]=g->expulsion[j+1]; - j=MAX_GUILDEXPULSION-1; - } - // Save the expulsion - g->expulsion[j].account_id=account_id; - strncpy(g->expulsion[j].acc,"dummy",NAME_LENGTH); - memcpy(g->expulsion[j].name,g->member[i].name,NAME_LENGTH); - memcpy(g->expulsion[j].mes,mes,40); - } + int i, j; - mapif_guild_leaved(guild_id,account_id,char_id,flag,g->member[i].name,mes); - inter_guild_removemember_tosql(g->member[i].account_id,g->member[i].char_id); + struct guild* g = inter_guild_fromsql(guild_id); + if( g == NULL ) + { + // Unknown guild, just update the player + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `guild_id`='0' WHERE `account_id`='%d' AND `char_id`='%d'", char_db, account_id, char_id) ) + Sql_ShowDebug(sql_handle); + // mapif_guild_leaved(guild_id,account_id,char_id,flag,g->member[i].name,mes); + return 0; + } - memset(&g->member[i],0,sizeof(struct guild_member)); + // Find the member + ARR_FIND( 0, g->max_member, i, g->member[i].account_id == account_id && g->member[i].char_id == char_id ); + if( i == g->max_member ) + { + //TODO + return 0; + } - if(!guild_check_empty(g)) { - break; - } - //Guild empty? break it. - mapif_parse_BreakGuild(-1,guild_id); //Break the guild. - return 0; - } + if( flag ) + { // Write expulsion reason + // Find an empty slot + ARR_FIND( 0, MAX_GUILDEXPULSION, j, g->expulsion[j].account_id == 0 ); + if( j == MAX_GUILDEXPULSION ) + { + // Expulsion list is full, flush the oldest one + for( j = 0; j < MAX_GUILDEXPULSION - 1; j++ ) + g->expulsion[j] = g->expulsion[j+1]; + j = MAX_GUILDEXPULSION-1; } + // Save the expulsion entry + g->expulsion[j].account_id = account_id; + safestrncpy(g->expulsion[j].name, g->member[i].name, NAME_LENGTH); + safestrncpy(g->expulsion[j].mes, mes, 40); + } + + mapif_guild_leaved(guild_id,account_id,char_id,flag,g->member[i].name,mes); + inter_guild_removemember_tosql(g->member[i].account_id,g->member[i].char_id); + + memset(&g->member[i],0,sizeof(struct guild_member)); + + if( guild_check_empty(g) ) + mapif_parse_BreakGuild(-1,guild_id); //Break the guild. + else { //Update member info. if (!guild_calcinfo(g)) mapif_guild_info(fd,g); g->save_flag |= GS_EXPULSION; - }else{ - // Unknown guild, just update the player - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `guild_id`='0' WHERE `account_id`='%d' AND `char_id`='%d'", char_db, account_id, char_id) ) - Sql_ShowDebug(sql_handle); - /* mapif_guild_leaved(guild_id,account_id,char_id,flag,g->member[i].name,mes); */ } return 0; @@ -1994,7 +1974,7 @@ int mapif_parse_GuildMasterChange(int fd, int guild_id, const char* name, int le int inter_guild_parse_frommap(int fd) { RFIFOHEAD(fd); - switch(RFIFOW(fd,0)){ + switch(RFIFOW(fd,0)) { case 0x3030: mapif_parse_CreateGuild(fd,RFIFOL(fd,4),(char*)RFIFOP(fd,8),(struct guild_member *)RFIFOP(fd,32)); break; case 0x3031: mapif_parse_GuildInfo(fd,RFIFOL(fd,2)); break; case 0x3032: mapif_parse_GuildAddMember(fd,RFIFOL(fd,4),(struct guild_member *)RFIFOP(fd,8)); break; @@ -2016,18 +1996,20 @@ int inter_guild_parse_frommap(int fd) default: return 0; } + return 1; } +// processes a mapserver connection event int inter_guild_mapif_init(int fd) { return mapif_guild_castle_alldataload(fd); } // サーバーから脱退要求(キャラ削除用) -int inter_guild_leave(int guild_id,int account_id,int char_id) +int inter_guild_leave(int guild_id, int account_id, int char_id) { - return mapif_parse_GuildLeave(-1,guild_id,account_id,char_id,0,"** Character Deleted **"); + return mapif_parse_GuildLeave(-1, guild_id, account_id, char_id, 0, "** Character Deleted **"); } int inter_guild_broken(int guild_id) diff --git a/src/char_sql/int_homun.c b/src/char_sql/int_homun.c index 25637c6e7..a838ebf1d 100644 --- a/src/char_sql/int_homun.c +++ b/src/char_sql/int_homun.c @@ -27,12 +27,12 @@ void inter_homunculus_sql_final(void){ return; } -int mapif_saved_homunculus(int fd, int account_id, unsigned char flag) +static int mapif_saved_homunculus(int fd, int account_id, bool flag) { WFIFOHEAD(fd, 7); WFIFOW(fd,0) = 0x3892; WFIFOL(fd,2) = account_id; - WFIFOB(fd,6) = flag; + WFIFOB(fd,6) = flag; // 1:success, 0:failure WFIFOSET(fd, 7); return 0; } @@ -71,7 +71,7 @@ int mapif_homunculus_created(int fd, int account_id, struct s_homunculus *sh, un } // Save/Update Homunculus Skills -int mapif_save_homunculus_skills(struct s_homunculus *hd) +static bool mapif_save_homunculus_skills(struct s_homunculus *hd) { SqlStmt* stmt; int i; @@ -89,18 +89,18 @@ int mapif_save_homunculus_skills(struct s_homunculus *hd) { SqlStmt_ShowDebug(stmt); SqlStmt_Free(stmt); - return 0; + return false; } } } SqlStmt_Free(stmt); - return 1; + return true; } -int mapif_save_homunculus(int fd, int account_id, struct s_homunculus *hd) +static bool mapif_save_homunculus(int fd, int account_id, struct s_homunculus *hd) { - int flag = 1; + bool flag = true; char esc_name[NAME_LENGTH*2+1]; Sql_EscapeStringLen(sql_handle, esc_name, hd->name, strnlen(hd->name, NAME_LENGTH)); @@ -114,7 +114,7 @@ int mapif_save_homunculus(int fd, int account_id, struct s_homunculus *hd) hd->hp, hd->max_hp, hd->sp, hd->max_sp, hd->skillpts, hd->rename_flag, hd->vaporize) ) { Sql_ShowDebug(sql_handle); - flag = 0; + flag = false; } else { @@ -128,7 +128,7 @@ int mapif_save_homunculus(int fd, int account_id, struct s_homunculus *hd) hd->hp, hd->max_hp, hd->sp, hd->max_sp, hd->skillpts, hd->rename_flag, hd->vaporize, hd->hom_id) ) { Sql_ShowDebug(sql_handle); - flag = 0; + flag = false; } else { diff --git a/src/common/mmo.h b/src/common/mmo.h index 56e4eb9ce..6bb916299 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -328,7 +328,6 @@ struct guild_member { unsigned int exp; int exp_payper; short online,position; - int rsv1,rsv2; char name[NAME_LENGTH]; struct map_session_data *sd; unsigned char modified; @@ -350,9 +349,7 @@ struct guild_alliance { struct guild_expulsion { char name[NAME_LENGTH]; char mes[40]; - char acc[40]; int account_id; - int rsv1,rsv2,rsv3; }; struct guild_skill { @@ -364,10 +361,6 @@ struct guild { short guild_lv, connect_member, max_member, average_lv; unsigned int exp,next_exp; int skill_point; -#ifdef TXT_ONLY - //FIXME: Gotta remove this variable completely, but doing so screws up the format of the txt save file... - int castle_id; -#endif char name[NAME_LENGTH],master[NAME_LENGTH]; struct guild_member member[MAX_GUILD]; struct guild_position position[MAX_GUILDPOSITION]; diff --git a/src/common/showmsg.c b/src/common/showmsg.c index 6fb8a2e6c..fa744f0e4 100644 --- a/src/common/showmsg.c +++ b/src/common/showmsg.c @@ -76,7 +76,7 @@ int msg_silent = 0; //Specifies how silent the console is. buf.d_ = StringBuf_Malloc(); \ buf.l_ = StringBuf_Vprintf(buf.d_, fmt, args); \ buf.v_ = StringBuf_Value(buf.d_); \ - ShowDebug("showmsg: dynamic buffer used, increase the static buffer size to %d or more.", buf.l_+1);\ + ShowDebug("showmsg: dynamic buffer used, increase the static buffer size to %d or more.\n", buf.l_+1);\ } \ //define BUFVPRINTF diff --git a/src/map/battle.c b/src/map/battle.c index 346948cb6..eeb368feb 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -3232,7 +3232,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f int t_guild = status_get_guild_id(t_bl); if ( !(map[m].flag.pvp && map[m].flag.pvp_noguild) && - s_guild && t_guild && (s_guild == t_guild || guild_idisallied(s_guild, t_guild)) + s_guild && t_guild && (s_guild == t_guild || guild_isallied(s_guild, t_guild)) ) state |= BCT_GUILD; else @@ -3260,7 +3260,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f if (flag&BCT_GUILD || state&BCT_ENEMY) { int s_guild = status_get_guild_id(s_bl); int t_guild = status_get_guild_id(t_bl); - if(s_guild && t_guild && (s_guild == t_guild || guild_idisallied(s_guild, t_guild))) + if(s_guild && t_guild && (s_guild == t_guild || guild_isallied(s_guild, t_guild))) state |= BCT_GUILD; } } diff --git a/src/map/chrif.c b/src/map/chrif.c index b2a3af4bf..a041d9957 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -92,7 +92,6 @@ static uint32 char_ip = 0; static uint16 char_port = 6121; static char userid[NAME_LENGTH], passwd[NAME_LENGTH]; static int chrif_state = 0; -static int char_init_done = 0; int other_mapserver_count=0; //Holds count of how many other map servers are online (apart of this instance) [Skotlex] //Interval at which map server updates online listing. [Valaris] @@ -342,20 +341,23 @@ int chrif_changemapserverack(int account_id, int login_id1, int login_id2, int c *------------------------------------------*/ int chrif_connectack(int fd) { + static bool char_init_done = false; + if (RFIFOB(fd,2)) { ShowFatalError("Connection to char-server failed %d.\n", RFIFOB(fd,2)); exit(EXIT_FAILURE); } + ShowStatus("Successfully logged on to Char Server (Connection: '"CL_WHITE"%d"CL_RESET"').\n",fd); chrif_state = 1; - chrif_connected=1; + chrif_connected = 1; chrif_sendmap(fd); ShowStatus("Event '"CL_WHITE"OnCharIfInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnCharIfInit")); ShowStatus("Event '"CL_WHITE"OnInterIfInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInit")); - if(!char_init_done) { - char_init_done = 1; + if( !char_init_done ) { + char_init_done = true; ShowStatus("Event '"CL_WHITE"OnInterIfInitOnce"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInitOnce")); } diff --git a/src/map/clif.c b/src/map/clif.c index 53227d286..e0d4c1ca0 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -6472,6 +6472,7 @@ int clif_guild_inviteack(struct map_session_data *sd,int flag) WFIFOSET(fd,packet_len(0x169)); return 0; } + /*========================================== * ギルドメンバ脱退通知 *------------------------------------------*/ @@ -6487,23 +6488,24 @@ int clif_guild_leave(struct map_session_data *sd,const char *name,const char *me clif_send(buf,packet_len(0x15a),&sd->bl,GUILD); return 0; } + /*========================================== * ギルドメンバ追放通知 *------------------------------------------*/ -int clif_guild_expulsion(struct map_session_data *sd,const char *name,const char *mes, - int account_id) +int clif_guild_expulsion(struct map_session_data *sd,const char *name,const char *mes,int account_id) { unsigned char buf[128]; nullpo_retr(0, sd); WBUFW(buf, 0)=0x15c; - memcpy(WBUFP(buf, 2),name,NAME_LENGTH); - memcpy(WBUFP(buf,26),mes,40); - memcpy(WBUFP(buf,66),"dummy",NAME_LENGTH); + safestrncpy(WBUFP(buf, 2),name,NAME_LENGTH); + safestrncpy(WBUFP(buf,26),mes,40); + safestrncpy(WBUFP(buf,66),"",NAME_LENGTH); // account name (not used for security reasons) clif_send(buf,packet_len(0x15c),&sd->bl,GUILD); return 0; } + /*========================================== * ギルド追放メンバリスト *------------------------------------------*/ @@ -6519,18 +6521,18 @@ int clif_guild_expulsionlist(struct map_session_data *sd) g=guild_search(sd->status.guild_id); if(g==NULL) return 0; - WFIFOHEAD(fd,MAX_GUILDEXPULSION * 88 + 4); + WFIFOHEAD(fd,4 + MAX_GUILDEXPULSION * 88); WFIFOW(fd,0)=0x163; for(i=c=0;i<MAX_GUILDEXPULSION;i++){ struct guild_expulsion *e=&g->expulsion[i]; if(e->account_id>0){ - memcpy(WFIFOP(fd,c*88+ 4),e->name,NAME_LENGTH); - memcpy(WFIFOP(fd,c*88+28),e->acc,24); - memcpy(WFIFOP(fd,c*88+52),e->mes,44); + safestrncpy(WFIFOP(fd,4 + c*88),e->name,NAME_LENGTH); + safestrncpy(WFIFOP(fd,4 + c*88+24),"",24); // account name (not used for security reasons) + safestrncpy(WFIFOP(fd,4 + c*88+48),e->mes,40); c++; } } - WFIFOW(fd,2)=c*88+4; + WFIFOW(fd,2) = 4 + c*88; WFIFOSET(fd,WFIFOW(fd,2)); return 0; } @@ -8542,7 +8544,9 @@ void clif_parse_TakeItem(int fd, struct map_session_data *sd) *------------------------------------------*/ void clif_parse_DropItem(int fd, struct map_session_data *sd) { - int item_index, item_amount; + int item_index = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0])-2; + int item_amount = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]); + item_index = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0])-2; item_amount = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]); do { @@ -8564,7 +8568,8 @@ void clif_parse_DropItem(int fd, struct map_session_data *sd) return; } while (0); - //Because the client does not likes being ignored. + + //Because the client does not like being ignored. clif_delitem(sd, item_index,0); } @@ -9991,7 +9996,8 @@ void clif_parse_GuildLeave(int fd,struct map_session_data *sd) } /*========================================== - * ギルド追放 + * Request to expel a member of a guild + * S 015b <guild_id>.L <account_id>.L <char_id>.L <reason>.39B 00 *------------------------------------------*/ void clif_parse_GuildExpulsion(int fd,struct map_session_data *sd) { diff --git a/src/map/guild.c b/src/map/guild.c index 889338a9c..ca571b3ce 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -655,9 +655,7 @@ int guild_invite(struct map_session_data *sd,struct map_session_data *tsd) } // 定員確認 - for(i=0;i<g->max_member;i++) - if(g->member[i].account_id==0) - break; + ARR_FIND( 0, g->max_member, i, g->member[i].account_id == 0 ); if(i==g->max_member){ clif_guild_inviteack(sd,3); return 0; @@ -669,60 +667,52 @@ int guild_invite(struct map_session_data *sd,struct map_session_data *tsd) clif_guild_invite(tsd,g); return 0; } -// ギルド勧誘への返答 -int guild_reply_invite(struct map_session_data *sd,int guild_id,int flag) + +/// Guild invitation reply. +/// flag: 0:rejected, 1:accepted +int guild_reply_invite(struct map_session_data* sd, int guild_id, int flag) { - struct map_session_data *tsd; + struct map_session_data* tsd; nullpo_retr(0, sd); - - //nullpo_retr(0, tsd= map_id2sd( sd->guild_invite_account )); - //I checked the code, and there's no "check" for the case where the guy - //that invites another to a guild quits the map-server before being replied. - //Hence that's a valid null pointer scenario. :) [Skotlex] - if ((tsd= map_id2sd( sd->guild_invite_account )) == NULL) - { //Do we send a "invitation failed" msg or something to the player? - //Or should we accept the invitation and add it to the guild anyway? - //afterall, guild_invite holds the guild id that the player was invited to. - sd->guild_invite=0; - sd->guild_invite_account=0; - return 0; - } - if(sd->guild_invite!=guild_id) // 勧誘とギルドIDが違う - return 0; + // subsequent requests may override the value + if( sd->guild_invite != guild_id ) + return 0; // mismatch - if(flag==1){ // 承諾 + // look up the person who sent the invite + //NOTE: this can be NULL because the person might have logged off in the meantime + tsd = map_id2sd(sd->guild_invite_account); + + // zero out the status data + sd->guild_invite = 0; + sd->guild_invite_account = 0; + + if( flag == 0 ) + {// rejected + if( tsd ) clif_guild_inviteack(tsd,1); + } + else + {// accepted struct guild_member m; - struct guild *g; + struct guild* g; int i; - // 定員確認 - if( (g=guild_search(tsd->status.guild_id))==NULL ){ - sd->guild_invite=0; - sd->guild_invite_account=0; + if( (g=guild_search(guild_id)) == NULL ) return 0; - } - for(i=0;i<g->max_member;i++) - if(g->member[i].account_id==0) - break; - if(i==g->max_member){ - sd->guild_invite=0; - sd->guild_invite_account=0; - clif_guild_inviteack(tsd,3); + + ARR_FIND( 0, g->max_member, i, g->member[i].account_id == 0 ); + if( i == g->max_member ) + { + if( tsd ) clif_guild_inviteack(tsd,3); return 0; } - //inter鯖へ追加要求 guild_makemember(&m,sd); - intif_guild_addmember( sd->guild_invite, &m ); + intif_guild_addmember(guild_id, &m); //TODO: send a minimap update to this player - return 0; - }else{ // 拒否 - sd->guild_invite=0; - sd->guild_invite_account=0; - clif_guild_inviteack(tsd,1); } + return 0; } // ギルドメンバが追加された @@ -1821,7 +1811,9 @@ int guild_castlealldataload(int len,struct guild_castle *gc) for( i = n-1; i >= 0 && !(gc[i].guild_id); --i ); ev = i; // offset of castle or -1 - // load received castles into memory, one by one + if( ev < 0 ) //No castles owned, invoke OnAgitInit as it is. + npc_event_doall("OnAgitInit"); + else // load received castles into memory, one by one for( i = 0; i < n; i++, gc++ ) { struct guild_castle *c = guild_castle_search(gc->castle_id); @@ -1842,9 +1834,6 @@ int guild_castlealldataload(int len,struct guild_castle *gc) } } - if( ev < 0 ) //No castles owned, invoke OnAgitInit as it is. - npc_event_doall("OnAgitInit"); - return 0; } @@ -1906,57 +1895,15 @@ int guild_checkcastles(struct guild *g) return nb_cas; } -// [MouseJstr] -// is this guild allied with this castle? -int guild_isallied(struct guild *g, struct guild_castle *gc) -{ - int i; - - nullpo_retr(0, g); - - if(g->guild_id == gc->guild_id) - return 1; - - if (gc->guild_id == 0) - return 0; - - - for(i=0;i<MAX_GUILDALLIANCE;i++) - if(g->alliance[i].guild_id == gc->guild_id) { - if(g->alliance[i].opposition == 0) - return 1; - else - return 0; - } - - return 0; -} - -int guild_idisallied(int guild_id, int guild_id2) +// Are these two guilds allied? +bool guild_isallied(int guild_id, int guild_id2) { int i; - struct guild *g; - - if (guild_id <= 0 || guild_id2 <= 0) - return 0; - - if(guild_id == guild_id2) - return 1; - - g = guild_search(guild_id); - + struct guild* g = guild_search(guild_id); nullpo_retr(0, g); - - for(i=0;i<MAX_GUILDALLIANCE;i++) - if(g->alliance[i].guild_id == guild_id2) { - if(g->alliance[i].opposition == 0) - return 1; - else - return 0; - } - - return 0; + ARR_FIND( 0, MAX_GUILDALLIANCE, i, g->alliance[i].guild_id == guild_id2 ); + return( i < MAX_GUILDALLIANCE && g->alliance[i].opposition == 0 ); } static int guild_infoevent_db_final(DBKey key,void *data,va_list ap) diff --git a/src/map/guild.h b/src/map/guild.h index 61c9e1778..bfa359fb1 100644 --- a/src/map/guild.h +++ b/src/map/guild.h @@ -18,8 +18,7 @@ int guild_skill_get_max(int id); int guild_checkskill(struct guild *g,int id); int guild_check_skill_require(struct guild *g,int id); // [Komurka] int guild_checkcastles(struct guild *g); // [MouseJstr] -int guild_isallied(struct guild *g, struct guild_castle *gc); -int guild_idisallied(int guild_id, int guild_id2); //Checks alliance based on guild Ids. [Skotlex] +bool guild_isallied(int guild_id, int guild_id2); //Checks alliance based on guild Ids. [Skotlex] void do_init_guild(void); struct guild *guild_search(int guild_id); diff --git a/src/map/intif.c b/src/map/intif.c index 5c8cfc9a0..bcb1eef2a 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -587,13 +587,12 @@ int intif_guild_leave(int guild_id,int account_id,int char_id,int flag,const cha WFIFOL(inter_fd, 6) = account_id; WFIFOL(inter_fd,10) = char_id; WFIFOB(inter_fd,14) = flag; - memcpy(WFIFOP(inter_fd,15),mes,40); + safestrncpy(WFIFOP(inter_fd,15),mes,40); WFIFOSET(inter_fd,55); return 0; } // ギルドメンバのオンライン状況/Lv更新要求 -int intif_guild_memberinfoshort(int guild_id, - int account_id,int char_id,int online,int lv,int class_) +int intif_guild_memberinfoshort(int guild_id,int account_id,int char_id,int online,int lv,int class_) { if (CheckForCharServer()) return 0; diff --git a/src/map/irc.c b/src/map/irc.c index 986efd51b..a7995e615 100644 --- a/src/map/irc.c +++ b/src/map/irc.c @@ -52,7 +52,7 @@ int irc_connect_timer(int tid, unsigned int tick, int id, int data) return 0; //Ok, this ShowInfo and printf are a little ugly, but they are meant to //debug just how long the code freezes here. [Skotlex] - ShowInfo("(IRC) Connecting to %s... ", irc_ip_str); + ShowInfo("(IRC) Connecting to %s...\n", irc_ip_str); irc_fd = make_connection(irc_ip,irc_port); if(irc_fd > 0){ printf("ok\n"); diff --git a/src/map/npc.c b/src/map/npc.c index a9ea50e89..6ddbffe01 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -59,7 +59,6 @@ struct event_data { struct npc_data *nd; int pos; }; -static struct tm ev_tm_b; // 時計イベント用 static struct eri *timer_event_ers; //For the npc timer data. [Skotlex] @@ -227,17 +226,20 @@ int npc_event_doall_sub(DBKey key, void* data, va_list ap) const char* p = key.str; struct event_data* ev; int* c; + const char* name; int rid; - char* name; - ev = (struct event_data *)data; - c = va_arg(ap, int *); - name = va_arg(ap,char *); + nullpo_retr(0, ev = (struct event_data *)data); + nullpo_retr(0, ap); + nullpo_retr(0, c = va_arg(ap, int *)); + nullpo_retr(0, name = va_arg(ap, const char *)); rid = va_arg(ap, int); - if( (p=strchr(p, ':')) && p && strcmpi(name, p)==0 ) { - if(rid) - npc_event_sub(((struct map_session_data *)map_id2bl(rid)),ev,key.str); + p = strchr(p, ':'); // match only the event name + if( p && strcmpi(name, p) == 0 ) + { + if(rid) // a player may only have 1 script running at the same time + npc_event_sub(map_id2sd(rid),ev,key.str); else run_script(ev->nd->u.scr.script,ev->pos,rid,ev->nd->bl.id); (*c)++; @@ -245,26 +247,8 @@ int npc_event_doall_sub(DBKey key, void* data, va_list ap) return 0; } -int npc_event_doall(const char* name) -{ - int c = 0; - char buf[64] = "::"; - strncpy(buf+2, name, 62); - ev_db->foreach(ev_db,npc_event_doall_sub,&c,buf,0); - return c; -} -int npc_event_doall_id(const char* name, int rid) -{ - int c = 0; - char buf[64] = "::"; - - strncpy(buf+2, name, 62); - ev_db->foreach(ev_db,npc_event_doall_sub,&c,buf,rid); - return c; -} - -int npc_event_do_sub(DBKey key, void* data, va_list ap) +static int npc_event_do_sub(DBKey key, void* data, va_list ap) { const char* p = key.str; struct event_data* ev; @@ -274,43 +258,61 @@ int npc_event_do_sub(DBKey key, void* data, va_list ap) nullpo_retr(0, ev = (struct event_data *)data); nullpo_retr(0, ap); nullpo_retr(0, c = va_arg(ap, int *)); + nullpo_retr(0, name = va_arg(ap, const char *)); - name = va_arg(ap, const char *); - - if (p && strcmpi(name, p)==0) { + if( p && strcmpi(name, p) == 0 ) + { run_script(ev->nd->u.scr.script,ev->pos,0,ev->nd->bl.id); (*c)++; } return 0; } + +// runs the specified event (supports both single-npc and global events) int npc_event_do(const char* name) { int c = 0; - if (*name == ':' && name[1] == ':') { - return npc_event_doall(name+2); - } + if( name[0] == ':' && name[1] == ':' ) + ev_db->foreach(ev_db,npc_event_doall_sub,&c,name,0); + else + ev_db->foreach(ev_db,npc_event_do_sub,&c,name); - ev_db->foreach(ev_db,npc_event_do_sub,&c,name); return c; } +// runs the specified event (global only) +int npc_event_doall(const char* name) +{ + return npc_event_doall_id(name, 0); +} +// runs the specified event, with a RID attached (global only) +int npc_event_doall_id(const char* name, int rid) +{ + int c = 0; + char buf[64]; + safesnprintf(buf, sizeof(buf), "::%s", name); + ev_db->foreach(ev_db,npc_event_doall_sub,&c,buf,rid); + return c; +} + /*========================================== * 時計イベント実行 *------------------------------------------*/ int npc_event_do_clock(int tid, unsigned int tick, int id, int data) { + static struct tm ev_tm_b; // tracks previous execution time time_t timer; - struct tm *t; + struct tm* t; char buf[64]; - char *day=""; - int c=0; + char* day; + int c = 0; - time(&timer); - t=localtime(&timer); + timer = time(NULL); + t = localtime(&timer); - switch (t->tm_wday) { + switch (t->tm_wday) { case 0: day = "Sun"; break; case 1: day = "Mon"; break; case 2: day = "Tue"; break; @@ -318,6 +320,7 @@ int npc_event_do_clock(int tid, unsigned int tick, int id, int data) case 4: day = "Thu"; break; case 5: day = "Fri"; break; case 6: day = "Sat"; break; + default:day = ""; break; } if (t->tm_min != ev_tm_b.tm_min ) { @@ -336,6 +339,7 @@ int npc_event_do_clock(int tid, unsigned int tick, int id, int data) sprintf(buf,"OnDay%02d%02d",t->tm_mon+1,t->tm_mday); c+=npc_event_doall(buf); } + memcpy(&ev_tm_b,t,sizeof(ev_tm_b)); return c; } @@ -345,8 +349,7 @@ int npc_event_do_clock(int tid, unsigned int tick, int id, int data) *------------------------------------------*/ void npc_event_do_oninit(void) { - int count = npc_event_doall("OnInit"); - ShowStatus("Event '"CL_WHITE"OnInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs."CL_CLL"\n", count); + ShowStatus("Event '"CL_WHITE"OnInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs."CL_CLL"\n", npc_event_doall("OnInit")); add_timer_interval(gettick()+100,npc_event_do_clock,0,0,1000); } @@ -361,7 +364,8 @@ int npc_timerevent_import(char* lname, void* data, va_list ap) struct npc_data *nd=va_arg(ap,struct npc_data *); int t=0,i=0; - if(sscanf(lname,"OnTimer%d%n",&t,&i)==1 && lname[i]==':') { + if(sscanf(lname,"OnTimer%d%n",&t,&i)==1 && lname[i]==':') + { // タイマーイベント struct npc_timerevent_list *te=nd->u.scr.timer_event; int j,i=nd->u.scr.timeramount; @@ -371,12 +375,9 @@ int npc_timerevent_import(char* lname, void* data, va_list ap) ShowFatalError("npc_timerevent_import: out of memory !\n"); exit(EXIT_FAILURE); } - for(j=0;j<i;j++){ - if(te[j].timer>t){ - memmove(te+j+1,te+j,sizeof(struct npc_timerevent_list)*(i-j)); - break; - } - } + ARR_FIND( 0, i, j, te[j].timer > t ); + if( j < i ) + memmove(te+j+1,te+j,sizeof(struct npc_timerevent_list)*(i-j)); te[j].timer=t; te[j].pos=pos; nd->u.scr.timer_event=te; @@ -465,10 +466,7 @@ int npc_timerevent_start(struct npc_data* nd, int rid) if( n==0 ) return 0; - for(j=0;j<n;j++){ - if( nd->u.scr.timer_event[j].timer > nd->u.scr.timer ) - break; - } + ARR_FIND( 0, n, j, nd->u.scr.timer_event[j].timer > nd->u.scr.timer ); if(j>=n) // check if there is a timer to use !!BEFORE!! you write stuff to the structures [Shinomori] return 0; if (nd->u.scr.rid > 0) { @@ -2931,7 +2929,6 @@ int do_init_npc(void) ev_db = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA,2*NAME_LENGTH+2+1); npcname_db = strdb_alloc(DB_OPT_BASE,NAME_LENGTH); - memset(&ev_tm_b, -1, sizeof(ev_tm_b)); timer_event_ers = ers_new(sizeof(struct timer_event_data)); // process all npc files diff --git a/src/map/npc.h b/src/map/npc.h index 6580e4f21..a0c1956b7 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -74,9 +74,9 @@ int do_init_npc(void); void npc_event_do_oninit(void); int npc_do_ontimer(int npc_id, int option); -int npc_event_doall(const char* name); int npc_event_do(const char* name); -int npc_event_doall_id(const char* name, int id); +int npc_event_doall(const char* name); +int npc_event_doall_id(const char* name, int rid); int npc_timerevent_start(struct npc_data* nd, int rid); int npc_timerevent_stop(struct npc_data* nd); diff --git a/src/map/status.c b/src/map/status.c index c8ffde37c..f9237f565 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -4065,7 +4065,7 @@ struct regen_data *status_get_regen_data(struct block_list *bl) struct status_data *status_get_status_data(struct block_list *bl) { nullpo_retr(&dummy_status, bl); - + switch (bl->type) { case BL_PC: return &((TBL_PC*)bl)->battle_status; case BL_MOB: return &((TBL_MOB*)bl)->status; diff --git a/src/map/status.h b/src/map/status.h index 0526bbd65..eac4b9d55 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -20,8 +20,8 @@ extern unsigned long StatusChangeFlagTable[]; // Status changes listing. These code are for use by the server. enum sc_type { //First we enumerate common status ailments which are often used around. - SC_COMMON_MIN = 0, // begin SC_STONE = 0, + SC_COMMON_MIN = 0, // begin SC_FREEZE, SC_STUN, SC_SLEEP, |