Kaynağa Gözat

Initial release of the clan system

Thanks to @cydh, @RagnarokNova and @aleos89 for their help.
Lemongrass3110 8 yıl önce
ebeveyn
işleme
ecc8cf9f0b
61 değiştirilmiş dosya ile 1906 ekleme ve 9 silme
  1. 2 0
      conf/inter_athena.conf
  2. 3 0
      conf/msg_conf/map_msg.conf
  3. 4 0
      conf/msg_conf/map_msg_chn.conf
  4. 3 0
      conf/msg_conf/map_msg_frn.conf
  5. 3 0
      conf/msg_conf/map_msg_grm.conf
  6. 3 0
      conf/msg_conf/map_msg_idn.conf
  7. 3 0
      conf/msg_conf/map_msg_por.conf
  8. 3 0
      conf/msg_conf/map_msg_rus.conf
  9. 3 0
      conf/msg_conf/map_msg_spn.conf
  10. 3 0
      conf/msg_conf/map_msg_tha.conf
  11. 6 0
      db/const.txt
  12. 6 0
      db/packet_db.txt
  13. 80 0
      doc/packet_interserv.txt
  14. 17 0
      doc/script_commands.txt
  15. 600 0
      npc/re/other/clans.txt
  16. 1 0
      npc/re/scripts_athena.conf
  17. 45 0
      sql-files/main.sql
  18. 46 0
      sql-files/upgrades/upgrade_20161116.sql
  19. 2 0
      src/char/CMakeLists.txt
  20. 26 6
      src/char/char.c
  21. 2 0
      src/char/char.h
  22. 244 0
      src/char/int_clan.c
  23. 10 0
      src/char/int_clan.h
  24. 5 0
      src/char/inter.c
  25. 19 1
      src/common/mmo.h
  26. 2 0
      src/map/CMakeLists.txt
  27. 5 0
      src/map/atcommand.c
  28. 2 0
      src/map/chrif.c
  29. 200 0
      src/map/clan.c
  30. 23 0
      src/map/clan.h
  31. 168 1
      src/map/clif.c
  32. 9 0
      src/map/clif.h
  33. 90 0
      src/map/intif.c
  34. 5 0
      src/map/intif.h
  35. 1 0
      src/map/log.h
  36. 6 0
      src/map/map.c
  37. 3 0
      src/map/pc.c
  38. 3 0
      src/map/pc.h
  39. 41 0
      src/map/script.c
  40. 7 0
      src/map/script_constants.h
  41. 11 0
      src/map/skill.c
  42. 104 1
      src/map/status.c
  43. 7 0
      src/map/status.h
  44. 2 0
      vcproj-10/char-server.vcxproj
  45. 6 0
      vcproj-10/char-server.vcxproj.filters
  46. 2 0
      vcproj-10/map-server.vcxproj
  47. 6 0
      vcproj-10/map-server.vcxproj.filters
  48. 2 0
      vcproj-12/char-server.vcxproj
  49. 6 0
      vcproj-12/char-server.vcxproj.filters
  50. 2 0
      vcproj-12/map-server.vcxproj
  51. 6 0
      vcproj-12/map-server.vcxproj.filters
  52. 2 0
      vcproj-13/char-server.vcxproj
  53. 6 0
      vcproj-13/char-server.vcxproj.filters
  54. 2 0
      vcproj-13/map-server.vcxproj
  55. 6 0
      vcproj-13/map-server.vcxproj.filters
  56. 2 0
      vcproj-14/char-server.vcxproj
  57. 6 0
      vcproj-14/char-server.vcxproj.filters
  58. 2 0
      vcproj-14/map-server.vcxproj
  59. 6 0
      vcproj-14/map-server.vcxproj.filters
  60. 8 0
      vcproj-9/char-server.vcproj
  61. 8 0
      vcproj-9/map-server.vcproj

+ 2 - 0
conf/inter_athena.conf

@@ -122,6 +122,8 @@ acc_reg_num_table: acc_reg_num
 acc_reg_str_table: acc_reg_str
 char_reg_str_table: char_reg_str
 char_reg_num_table: char_reg_num
+clan_table: clan
+clan_alliance_table: clan_alliance
 
 // Map Database Tables
 buyingstore_db: buyingstores

+ 3 - 0
conf/msg_conf/map_msg.conf

@@ -1622,5 +1622,8 @@
 // Roulette
 1497: Roulette is disabled
 
+// @guild
+1498: You cannot create a guild because you are in a clan.
+
 //Custom translations
 //import: conf/msg_conf/import/map_msg_eng_conf.txt

+ 4 - 0
conf/msg_conf/map_msg_chn.conf

@@ -1483,5 +1483,9 @@
 1492: 使用方法: @dropall {<類型>}
 1493: 類型列表: (預設值) 全部 = -1, 藥水/料理 = 0, 消耗品 = 2, 其他 = 3, 武器 = 4, 防具 = 5, 卡片 = 6, 寵物蛋 = 7, 寵物裝備 = 8, 箭/子彈 = 10
 1494: %d 物品已掉落!
+
+// @guild
+1498: You cannot create a guild because you are in a clan.
+
 //Custom translations
 //import: conf/msg_conf/import/map_msg_chn_conf.txt

+ 3 - 0
conf/msg_conf/map_msg_frn.conf

@@ -1476,5 +1476,8 @@
 1478: Différence de niveau pour le partage en équipe changé.
 1479: Mise à jour de la configuration échouée. Character serveur est hors ligne.
 
+// @guild
+1498: You cannot create a guild because you are in a clan.
+
 //Custom translations
 //import: conf/msg_conf/import/map_msg_frn_conf.txt

+ 3 - 0
conf/msg_conf/map_msg_grm.conf

@@ -590,5 +590,8 @@
 696: Oktoberfest
 697: Summoner
 
+// @guild
+1498: You cannot create a guild because you are in a clan.
+
 //Custom translations
 import: conf/msg_conf/import/map_msg_grm_conf.txt

+ 3 - 0
conf/msg_conf/map_msg_idn.conf

@@ -1592,5 +1592,8 @@
 
 1497: Roulette tidak tersedia.
 
+// @guild
+1498: You cannot create a guild because you are in a clan.
+
 //Bila ada terjemahan lain
 //import: conf/msg_conf/import/map_msg_idn_conf.txt

+ 3 - 0
conf/msg_conf/map_msg_por.conf

@@ -1452,5 +1452,8 @@
 1475: ---- Meus Canais ----
 1476: Vocę ainda năo está em nenhum canal.
 
+// @guild
+1498: You cannot create a guild because you are in a clan.
+
 //Custom translations
 //import: conf/msg_conf/import/map_msg_por_conf.txt

+ 3 - 0
conf/msg_conf/map_msg_rus.conf

@@ -1476,5 +1476,8 @@
 1478: Диапазон уровней разделения опыта между участниками группы успешно изменен.
 1479: Невозможно обновить конфигурацию. Character-сервер выключен.
 
+// @guild
+1498: You cannot create a guild because you are in a clan.
+
 // Пользовательский перевод
 //import: conf/msg_conf/import/map_msg_rus_conf.txt

+ 3 - 0
conf/msg_conf/map_msg_spn.conf

@@ -1455,5 +1455,8 @@
 1475: ---- Mis canales ----
 1476: No te has unido a ningún canal.
 
+// @guild
+1498: You cannot create a guild because you are in a clan.
+
 //Traducciones personalizadas
 //import: conf/msg_conf/import/map_msg_spn_conf.txt

+ 3 - 0
conf/msg_conf/map_msg_tha.conf

@@ -1495,5 +1495,8 @@
 // Roulette
 1497: ĂĐşş Roulette ťÔ´ĄŇĂăŞé§Ňš
 
+// @guild
+1498: You cannot create a guild because you are in a clan.
+
 //Custom translations
 //import: conf/msg_conf/import/map_msg_tha_conf.txt

+ 6 - 0
db/const.txt

@@ -2726,3 +2726,9 @@ THANATOS_KEEP	10009
 4_ELDER	10205
 4_LUNATIC	10206
 4_F_NOVICE2	10207
+
+SWORDCLAN	1
+ARCWANDCLAN	2
+GOLDENMACECLAN	3
+CROSSBOWCLAN	4
+JUMPINGCLAN	5

+ 6 - 0
db/packet_db.txt

@@ -2330,6 +2330,12 @@ packet_keys: 0x631C511C,0x111C111C,0x111C111C // [Shakto]
 0x09D6,-1,npcmarketpurchase,2:4:6
 0x09D7,-1
 0x09D8,2,npcmarketclosed,0
+// Clan System
+0x0988,6
+0x0989,2
+0x098A,-1
+0x098D,-1,clanchat,2:4
+0x098E,-1
 
 // New Packet
 0x097A,-1		// ZC_ALL_QUEST_LIST2

+ 80 - 0
doc/packet_interserv.txt

