Browse Source

* Fixed more typos in /cities/payon.txt
* Added 2 char-server packets to support Freya's login server
* Rewrite on Full Strip

git-svn-id: https://svn.code.sf.net/p/rathena/svn/branches/stable@1243 54d463be-8e91-2dee-dedb-b68131a5f0ec

celest 20 năm trước cách đây
mục cha
commit
f4b515d055
6 tập tin đã thay đổi với 243 bổ sung23 xóa
  1. 2 0
      Changelog-SVN.txt
  2. 3 0
      npc/Changelog.txt
  3. 18 11
      npc/cities/payon.txt
  4. 87 0
      src/char/char.c
  5. 87 0
      src/char_sql/char.c
  6. 46 12
      src/map/skill.c

+ 2 - 0
Changelog-SVN.txt

@@ -1,6 +1,8 @@
 Date	Added
 
 03/17
+        * Added 2 char-server packets to support Freya's login server [celest]
+        * Rewrite on Full Strip [celest]
 	* Fixed heap corrupion in map.c caused while loading maps 
 	  [SVN 1241: MouseJstr]
         * Re-fixed compile error in map.c -- sorry ^^; [celest]

+ 3 - 0
npc/Changelog.txt

@@ -35,6 +35,9 @@ Other Ppl
 Date		Added
 ======
 
+03/17
+        * Fixed more typos in /cities/payon.txt, thanks to TheUltimateEnd [celest]
+
 03/16
         * Fixed some typos in /cites/payon.txt, thanks to Hibiki [celest]
 

+ 18 - 11
npc/cities/payon.txt

@@ -6,13 +6,14 @@
 //= Muad Dib (1.2)
 //= Darkchild (1.3)
 //===== Current Version: ===================================== 
-//= 1.3
+//= 1.4
 //===== Compatible With: ===================================== 
 //= Any eAthena Mod
 //===== Description: ========================================= 
 //= (New) Payon City Npcs
 //===== Additional Comments: ================================= 
 //= Most Credits To Muad Dib, Some Stuff By Me