@@ -1416,7 +1416,51 @@ Currently the max packet size is 0xFFFF (see 'WFIFOSET()' in 'src/common/socket.
 	desc:
 		- Homunculus rename
 
+0x30A0:
+	Type: ZI
+	Structure: <cmd>.W
+	index: 0
+	len: 2
+	parameter:
+		- cmd : packet identification (0x30A0)
+	desc:
+		- Requests the loaded clans from the inter server
 
+0x30A1
+	Type: ZI
+	Structure: <cmd>.W <size>.W <clan id>.L <account id>.L <message>.?B
+	index: 0,2,4,8,12
+	len: variable: 12+message
+	parameter:
+		- cmd : packet identification (0x30A1)
+		- size
+		- clan id : the clan id the message is sent to
+		- account id : the account id of the sender
+		- message : the message to be sent
+	desc:
+		- Sends a clan message to the inter server to relay it to all other mapservers
+
+0x30A2:
+	Type: ZI
+	Structure: <cmd>.W <clan id>.L
+	index: 0,2
+	len: 6
+	parameter:
+		- cmd : packet identification (0x30A2)
+		- clan id : the clan id
+	desc:
+		- Notifies the inter server that a player has left the clan or disconnected
+
+0x30A3:
+	Type: ZI
+	Structure: <cmd>.W <clan id>.L
+	index: 0,2
+	len: 6
+	parameter:
+		- cmd : packet identification (0x30A3)
+		- clan id : the clan id
+	desc:
+		- Notifies the inter server that a player has joined the clan or connected
 
 0x3800:
 	Type: IZ
@@ -2256,6 +2300,42 @@ Currently the max packet size is 0xFFFF (see 'WFIFOSET()' in 'src/common/socket.
 	desc:
 		- Send homunculus deletion status
 
+0x38A0
+	Type: IZ
+	Structure: <cmd>.W <size>.W <clan structure>.?B * n
+	index: 0, 2, 4
+	len: variable: 4+clan*n
+	parameter:
+		- cmd : packet identification (0x38A0)
+		- size
+		- clan structure
+	desc:
+		- Send all loaded clans to the map server
+
+0x38A1
+	Type: IZ
+	Structure: <cmd>.W <size>.W <message>.?B
+	index: 0, 2, 4
+	len: variable: 4+message
+	parameter:
+		- cmd : packet identification (0x38A1)
+		- size
+		- message : the data of the clan chat message packet
+	desc:
+		- Sends a clan chat message to other map servers
+
+0x38A2
+	Type: IZ
+	Structure: <cmd>.W <clan id>.L <online count>.W
+	index: 0, 2, 6
+	len: 8
+	parameter:
+		- cmd : packet identification (0x38A2)
+		- clan id : the clan id of the clan that needs an update
+		- online count : the amount of currently connected players in the clan
+	desc:
+		- Updates the online clan member count for all other map servers
+
 ========================
 | 3.2 Char-Map Packets |
 ========================

+ 17 - 0
doc/script_commands.txt

@@ -2356,6 +2356,7 @@ Type is the kind of associated ID number required:
  2 - Guild ID
  3 - Account ID
  4 - Battle Ground ID
+ 5 - Clan ID
 
 For most purposes other than printing it, a number is better to have than a name 
 (people do horrifying things to their character names).
@@ -9343,5 +9344,21 @@ Param - Parameter of random option
 
 ---------------------------------------
 
+*clan_join(<clan id>{,<char id>});
+
+The attached player joins the clan with the <clan id>. On a successful join,
+true is returned, else false if the join failed.
+If <char id> is specified, the specified player is used rather than the attached one.
+
+---------------------------------------
+
+*clan_leave({<char id>});
+
+The attached player will leave their clan. On a successful leave, true is returned,
+else false if the leave failed.
+If <char id> is specified, the specified player is used rather than the attached one.
+
+---------------------------------------
+
 Whew.
 That's about all of them.

+ 600 - 0
npc/re/other/clans.txt

@@ -0,0 +1,600 @@
+//===== rAthena Script =======================================
+//= Clan masters
+//===== Description: =========================================
+//= The clan master NPCs that allow you to join and leave
+//= one of the clans.
+//===== Changelogs: ==========================================
+//= 1.0 Initial release. [Lemongrass]
+//= 1.1 iRO translation. [RagnarokNova]
+//= 1.2 Dialogue cleanup. [Aleos]
+//============================================================
+
+prt_in,33,114,5	script	Raffam Oranpere	10058,{
+	cutin "laperm01.bmp", 2;
+	mes "[Raffam Oranpere]";
+	mes "Hi! I'm Raffam, master of the ^3131FFSword Clan^000000 in the Rune-Midgard Kingdom.";
+	next;
+	switch( select( "Clan Information:Join.:Leave." ) ){
+		case 1:
+			switch( select( "What are Clans?:About the Sword Clan:Cancel." ) ){
+				case 1:
+					mes "[Raffam Oranpere]";
+					mes "The ^3131FFClans^000000 are a type of guild ran by the Kingdom.";
+					mes "They don't participate in the Siege, so members are free to join/leave anytime.";
+					next;
+					mes "[Raffam Oranpere]";
+					mes "I wish we could join the Siege. I'd love flying over on my dragon and burning everyone in my way!";
+					mes "Oops, too thrilled!";
+					next;
+					mes "[Raffam Oranpere]";
+					mes "Join us, if no Clan suits your taste.";
+					mes "New members are given ^3131FFfree stat bonuses^000000.";
+					next;
+					mes "[Raffam Oranpere]";
+					mes "Melee stats are offered as the name ^3131FFSword Clan^000000 suggests, but not all members are Melee classes.";
+					mes "Don't feel pressured, just count on me!";
+					next;
+					cutin "laperm02.bmp", 2;
+					mes "[Raffam Oranpere]";
+					mes "Differences in variety creates the fun.";
+					mes "These odd bunches never bore me in the party.";
+					next;
+					mes "[Raffam Oranpere]";
+					mes "And who knows you might meet your soul mate in the Clan? Hahah!";
+					break;
+				case 2:
+					mes "[Raffam Oranpere]";
+					mes "The ^3131FFSword Clan^000000 mainly supports Melee adventurers.";
+					mes "Join for free ^FF0000<STR+1, VIT+1, MHP+30, MSP+10>^000000!";
+					next;
+					mes "[Raffam Oranpere]";
+					mes "Remember, no Siege participation.";
+					mes "You should contact other guilds for Siege.";
+					next;
+					mes "[Raffam Oranpere]";
+					mes "A question?";
+					mes "Excited to join me? Hahah!";
+					break;
+				case 3:
+					break;
+			}			
+			break;
+		case 2:
+			mes "[Raffam Oranpere]";
+			mes "Oh, you'll join? Good choice!";
+			mes "Let's check the Clan policy then to begin admission procedures.";
+			next;
+			mes "[Raffam Oranpere]";
+			mes "^3131FFClansmen^000000 cannot participate in the Siege.";
+			mes "New members are given these stat bonuses: ^FF0000<STR+1, VIT+1, MHP+30, MSP+10>^000000.";
+			mes "You with me so far?";
+			next;
+			if( select( "Yes.:No." ) == 1 ){
+				mes "[Raffam Oranpere]";
+				mes "You can join and leave a Clan anytime, but if you don't login for ^FF0000more than 2 weeks^000000, you'll be ^FF0000expelled^000000.";
+				mes "Clan masters exist for reason, like I.";
+				mes "Understood?";
+				next;
+				if( select( "Yes.:No." ) == 1 ){
+					mes "[Raffam Oranpere]";
+					mes "Great, sign your name here to register.";
+					next;
+					input .@name$;
+					mes "[Raffam Oranpere]";
+					mes "So, you're ^3131FF" + strcharinfo( 0 ) + "^000000! Nice name!";
+					mes "Let me register you.";
+					next;
+					if( getcharid( 2 ) ){
+						mes "[Raffam Oranpere]";
+						mes "Come back to join after you leave your current guild.";
+						close;
+					}else if( getcharid( 5 ) != 0 ){
+						cutin "laperm04.bmp", 2;
+						mes "[Raffam Oranpere]";
+						mes "Eh? Oh, you're in a Clan.";
+						mes "Don't mess with me, it's not cool!";
+					}else{
+						cutin "laperm02.bmp", 2;
+						if (clan_join(SWORDCLAN)) {
+							sc_start2 SC_SWORDCLAN, -1, 0, SWORDCLAN;
+							mes "[Raffam Oranpere]";
+							mes "Welcome to the ^3131FFSword Clan^000000!";
+							mes "You can review Clan info with ^3131FFCtrl+G^000000.";
+							mes "At your service!";
+						} else
+							mes "An error has occurred.";
+					}
+				}else{
+					mes "[Raffam Oranpere]";
+					mes "Uh, oh. Let's go back to the beginning.";
+				}
+			}else{
+				cutin "laperm03.bmp", 2;
+				mes "[Raffam Oranpere]";
+				mes "Uh, oh. Let's go back to the beginning.";
+			}
+			break;
+		case 3:
+			cutin "laperm01.bmp", 2;
+			mes "[Raffam Oranpere]";
+			mes "You want to leave?";
+			mes "No problem. I hope you'll find a more suitable Clan.";
+			mes "Ready for withdrawal?";
+			next;
+			if( select( "Continue.:Cancel." ) == 1 ){
+				if( getcharid( 5 ) == 0 ){
+					cutin "laperm04.bmp", 2;
+					mes "[Raffam Oranpere]";
+					mes "Wait, you're not with us! Grr, don't make me breathe fire at you!";
+				}else if( getcharid( 5 ) != SWORDCLAN ){
+					cutin "laperm04.bmp", 2;
+					mes "[Raffam Oranpere]";
+					mes "Hey, talk to your guild master if you want to leave.";
+				}else{
+					if (clan_leave()) {
+						sc_end SC_SWORDCLAN;
+						mes "[Raffam Oranpere]";
+						mes "Okay, it's done. But let's not be strangers, okay?";
+						mes "It was nice having you!";
+					} else
+						mes "An error has occurred.";
+				}
+			}
+			break;
+	}
+	close2;
+	cutin "", 255;
+	end;
+}
+
+prt_in,35,114,5	script	Devon Aire	10059,{
+	cutin "debon01.bmp", 2;
+	mes "[Devon Aire]";
+	mes "I'm Devon, master of the ^3131FFArc Wand Clan^000000.";
+	next;
+	switch( select( "Clan Information:Join.:Leave." ) ){
+		case 1:
+			switch( select( "What are Clans?:About the Arc Wand Clan:Cancel." ) ){
+				case 1:
+					mes "[Devon Aire]";
+					mes "The ^3131FFClans^000000 are ran by the Kingdom, not privately like others.";
+					mes "And I manage one of them.";
+					next;
+					cutin "debon02.bmp", 2;
+					mes "[Devon Aire]";
+					mes "...";
+					mes "What's with that look? You got a problem?";
+					next;
+					cutin "birman01.bmp", 2;
+					mes "[Berman Aire]";
+					mes "Brother, you're scaring a potential member, be nice.";
+					next;
+					cutin "debon02.bmp", 2;
+					mes "[Devon Aire]";
+					mes "...";
+					next;
+					cutin "debon01.bmp", 2;
+					mes "[Devon Aire]";
+					mes "Join if you are seeking a place to fit in. We give ^3131FFfree bonus stats^000000. But no Siege participation.";
+					next;
+					mes "[Devon Aire]";
+					mes "Most members are offensive Mage classes as the name ^3131FFArc Wand Clan^000000 suggests, but that's no requirement.";
+					next;
+					cutin "debon02.bmp", 2;
+					mes "[Devon Aire]";
+					mes "...Hey, Shaam Rumi.";
+					mes "Stop hitting on my brother and get to work.";
+					next;
+					cutin "sham03.bmp", 2;
+					mes "[Shaam Rumi]";
+					mes "Whatever!";
+					next;
+					cutin "debon02.bmp", 2;
+					mes "[Devon Aire]";
+					mes "...Hmpf!";
+					mes "Listen, Crossbow Clan's master is evil.";
+					next;
+					cutin "sham02.bmp", 2;
+					mes "[Shaam Rumi]";
+					mes "Get over me, Devon! Don't spread rumors!";
+					next;
+					cutin "birman01.bmp", 2;
+					mes "[Berman Aire]";
+					mes "Haha. Stop it. You two are making a scene.";
+					mes "Come on, back to work guys.";
+					break;
+				case 2:
+					cutin "debon01.bmp", 2;
+					mes "[Devon Aire]";
+					mes "The ^3131FFArc Wand Clan^000000 mainly supports offensive Mage classes.";
+					mes "We offer ^FF0000<INT+1, DEX+1, MHP+30, MSP+10>^000000 to new members. Don't ask for more; it's the Kingdom's rule.";
+					next;
+					mes "[Devon Aire]";
+					mes "^3131FFClansmen^000000 can't participate in the Siege.";
+					mes "If you like the Siege, then go join a regular guild.";
+					next;
+					mes "[Devon Aire]";
+					mes "That is all. No questions.";
+					break;
+				case 3:
+					break;
+			}
+			break;
+		case 2:
+			cutin "debon01.bmp", 2;
+			mes "[Devon Aire]";
+			mes "...";
+			mes "Let's check the Clan policy then to begin admission procedures.";
+			next;
+			mes "[Devon Aire]";
+			mes "^3131FFClansmen^000000 cannot participate in the Siege.";
+			mes "New members are given these stat bonuses: ^FF0000<INT+1, DEX+1, MHP+30, MSP+10>^000000.";
+			mes "You with me so far?";
+			next;
+			if( select( "Yes.:No." ) == 1 ){
+				mes "[Devon Aire]";
+				mes "You can join and leave a Clan anytime, but if you don't login for ^FF0000more than 2 weeks^000000, you'll be ^FF0000expelled^000000.";
+				mes "Do you agree?";
+				next;
+				if( select( "Yes.:No." ) == 1 ){
+					mes "[Devon Aire]";
+					mes "Sign your name here.";
+					next;
+					input .@name$;
+					mes "[Devon Aire]";
+					mes "^3131FF" + strcharinfo( 0 ) + "^000000.....";
+					mes "Good, let me invite you in.";
+					next;
+					if( getcharid( 2 ) ){
+						mes "[Devon Aire]";
+						mes "Leave your guild first to join my Clan, duh.";
+						close;
+					}else if( getcharid( 5 ) != 0 ){
+						cutin "debon03.bmp", 2;
+						mes "[Devon Aire]";
+						mes "You're already in a Clan. You joking?!";
+						mes "Oh, I can be funny, too--FIRE PILLAR!";
+					}else{
+						if (clan_join(ARCWANDCLAN)) {
+							sc_start2 SC_ARCWANDCLAN, -1, 0, ARCWANDCLAN;
+							mes "[Devon Aire]";
+							mes "You have joined the ^3131FFArc Wand Clan^000000.";
+							next;
+							mes "[Devon Aire]";
+							mes "You can review Clan info with ^3131FFCtrl+G^000000.";
+							mes "So don't bother me later.";
+							next;
+							mes "[Devon Aire]";
+							mes "That's all. Visit often or be expelled. Dismissed.";
+						} else
+							mes "An error has occurred.";
+					}
+				}else{
+					mes "[Devon Aire]";
+					mes "Then I don't want you.";
+				}
+			}else{
+				mes "[Devon Aire]";
+				mes "Gosh, listen to the policy again.";
+			}
+			break;
+		case 3:
+			mes "[Devon Aire]";
+			mes "Want to leave, huh?";
+			mes "I understand, it's about Sieges. If not, why are..Never mind..";
+			mes "I'll process your withdrawal.";
+			next;
+			if( select( "Continue.:Cancel." ) == 1 ){
+				if( getcharid( 5 ) == 0 ){
+					cutin "debon03.bmp", 2;
+					mes "[Devon Aire]";
+					mes "Naughty children deserve a good Jupitel Thunder.";
+				}else if( getcharid( 5 ) != ARCWANDCLAN ){
+					cutin "debon02.bmp", 2;
+					mes "[Devon Aire]";
+					mes "You're barking up the wrong tree. Go to your Clan master.";
+				}else{
+					if (clan_leave()) {
+						sc_end SC_ARCWANDCLAN;
+						mes "[Devon Aire]";
+						mes "You are withdrawn from the Clan.";
+						mes "Now leave. I don't feel like talking anymore.";
+					} else
+						mes "An error has occurred.";
+				}
+			}		
+			break;
+	}
+	close2;
+	cutin "", 255;
+	end;
+}
+
+prt_in,37,114,5	script	Berman Aire	10060,{
+	cutin "birman01.bmp", 2;
+	mes "[Berman Aire]";
+	mes "Nice to meet you. I'm Berman Aire, master of the ^3131FFGolden Mace Clan^000000.";
+	mes "I'm also the older brother of Devon Aire. Devon looks tough, but he's kind hearted.";
+	next;
+	switch( select( "Clan Information:Join.:Leave." ) ){
+		case 1:
+			switch( select( "What are Clans?:About the Golden Mace Clan:Cancel." ) ){
+				case 1:
+					mes "[Berman Aire]";
+					mes "The ^3131FFClans^000000 are established by the Kingdom to help adventurers connect and share information.";
+					next;
+					mes "[Berman Aire]";
+					mes "Because the Kingdom runs the Clan, there is no Siege participation, but at least the members are given ^3131FFstat bonuses^000000.";
+					mes "The stat bonuses are small, but can be very useful for beginning adventurers.";
+					next;
+					mes "[Berman Aire]";
+					mes "We're named the ^3131FFGolden Mace Clan^000000, but we don't discriminate against applicants based on their classes.";
+					mes "The name is just to help you easily choose your Clan.";
+					next;
+					cutin "sham02.bmp", 2;
+					mes "[Shaam Rumi]";
+					mes "Berman, enough with the explanation. Let's go hang out in Glast Heim.";
+					next;
+					cutin "debon03.bmp", 2;
+					mes "[Devon Aire]";
+					mes "... Hey.";
+					next;
+					cutin "sham03.bmp", 2;
+					mes "[Shaam Rumi]";
+					mes "Ooh, you're scaring me.";
+					mes "Berman, call me when you can!~";
+					next;
+					cutin "birman03.bmp", 2;
+					mes "[Berman Aire]";
+					mes "Hah hah, I apologize for their bickering.";
+					next;
+					cutin "birman01.bmp", 2;
+					mes "[Berman Aire]";
+					mes "Do you have a question?";
+					mes "If you're tired of traveling alone, join us! You can join and leave the Clan anytime you want.";
+					break;
+				case 2:
+					mes "[Berman Aire]";
+					mes "The ^3131FFGolden Mace Clan^000000 mainly helps supportive classes.";
+					mes "We offer ^FF0000<INT+1, LUK+1, MHP+30, MSP+10>^000000 to new members.";
+					next;
+					mes "[Berman Aire]";
+					mes "As I told you earlier, Clans cannot join the Siege because they already belong to the Kingdom.";
+					mes "If you want to be in the Siege, then I recommend you join a regular guild.";
+					next;
+					mes "[Berman Aire]";
+					mes "Do you understand what the Clans are about now?";
+					break;
+				case 3:
+					break;
+			}
+			break;
+		case 2:
+			mes "[Berman Aire]";
+			mes "Great!";
+			mes "Let's check the Clan policy then to begin admission procedures.";
+			next;
+			mes "[Berman Aire]";
+			mes "^3131FFClansmen^000000 cannot participate in the Siege.";
+			mes "As our new member, you'll receive the following stat bonuses: ^FF0000<INT+1, LUK+1, MHP+30, MSP+10>^000000.";
+			mes "Do you agree?";
+			next;
+			if( select( "Yes.:No." ) == 1 ){
+				mes "[Berman Aire]";
+				mes "You can join and leave a Clan anytime, but if you don't login for ^FF0000more than 2 weeks^000000, you'll be ^FF0000expelled^000000.";
+				mes "Do you agree to maintain good standing in the Clan?";
+				next;
+				if( select( "Yes.:No." ) == 1 ){
+					mes "[Berman Aire]";
+					mes "Now, please write your name here.";
+					next;
+					input .@name$;
+					mes "[Berman Aire]";
+					mes "^3131FF" + strcharinfo( 0 ) + "^000000! What a good name!";
+					mes "Okay, then...";
+					next;
+					if( getcharid( 2 ) ){
+						mes "[Berman Aire]";
+						mes "Oh, no.";
+						mes "In order to join, you first have to leave your current guild.";
+						close;
+					}else if( getcharid( 5 ) != 0 ){
+						mes "[Berman Aire]";
+						mes "You're already in a Clan.";
+						mes "You're just confused, right?";
+					}else{
+						if (clan_join(GOLDENMACECLAN)) {
+							sc_start2 SC_GOLDENMACECLAN, -1, 0, GOLDENMACECLAN;
+							cutin "birman02.bmp", 2;
+							mes "[Berman Aire]";
+							mes "Welcome to the ^3131FFGolden Mace Clan^000000!";
+							next;
+							mes "[Berman Aire]";
+							mes "You can review Clan info with ^3131FFCtrl+G^000000.";
+							next;
+							mes "[Berman Aire]";
+							mes "Please remember the few precautions I gave you, and enjoy your Clan activities!";
+						} else
+							mes "An error has occurred.";
+					}
+				}
+			}
+			break;
+		case 3:
+			mes "[Berman Aire]";
+			mes "With meeting, there is parting.";
+			mes "I hope you enjoyed your time in the ^3131FFGolden Mace Clan^000000.";
+			mes "Now, should I process your withdrawal?";
+			next;
+			if( select( "Continue.:Cancel." ) == 1 ){
+				if( getcharid( 5 ) == 0 ){
+					mes "[Berman Aire]";
+					mes "You can't leave the Clan without joining it first.";
+				}else if( getcharid( 5 ) != GOLDENMACECLAN ){
+					mes "[Berman Aire]";
+					mes "I'm sorry, but I can't remove you from another Clan...";
+				}else{
+					if (clan_leave()) {
+						sc_end SC_GOLDENMACECLAN;
+						mes "[Berman Aire]";
+						mes "It's processed.";
+						mes "Come back anytime to the ^3131FFGolden Mace Clan^000000. I'll be here.";
+					} else
+						mes "An error has occurred.";
+				}
+			}
+			break;
+	}
+	close2;
+	cutin "", 255;
+	end;
+}
+
+prt_in,39,114,5	script	Shaam Rumi	10027,{
+	cutin "sham01.bmp", 2;
+	mes "[Shaam Rumi]";
+	mes "Hi, there! I'm Shaam, master of the ^3131FFCrossbow Clan^000000";
+	mes "What can I do for you?";
+	next;
+	switch( select( "Clan Information:Join.:Leave." ) ){
+		case 1:
+			switch( select( "What are Clans?:About the Crossbow Clan:Cancel." ) ){
+				case 1:
+					mes "[Shaam Rumi]";
+					mes "The Clans were established by the Rune-Midgarts Kingdom to...";
+					mes "Raffam, why were our ^3131FFclans^000000 made?";
+					next;
+					cutin "laperm01.bmp", 2;
+					mes "[Raffam Oranpere]";
+					mes "Did you sleep in class? Gosh.";
+					mes "The Clans help lone adventurers connect with each other and share information.";
+					next;
+					cutin "sham01.bmp", 2;
+					mes "[Shaam Rumi]";
+					mes "A-ha, got it! Thank you, Captain!";
+					mes "You heard that too, right?";
+					next;
+					mes "[Shaam Rumi]";
+					mes "Run by the Kingdom itself, the Clans are not allowed to participate in the Siege, but the good news is that the members are given some ^3131FFstat bonuses^000000.";
+					next;
+					mes "[Shaam Rumi]";
+					mes "In case you wonder if the ^3131FFCrossbow Clan^000000 only recruits Archers, no, it doesn't.";
+					mes "All the Clans accept all classes. You can choose the one that suits your needs best.";
+					next;
+					cutin "sham02.bmp", 2;
+					mes "[Shaam Rumi]";
+					mes "That should cover everything there is to know.";
+					mes "Berman, let's go hang out in Glast Heim.";
+					next;
+					cutin "debon03.bmp", 2;
+					mes "[Devon Aire]";
+					mes "You...";
+					next;
+					cutin "sham03.bmp", 2;
+					mes "[Shaam Rumi]";
+					mes "Ooh, scary! You're so protective of your brother.";
+					break;
+				case 2:
+					mes "[Shaam Rumi]";
+					mes "The ^3131FFCrossbow Clan^000000 is ideal for ranged classes.";
+					next;
+					mes "[Shaam Rumi]";
+					mes "Eh, let me check the Clan manual. Ah, and we offer stat bonuses to new members: ^FF0000<DEX+1, AGI+1, MHP+30, MSP+10>^000000.";
+					next;
+					mes "[Shaam Rumi]";
+					mes "The Clans are not allowed to participate in the Siege; you should join a private guild instead for Siege.";
+					mes "The Clans are for adventurers that hate being tied down.";
+					next;
+					mes "[Shaam Rumi]";
+					mes "Do you have a question?";
+					break;
+				case 3:
+					break;
+			}
+			break;
+		case 2:
+			mes "[Shaam Rumi]";
+			mes "Oh, yeah? Good choice!";
+			mes "Let's check the Clan policy then to begin admission procedures.";
+			next;
+			mes "[Shaam Rumi]";
+			mes "^3131FFClansmen^000000 cannot participate in the Siege.";
+			mes "As our new member, you'll receive the following stat bonuses: ^FF0000<DEX+1, AGI+1, MHP+30, MSP+10>^000000.";
+			mes "Do you agree?";
+			next;
+			if( select( "Yes.:No." ) == 1 ){
+				mes "[Shaam Rumi]";
+				mes "You can join and leave a Clan anytime, but if you don't login for ^FF0000more than 2 weeks^000000, you'll be ^FF0000expelled^000000.";
+				mes "Do you promise you'll maintain good standing?";
+				next;
+				if( select( "Yes.:No." ) == 1 ){
+					mes "[Shaam Rumi]";
+					mes "Good, write your name here.";
+					next;
+					input .@name$;
+					mes "[Shaam Rumi]";
+					mes "^3131FF" + strcharinfo( 0 ) + "^000000..!";
+					mes "Ugh, your penmanship needs work. Let me process your application.";
+					next;
+					if( getcharid( 2 ) ){
+						mes "[Shaam Rumi]";
+						mes "Did you finish things up with your guild?";
+						close;
+					}else if( getcharid( 5 ) != 0 ){
+						mes "[Shaam Rumi]";
+						mes "Eh, you're already in a Clan. Hey, this isn't funny.";
+					}else{
+						if (clan_join(CROSSBOWCLAN)) {
+							sc_start2 SC_CROSSBOWCLAN, -1, 0, CROSSBOWCLAN;
+							cutin "sham02.bmp", 2;
+							mes "[Shaam Rumi]";
+							mes "Welcome to the ^3131FFCrossbow Clan^000000!";
+							next;
+							cutin "sham01.bmp", 2;
+							mes "[Shaam Rumi]";
+							mes "You can review Clan info with ^3131FFCtrl+G^000000.";
+							next;
+							mes "[Shaam Rumi]";
+							mes "Don't pick fights with other clansmen. Be social.";
+							mes "If you need help, you can always whisper me, okay? See you around!";
+						} else
+							mes "An error has occurred.";
+					}
+				}else{
+					mes "[Shaam Rumi]";
+					mes "All right then. I'm just going to go have some fun.";
+				}
+			}else{
+				mes "[Shaam Rumi]";
+				mes "Ah, do you need time to think about this? No problem.";
+			}
+			break;
+		case 3:
+			mes "[Shaam Rumi]";
+			mes "Why, did you find a better Clan?";
+			mes "I'm disappointed, but it's your call. Let me process your withdrawal.";
+			next;
+			if( select( "Continue.:Cancel." ) == 1 ){
+				if( getcharid( 5 ) == 0 ){
+					cutin "sham04.bmp", 2;
+					mes "[Shaam Rumi]";
+					mes "I can't let you leave--you're not even in my Clan!";
+				}else if( getcharid( 5 ) != CROSSBOWCLAN ){
+					mes "[Shaam Rumi]";
+					mes "Sorry, but I don't meddle with other Clans' business.";
+				}else{
+					if (clan_leave()) {
+						sc_end SC_CROSSBOWCLAN;
+						mes "[Shaam Rumi]";
+						mes "It's done.";
+						mes "If you ever miss us, don't hesitate to come back, alright?";
+					} else
+						mes "An error has occurred.";
+				}
+			}
+			break;
+	}
+	close2;
+	cutin "", 255;
+	end;
+}

+ 1 - 0
npc/re/scripts_athena.conf

@@ -97,6 +97,7 @@ npc: npc/re/merchants/te_merchant.txt
 npc: npc/re/other/adven_boards.txt
 npc: npc/re/other/bulletin_boards.txt
 npc: npc/re/other/Global_Functions.txt
+npc: npc/re/other/clans.txt
 npc: npc/re/other/dimensional_gap.txt
 npc: npc/re/other/item_merge.txt
 npc: npc/re/other/mail.txt

+ 45 - 0
sql-files/main.sql

@@ -229,6 +229,7 @@ CREATE TABLE IF NOT EXISTS `char` (
   `uniqueitem_counter` int(11) unsigned NOT NULL default '0',
   `sex` ENUM('M','F','U') NOT NULL default 'U',
   `hotkey_rowshift` tinyint(3) unsigned NOT NULL default '0',
+  `clan_id` int(11) unsigned NOT NULL default '0',
   PRIMARY KEY  (`char_id`),
   UNIQUE KEY `name_key` (`name`),
   KEY `account_id` (`account_id`),
@@ -283,6 +284,50 @@ CREATE TABLE IF NOT EXISTS `charlog` (
   `hair_color` int(11) NOT NULL default '0'
 ) ENGINE=MyISAM; 
 
+--
+-- Table structure for table `clan`
+--
+CREATE TABLE `clan` (
+  `clan_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `name` varchar(24) NOT NULL DEFAULT '',
+  `master` varchar(24) NOT NULL DEFAULT '',
+  `mapname` varchar(24) NOT NULL DEFAULT '',
+  `max_member` smallint(6) unsigned NOT NULL DEFAULT '0',
+  PRIMARY KEY (`clan_id`)
+) ENGINE=MyISAM AUTO_INCREMENT=5;
+
+-- ----------------------------
+-- Records of clan
+-- ----------------------------
+INSERT INTO `clan` VALUES ('1', 'Swordman Clan', 'Raffam Oranpere', 'prontera', '500');
+INSERT INTO `clan` VALUES ('2', 'Arcwand Clan', 'Devon Aire', 'geffen', '500');
+INSERT INTO `clan` VALUES ('3', 'Golden Mace Clan', 'Berman Aire', 'prontera', '500');
+INSERT INTO `clan` VALUES ('4', 'Crossbow Clan', 'Shaam Rumi', 'payon', '500');
+
+-- ----------------------------
+-- Table structure for `clan_alliance`
+-- ----------------------------
+CREATE TABLE `clan_alliance` (
+  `clan_id` int(11) unsigned NOT NULL DEFAULT '0',
+  `opposition` int(11) unsigned NOT NULL DEFAULT '0',
+  `alliance_id` int(11) unsigned NOT NULL DEFAULT '0',
+  `name` varchar(24) NOT NULL DEFAULT '',
+  PRIMARY KEY (`clan_id`,`alliance_id`),
+  KEY `alliance_id` (`alliance_id`)
+) ENGINE=MyISAM;
+
+-- ----------------------------
+-- Records of clan_alliance
+-- ----------------------------
+INSERT INTO `clan_alliance` VALUES ('1', '0', '3', 'Golden Mace Clan');
+INSERT INTO `clan_alliance` VALUES ('2', '0', '3', 'Golden Mace Clan');
+INSERT INTO `clan_alliance` VALUES ('2', '1', '4', 'Crossbow Clan');
+INSERT INTO `clan_alliance` VALUES ('3', '0', '1', 'Swordman Clan');
+INSERT INTO `clan_alliance` VALUES ('3', '0', '2', 'Arcwand Clan');
+INSERT INTO `clan_alliance` VALUES ('3', '0', '4', 'Crossbow Clan');
+INSERT INTO `clan_alliance` VALUES ('4', '0', '3', 'Golden Mace Clan');
+INSERT INTO `clan_alliance` VALUES ('4', '1', '2', 'Arcwand Clan');
+
 --
 -- Table structure for table `elemental`
 --

+ 46 - 0
sql-files/upgrades/upgrade_20161116.sql

@@ -0,0 +1,46 @@
+--
+-- Table structure for table `clan`
+--
+CREATE TABLE `clan` (
+  `clan_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `name` varchar(24) NOT NULL DEFAULT '',
+  `master` varchar(24) NOT NULL DEFAULT '',
+  `mapname` varchar(24) NOT NULL DEFAULT '',
+  `max_member` smallint(6) unsigned NOT NULL DEFAULT '0',
+  PRIMARY KEY (`clan_id`)
+) ENGINE=MyISAM AUTO_INCREMENT=5;
+
+-- ----------------------------
+-- Records of clan
+-- ----------------------------
+INSERT INTO `clan` VALUES ('1', 'Swordman Clan', 'Raffam Oranpere', 'prontera', '500');
+INSERT INTO `clan` VALUES ('2', 'Arcwand Clan', 'Devon Aire', 'geffen', '500');
+INSERT INTO `clan` VALUES ('3', 'Golden Mace Clan', 'Berman Aire', 'prontera', '500');
+INSERT INTO `clan` VALUES ('4', 'Crossbow Clan', 'Shaam Rumi', 'payon', '500');
+
+ALTER TABLE `char`
+	ADD COLUMN `clan_id` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `hotkey_rowshift`;
+	
+-- ----------------------------
+-- Table structure for `clan_alliance`
+-- ----------------------------
+CREATE TABLE `clan_alliance` (
+  `clan_id` int(11) unsigned NOT NULL DEFAULT '0',
+  `opposition` int(11) unsigned NOT NULL DEFAULT '0',
+  `alliance_id` int(11) unsigned NOT NULL DEFAULT '0',
+  `name` varchar(24) NOT NULL DEFAULT '',
+  PRIMARY KEY (`clan_id`,`alliance_id`),
+  KEY `alliance_id` (`alliance_id`)
+) ENGINE=MyISAM;
+
+-- ----------------------------
+-- Records of clan_alliance
+-- ----------------------------
+INSERT INTO `clan_alliance` VALUES ('1', '0', '3', 'Golden Mace Clan');
+INSERT INTO `clan_alliance` VALUES ('2', '0', '3', 'Golden Mace Clan');
+INSERT INTO `clan_alliance` VALUES ('2', '1', '4', 'Crossbow Clan');
+INSERT INTO `clan_alliance` VALUES ('3', '0', '1', 'Swordman Clan');
+INSERT INTO `clan_alliance` VALUES ('3', '0', '2', 'Arcwand Clan');
+INSERT INTO `clan_alliance` VALUES ('3', '0', '4', 'Crossbow Clan');
+INSERT INTO `clan_alliance` VALUES ('4', '0', '3', 'Golden Mace Clan');
+INSERT INTO `clan_alliance` VALUES ('4', '1', '2', 'Arcwand Clan');

+ 2 - 0
src/char/CMakeLists.txt

@@ -16,6 +16,7 @@ set( CHAR_HEADERS
 	"${SERVER_CHAR_SOURCE_DIR}/char_logif.h"
 	"${SERVER_CHAR_SOURCE_DIR}/char_mapif.h"
 	"${SERVER_CHAR_SOURCE_DIR}/int_auction.h"
+	"${SERVER_CHAR_SOURCE_DIR}/int_clan.h"
 	"${SERVER_CHAR_SOURCE_DIR}/int_elemental.h"
 	"${SERVER_CHAR_SOURCE_DIR}/int_guild.h"
 	"${SERVER_CHAR_SOURCE_DIR}/int_homun.h"
@@ -34,6 +35,7 @@ set( CHAR_SOURCES
 	"${SERVER_CHAR_SOURCE_DIR}/char_logif.c"
 	"${SERVER_CHAR_SOURCE_DIR}/char_mapif.c"
 	"${SERVER_CHAR_SOURCE_DIR}/int_auction.c"
+	"${SERVER_CHAR_SOURCE_DIR}/int_clan.c"
 	"${SERVER_CHAR_SOURCE_DIR}/int_elemental.c"
 	"${SERVER_CHAR_SOURCE_DIR}/int_guild.c"
 	"${SERVER_CHAR_SOURCE_DIR}/int_homun.c"

+ 26 - 6
src/char/char.c

@@ -296,7 +296,7 @@ int char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p){
 		(p->head_mid != cp->head_mid) || (p->head_bottom != cp->head_bottom) || (p->delete_date != cp->delete_date) ||
 		(p->rename != cp->rename) || (p->robe != cp->robe) || (p->character_moves != cp->character_moves) ||
 		(p->unban_time != cp->unban_time) || (p->font != cp->font) || (p->uniqueitem_counter != cp->uniqueitem_counter) ||
-		(p->hotkey_rowshift != cp->hotkey_rowshift)
+		(p->hotkey_rowshift != cp->hotkey_rowshift) || (p->clan_id != cp->clan_id )
 	)
 	{	//Save status
 		if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `base_level`='%d', `job_level`='%d',"
@@ -307,7 +307,7 @@ int char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p){
 			"`weapon`='%d',`shield`='%d',`head_top`='%d',`head_mid`='%d',`head_bottom`='%d',"
 			"`last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d', `rename`='%d',"
 			"`delete_date`='%lu',`robe`='%d',`moves`='%d',`font`='%u',`uniqueitem_counter`='%u',"
-			"`hotkey_rowshift`='%d'"
+			"`hotkey_rowshift`='%d', `clan_id`='%d'"
 			" WHERE `account_id`='%d' AND `char_id` = '%d'",
 			schema_config.char_db, p->base_level, p->job_level,
 			p->base_exp, p->job_exp, p->zeny,
@@ -319,7 +319,7 @@ int char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p){
 			mapindex_id2name(p->save_point.map), p->save_point.x, p->save_point.y, p->rename,
 			(unsigned long)p->delete_date, // FIXME: platform-dependent size
 			p->robe, p->character_moves, p->font, p->uniqueitem_counter,
-			p->hotkey_rowshift,
+			p->hotkey_rowshift, p->clan_id,
 			p->account_id, p->char_id) )
 		{
 			Sql_ShowDebug(sql_handle);
@@ -1022,7 +1022,7 @@ int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_ev
 		"`status_point`,`skill_point`,`option`,`karma`,`manner`,`party_id`,`guild_id`,`pet_id`,`homun_id`,`elemental_id`,`hair`,"
 		"`hair_color`,`clothes_color`,`body`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`last_x`,`last_y`,"
 		"`save_map`,`save_x`,`save_y`,`partner_id`,`father`,`mother`,`child`,`fame`,`rename`,`delete_date`,`robe`, `moves`,"
-		"`unban_time`,`font`,`uniqueitem_counter`,`sex`,`hotkey_rowshift`"
+		"`unban_time`,`font`,`uniqueitem_counter`,`sex`,`hotkey_rowshift`,`clan_id`"
 		" FROM `%s` WHERE `char_id`=? LIMIT 1", schema_config.char_db)
 	||	SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0)
 	||	SQL_ERROR == SqlStmt_Execute(stmt)
@@ -1085,6 +1085,7 @@ int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_ev
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 56, SQLDT_UINT,   &p->uniqueitem_counter, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 57, SQLDT_ENUM,   &sex, sizeof(sex), NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 58, SQLDT_UCHAR,  &p->hotkey_rowshift, 0, NULL, NULL)
+	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 59, SQLDT_INT,    &p->clan_id, 0, NULL, NULL)
 	)
 	{
 		SqlStmt_ShowDebug(stmt);
@@ -2192,7 +2193,8 @@ bool char_checkdb(void){
 		schema_config.party_db, schema_config.pet_db, schema_config.friend_db, schema_config.mail_db, 
                 schema_config.auction_db, schema_config.quest_db, schema_config.homunculus_db, schema_config.skill_homunculus_db,
                 schema_config.mercenary_db, schema_config.mercenary_owner_db,
-		schema_config.elemental_db, schema_config.ragsrvinfo_db, schema_config.skillcooldown_db, schema_config.bonus_script_db
+		schema_config.elemental_db, schema_config.ragsrvinfo_db, schema_config.skillcooldown_db, schema_config.bonus_script_db,
+		schema_config.clan_table, schema_config.clan_alliance_table
 	};
 	ShowInfo("Start checking DB integrity\n");
 	for (i=0; i<ARRAYLENGTH(sqltable); i++){ //check if they all exist and we can acces them in sql-server
@@ -2206,7 +2208,7 @@ bool char_checkdb(void){
 		"`guild_id`,`pet_id`,`homun_id`,`elemental_id`,`hair`,`hair_color`,`clothes_color`,`weapon`,"
 		"`shield`,`head_top`,`head_mid`,`head_bottom`,`robe`,`last_map`,`last_x`,`last_y`,`save_map`,"
 		"`save_x`,`save_y`,`partner_id`,`online`,`father`,`mother`,`child`,`fame`,`rename`,`delete_date`,"
-		"`moves`,`unban_time`,`font`,`sex`,`hotkey_rowshift`"
+		"`moves`,`unban_time`,`font`,`sex`,`hotkey_rowshift`,`clan_id`"
 		" FROM `%s` LIMIT 1;", schema_config.char_db) ){
 		Sql_ShowDebug(sql_handle);
 		return false;
@@ -2413,6 +2415,18 @@ bool char_checkdb(void){
 		Sql_ShowDebug(sql_handle);
 		return false;
 	}
+	//checking clan table
+	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT  `clan_id`,`name`,`master`,`mapname`,`max_member`"
+		" FROM `%s` LIMIT 1;", schema_config.clan_table) ){
+		Sql_ShowDebug(sql_handle);
+		return false;
+	}
+	//checking clan alliance table
+	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT  `clan_id`,`opposition`,`alliance_id`,`name`"
+		" FROM `%s` LIMIT 1;", schema_config.clan_alliance_table) ){
+		Sql_ShowDebug(sql_handle);
+		return false;
+	}
 	Sql_FreeResult(sql_handle);
 	ShowInfo("DB integrity check finished with success\n");
 	return true;
@@ -2502,6 +2516,10 @@ void char_sql_config_read(const char* cfgName) {
 			safestrncpy(schema_config.acc_reg_str_table, w2, sizeof(schema_config.acc_reg_str_table));
 		else if(!strcmpi(w1,"acc_reg_num_table"))
 			safestrncpy(schema_config.acc_reg_num_table, w2, sizeof(schema_config.acc_reg_num_table));
+		else if(!strcmpi(w1,"clan_table"))
+			safestrncpy(schema_config.clan_table, w2, sizeof(schema_config.clan_table));
+		else if(!strcmpi(w1,"clan_alliance_table"))
+			safestrncpy(schema_config.clan_alliance_table, w2, sizeof(schema_config.clan_alliance_table));
 		//support the import command, just like any other config
 		else if(!strcmpi(w1,"import"))
 			char_sql_config_read(w2);
@@ -2549,6 +2567,8 @@ void char_set_default_sql(){
 	safestrncpy(schema_config.char_reg_str_table,"char_reg_str",sizeof(schema_config.char_reg_str_table));
 	safestrncpy(schema_config.acc_reg_str_table,"acc_reg_str",sizeof(schema_config.acc_reg_str_table));
 	safestrncpy(schema_config.acc_reg_num_table,"acc_reg_num",sizeof(schema_config.acc_reg_num_table));
+	safestrncpy(schema_config.clan_table,"clan",sizeof(schema_config.clan_table));
+	safestrncpy(schema_config.clan_table,"clan_alliance",sizeof(schema_config.clan_alliance_table));
 }
 
 //set default config

+ 2 - 0
src/char/char.h

@@ -73,6 +73,8 @@ struct Schema_Config {
 	char acc_reg_str_table[DB_NAME_LEN];
 	char char_reg_str_table[DB_NAME_LEN];
 	char char_reg_num_table[DB_NAME_LEN];
+	char clan_table[DB_NAME_LEN];
+	char clan_alliance_table[DB_NAME_LEN];
 };
 extern struct Schema_Config schema_config;
 

+ 244 - 0
src/char/int_clan.c

@@ -0,0 +1,244 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "../common/cbasetypes.h"
+#include "../common/malloc.h"
+#include "../common/mmo.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h"
+#include "../common/strlib.h"
+
+#include "char.h"
+#include "char_mapif.h"
+#include "inter.h"
+
+#include <stdlib.h>
+
+//clan cache
+static DBMap* clan_db; // int clan_id -> struct clan*
+
+int inter_clan_removemember_tosql(uint32 account_id, uint32 char_id){
+	if( SQL_ERROR == Sql_Query( sql_handle, "UPDATE `%s` SET `clan_id` = '0' WHERE `char_id` = '%d'", schema_config.char_db, char_id ) ){
+		Sql_ShowDebug( sql_handle );
+		return 1;
+	}else{
+		return 0;
+	}
+}
+
+struct clan* inter_clan_fromsql(int clan_id){
+	struct clan* clan;
+	char* data;
+	size_t len;
+	int i;
+
+	if( clan_id <= 0 )
+		return NULL;
+
+	clan = (struct clan*)idb_get(clan_db, clan_id);
+
+	if( clan ){
+		return clan;
+	}
+
+	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `name`, `master`, `mapname`, `max_member` FROM `%s` WHERE `clan_id`='%d'", schema_config.clan_table, clan_id) ){
+		Sql_ShowDebug(sql_handle);
+		return NULL;
+	}
+
+	if( SQL_SUCCESS != Sql_NextRow(sql_handle) ){
+		return NULL;// Clan does not exists.
+	}
+
+	CREATE(clan, struct clan, 1);
+	memset(clan, 0, sizeof(struct clan));
+
+	clan->id = clan_id;
+	Sql_GetData(sql_handle,  0, &data, &len); memcpy(clan->name, data, min(len, NAME_LENGTH));
+	Sql_GetData(sql_handle,  1, &data, &len); memcpy(clan->master, data, min(len, NAME_LENGTH));
+	Sql_GetData(sql_handle,  2, &data, &len); memcpy(clan->map, data, min(len, MAP_NAME_LENGTH_EXT));
+	Sql_GetData(sql_handle,  3, &data, NULL); clan->max_member = atoi(data);
+
+	clan->connect_member = 0;
+
+	Sql_FreeResult( sql_handle );
+
+	if( clan->max_member > MAX_CLAN ){
+		ShowWarning("Clan %d:%s specifies higher capacity (%d) than MAX_CLAN (%d)\n", clan_id, clan->name, clan->max_member, MAX_CLAN);
+		clan->max_member = MAX_CLAN;
+	}
+
+	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `opposition`,`alliance_id`,`name` FROM `%s` WHERE `clan_id`='%d'", schema_config.clan_alliance_table, clan_id) ){
+		Sql_ShowDebug(sql_handle);
+		aFree(clan);
+		return NULL;
+	}
+
+	for( i = 0; i < MAX_CLANALLIANCE && SQL_SUCCESS == Sql_NextRow(sql_handle); i++ ){
+		struct clan_alliance* a = &clan->alliance[i];
+
+		Sql_GetData(sql_handle, 0, &data, NULL); a->opposition = atoi(data);
+		Sql_GetData(sql_handle, 1, &data, NULL); a->clan_id = atoi(data);
+		Sql_GetData(sql_handle, 2, &data, &len); memcpy(a->name, data, zmin(len, NAME_LENGTH));
+	}
+
+	idb_put( clan_db, clan_id, clan);
+
+	if (charserv_config.save_log)
+		ShowInfo("Clan loaded (%d - %s)\n", clan_id, clan->name);
+
+	return clan;
+}
+
+int mapif_clan_info( int fd ){
+	DBIterator *iter;
+	int offset;
+	struct clan* clan;
+	int length;
+
+	length = 4 + db_size(clan_db) * sizeof( struct clan );
+
+	WFIFOHEAD( fd, length );
+	WFIFOW( fd, 0 ) = 0x38A0;
+	WFIFOW( fd, 2 ) = length;
+
+	offset = 4;
+	iter = db_iterator(clan_db);
+	for( clan = (struct clan*)dbi_first(iter); dbi_exists(iter); clan = (struct clan*)dbi_next(iter) ){
+		memcpy( WFIFOP( fd, offset ), clan, sizeof( struct clan ) );
+		offset += sizeof( struct clan );
+	}
+	dbi_destroy(iter);
+
+	WFIFOSET( fd, length );
+
+	return 0;
+}
+
+static int mapif_parse_clan_request( int fd ){
+	mapif_clan_info( fd );
+
+	return 0;
+}
+
+static int mapif_parse_clan_message( int fd ){
+	unsigned char buf[500];
+	uint16 len;
+
+	len = RFIFOW(fd,2);
+
+	WBUFW(buf,0) = 0x38A1;
+	memcpy( WBUFP(buf,2), RFIFOP(fd,2), len-2 );
+
+	chmapif_sendallwos( fd, buf, len );
+
+	return 0;
+}
+
+static void mapif_clan_refresh_onlinecount( int fd, struct clan* clan ){
+	unsigned char buf[8];
+
+	WBUFW(buf,0) = 0x38A2;
+	WBUFL(buf,2) = clan->id;
+	WBUFW(buf,6) = clan->connect_member;
+
+	chmapif_sendallwos( fd, buf, 8 );
+}
+
+static void mapif_parse_clan_member_left( int fd ){
+	struct clan* clan = (struct clan*)idb_get(clan_db, RFIFOL(fd,2) );
+
+	if( clan == NULL ){ // Unknown clan
+		return;
+	}
+
+	if( clan->connect_member > 0 ){
+		clan->connect_member--;
+
+		mapif_clan_refresh_onlinecount( fd, clan );
+	}
+}
+
+static void mapif_parse_clan_member_joined( int fd ){
+	struct clan* clan = (struct clan*)idb_get(clan_db, RFIFOL(fd,2) );
+
+	if( clan == NULL ){ // Unknown clan
+		return;
+	}
+
+	clan->connect_member++;
+
+	mapif_clan_refresh_onlinecount( fd, clan );
+}
+
+// Communication from the map server
+// - Can analyzed only one by one packet
+// Data packet length that you set to inter.c
+//- Shouldn't do checking and packet length, RFIFOSKIP is done by the caller
+// Must Return
+//	1 : ok
+//  0 : error
+int inter_clan_parse_frommap( int fd ){
+	RFIFOHEAD(fd);
+	switch(RFIFOW(fd,0)) {
+		case 0x30A0:
+			mapif_parse_clan_request( fd );
+			return 1;
+		case 0x30A1:
+			mapif_parse_clan_message( fd );
+			return 1;
+		case 0x30A2:
+			mapif_parse_clan_member_left( fd );
+			return 1;
+		case 0x30A3:
+			mapif_parse_clan_member_joined( fd );
+			return 1;
+		default:
+			return 0;
+	}
+}
+
+// Initialize clan sql
+int inter_clan_init(void){
+	char* data;
+	int* clan_ids;
+	int amount;
+
+	clan_db = idb_alloc(DB_OPT_RELEASE_DATA);
+
+	if( SQL_ERROR == Sql_Query( sql_handle, "SELECT `clan_id` FROM `%s`", schema_config.clan_table ) ){
+		Sql_ShowDebug(sql_handle);
+		return 1;
+	}
+
+	amount = (int)Sql_NumRows( sql_handle );
+
+	if( amount > 0 ){
+		int i;
+
+		CREATE( clan_ids, int, amount );
+		i = 0;
+
+		while( SQL_SUCCESS == Sql_NextRow(sql_handle) ){
+			Sql_GetData(sql_handle,  0, &data, NULL);
+			clan_ids[i++] = atoi(data);
+		}
+
+		Sql_FreeResult( sql_handle );
+
+		// If we didnt load a row as expected
+		amount = i;
+
+		for( i = 0; i < amount; i++ ){
+			inter_clan_fromsql( clan_ids[i] );
+		}
+
+		aFree(clan_ids);
+	}
+
+	return 0;
+}
+
+void inter_clan_final(){
+	db_destroy(clan_db);
+}