+//= 1.4 - Corrected a few typos
 //============================================================ 
 
 payon.gat,190,115,0	script	Lady	90,{
@@ -82,23 +83,25 @@ payon_in01.gat,180,7,0	script	Waitress	90,{
 	next;
 	mes "[Waitress]";
 	mes "Where can I find the right person who is a really hot, sexy hunk, and who can take me out of this small place?";
-	   check Gender = 1,-,LStartF;
-  	mes "[Waitress]";
-  	mes "Hello, mister?";
+	if(Sex == 0) goto LStartF;
+	mes "[Waitress]";
+	mes "Hello, mister?";
+	goto L_Start;
 LStartF:
    	mes "[Waitress]";
    	mes "Hello, lady?";
+L_Start:
 	next;
 	mes "[Waitress]";
 	mes "Grandma the fortuneteller told me that I would meet great luck in the near future!"; 
 	mes "But look at me, what's wrong with me!! I am leaving a managable life everyday!!";
 	mes "Oh..boy. What a dumb wishy-washy person I am.";
-	   emotion 6;
+	emotion 6;
 	next;
 	mes "[Waitress]";
 	mes "I am so sorry, I should haven't said this to you. Now I am acting like i'm stupid.";  
  	mes "I am sorry dear, please forgive my misbehaviour.";
-	   emotion 4;
+	emotion 4;
 	next;
 	mes "[Waitress]";
 	mes "So, how may I help you? ";
@@ -124,7 +127,7 @@ L_Menu2:
 	   emotion 5;
  	next;
 	mes "[Waitress]";
-	mes "On the first place, she stayed here to mind her business, but ever since the chief recognized her talent, she's stayed in the central palace."
+	mes "On the first place, she stayed here to mind her business, but ever since the chief recognized her talent, she's stayed in the central palace.";
 	mes "You'd better go to there if you want to see her.";
 	close;
 L_Menu3:
@@ -165,16 +168,18 @@ payon.gat,193,116,1	script	Woman	66,{
 	mes "Hmm... you look as strong as a Rocker! How many monsters have you killed?";
 	mes "Let me tell you about a place where you can go train and become even stronger.";
 	   emotion 20;
+	goto L_Start;
 LStartF:
 	mes "Miss, how many monsters have you killed?";
 	mes "I know a very good place for you to go train and get good monster drops.";
 	   emotion 20;
+L_Start:
     	next;
     	mes "[Woman]";
 	mes "I know of a cave near Archer Village.  Just take the exit north of town and follow the path to your left.";
     	mes "The cave is full of monsters and their spawn rate is very high.  Does it sound interesting to you?";
       next;
-      menu "It sounds dangerous."L_Menu1,"I think I need to fully prepare for that place.",L_Menu2,"Lady, you wear nice clothing~",L_Menu3;
+      menu "It sounds dangerous.",L_Menu1,"I think I need to fully prepare for that place.",L_Menu2,"Lady, you wear nice clothing~",L_Menu3;
 L_Menu1:
 	mes "[Woman]";
 	mes "Oh don't be such a coward! It's just a simple cave filled with normal monsters.  Archer Village is near by so you shouldn't be worried~ hohoho~";
@@ -214,12 +219,14 @@ payon.gat,190,119,5	script	Woman	66,{
 	mes "Anyway, you look like a new face.  Are you new in town?";
 	next;
 	mes "[Jim's Mother]";
-	  if(Sex == 0) goto LStartF;
+	if(Sex == 0) goto LStartF;
 	mes "... Oh, you have broad shoulders ... tehehe! Will you go out with me? I'd like to make you a nice dinner...(bats eyelashes)";
-	   emotion 30;
+	emotion 30;
+	goto L_Menu;
 LStartF:
 	mes "Don't you think your dress is too lousy?";
 	mes "I don't like young ladies pounce up.";
+L_Menu:
 	next;
 	menu "Fortune Telling?",L_Menu1,"...Good Bye.",L_Menu2;
 L_Menu1:
@@ -401,7 +408,7 @@ L_case:
 	menu "Cave?!",L_para1,"Chief?",L_para2,"Oh man I hate this stupid town~",L_para3;
 L_para1:
 	mes "[Archer Wolt]";
-	mes "Head north of town, you can see the cave I told you about."
+	mes "Head north of town, you can see the cave I told you about.";
 	mes "Inside there, you will encounter lots of ugly monsters such as bastard looking like a bat or the walking dead.";
 	mes "If we let them out of the place, they would invade our town. We frequently clean up the cave.";
 	next;

+ 87 - 0
src/char/char.c

@@ -1703,6 +1703,35 @@ int parse_tologin(int fd) {
 			RFIFOSKIP(fd,2);
 			break;
 
+		// Receiving authentification from Freya-type login server (to avoid char->login->char)
+		case 0x2719:
+			if (RFIFOREST(fd) < 18)
+				return 0;
+			// to conserv a maximum of authentification, search if account is already authentified and replace it
+			// that will reduce multiple connection too
+			for(i = 0; i < AUTH_FIFO_SIZE; i++)
+				if (auth_fifo[i].account_id == RFIFOL(fd,2))
+					break;
+			// if not found, use next value
+			if (i == AUTH_FIFO_SIZE) {
+				if (auth_fifo_pos >= AUTH_FIFO_SIZE)
+					auth_fifo_pos = 0;
+				i = auth_fifo_pos;
+				auth_fifo_pos++;
+			}
+			//printf("auth_fifo set (auth #%d) - account: %d, secure: %08x-%08x\n", i, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10));
+			auth_fifo[i].account_id = RFIFOL(fd,2);
+			auth_fifo[i].char_id = 0;
+			auth_fifo[i].login_id1 = RFIFOL(fd,6);
+			auth_fifo[i].login_id2 = RFIFOL(fd,10);
+			auth_fifo[i].delflag = 2; // 0: auth_fifo canceled/void, 2: auth_fifo received from login/map server in memory, 1: connection authentified
+			auth_fifo[i].char_pos = 0;
+			auth_fifo[i].connect_until_time = 0; // unlimited/unknown time by default (not display in map-server)
+			auth_fifo[i].ip = RFIFOL(fd,14);
+			//auth_fifo[i].map_auth = 0;
+			RFIFOSKIP(fd,18);
+			break;
+
 		case 0x2721:	// gm reply
 			if (RFIFOREST(fd) < 10)
 				return 0;
@@ -1965,6 +1994,64 @@ int parse_tologin(int fd) {
 			RFIFOSKIP(fd,RFIFOW(fd,2));
 			break;
 
+		// Receive GM accounts [Freya login server packet by Yor]
+		case 0x2733:
+		// add test here to remember that the login-server is Freya-type
+		// sprintf (login_server_type, "Freya");
+			if (RFIFOREST(fd) < 7)
+				return 0;
+			{
+				unsigned char buf[32000];
+				int new_level = 0;
+				for(i = 0; i < GM_num; i++)
+					if (gm_account[i].account_id == RFIFOL(fd,2)) {
+						if (gm_account[i].level != (int)RFIFOB(fd,6)) {
+							gm_account[i].level = (int)RFIFOB(fd,6);
+							new_level = 1;
+						}
+						break;
+					}
+				// if not found, add it
+				if (i == GM_num) {
+					// limited to 4000, because we send information to char-servers (more than 4000 GM accounts???)
+					// int (id) + int (level) = 8 bytes * 4000 = 32k (limit of packets in windows)
+					if (((int)RFIFOB(fd,6)) > 0 && GM_num < 4000) {
+						if (GM_num == 0) {
+							gm_account = (struct gm_account*)aMalloc(sizeof(struct gm_account));
+						} else {
+							gm_account = (struct gm_account*)aRealloc(gm_account, sizeof(struct gm_account) * (GM_num + 1));						
+						}
+						gm_account[GM_num].account_id = RFIFOL(fd,2);
+						gm_account[GM_num].level = (int)RFIFOB(fd,6);
+						new_level = 1;
+						GM_num++;
+						if (GM_num >= 4000) {
+							printf("***WARNING: 4000 GM accounts found. Next GM accounts are not readed.\n");
+							char_log("***WARNING: 4000 GM accounts found. Next GM accounts are not readed." RETCODE);
+						}
+					}
+				}
+				if (new_level == 1) {
+					int len;
+					printf("From login-server: receiving a GM account information (%d: level %d).\n", RFIFOL(fd,2), (int)RFIFOB(fd,6));
+					char_log("From login-server: receiving a GM account information (%d: level %d)." RETCODE, RFIFOL(fd,2), (int)RFIFOB(fd,6));
+					//create_online_files(); // not change online file for only 1 player (in next timer, that will be done
+					// send gm acccounts level to map-servers
+					len = 4;
+					WBUFW(buf,0) = 0x2b15;
+				
+					for(i = 0; i < GM_num; i++) {
+						WBUFL(buf, len) = gm_account[i].account_id;
+						WBUFB(buf, len+4) = (unsigned char)gm_account[i].level;
+						len += 5;
+					}
+					WBUFW(buf, 2) = len;
+					mapif_sendall(buf, len);
+				}
+			}
+			RFIFOSKIP(fd,7);
+			break;
+
 		default:
 			printf("parse_tologin: unknown packet %x! \n", RFIFOW(fd,0));
 			session[fd]->eof = 1;

+ 87 - 0
src/char_sql/char.c

@@ -1555,6 +1555,35 @@ int parse_tologin(int fd) {
 			RFIFOSKIP(fd,2);
 			break;
 
+		// Receiving authentification from Freya-type login server (to avoid char->login->char)
+		case 0x2719:
+			if (RFIFOREST(fd) < 18)
+				return 0;
+			// to conserv a maximum of authentification, search if account is already authentified and replace it
+			// that will reduce multiple connection too
+			for(i = 0; i < AUTH_FIFO_SIZE; i++)
+				if (auth_fifo[i].account_id == RFIFOL(fd,2))
+					break;
+			// if not found, use next value
+			if (i == AUTH_FIFO_SIZE) {
+				if (auth_fifo_pos >= AUTH_FIFO_SIZE)
+					auth_fifo_pos = 0;
+				i = auth_fifo_pos;
+				auth_fifo_pos++;
+			}
+			//printf("auth_fifo set (auth #%d) - account: %d, secure: %08x-%08x\n", i, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10));
+			auth_fifo[i].account_id = RFIFOL(fd,2);
+			auth_fifo[i].char_id = 0;
+			auth_fifo[i].login_id1 = RFIFOL(fd,6);
+			auth_fifo[i].login_id2 = RFIFOL(fd,10);
+			auth_fifo[i].delflag = 2; // 0: auth_fifo canceled/void, 2: auth_fifo received from login/map server in memory, 1: connection authentified
+			auth_fifo[i].char_pos = 0;
+			auth_fifo[i].connect_until_time = 0; // unlimited/unknown time by default (not display in map-server)
+			auth_fifo[i].ip = RFIFOL(fd,14);
+			//auth_fifo[i].map_auth = 0;
+			RFIFOSKIP(fd,18);
+			break;
+
 /*		case 0x2721:	// gm reply. I don't want to support this function.
 			printf("0x2721:GM reply\n");
 		  {
@@ -1707,6 +1736,64 @@ int parse_tologin(int fd) {
 			RFIFOSKIP(fd,11);
 			break;
 
+		// Receive GM accounts [Freya login server packet by Yor]
+		case 0x2733:
+		// add test here to remember that the login-server is Freya-type
+		// sprintf (login_server_type, "Freya");
+			if (RFIFOREST(fd) < 7)
+				return 0;
+			{
+				unsigned char buf[32000];
+				int new_level = 0;
+				for(i = 0; i < GM_num; i++)
+					if (gm_account[i].account_id == RFIFOL(fd,2)) {
+						if (gm_account[i].level != (int)RFIFOB(fd,6)) {
+							gm_account[i].level = (int)RFIFOB(fd,6);
+							new_level = 1;
+						}
+						break;
+					}
+				// if not found, add it
+				if (i == GM_num) {
+					// limited to 4000, because we send information to char-servers (more than 4000 GM accounts???)
+					// int (id) + int (level) = 8 bytes * 4000 = 32k (limit of packets in windows)
+					if (((int)RFIFOB(fd,6)) > 0 && GM_num < 4000) {
+						if (GM_num == 0) {
+							gm_account = (struct gm_account*)aMalloc(sizeof(struct gm_account));
+						} else {
+							gm_account = (struct gm_account*)aRealloc(gm_account, sizeof(struct gm_account) * (GM_num + 1));						
+						}
+						gm_account[GM_num].account_id = RFIFOL(fd,2);
+						gm_account[GM_num].level = (int)RFIFOB(fd,6);
+						new_level = 1;
+						GM_num++;
+						if (GM_num >= 4000) {
+							printf("***WARNING: 4000 GM accounts found. Next GM accounts are not readed.\n");
+							char_log("***WARNING: 4000 GM accounts found. Next GM accounts are not readed." RETCODE);
+						}
+					}
+				}
+				if (new_level == 1) {
+					int len;
+					printf("From login-server: receiving a GM account information (%d: level %d).\n", RFIFOL(fd,2), (int)RFIFOB(fd,6));
+					char_log("From login-server: receiving a GM account information (%d: level %d)." RETCODE, RFIFOL(fd,2), (int)RFIFOB(fd,6));
+					//create_online_files(); // not change online file for only 1 player (in next timer, that will be done
+					// send gm acccounts level to map-servers
+					len = 4;
+					WBUFW(buf,0) = 0x2b15;
+				
+					for(i = 0; i < GM_num; i++) {
+						WBUFL(buf, len) = gm_account[i].account_id;
+						WBUFB(buf, len+4) = (unsigned char)gm_account[i].level;
+						len += 5;
+					}
+					WBUFW(buf, 2) = len;
+					mapif_sendall(buf, len);
+				}
+			}
+			RFIFOSKIP(fd,7);
+			break;
+
 		default:
 			printf("set eof.\n");
 			session[fd]->eof = 1;

+ 46 - 12
src/map/skill.c

@@ -1247,7 +1247,7 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
 		return 0;
 	if(src->type == BL_PC && pc_isdead((struct map_session_data *)src)) //術者?がPCですでに死んでいたら何もしない
 		return 0;
-	if(dsrc->type == BL_PC && pc_isdead((struct map_session_data *)dsrc)) //術者?がPCですでに死んでいたら何もしない
+	if(src != dsrc && dsrc->type == BL_PC && pc_isdead((struct map_session_data *)dsrc)) //術者?がPCですでに死んでいたら何もしない
 		return 0;
 	if(bl->type == BL_PC && pc_isdead((struct map_session_data *)bl)) //?象がPCですでに死んでいたら何もしない
 		return 0;
@@ -2751,7 +2751,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
 	struct mob_data *md=NULL;
 	struct mob_data *dstmd=NULL;
 	int i,abra_skillid=0,abra_skilllv;
-	int sc_def_vit,sc_def_mdef,strip_time,strip_per;
+	int sc_def_vit,sc_def_mdef;
 	int sc_dex,sc_luk;
 	//クラスチェンジ用ボスモンスタ?ID
 	int changeclass[]={1038,1039,1046,1059,1086,1087,1112,1115
@@ -3777,10 +3777,12 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
 	case RG_STRIPSHIELD:		/* ストリップシールド */
 	case RG_STRIPARMOR:			/* ストリップアーマー */
 	case RG_STRIPHELM:			/* ストリップヘルム */
-	case ST_FULLSTRIP:	// Celest
 	{
-		struct status_change *tsc_data = status_get_sc_data(bl);
-		int scid, cp_scid = 0, equip, strip_fix, strip_num = 0;
+		struct status_change *tsc_data;
+		int strip_time, strip_per, strip_fix;
+		int scid, cp_scid = 0, equip;
+
+		tsc_data = status_get_sc_data(bl);
 		scid = SkillStatusChangeTable[skillid];
 		switch (skillid) {
 			case RG_STRIPWEAPON:
@@ -3799,17 +3801,13 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
 				equip = EQP_HELM;
 				cp_scid = SC_CP_HELM;
 				break;
-			case ST_FULLSTRIP:
-				equip = EQP_WEAPON | EQP_SHIELD | EQP_ARMOR | EQP_HELM;
-				strip_num = 3;
-				break;
 			default:
 				map_freeblock_unlock();
 				return 1;
 		}
 
 		if (tsc_data && (tsc_data[scid].timer != -1 || tsc_data[cp_scid].timer != -1))
-				break;
+			break;
 		if (dstsd && dstsd->unstripable_equip & equip)
 			break;
 
@@ -3824,8 +3822,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
 			for (i=0;i<MAX_INVENTORY;i++) {
 				if (dstsd->status.inventory[i].equip && (dstsd->status.inventory[i].equip & equip)){
 					pc_unequipitem(dstsd,i,3);
-					if ((--strip_num) <= 0)
-						break;
+					break;
 				}
 			}
 			if (i == MAX_INVENTORY)
@@ -3836,6 +3833,43 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
 		status_change_start(bl,scid,skilllv,0,0,0,strip_time,0 );
 		break;
 	}
+	case ST_FULLSTRIP:	// Celest
+	{
+		struct status_change *tsc_data;
+		int i, j, strip_time, strip_per, strip_fix;
+		int equip[4] = { EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HELM };
+		int scid[4] = { SC_STRIPWEAPON, SC_STRIPSHIELD, SC_STRIPARMOR, SC_STRIPHELM };
+		int cp_scid[4] = { SC_CP_WEAPON, SC_CP_SHIELD, SC_CP_ARMOR, SC_CP_HELM };
+		
+		tsc_data = status_get_sc_data(bl);
+		strip_fix = status_get_dex(src) - status_get_dex(bl);
+		if(strip_fix < 0)
+			strip_fix = 0;
+		strip_per = 5+2*skilllv+strip_fix/5;
+		if (rand()%100 >= strip_per)
+			break;
+		strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
+
+		for (i=0; i<4; i++) {
+			if (dstsd) {
+				if (tsc_data && (tsc_data[scid[i]].timer != -1 || tsc_data[cp_scid[i]].timer != -1))
+					continue;
+				if (dstsd->unstripable_equip & equip[i])
+					continue;
+				for (j=0; j<MAX_INVENTORY; j++) {
+					if (dstsd->status.inventory[j].equip && (dstsd->status.inventory[j].equip & equip[i])){
+						pc_unequipitem(dstsd,j,3);
+						break;
+					}
+				}
+				if (j == MAX_INVENTORY)
+					continue;
+			}
+			status_change_start(bl,scid[i],skilllv,0,0,0,strip_time,0 );
+		}
+		clif_skill_nodamage(src,bl,skillid,skilllv,1);
+		break;
+	}
 
 	/* PotionPitcher */
 	case AM_POTIONPITCHER:		/* ポ?ションピッチャ? */