+ 10 - 0
src/char/int_clan.h

@@ -0,0 +1,10 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#ifndef _INT_CLAN_H_
+#define _INT_CLAN_H_
+
+	int inter_clan_parse_frommap( int fd );
+	int inter_clan_init(void);
+	void inter_clan_final(void);
+#endif /* _INT_CLAN_H_ */

+ 5 - 0
src/char/inter.c

@@ -21,6 +21,7 @@
 #include "int_auction.h"
 #include "int_quest.h"
 #include "int_elemental.h"
+#include "int_clan.h"
 
 #include <stdlib.h>
 
@@ -54,6 +55,7 @@ int inter_recv_packet_length[] = {
 	-1,10, 6,-1,  0, 0, 0, 0,  0, 0, 0, 0, -1,10,  6,-1,	// 3070-  Mercenary packets [Zephyrus], Elemental packets [pakpil]
 	48,14,-1, 6,  0, 0, 0, 0,  0, 0,13,-1,  0, 0,  0, 0,	// 3080-  Pet System, Storage
 	-1,10,-1, 6,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,	// 3090-  Homunculus packets [albator]
+	 2,-1, 6, 6,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,	// 30A0-  Clan packets
 };
 
 struct WisData {
@@ -913,6 +915,7 @@ int inter_init_sql(const char *file)
 	inter_elemental_sql_init();
 	inter_mail_sql_init();
 	inter_auction_sql_init();
+	inter_clan_init();
 
 	geoip_readdb();
 	return 0;
@@ -933,6 +936,7 @@ void inter_final(void)
 	inter_elemental_sql_final();
 	inter_mail_sql_final();
 	inter_auction_sql_final();
+	inter_clan_final();
 
 	if(geoip_cache) aFree(geoip_cache);
 	
@@ -1377,6 +1381,7 @@ int inter_parse_frommap(int fd)
 		  || inter_mail_parse_frommap(fd)
 		  || inter_auction_parse_frommap(fd)
 		  || inter_quest_parse_frommap(fd)
+		  || inter_clan_parse_frommap(fd)
 		   )
 			break;
 		else

+ 19 - 1
src/common/mmo.h

@@ -80,6 +80,8 @@
 #define MAX_PC_BONUS_SCRIPT 50 ///Max bonus script can be fetched from `bonus_script` table on player load [Cydh]
 #define MAX_ITEM_RDM_OPT 5	 /// Max item random option [Napster]
 #define DB_NAME_LEN 256 //max len of dbs
+#define MAX_CLAN 500
+#define MAX_CLANALLIANCE 6
 
 // for produce
 #define MIN_ATTRIBUTE 0
@@ -439,7 +441,7 @@ struct mmo_charstatus {
 	short manner; // Defines how many minutes a char will be muted, each negative point is equivalent to a minute.
 	unsigned char karma;
 	short hair,hair_color,clothes_color,body;
-	int party_id,guild_id,pet_id,hom_id,mer_id,ele_id;
+	int party_id,guild_id,pet_id,hom_id,mer_id,ele_id,clan_id;
 	int fame;
 
 	// Mercenary Guilds Rank
@@ -880,6 +882,22 @@ enum e_rank {
 	RANK_KILLER = 3
 };
 
+struct clan_alliance {
+	int opposition;
+	int clan_id;
+	char name[NAME_LENGTH];
+};
+
+struct clan{
+	int id;
+	char name[NAME_LENGTH];
+	char master[NAME_LENGTH];
+	char map[MAP_NAME_LENGTH_EXT];
+	short max_member, connect_member;
+	struct map_session_data *members[MAX_CLAN];
+	struct clan_alliance alliance[MAX_CLANALLIANCE];
+};
+
 // Sanity checks...
 #if MAX_ZENY > INT_MAX
 #error MAX_ZENY is too big

+ 2 - 0
src/map/CMakeLists.txt

@@ -16,6 +16,7 @@ set( MAP_HEADERS
 	"${MAP_SOURCE_DIR}/buyingstore.h"
 	"${MAP_SOURCE_DIR}/chat.h"
 	"${MAP_SOURCE_DIR}/chrif.h"
+	"${MAP_SOURCE_DIR}/clan.h"
 	"${MAP_SOURCE_DIR}/clif.h"
 	"${MAP_SOURCE_DIR}/date.h"
 	"${MAP_SOURCE_DIR}/duel.h"
@@ -57,6 +58,7 @@ set( MAP_SOURCES
 	"${MAP_SOURCE_DIR}/buyingstore.c"
 	"${MAP_SOURCE_DIR}/chat.c"
 	"${MAP_SOURCE_DIR}/chrif.c"
+	"${MAP_SOURCE_DIR}/clan.c"
 	"${MAP_SOURCE_DIR}/clif.c"
 	"${MAP_SOURCE_DIR}/date.c"
 	"${MAP_SOURCE_DIR}/duel.c"

+ 5 - 0
src/map/atcommand.c

@@ -3432,6 +3432,11 @@ ACMD_FUNC(guild)
 
 	memset(guild, '\0', sizeof(guild));
 
+	if (sd->clan) {
+		clif_displaymessage(fd, msg_txt(sd, 1498)); // You cannot create a guild because you are in a clan.
+		return -1;
+	}
+
 	if (!message || !*message || sscanf(message, "%23[^\n]", guild) < 1) {
 		clif_displaymessage(fd, msg_txt(sd,1030)); // Please enter a guild name (usage: @guild <guild_name>).
 		return -1;

+ 2 - 0
src/map/chrif.c

@@ -12,6 +12,7 @@
 
 #include "map.h"
 #include "battle.h"
+#include "clan.h"
 #include "clif.h"
 #include "intif.h"
 #include "npc.h"
@@ -508,6 +509,7 @@ int chrif_connectack(int fd) {
 	if( !char_init_done ) {
 		ShowStatus("Event '"CL_WHITE"OnInterIfInitOnce"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInitOnce"));
 		guild_castle_map_init();
+		intif_clan_requestclans();
 	}
 
 	return 0;

+ 200 - 0
src/map/clan.c

@@ -0,0 +1,200 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "../common/cbasetypes.h"
+#include "../common/mmo.h"
+#include "../common/malloc.h"
+#include "../common/nullpo.h"
+#include "../common/showmsg.h"
+
+#include "clan.h"
+#include "clif.h"
+#include "intif.h"
+#include "pc.h"
+#include "script.h"
+#include "status.h"
+
+static DBMap* clan_db; // int clan_id -> struct clan*
+
+void do_init_clan(){
+	clan_db = idb_alloc(DB_OPT_RELEASE_DATA);
+}
+
+void do_final_clan(){
+	db_destroy(clan_db);
+}
+
+void clan_load_clandata( int count, struct clan* clans ){
+	int i,j;
+
+	nullpo_retv( clans );
+
+	for( i = 0, j = 0; i < count; i++, clans++ ){
+		struct clan* clan = clans;
+		struct clan* clanCopy;
+
+		clanCopy = (struct clan*)aMalloc( sizeof( struct clan ) );
+
+		if( clanCopy == NULL ){
+			ShowError("Memory could not be allocated for a clan.\n");
+			break;
+		}
+
+		memcpy( clanCopy, clan, sizeof( struct clan ) );
+		memset( clanCopy->members, 0, sizeof( clanCopy->members ) );
+
+		idb_put( clan_db, clanCopy->id, clanCopy );
+		j++;
+	}
+
+	ShowStatus( "Received '"CL_WHITE"%d"CL_RESET"' clans from char-server.\n", j );
+}
+
+struct clan* clan_search( int id ){
+	return (struct clan*)idb_get(clan_db,id);
+}
+
+struct map_session_data* clan_getavailablesd( struct clan* clan ){
+	int i;
+
+	nullpo_retr(NULL, clan);
+
+	ARR_FIND( 0, clan->max_member, i, clan->members[i] != NULL );
+	return ( i < clan->max_member ) ? clan->members[i] : NULL;
+}
+
+int clan_getMemberIndex( struct clan* clan, uint32 account_id ){
+	int i;
+
+	nullpo_retr(-1,clan);
+
+	ARR_FIND( 0, clan->max_member, i, clan->members[i] != NULL && clan->members[i]->status.account_id == account_id );
+
+	if( i == clan->max_member ){
+		return -1;
+	}else{
+		return i;
+	}
+}
+
+int clan_getNextFreeMemberIndex( struct clan* clan ){
+	int i;
+
+	nullpo_retr(-1,clan);
+
+	ARR_FIND( 0, clan->max_member, i, clan->members[i] == NULL );
+
+	if( i == clan->max_member ){
+		return -1;
+	}else{
+		return i;
+	}
+}
+
+void clan_member_joined( struct map_session_data* sd ){
+	struct clan* clan;
+	int index;
+
+	nullpo_retv(sd);
+
+	clan = clan_search(sd->status.clan_id);
+
+	nullpo_retv(clan);
+
+	if( ( index = clan_getNextFreeMemberIndex(clan) ) >= 0 ){
+		sd->clan = clan;
+		clan->members[index] = sd;
+		clan->connect_member++;
+
+		clif_clan_basicinfo(sd);
+
+		intif_clan_member_joined(clan->id);
+		clif_clan_onlinecount(clan);
+	}
+}
+
+void clan_member_left( struct map_session_data* sd ){
+	int index;
+	struct clan* clan;
+
+	nullpo_retv(sd);
+	nullpo_retv(clan = sd->clan);
+
+	if( ( index = clan_getMemberIndex(clan,sd->status.account_id) ) >= 0 ){
+		clan->members[index] = NULL;
+		clan->connect_member--;
+
+		intif_clan_member_left(clan->id);
+		clif_clan_onlinecount(clan);
+	}
+}
+
+bool clan_member_join( struct map_session_data *sd, int clan_id, uint32 account_id, uint32 char_id ){
+	struct clan *clan;
+
+	nullpo_ret(sd);
+
+	if( ( clan = clan_search( clan_id ) ) == NULL ){
+		return false;
+	}
+
+	if( sd->status.account_id != account_id || sd->status.char_id != char_id || sd->status.clan_id != 0 ){
+		return false;
+	}
+
+	sd->status.clan_id = clan->id;
+
+	clan_member_joined(sd);
+
+	return true;
+}
+
+bool clan_member_leave( struct map_session_data* sd, int clan_id, uint32 account_id, uint32 char_id ){
+	struct clan *clan;
+
+	nullpo_ret(sd);
+
+	if( sd->status.account_id != account_id || sd->status.char_id != char_id || sd->status.clan_id != clan_id || ( clan = sd->clan ) == NULL ){
+		return false;
+	}
+
+	clan_member_left(sd);
+
+	sd->clan = NULL;
+	sd->status.clan_id = 0;
+
+	clif_clan_leave(sd);
+
+	return true;
+}
+
+void clan_recv_message(int clan_id,uint32 account_id,const char *mes,int len) {
+	struct clan *clan;
+
+	nullpo_retv( clan = clan_search(clan_id) );
+
+	clif_clan_message(clan,mes,len);
+}
+
+void clan_send_message( struct map_session_data *sd, const char *mes, int len ){
+	nullpo_retv(sd);
+	nullpo_retv(sd->clan);
+
+	intif_clan_message(sd->status.clan_id,sd->status.account_id,mes,len);
+	clan_recv_message(sd->status.clan_id,sd->status.account_id,mes,len);
+	log_chat( LOG_CHAT_CLAN, sd->status.clan_id, sd->status.char_id, sd->status.account_id, mapindex_id2name( sd->mapindex ), sd->bl.x, sd->bl.y, NULL, mes );
+}
+
+int clan_get_alliance_count( struct clan *clan, int flag ){
+	int i, count;
+
+	nullpo_ret(clan);
+
+	for( i = 0, count = 0; i < MAX_CLANALLIANCE; i++ ){
+		if(	clan->alliance[i].clan_id > 0 && clan->alliance[i].opposition == flag ){
+			count++;
+		}
+	}
+
+	return count;
+}

+ 23 - 0
src/map/clan.h

@@ -0,0 +1,23 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#ifndef _CLAN_H_
+	#define _CLAN_H_
+
+	#include "../common/mmo.h"
+	#include "status.h"
+
+	void do_init_clan();
+	void do_final_clan();
+	struct clan* clan_search( int id );
+	void clan_load_clandata( int count, struct clan* clans );
+	void clan_member_joined( struct map_session_data* sd );
+	void clan_member_left( struct map_session_data* sd );
+	bool clan_member_join( struct map_session_data *sd, int clan_id, uint32 account_id, uint32 char_id );
+	bool clan_member_leave( struct map_session_data* sd, int clan_id, uint32 account_id, uint32 char_id );
+	void clan_send_message( struct map_session_data *sd, const char *mes, int len );
+	void clan_recv_message(int clan_id,uint32 account_id,const char *mes,int len);
+	struct map_session_data* clan_getavailablesd( struct clan* clan );
+	int clan_get_alliance_count( struct clan *clan, int flag );
+
+#endif

+ 168 - 1
src/map/clif.c

@@ -632,6 +632,23 @@ int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target
 			}
 		}
 		break;
+	case CLAN:
+		if( sd && sd->clan ){
+			struct clan* clan = sd->clan;
+
+			for( i = 0; i < clan->max_member; i++ ){
+				if( ( sd = clan->members[i] ) == NULL || !(fd = sd->fd) ){
+					continue;
+				}
+
+				if( packet_db[sd->packet_ver][RBUFW(buf,0)].len ){ // packet must exist for the client version
+					WFIFOHEAD(fd,len);
+					memcpy(WFIFOP(fd,0), buf, len);
+					WFIFOSET(fd,len);
+				}
+			}
+		}
+		break;
 
 	default:
 		ShowError("clif_send: Unrecognized type %d\n",type);
@@ -13070,6 +13087,11 @@ void clif_parse_CreateGuild(int fd,struct map_session_data *sd){
 		return;
 	}
 
+	if(sd->clan){
+		// Should display a clientside message "You are currently joined in Clan !!" so we ignore it
+		return;
+	}
+
 	guild_create(sd, name);
 }
 
@@ -13276,6 +13298,11 @@ int clif_sub_guild_invite(int fd, struct map_session_data *sd, struct map_sessio
 		return 1;
 	}
 
+	// Players in a clan can not join a guild
+	if(t_sd && t_sd->clan){
+		return 1;
+	}
+
 	guild_invite(sd, t_sd);
 	return 0;
 }
@@ -18010,6 +18037,144 @@ void clif_party_leaderchanged(struct map_session_data *sd, int prev_leader_aid,
 	clif_send(buf, packet_len(0x7fc), &sd->bl, PARTY);
 }
 
+/**
+* Sends a clan message to a player
+* 098e <length>.W <name>.24B <message>.?B (ZC_NOTIFY_CLAN_CHAT)
+**/
+void clif_clan_message(struct clan *clan,const char *mes,int len){
+#if PACKETVER >= 20131223
+	struct map_session_data *sd;
+	uint8 buf[256];
+
+	if( len == 0 ){
+		return;
+	}else if( len > (sizeof(buf)-5-NAME_LENGTH) ){
+		ShowWarning("clif_clan_message: Truncated message '%s' (len=%d, max=%d, clan_id=%d).\n", mes, len, sizeof(buf)-5, clan->id);
+		len = sizeof(buf)-5-NAME_LENGTH;
+	}
+
+	WBUFW(buf, 0) = 0x98e;
+	WBUFW(buf, 2) = len + 5 + NAME_LENGTH;
+	
+	// Offially the sender name should also be filled here, but it is not required by the client and since it's in the message too we do not fill it
+	//safestrncpy(WBUFCP(buf,4), sendername, NAME_LENGTH);
+	safestrncpy(WBUFCP(buf,4+NAME_LENGTH), mes, len+1);
+
+	if((sd = clan_getavailablesd(clan)) != NULL)
+		clif_send(buf, WBUFW(buf,2), &sd->bl, CLAN);
+#endif
+}
+
+/**
+* Parses a clan message from a player.
+* 098d <length>.W <text>.?B (<name> : <message>) (CZ_CLAN_CHAT)
+**/
+void clif_parse_clan_chat( int fd, struct map_session_data* sd ){
+#if PACKETVER >= 20131223
+	char name[NAME_LENGTH], message[CHAT_SIZE_MAX], output[CHAT_SIZE_MAX+NAME_LENGTH*2];
+
+	// validate packet and retrieve name and message
+	if( !clif_process_message(sd, false, name, message, output ) )
+		return;
+
+	clan_send_message( sd, RFIFOCP(fd,4), RFIFOW(fd,2) - 4 );
+#endif
+}
+
+/**
+* Sends the basic clan informations to the client.
+* 098a <length>.W <clan id>.L <clan name>.24B <clan master>.24B <clan map>.16B <alliance count>.B
+*      <antagonist count>.B { <alliance>.24B } * alliance count { <antagonist>.24B } * antagonist count (ZC_CLANINFO)
+**/
+void clif_clan_basicinfo( struct map_session_data *sd ){
+#if PACKETVER >= 20131223
+	int fd, offset, length, i, flag;
+	struct clan* clan;
+	char mapname[MAP_NAME_LENGTH_EXT];
+	
+	nullpo_retv( sd );
+	nullpo_retv( clan = sd->clan );
+	
+	// Check if the player has a valid session and is not autotrading
+	if( !clif_session_isValid( sd ) ){
+		return;
+	}
+
+	length = 8 + 2 * NAME_LENGTH + MAP_NAME_LENGTH_EXT + 2;
+	fd = sd->fd;
+
+	WFIFOHEAD(fd,length);
+
+	memset( WFIFOP(fd, 0), 0, length );
+
+	WFIFOW( fd, 0 ) = 0x98a;
+	WFIFOL( fd, 4 ) = clan->id;
+	offset = 8;
+	safestrncpy( WFIFOCP( fd, offset ), clan->name, NAME_LENGTH );
+	offset += NAME_LENGTH;
+	safestrncpy( WFIFOCP( fd, offset ), clan->master, NAME_LENGTH );
+	offset += NAME_LENGTH;
+	mapindex_getmapname_ext( clan->map, mapname );
+	safestrncpy( WFIFOCP( fd, offset ), mapname, MAP_NAME_LENGTH_EXT );
+	offset += MAP_NAME_LENGTH_EXT;
+
+	WFIFOB(fd,offset++) = clan_get_alliance_count(clan,0);
+	WFIFOB(fd,offset++) = clan_get_alliance_count(clan,1);
+
+	for( flag = 0; flag < 2; flag++ ){
+		for( i = 0; i < MAX_CLANALLIANCE; i++ ){
+			if( clan->alliance[i].clan_id > 0 && clan->alliance[i].opposition == flag ){
+				safestrncpy( WFIFOCP( fd, offset ), clan->alliance[i].name, NAME_LENGTH );
+				offset += NAME_LENGTH;
+			}
+		}
+	}
+
+	WFIFOW( fd, 2 ) = offset;
+	WFIFOSET(fd,offset);
+#endif
+}
+
+/**
+* Updates the online and maximum player count of a clan.
+* 0988 <online count>.W <maximum member amount>.W (ZC_NOTIFY_CLAN_CONNECTINFO)
+**/
+void clif_clan_onlinecount( struct clan* clan ){
+#if PACKETVER >= 20131223
+	uint8 buf[6];
+	struct map_session_data *sd;
+
+	WBUFW(buf,0) = 0x988;
+	WBUFW(buf,2) = clan->connect_member;
+	WBUFW(buf,4) = clan->max_member;
+
+	if((sd = clan_getavailablesd(clan)) != NULL)
+		clif_send(buf, 6, &sd->bl, CLAN);
+#endif
+}
+
+/**
+* Notifies the client that the player has left his clan.
+* 0989 (ZC_ACK_CLAN_LEAVE)
+**/
+void clif_clan_leave( struct map_session_data* sd ){
+#if PACKETVER >= 20131223
+	int fd;
+	
+	nullpo_retv( sd );
+	
+	if( !clif_session_isValid( sd ) ){
+		return;
+	}
+	
+	fd = sd->fd;
+
+	WFIFOHEAD(fd,2);
+	WFIFOW(fd,0) = 0x989;
+	WFIFOSET(fd,2);
+#endif
+}
+
 /**
  * Decrypt packet identifier for player
  * @param fd
@@ -19074,7 +19239,7 @@ void packetdb_readdb(bool reload)
 		0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, -1, -1,  7,
 		0,  0,  0,  0,  2,  0,  0, 14,  6, 50,  -1,  0,  0, 0, 12, -1,
 	//#0x0980
-		7,  0,  0, 29, 28,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+		7,  0,  0, 29, 28,  0,  0,  0,  6,  2, -1,  0,  0, -1, -1,  0,
 		31, 0,  0,  0,  0,  0,  0, -1,  8, 11,  9,  8,  0,  0,  0, 22,
 		0,  0,  0,  0,  0,  0, 12, 10, 14, 10, 14,  6,  0,  0,  0,  0,
 		0,  0,  0,  0,  0,  0,  6,  4,  6,  4,  0,  0,  0,  0,  0,  0,
@@ -19333,6 +19498,8 @@ void packetdb_readdb(bool reload)
 		{ clif_parse_Oneclick_Itemidentify, "oneclick_itemidentify" },
 		// NewChange Cart2
 		{ clif_parse_SelectCart, "selectcart" },
+		// Clan System
+		{ clif_parse_clan_chat, "clanchat" },
 		{NULL,NULL}
 	};
 	struct {

+ 9 - 0
src/map/clif.h

@@ -9,6 +9,7 @@
 //#include "../common/mmo.h"
 
 struct Channel;
+struct clan;
 struct item;
 struct s_storage;
 //#include "map.h"
@@ -202,6 +203,8 @@ typedef enum send_target {
 	BG_SAMEMAP_WOS,
 	BG_AREA,
 	BG_AREA_WOS,
+
+	CLAN,				// Clan System
 } send_target;
 
 typedef enum broadcast_flags {
@@ -979,6 +982,12 @@ void clif_spiritcharm(struct map_session_data *sd);
 void clif_snap( struct block_list *bl, short x, short y );
 void clif_monster_hp_bar( struct mob_data* md, int fd );
 
+// Clan System
+void clif_clan_basicinfo( struct map_session_data *sd );
+void clif_clan_message(struct clan *clan,const char *mes,int len);
+void clif_clan_onlinecount( struct clan* clan );
+void clif_clan_leave( struct map_session_data* sd );
+
 /**
  * Color Table
  **/

+ 90 - 0
src/map/intif.c

@@ -10,6 +10,7 @@
 #include "map.h"
 #include "battle.h"
 #include "chrif.h"
+#include "clan.h"
 #include "clif.h"
 #include "pc.h"
 #include "intif.h"
@@ -37,6 +38,7 @@ static const int packet_len_table[] = {
 	-1, 3, 3, 0,  0, 0, 0, 0,  0, 0, 0, 0, -1, 3,  3, 0, //0x3870  Mercenaries [Zephyrus] / Elemental [pakpil]
 	12,-1, 7, 3,  0, 0, 0, 0,  0, 0,-1, 9, -1, 0,  0, 0, //0x3880  Pet System,  Storages
 	-1,-1, 7, 3,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0, //0x3890  Homunculus [albator]
+	-1,-1, 8, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0, //0x38A0  Clans
 };
 
 extern int char_fd; // inter server Fd used for char_fd
@@ -3364,6 +3366,89 @@ bool intif_storage_save(struct map_session_data *sd, struct s_storage *stor)
 	return true;
 }
 
+int intif_clan_requestclans(){
+	if (CheckForCharServer())
+		return 0;
+	WFIFOHEAD(inter_fd, 2);
+	WFIFOW(inter_fd, 0) = 0x30A0;
+	WFIFOSET(inter_fd, 2);
+	return 1;
+}
+
+void intif_parse_clans( int fd ){
+	clan_load_clandata( ( RFIFOW(fd, 2) - 4 ) / sizeof( struct clan ), (struct clan*)RFIFOP(fd,4) );
+}
+
+int intif_clan_message(int clan_id,uint32 account_id,const char *mes,int len){
+	if (CheckForCharServer())
+		return 0;
+
+	if (other_mapserver_count < 1)
+		return 0; //No need to send.
+
+	WFIFOHEAD(inter_fd, len + 12);
+	WFIFOW(inter_fd,0)=0x30A1;
+	WFIFOW(inter_fd,2)=len+12;
+	WFIFOL(inter_fd,4)=clan_id;
+	WFIFOL(inter_fd,8)=account_id;
+	memcpy(WFIFOP(inter_fd,12),mes,len);
+	WFIFOSET(inter_fd,len+12);
+
+	return 1;
+}
+
+int intif_parse_clan_message( int fd ){
+	clan_recv_message(RFIFOL(fd,4),RFIFOL(fd,8),(char *) RFIFOP(fd,12),RFIFOW(fd,2)-12);
+
+	return 1;
+}
+
+int intif_clan_member_left( int clan_id ){
+	if (CheckForCharServer())
+		return 0;
+
+	if (other_mapserver_count < 1)
+		return 0; //No need to send.
+
+	WFIFOHEAD(inter_fd,6);
+	WFIFOW(inter_fd,0) = 0x30A2;
+	WFIFOL(inter_fd,2) = clan_id;
+	WFIFOSET(inter_fd,6);
+	
+	return 1;
+}
+
+int intif_clan_member_joined( int clan_id ){
+	if (CheckForCharServer())
+		return 0;
+
+	if (other_mapserver_count < 1)
+		return 0; //No need to send.
+
+	WFIFOHEAD(inter_fd,6);
+	WFIFOW(inter_fd,0) = 0x30A3;
+	WFIFOL(inter_fd,2) = clan_id;
+	WFIFOSET(inter_fd,6);
+	
+	return 1;
+}
+
+int intif_parse_clan_onlinecount( int fd ){
+	struct clan* clan = clan_search(RFIFOL(fd,2));
+
+	if( clan == NULL ){
+		return 0;
+	}
+
+	clan->connect_member = RFIFOW(fd,6);
+
+	clif_clan_onlinecount(clan);
+
+	return 1;
+}
+
+//-----------------------------------------------------------------
+
 /**
  * Communication from the inter server, Main entry point interface (inter<=>map) 
  * @param fd : inter-serv link
@@ -3487,6 +3572,11 @@ int intif_parse(int fd)
 	case 0x3892:	intif_parse_SaveHomunculusOk(fd); break;
 	case 0x3893:	intif_parse_DeleteHomunculusOk(fd); break;
 
+	// Clan system
+	case 0x38A0:	intif_parse_clans(fd); break;
+	case 0x38A1:	intif_parse_clan_message(fd); break;
+	case 0x38A2:	intif_parse_clan_onlinecount(fd); break;
+
 	default:
 		ShowError("intif_parse : unknown packet %d %x\n",fd,RFIFOW(fd,0));
 		return 0;

+ 5 - 0
src/map/intif.h

@@ -107,6 +107,11 @@ int intif_elemental_create(struct s_elemental *ele);
 int intif_elemental_request(int ele_id, uint32 char_id);
 int intif_elemental_delete(int ele_id);
 int intif_elemental_save(struct s_elemental *ele);
+// CLAN SYSTEM
+int intif_clan_requestclans();
+int intif_clan_message(int clan_id,uint32 account_id,const char *mes,int len);
+int intif_clan_member_joined( int clan_id );
+int intif_clan_member_left( int clan_id );
 
 int intif_request_accinfo(int u_fd, int aid, int group_lv, char* query, char type);
 

+ 1 - 0
src/map/log.h

@@ -17,6 +17,7 @@ typedef enum e_log_chat_type
 	LOG_CHAT_PARTY       = 0x04,
 	LOG_CHAT_GUILD       = 0x08,
 	LOG_CHAT_MAINCHAT    = 0x10,
+	LOG_CHAT_CLAN        = 0x20,
 	// all
 	LOG_CHAT_ALL         = 0xFF,
 } e_log_chat_type;

+ 6 - 0
src/map/map.c

@@ -18,6 +18,7 @@
 #include "map.h"
 #include "path.h"
 #include "chrif.h"
+#include "clan.h"
 #include "clif.h"
 #include "duel.h"
 #include "intif.h"
@@ -1982,6 +1983,9 @@ int map_quit(struct map_session_data *sd) {
 	if( sd->bg_id )
 		bg_team_leave(sd,1);
 
+	if( sd->status.clan_id )
+		clan_member_left(sd);
+
 	pc_itemcd_do(sd,false);
 
 	npc_script_event(sd, NPCE_LOGOUT);
@@ -4385,6 +4389,7 @@ void do_final(void)
 	do_final_atcommand();
 	do_final_battle();
 	do_final_chrif();
+	do_final_clan();
 	do_final_clif();
 	do_final_npc();
 	do_final_quest();
@@ -4725,6 +4730,7 @@ int do_init(int argc, char *argv[])
 	do_init_instance();
 	do_init_channel();
 	do_init_chrif();
+	do_init_clan();
 	do_init_clif();
 	do_init_script();
 	do_init_itemdb();

+ 3 - 0
src/map/pc.c

@@ -20,6 +20,7 @@
 #include "channel.h"
 #include "chat.h"
 #include "chrif.h"
+#include "clan.h"
 #include "date.h" // is_day_of_*()
 #include "duel.h"
 #include "intif.h"
@@ -1412,6 +1413,8 @@ void pc_reg_received(struct map_session_data *sd)
 		party_member_joined(sd);
 	if (sd->status.guild_id)
 		guild_member_joined(sd);
+	if( sd->status.clan_id )
+		clan_member_joined(sd);
 
 	// pet
 	if (sd->status.pet_id > 0)

+ 3 - 0
src/map/pc.h

@@ -12,6 +12,7 @@
 #include "atcommand.h" // AtCommandType
 #include "battle.h" // battle_config
 #include "buyingstore.h"  // struct s_buyingstore
+#include "clan.h"
 #include "itemdb.h" // MAX_ITEMGROUP
 #include "script.h" // struct script_reg, struct script_regstr
 #include "searchstore.h"  // struct s_search_store_info
@@ -516,6 +517,8 @@ struct map_session_data {
 	int guildspy; // [Syrus22]
 	int partyspy; // [Syrus22]
 
+	struct clan *clan;
+
 	int vended_id;
 	int vender_id;
 	int vend_num;

+ 41 - 0
src/map/script.c

@@ -30,6 +30,7 @@
 
 #include "map.h"
 #include "path.h"
+#include "clan.h"
 #include "clif.h"
 #include "chrif.h"
 #include "itemdb.h"
@@ -7808,6 +7809,7 @@ BUILDIN_FUNC(readparam)
  *	2 : guild_id
  *	3 : account_id
  *	4 : bg_id
+ *	5 : clan_id
  *------------------------------------------*/
 BUILDIN_FUNC(getcharid)
 {
@@ -7831,6 +7833,7 @@ BUILDIN_FUNC(getcharid)
 	case 2: script_pushint(st,sd->status.guild_id); break;
 	case 3: script_pushint(st,sd->status.account_id); break;
 	case 4: script_pushint(st,sd->bg_id); break;
+	case 5: script_pushint(st,sd->status.clan_id); break;
 	default:
 		ShowError("buildin_getcharid: invalid parameter (%d).\n", num);
 		script_pushint(st,0);
@@ -21175,6 +21178,40 @@ BUILDIN_FUNC(npcshopupdate) {
 	return SCRIPT_CMD_SUCCESS;
 }
 
+// Clan System
+BUILDIN_FUNC(clan_join){
+	struct map_session_data *sd;
+	int clan_id = script_getnum(st,2);
+
+	if( !script_charid2sd( 3, sd ) ){
+		script_pushint(st, false);
+		return SCRIPT_CMD_FAILURE;
+	}
+
+	if( clan_member_join( sd, clan_id, sd->status.account_id, sd->status.char_id ) )
+		script_pushint(st, true);
+	else
+		script_pushint(st, false);
+
+	return SCRIPT_CMD_SUCCESS;
+}
+
+BUILDIN_FUNC(clan_leave){
+	struct map_session_data *sd;
+
+	if( !script_charid2sd( 2, sd ) ){
+		script_pushint(st, false);
+		return SCRIPT_CMD_FAILURE;
+	}
+
+	if( clan_member_leave( sd, sd->status.clan_id, sd->status.account_id, sd->status.char_id ) )
+		script_pushint(st, true);
+	else
+		script_pushint(st, false);
+
+	return SCRIPT_CMD_SUCCESS;
+}
+
 /**
  * Get rid from running script.
  * getattachedrid();
@@ -22553,6 +22590,10 @@ struct script_function buildin_func[] = {
 	BUILDIN_DEF(party_changeoption,"iii"),
 	BUILDIN_DEF(party_destroy,"i"),
 
+	// Clan system
+	BUILDIN_DEF(clan_join,"i?"),
+	BUILDIN_DEF(clan_leave,"?"),
+
 	BUILDIN_DEF(is_clientver,"ii?"),
 	BUILDIN_DEF2(montransform, "transform", "vi?????"), // Monster Transform [malufett/Hercules]
 	BUILDIN_DEF2(montransform, "active_transform", "vi?????"),

+ 7 - 0
src/map/script_constants.h

@@ -1424,6 +1424,12 @@
 	export_constant(SC_GVG_CURSE);
 	export_constant(SC_GVG_SILENCE);
 	export_constant(SC_GVG_BLIND);
+	export_constant(SC_CLAN_INFO);
+	export_constant(SC_SWORDCLAN);
+	export_constant(SC_ARCWANDCLAN);
+	export_constant(SC_GOLDENMACECLAN);
+	export_constant(SC_CROSSBOWCLAN);
+	export_constant(SC_JUMPINGCLAN);
 #ifdef RENEWAL
 	export_constant(SC_EXTREMITYFIST2);
 #endif
@@ -2665,6 +2671,7 @@
 	export_constant(BG_SAMEMAP_WOS);
 	export_constant(BG_AREA);
 	export_constant(BG_AREA_WOS);
+	export_constant(CLAN);
 
 	/* mercenary guilds */
 	export_constant(ARCH_MERC_GUILD);

+ 11 - 0
src/map/skill.c

@@ -1827,6 +1827,8 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
 					case SC_REUSE_LIMIT_ASPD_POTION:	case SC_REUSE_MILLENNIUMSHIELD:	case SC_REUSE_CRUSHSTRIKE:
 					case SC_REUSE_STORMBLAST:	case SC_ALL_RIDING_REUSE_LIMIT:
 					case SC_SPRITEMABLE:		case SC_BITESCAR:
+					case SC_CLAN_INFO:		case SC_SWORDCLAN:		case SC_ARCWANDCLAN:
+					case SC_GOLDENMACECLAN:	case SC_CROSSBOWCLAN:
 						continue;
 					case SC_WHISTLE:		case SC_ASSNCROS:		case SC_POEMBRAGI:
 					case SC_APPLEIDUN:		case SC_HUMMING:		case SC_DONTFORGETME:
@@ -7741,6 +7743,13 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 					case SC_REUSE_STORMBLAST:	case SC_ALL_RIDING_REUSE_LIMIT:
 					case SC_SPRITEMABLE:		case SC_BITESCAR:	case SC_CRUSHSTRIKE:
 					case SC_QUEST_BUFF1:	case SC_QUEST_BUFF2:	case SC_QUEST_BUFF3:
+					// Clans
+					case SC_CLAN_INFO:
+					case SC_SWORDCLAN:
+					case SC_ARCWANDCLAN:
+					case SC_GOLDENMACECLAN:
+					case SC_CROSSBOWCLAN:
+					case SC_JUMPINGCLAN:
 						continue;
 					//bugreport:4888 these songs may only be dispelled if you're not in their song area anymore
 					case SC_WHISTLE:
@@ -9249,6 +9258,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 					case SC_REUSE_STORMBLAST:	case SC_ALL_RIDING_REUSE_LIMIT:
 					case SC_SPRITEMABLE:
 					case SC_QUEST_BUFF1:	case SC_QUEST_BUFF2:	case SC_QUEST_BUFF3:
+					case SC_CLAN_INFO:		case SC_SWORDCLAN:		case SC_ARCWANDCLAN:
+					case SC_GOLDENMACECLAN:	case SC_CROSSBOWCLAN:
 					continue;
 				case SC_ASSUMPTIO:
 					if( bl->type == BL_MOB )

+ 104 - 1
src/map/status.c

@@ -1096,6 +1096,14 @@ void initChangeTables(void)
 	StatusIconChangeTable[SC_REUSE_STORMBLAST] = SI_REUSE_STORMBLAST;
 	StatusIconChangeTable[SC_ALL_RIDING_REUSE_LIMIT] = SI_ALL_RIDING_REUSE_LIMIT;
 
+	// Clan System
+	StatusIconChangeTable[SC_CLAN_INFO] = SI_CLAN_INFO;
+	StatusIconChangeTable[SC_SWORDCLAN] = SI_SWORDCLAN;
+	StatusIconChangeTable[SC_ARCWANDCLAN] = SI_ARCWANDCLAN;
+	StatusIconChangeTable[SC_GOLDENMACECLAN] = SI_GOLDENMACECLAN;
+	StatusIconChangeTable[SC_CROSSBOWCLAN] = SI_CROSSBOWCLAN;
+	StatusIconChangeTable[SC_JUMPINGCLAN] = SI_JUMPINGCLAN;
+
 	/* Other SC which are not necessarily associated to skills */
 	StatusChangeFlagTable[SC_ASPDPOTION0] |= SCB_ASPD;
 	StatusChangeFlagTable[SC_ASPDPOTION1] |= SCB_ASPD;
@@ -1227,6 +1235,14 @@ void initChangeTables(void)
 	StatusChangeFlagTable[SC_TIME_ACCESSORY] |= SCB_NONE;
 	StatusChangeFlagTable[SC_MAGICAL_FEATHER] |= SCB_NONE;
 
+	// Clan System
+	StatusChangeFlagTable[SC_CLAN_INFO] |= SCB_NONE;
+	StatusChangeFlagTable[SC_SWORDCLAN] |= SCB_STR|SCB_VIT|SCB_MAXHP|SCB_MAXSP;
+	StatusChangeFlagTable[SC_ARCWANDCLAN] |= SCB_INT|SCB_DEX|SCB_MAXHP|SCB_MAXSP;
+	StatusChangeFlagTable[SC_GOLDENMACECLAN] |= SCB_LUK|SCB_INT|SCB_MAXHP|SCB_MAXSP;
+	StatusChangeFlagTable[SC_CROSSBOWCLAN] |= SCB_DEX|SCB_AGI|SCB_MAXHP|SCB_MAXSP;
+	StatusChangeFlagTable[SC_JUMPINGCLAN] |= SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK;
+
 #ifdef RENEWAL
 	// renewal EDP increases your weapon atk
 	StatusChangeFlagTable[SC_EDP] |= SCB_WATK;
@@ -1289,6 +1305,9 @@ void initChangeTables(void)
 	StatusDisplayType[SC_TIME_ACCESSORY] = true;
 	StatusDisplayType[SC_MAGICAL_FEATHER] = true;
 
+	// Clans
+	StatusDisplayType[SC_CLAN_INFO] = true;
+
 	/* StatusChangeState (SCS_) NOMOVE */
 	StatusChangeStateTable[SC_ANKLE]				|= SCS_NOMOVE;
 	StatusChangeStateTable[SC_AUTOCOUNTER]			|= SCS_NOMOVE;
@@ -2890,6 +2909,14 @@ static int status_get_hpbonus(struct block_list *bl, enum e_status_bonus type) {
 				bonus += sc->data[SC_MTF_MHP]->val1;
 			if(sc->data[SC_MARIONETTE])
 				bonus -= 1000;
+			if(sc->data[SC_SWORDCLAN])
+				bonus += 30;
+			if(sc->data[SC_ARCWANDCLAN])
+				bonus += 30;
+			if(sc->data[SC_GOLDENMACECLAN])
+				bonus += 30;
+			if(sc->data[SC_CROSSBOWCLAN])
+				bonus += 30;
 		}
 	} else if (type == STATUS_BONUS_RATE) {
 		struct status_change *sc = status_get_sc(bl);
@@ -3002,6 +3029,14 @@ static int status_get_spbonus(struct block_list *bl, enum e_status_bonus type) {
 				bonus += 50;
 			if(sc->data[SC_MTF_MSP])
 				bonus += sc->data[SC_MTF_MSP]->val1;
+			if(sc->data[SC_SWORDCLAN])
+				bonus += 10;
+			if(sc->data[SC_ARCWANDCLAN])
+				bonus += 10;
+			if(sc->data[SC_GOLDENMACECLAN])
+				bonus += 10;
+			if(sc->data[SC_CROSSBOWCLAN])
+				bonus += 10;
 		}
 	} else if (type == STATUS_BONUS_RATE) {
 		struct status_change *sc = status_get_sc(bl);
@@ -5265,6 +5300,10 @@ static unsigned short status_calc_str(struct block_list *bl, struct status_chang
 		str -= sc->data[SC_STOMACHACHE]->val1;
 	if(sc->data[SC_KYOUGAKU])
 		str -= sc->data[SC_KYOUGAKU]->val2;
+	if(sc->data[SC_SWORDCLAN])
+		str += 1;
+	if(sc->data[SC_JUMPINGCLAN])
+		str += 1;
 	if(sc->data[SC_FULL_THROTTLE])
 		str += str * sc->data[SC_FULL_THROTTLE]->val3 / 100;
 
@@ -5331,6 +5370,10 @@ static unsigned short status_calc_agi(struct block_list *bl, struct status_chang
 		agi -= sc->data[SC_STOMACHACHE]->val1;
 	if(sc->data[SC_KYOUGAKU])
 		agi -= sc->data[SC_KYOUGAKU]->val2;
+	if(sc->data[SC_CROSSBOWCLAN])
+		agi += 1;
+	if(sc->data[SC_JUMPINGCLAN])
+		agi += 1;
 	if(sc->data[SC_FULL_THROTTLE])
 		agi += agi * sc->data[SC_FULL_THROTTLE]->val3 / 100;
 	if (sc->data[SC_ARCLOUSEDASH])
@@ -5387,6 +5430,10 @@ static unsigned short status_calc_vit(struct block_list *bl, struct status_chang
 		vit -= sc->data[SC_STOMACHACHE]->val1;
 	if(sc->data[SC_KYOUGAKU])
 		vit -= sc->data[SC_KYOUGAKU]->val2;
+	if(sc->data[SC_SWORDCLAN])
+		vit += 1;
+	if(sc->data[SC_JUMPINGCLAN])
+		vit += 1;
 	if(sc->data[SC_STRIPARMOR] && bl->type != BL_PC)
 		vit -= vit * sc->data[SC_STRIPARMOR]->val2/100;
 	if(sc->data[SC_FULL_THROTTLE])
@@ -5457,6 +5504,12 @@ static unsigned short status_calc_int(struct block_list *bl, struct status_chang
 		int_ -= sc->data[SC_STOMACHACHE]->val1;
 	if(sc->data[SC_KYOUGAKU])
 		int_ -= sc->data[SC_KYOUGAKU]->val2;
+	if(sc->data[SC_ARCWANDCLAN])
+		int_ += 1;
+	if(sc->data[SC_GOLDENMACECLAN])
+		int_ += 1;
+	if(sc->data[SC_JUMPINGCLAN])
+		int_ += 1;
 	if(sc->data[SC_FULL_THROTTLE])
 		int_ += int_ * sc->data[SC_FULL_THROTTLE]->val3 / 100;
 
@@ -5528,7 +5581,12 @@ static unsigned short status_calc_dex(struct block_list *bl, struct status_chang
 		dex -= sc->data[SC_STOMACHACHE]->val1;
 	if(sc->data[SC_KYOUGAKU])
 		dex -= sc->data[SC_KYOUGAKU]->val2;
-
+	if(sc->data[SC_ARCWANDCLAN])
+		dex += 1;
+	if(sc->data[SC_CROSSBOWCLAN])
+		dex += 1;
+	if(sc->data[SC_JUMPINGCLAN])
+		dex += 1;
 	if(sc->data[SC__STRIPACCESSORY] && bl->type != BL_PC)
 		dex -= dex * sc->data[SC__STRIPACCESSORY]->val2 / 100;
 	if(sc->data[SC_MARSHOFABYSS])
@@ -5591,6 +5649,10 @@ static unsigned short status_calc_luk(struct block_list *bl, struct status_chang
 		luk -= luk * sc->data[SC__STRIPACCESSORY]->val2 / 100;
 	if(sc->data[SC_BANANA_BOMB])
 		luk -= 75;
+	if(sc->data[SC_GOLDENMACECLAN])
+		luk += 1;
+	if(sc->data[SC_JUMPINGCLAN])
+		luk += 1;
 	if(sc->data[SC_FULL_THROTTLE])
 		luk += luk * sc->data[SC_FULL_THROTTLE]->val3 / 100;
 
@@ -9036,6 +9098,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 		case SC_DODGE:
 		case SC_PUSH_CART:
 		case SC_SPRITEMABLE:
+		case SC_CLAN_INFO:
 			tick = -1;
 			break;
 
@@ -10661,6 +10724,14 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 			val2 = (status->max_hp * (val1 * 10) / 100); // %Max HP to absorb
 			//val3 = 6 + val1; // Hits !TODO: Does it have hits too?
 			break;
+		case SC_SWORDCLAN:
+		case SC_ARCWANDCLAN:
+		case SC_GOLDENMACECLAN:
+		case SC_CROSSBOWCLAN:
+		case SC_JUMPINGCLAN:
+			tick = -1;
+			status_change_start(src,bl,SC_CLAN_INFO,10000,0,val2,0,0,-1,flag);
+			break;
 
 		default:
 			if( calc_flag == SCB_NONE && StatusSkillChangeTable[type] == -1 && StatusIconChangeTable[type] == SI_BLANK ) {
@@ -10718,6 +10789,11 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 		case SC_ITEMBOOST:
 		case SC_JP_EVENT04:
 		case SC_PUSH_CART:
+		case SC_SWORDCLAN:
+		case SC_ARCWANDCLAN:
+		case SC_GOLDENMACECLAN:
+		case SC_CROSSBOWCLAN:
+		case SC_JUMPINGCLAN:
 			val_flag |= 1;
 			break;
 		// Start |1|2 val_flag setting
@@ -10738,6 +10814,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 		case SC_WILD_STORM_OPTION:
 		case SC_UPHEAVAL_OPTION:
 		case SC_CIRCLE_OF_FIRE_OPTION:
+		case SC_CLAN_INFO:
 			val_flag |= 1|2;
 			break;
 		// Start |1|2|4 val_flag setting
@@ -10771,6 +10848,11 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 			case SC_ALL_RIDING:
 				dval1 = 1;
 				break;
+			case SC_CLAN_INFO:
+				dval1 = val1;
+				dval2 = val2;
+				dval3 = val3;
+				break;
 			default: /* All others: just copy val1 */
 				dval1 = val1;
 				break;
@@ -11335,6 +11417,13 @@ int status_change_clear(struct block_list* bl, int type)
 			case SC_MAPLE_FALLS:
 			case SC_TIME_ACCESSORY:
 			case SC_MAGICAL_FEATHER:
+			// Clans
+			case SC_CLAN_INFO:
+			case SC_SWORDCLAN:
+			case SC_ARCWANDCLAN:
+			case SC_GOLDENMACECLAN:
+			case SC_CROSSBOWCLAN:
+			case SC_JUMPINGCLAN:
 				continue;
 			}
 		}
@@ -11361,6 +11450,13 @@ int status_change_clear(struct block_list* bl, int type)
 			case SC_MAPLE_FALLS:
 			case SC_TIME_ACCESSORY:
 			case SC_MAGICAL_FEATHER:
+			// Clans
+			case SC_CLAN_INFO:
+			case SC_SWORDCLAN:
+			case SC_ARCWANDCLAN:
+			case SC_GOLDENMACECLAN:
+			case SC_CROSSBOWCLAN:
+			case SC_JUMPINGCLAN:
 				continue;
 			}
 		}
@@ -11913,6 +12009,13 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
 			///< !CHECKME: Seems on official, there's delay before same target can be vacuumed in same area again [Cydh]
 			sc_start2(bl, bl, SC_VACUUM_EXTREME_POSTDELAY, 100, sce->val1, sce->val2, skill_get_time2(SO_VACUUM_EXTREME,sce->val1));
 			break;
+		case SC_SWORDCLAN:
+		case SC_ARCWANDCLAN:
+		case SC_GOLDENMACECLAN:
+		case SC_CROSSBOWCLAN:
+		case SC_JUMPINGCLAN:
+			status_change_end(bl,SC_CLAN_INFO,INVALID_TIMER);
+			break;
 	}
 
 	opt_flag = 1;

+ 7 - 0
src/map/status.h

@@ -779,6 +779,13 @@ typedef enum sc_type {
 	SC_GVG_SILENCE,
 	SC_GVG_BLIND,
 
+	SC_CLAN_INFO,
+	SC_SWORDCLAN,
+	SC_ARCWANDCLAN,
+	SC_GOLDENMACECLAN,
+	SC_CROSSBOWCLAN,
+	SC_JUMPINGCLAN,
+
 #ifdef RENEWAL
 	SC_EXTREMITYFIST2, //! NOTE: This SC should be right before SC_MAX, so it doesn't disturb if RENEWAL is disabled
 #endif

+ 2 - 0
vcproj-10/char-server.vcxproj

@@ -167,6 +167,7 @@
     <ClInclude Include="..\src\char\char_logif.h" />
     <ClInclude Include="..\src\char\char_mapif.h" />
     <ClInclude Include="..\src\char\int_auction.h" />
+    <ClInclude Include="..\src\char\int_clan.h" />
     <ClInclude Include="..\src\char\int_elemental.h" />
     <ClInclude Include="..\src\char\int_guild.h" />
     <ClInclude Include="..\src\char\int_homun.h" />
@@ -211,6 +212,7 @@
     <ClCompile Include="..\src\char\char_logif.c" />
     <ClCompile Include="..\src\char\char_mapif.c" />
     <ClCompile Include="..\src\char\int_auction.c" />
+    <ClCompile Include="..\src\char\int_clan.c" />
     <ClCompile Include="..\src\char\int_elemental.c" />
     <ClCompile Include="..\src\char\int_guild.c" />
     <ClCompile Include="..\src\char\int_homun.c" />

+ 6 - 0
vcproj-10/char-server.vcxproj.filters

@@ -58,6 +58,9 @@
     <ClCompile Include="..\src\char\int_auction.c">
       <Filter>char</Filter>
     </ClCompile>
+    <ClCompile Include="..\src\char\int_clan.c">
+      <Filter>char</Filter>
+    </ClCompile>
     <ClCompile Include="..\src\char\int_elemental.c">
       <Filter>char</Filter>
     </ClCompile>
@@ -195,6 +198,9 @@
     <ClInclude Include="..\src\char\int_auction.h">
       <Filter>char</Filter>
     </ClInclude>
+    <ClInclude Include="..\src\char\int_clan.h">
+      <Filter>char</Filter>
+    </ClInclude>
     <ClInclude Include="..\src\char\int_elemental.h">
       <Filter>char</Filter>
     </ClInclude>

+ 2 - 0
vcproj-10/map-server.vcxproj

@@ -168,6 +168,7 @@
     <ClInclude Include="..\src\map\channel.h" />
     <ClInclude Include="..\src\map\chat.h" />
     <ClInclude Include="..\src\map\chrif.h" />
+    <ClInclude Include="..\src\map\clan.h" />
     <ClInclude Include="..\src\map\clif.h" />
     <ClInclude Include="..\src\map\date.h" />
     <ClInclude Include="..\src\map\duel.h" />
@@ -243,6 +244,7 @@
     <ClCompile Include="..\src\map\channel.c" />
     <ClCompile Include="..\src\map\chat.c" />
     <ClCompile Include="..\src\map\chrif.c" />
+    <ClCompile Include="..\src\map\clan.c" />
     <ClCompile Include="..\src\map\clif.c" />
     <ClCompile Include="..\src\map\date.c" />
     <ClCompile Include="..\src\map\duel.c" />

+ 6 - 0
vcproj-10/map-server.vcxproj.filters

@@ -25,6 +25,9 @@
     <ClCompile Include="..\src\map\chrif.c">
       <Filter>map</Filter>
     </ClCompile>
+    <ClCompile Include="..\src\map\clan.c">
+      <Filter>map</Filter>
+    </ClCompile>
     <ClCompile Include="..\src\map\clif.c">
       <Filter>map</Filter>
     </ClCompile>
@@ -234,6 +237,9 @@
     <ClInclude Include="..\src\map\chrif.h">
       <Filter>map</Filter>
     </ClInclude>
+    <ClInclude Include="..\src\map\clan.h">
+      <Filter>map</Filter>
+    </ClInclude>
     <ClInclude Include="..\src\map\clif.h">
       <Filter>map</Filter>
     </ClInclude>

+ 2 - 0
vcproj-12/char-server.vcxproj

@@ -170,6 +170,7 @@
     <ClInclude Include="..\src\char\char_logif.h" />
     <ClInclude Include="..\src\char\char_mapif.h" />
     <ClInclude Include="..\src\char\int_auction.h" />
+    <ClInclude Include="..\src\char\int_clan.h" />
     <ClInclude Include="..\src\char\int_elemental.h" />
     <ClInclude Include="..\src\char\int_guild.h" />
     <ClInclude Include="..\src\char\int_homun.h" />
@@ -214,6 +215,7 @@
     <ClCompile Include="..\src\char\char_logif.c" />
     <ClCompile Include="..\src\char\char_mapif.c" />
     <ClCompile Include="..\src\char\int_auction.c" />
+    <ClCompile Include="..\src\char\int_clan.c" />
     <ClCompile Include="..\src\char\int_elemental.c" />
     <ClCompile Include="..\src\char\int_guild.c" />
     <ClCompile Include="..\src\char\int_homun.c" />

+ 6 - 0
vcproj-12/char-server.vcxproj.filters

@@ -67,6 +67,9 @@
     <ClCompile Include="..\src\char\int_auction.c">
       <Filter>char</Filter>
     </ClCompile>
+    <ClCompile Include="..\src\char\int_clan.c">
+      <Filter>char</Filter>
+    </ClCompile>
     <ClCompile Include="..\src\char\int_elemental.c">
       <Filter>char</Filter>
     </ClCompile>
@@ -203,6 +206,9 @@
     </ClInclude>
     <ClInclude Include="..\src\char\int_auction.h">
       <Filter>char</Filter>
+    </ClInclude>
+	<ClInclude Include="..\src\char\int_clan.h">
+      <Filter>char</Filter>
     </ClInclude>
     <ClInclude Include="..\src\char\int_elemental.h">
       <Filter>char</Filter>

+ 2 - 0
vcproj-12/map-server.vcxproj

@@ -172,6 +172,7 @@
     <ClInclude Include="..\src\map\channel.h" />
     <ClInclude Include="..\src\map\chat.h" />
     <ClInclude Include="..\src\map\chrif.h" />
+	<ClInclude Include="..\src\map\clan.h" />
     <ClInclude Include="..\src\map\clif.h" />
     <ClInclude Include="..\src\map\date.h" />
     <ClInclude Include="..\src\map\duel.h" />
@@ -247,6 +248,7 @@
     <ClCompile Include="..\src\map\channel.c" />
     <ClCompile Include="..\src\map\chat.c" />
     <ClCompile Include="..\src\map\chrif.c" />
+    <ClCompile Include="..\src\map\clan.c" />
     <ClCompile Include="..\src\map\clif.c" />
     <ClCompile Include="..\src\map\date.c" />
     <ClCompile Include="..\src\map\duel.c" />

+ 6 - 0
vcproj-12/map-server.vcxproj.filters

@@ -25,6 +25,9 @@
     <ClCompile Include="..\src\map\chrif.c">
       <Filter>map</Filter>
     </ClCompile>
+    <ClCompile Include="..\src\map\clan.c">
+      <Filter>map</Filter>
+    </ClCompile>
     <ClCompile Include="..\src\map\clif.c">
       <Filter>map</Filter>
     </ClCompile>
@@ -233,6 +236,9 @@
     </ClInclude>
     <ClInclude Include="..\src\map\chrif.h">
       <Filter>map</Filter>
+    </ClInclude>
+	<ClInclude Include="..\src\map\clan.h">
+      <Filter>map</Filter>
     </ClInclude>
     <ClInclude Include="..\src\map\clif.h">
       <Filter>map</Filter>

+ 2 - 0
vcproj-13/char-server.vcxproj

@@ -167,6 +167,7 @@
     <ClInclude Include="..\src\char\char_logif.h" />
     <ClInclude Include="..\src\char\char_mapif.h" />
     <ClInclude Include="..\src\char\int_auction.h" />
+    <ClInclude Include="..\src\char\int_clan.h" />
     <ClInclude Include="..\src\char\int_elemental.h" />
     <ClInclude Include="..\src\char\int_guild.h" />
     <ClInclude Include="..\src\char\int_homun.h" />
@@ -213,6 +214,7 @@
     <ClCompile Include="..\src\char\char_logif.c" />
     <ClCompile Include="..\src\char\char_mapif.c" />
     <ClCompile Include="..\src\char\int_auction.c" />
+    <ClCompile Include="..\src\char\int_clan.c" />
     <ClCompile Include="..\src\char\int_elemental.c" />
     <ClCompile Include="..\src\char\int_guild.c" />
     <ClCompile Include="..\src\char\int_homun.c" />

+ 6 - 0
vcproj-13/char-server.vcxproj.filters

@@ -64,6 +64,9 @@
     <ClCompile Include="..\src\char\int_auction.c">
       <Filter>char</Filter>
     </ClCompile>
+    <ClCompile Include="..\src\char\int_clan.c">
+      <Filter>char</Filter>
+    </ClCompile>
     <ClCompile Include="..\src\char\int_elemental.c">
       <Filter>char</Filter>
     </ClCompile>
@@ -201,6 +204,9 @@
     <ClInclude Include="..\src\char\int_auction.h">
       <Filter>char</Filter>
     </ClInclude>
+    <ClInclude Include="..\src\char\int_clan.h">
+      <Filter>char</Filter>
+    </ClInclude>
     <ClInclude Include="..\src\char\int_elemental.h">
       <Filter>char</Filter>
     </ClInclude>

+ 2 - 0
vcproj-13/map-server.vcxproj

@@ -172,6 +172,7 @@
     <ClInclude Include="..\src\map\channel.h" />
     <ClInclude Include="..\src\map\chat.h" />
     <ClInclude Include="..\src\map\chrif.h" />
+    <ClInclude Include="..\src\map\clan.h" />
     <ClInclude Include="..\src\map\clif.h" />
     <ClInclude Include="..\src\map\date.h" />
     <ClInclude Include="..\src\map\duel.h" />
@@ -247,6 +248,7 @@
     <ClCompile Include="..\src\map\channel.c" />
     <ClCompile Include="..\src\map\chat.c" />
     <ClCompile Include="..\src\map\chrif.c" />
+    <ClCompile Include="..\src\map\clan.c" />
     <ClCompile Include="..\src\map\clif.c" />
     <ClCompile Include="..\src\map\date.c" />
     <ClCompile Include="..\src\map\duel.c" />

+ 6 - 0
vcproj-13/map-server.vcxproj.filters

@@ -25,6 +25,9 @@
     <ClCompile Include="..\src\map\chrif.c">
       <Filter>map</Filter>
     </ClCompile>
+    <ClCompile Include="..\src\map\clan.c">
+      <Filter>map</Filter>
+    </ClCompile>
     <ClCompile Include="..\src\map\clif.c">
       <Filter>map</Filter>
     </ClCompile>
@@ -234,6 +237,9 @@
     <ClInclude Include="..\src\map\chrif.h">
       <Filter>map</Filter>
     </ClInclude>
+    <ClInclude Include="..\src\map\clan.h">
+      <Filter>map</Filter>
+    </ClInclude>
     <ClInclude Include="..\src\map\clif.h">
       <Filter>map</Filter>
     </ClInclude>

+ 2 - 0
vcproj-14/char-server.vcxproj

@@ -165,6 +165,7 @@
     <ClInclude Include="..\src\char\char_logif.h" />
     <ClInclude Include="..\src\char\char_mapif.h" />
     <ClInclude Include="..\src\char\int_auction.h" />
+    <ClInclude Include="..\src\char\int_clan.h" />
     <ClInclude Include="..\src\char\int_elemental.h" />
     <ClInclude Include="..\src\char\int_guild.h" />
     <ClInclude Include="..\src\char\int_homun.h" />
@@ -211,6 +212,7 @@
     <ClCompile Include="..\src\char\char_logif.c" />
     <ClCompile Include="..\src\char\char_mapif.c" />
     <ClCompile Include="..\src\char\int_auction.c" />
+    <ClCompile Include="..\src\char\int_clan.c" />
     <ClCompile Include="..\src\char\int_elemental.c" />
     <ClCompile Include="..\src\char\int_guild.c" />
     <ClCompile Include="..\src\char\int_homun.c" />

+ 6 - 0
vcproj-14/char-server.vcxproj.filters

@@ -64,6 +64,9 @@
     <ClCompile Include="..\src\char\int_auction.c">
       <Filter>char</Filter>
     </ClCompile>
+    <ClCompile Include="..\src\char\int_clan.c">
+      <Filter>char</Filter>
+    </ClCompile>
     <ClCompile Include="..\src\char\int_elemental.c">
       <Filter>char</Filter>
     </ClCompile>
@@ -201,6 +204,9 @@
     <ClInclude Include="..\src\char\int_auction.h">
       <Filter>char</Filter>
     </ClInclude>
+    <ClInclude Include="..\src\char\int_clan.h">
+      <Filter>char</Filter>
+    </ClInclude>
     <ClInclude Include="..\src\char\int_elemental.h">
       <Filter>char</Filter>
     </ClInclude>

+ 2 - 0
vcproj-14/map-server.vcxproj

@@ -170,6 +170,7 @@
     <ClInclude Include="..\src\map\channel.h" />
     <ClInclude Include="..\src\map\chat.h" />
     <ClInclude Include="..\src\map\chrif.h" />
+    <ClInclude Include="..\src\map\clan.h" />
     <ClInclude Include="..\src\map\clif.h" />
     <ClInclude Include="..\src\map\date.h" />
     <ClInclude Include="..\src\map\duel.h" />
@@ -245,6 +246,7 @@
     <ClCompile Include="..\src\map\channel.c" />
     <ClCompile Include="..\src\map\chat.c" />
     <ClCompile Include="..\src\map\chrif.c" />
+    <ClCompile Include="..\src\map\clan.c" />
     <ClCompile Include="..\src\map\clif.c" />
     <ClCompile Include="..\src\map\date.c" />
     <ClCompile Include="..\src\map\duel.c" />

+ 6 - 0
vcproj-14/map-server.vcxproj.filters

@@ -25,6 +25,9 @@
     <ClCompile Include="..\src\map\chrif.c">
       <Filter>map</Filter>
     </ClCompile>
+    <ClCompile Include="..\src\map\clan.c">
+      <Filter>map</Filter>
+    </ClCompile>
     <ClCompile Include="..\src\map\clif.c">
       <Filter>map</Filter>
     </ClCompile>
@@ -234,6 +237,9 @@
     <ClInclude Include="..\src\map\chrif.h">
       <Filter>map</Filter>
     </ClInclude>
+    <ClInclude Include="..\src\map\clan.h">
+      <Filter>map</Filter>
+    </ClInclude>
     <ClInclude Include="..\src\map\clif.h">
       <Filter>map</Filter>
     </ClInclude>

+ 8 - 0
vcproj-9/char-server.vcproj

@@ -496,6 +496,14 @@
 				RelativePath="..\src\char\int_auction.h"
 				>
 			</File>
+			<File
+				RelativePath="..\src\char\int_clan.c"
+				>
+			</File>
+			<File
+				RelativePath="..\src\char\int_clan.h"
+				>
+			</File>
 			<File
 				RelativePath="..\src\char\int_elemental.c"
 				>

+ 8 - 0
vcproj-9/map-server.vcproj

@@ -536,6 +536,14 @@
 				RelativePath="..\src\map\chrif.h"
 				>
 			</File>
+			<File
+				RelativePath="..\src\map\clan.c"
+				>
+			</File>
+			<File
+				RelativePath="..\src\map\clan.h"
+				>
+			</File>
 			<File
 				RelativePath="..\src\map\clif.c"
 				>