viewing paste ra_rawdiff | Diff

Posted on the
  1. Index: src/login/login.c
  2. ===================================================================
  3. --- src/login/login.c	(revision 17365)
  4. +++ src/login/login.c	(working copy)
  5. @@ -567,6 +567,7 @@
  6.  				char birthdate[10+1] = "";
  7.  				char pincode[PINCODE_LENGTH+1];
  8.  				int account_id = RFIFOL(fd,2);
  9. +				int cl_version = 0;
  10.  
  11.  				memset(pincode,0,PINCODE_LENGTH+1);
  12.  
  13. @@ -575,15 +576,18 @@
  14.  				if( !accounts->load_num(accounts, &acc, account_id) )
  15.  					ShowNotice("Char-server '%s': account %d NOT found (ip: %s).\n", server[id].name, account_id, ip);
  16.  				else{
  17. +					struct auth_node *node = (struct auth_node*)idb_get(auth_db, account_id);
  18.  					safestrncpy(email, acc.email, sizeof(email));
  19.  					expiration_time = acc.expiration_time;
  20.  					group_id = acc.group_id;
  21.  					char_slots = acc.char_slots;
  22.  					safestrncpy(birthdate, acc.birthdate, sizeof(birthdate));
  23.  					safestrncpy(pincode, acc.pincode, sizeof(pincode));
  24. +					if(node) cl_version = node->version;
  25. +					ShowInfo("login R_0x2716, S_0x2717 version = %d, node=%d\n",cl_version,node);
  26.  				}
  27.  
  28. -				WFIFOHEAD(fd,72);
  29. +				WFIFOHEAD(fd,73);
  30.  				WFIFOW(fd,0) = 0x2717;
  31.  				WFIFOL(fd,2) = account_id;
  32.  				safestrncpy((char*)WFIFOP(fd,6), email, 40);
  33. @@ -593,13 +597,13 @@
  34.  				safestrncpy((char*)WFIFOP(fd,52), birthdate, 10+1);
  35.  				safestrncpy((char*)WFIFOP(fd,63), pincode, 4+1 );
  36.  				WFIFOL(fd,68) = (uint32)acc.pincode_change;
  37. -				WFIFOSET(fd,72);
  38. +				WFIFOB(fd,72) = cl_version;
  39. +				WFIFOSET(fd,73);
  40.  			}
  41.  		break;
  42.  
  43.  		case 0x2719: // ping request from charserver
  44.  			RFIFOSKIP(fd,2);
  45. -
  46.  			WFIFOHEAD(fd,2);
  47.  			WFIFOW(fd,0) = 0x2718;
  48.  			WFIFOSET(fd,2);
  49. @@ -1270,10 +1274,8 @@
  50.  
  51.  	{
  52.  		struct online_login_data* data;
  53. -
  54.  		// mark client as 'online'
  55.  		data = add_online_user(-1, sd->account_id);
  56. -
  57.  		// schedule deletion of this node
  58.  		data->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, waiting_disconnect_timer, sd->account_id, 0);
  59.  	}
  60. Index: src/map/status.c
  61. ===================================================================
  62. --- src/map/status.c	(revision 17365)
  63. +++ src/map/status.c	(working copy)
  64. @@ -49,10 +49,12 @@
  65.  };
  66.  
  67.  static int max_weight_base[CLASS_COUNT];
  68. -static int hp_coefficient[CLASS_COUNT];
  69. -static int hp_coefficient2[CLASS_COUNT];
  70. -static int hp_sigma_val[CLASS_COUNT][MAX_LEVEL+1];
  71. -static int sp_coefficient[CLASS_COUNT];
  72. +static struct {
  73. +	int hp_table[MAX_LEVEL];
  74. +	int sp_table[MAX_LEVEL];
  75. +	int max_level;
  76. +} hpsp_info[CLASS_COUNT];
  77. +
  78.  #ifdef RENEWAL_ASPD
  79.  static int aspd_base[CLASS_COUNT][MAX_WEAPON_TYPE+1];
  80.  #else
  81. @@ -2239,39 +2241,11 @@
  82.  	return 1;
  83.  }
  84.  
  85. -/// Helper function for status_base_pc_maxhp(), used to pre-calculate the hp_sigma_val[] array
  86. -static void status_calc_sigma(void)
  87. -{
  88. -	int i,j;
  89. -
  90. -	for(i = 0; i < CLASS_COUNT; i++)
  91. -	{
  92. -		unsigned int k = 0;
  93. -		hp_sigma_val[i][0] = hp_sigma_val[i][1] = 0;
  94. -		for(j = 2; j <= MAX_LEVEL; j++)
  95. -		{
  96. -			k += (hp_coefficient[i]*j + 50) / 100;
  97. -			hp_sigma_val[i][j] = k;
  98. -			if (k >= INT_MAX)
  99. -				break; //Overflow protection. [Skotlex]
  100. -		}
  101. -		for(; j <= MAX_LEVEL; j++)
  102. -			hp_sigma_val[i][j] = INT_MAX;
  103. -	}
  104. -}
  105. -
  106. -/// Calculates base MaxHP value according to class and base level
  107. -/// The recursive equation used to calculate level bonus is (using integer operations)
  108. -///    f(0) = 35 | f(x+1) = f(x) + A + (x + B)*C/D
  109. -/// which reduces to something close to
  110. -///    f(x) = 35 + x*(A + B*C/D) + sum(i=2..x){ i*C/D }
  111. +//Calculate maxHP from tables
  112.  static unsigned int status_base_pc_maxhp(struct map_session_data* sd, struct status_data* status)
  113.  {
  114. -	uint64 val = pc_class2idx(sd->status.class_);
  115. -	val = 35 + sd->status.base_level*(int64)hp_coefficient2[val]/100 + hp_sigma_val[val][sd->status.base_level];
  116. +	uint32 val = hpsp_info[pc_class2idx(sd->status.class_)].hp_table[sd->status.base_level-1];
  117.  
  118. -	if((sd->class_&MAPID_UPPERMASK) == MAPID_NINJA || (sd->class_&MAPID_UPPERMASK) == MAPID_GUNSLINGER)
  119. -		val += 100; //Since their HP can't be approximated well enough without this.
  120.  	if((sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc_famerank(sd->status.char_id, MAPID_TAEKWON))
  121.  		val *= 3; //Triple max HP for top ranking Taekwons over level 90.
  122.  	if((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.base_level >= 99)
  123. @@ -2286,11 +2260,11 @@
  124.  	return (unsigned int)val;
  125.  }
  126.  
  127. +//Calculate maxSP from tables
  128.  static unsigned int status_base_pc_maxsp(struct map_session_data* sd, struct status_data *status)
  129.  {
  130. -	uint64 val;
  131. +	uint32 val = hpsp_info[pc_class2idx(sd->status.class_)].sp_table[sd->status.base_level-1];
  132.  
  133. -	val = 10 + sd->status.base_level*(int64)sp_coefficient[pc_class2idx(sd->status.class_)]/100;
  134.  	val += val * status->int_/100;
  135.  
  136.  	if (sd->class_&JOBL_UPPER)
  137. @@ -3950,8 +3924,8 @@
  138.  				status->matk_max += sd->bonus.ematk;
  139.  				status->matk_min += sd->bonus.ematk;
  140.  			}
  141. -            status->matk_min = status_calc_ematk(bl, sc, status->matk_min);
  142. -            status->matk_max = status_calc_ematk(bl, sc, status->matk_max);
  143. +			status->matk_min = status_calc_ematk(bl, sc, status->matk_min);
  144. +			status->matk_max = status_calc_ematk(bl, sc, status->matk_max);
  145.  			//This is the only portion in MATK that varies depending on the weapon level and refinement rate.
  146.  			if( status->rhw.matk > 0 ){
  147.  				int wMatk = status->rhw.matk;
  148. @@ -3961,17 +3935,19 @@
  149.  			}
  150.  		}
  151.  #endif
  152. -        if (bl->type&BL_PC && sd->matk_rate != 100) {
  153. +		if (bl->type&BL_PC && sd->matk_rate != 100) {
  154.  			status->matk_max = status->matk_max * sd->matk_rate/100;
  155.  			status->matk_min = status->matk_min * sd->matk_rate/100;
  156.  		}
  157.  
  158. -		status->matk_min = status_calc_matk(bl, sc, status->matk_min);
  159. +
  160.  		status->matk_max = status_calc_matk(bl, sc, status->matk_max);
  161.  
  162. -        if ((bl->type&BL_HOM && battle_config.hom_setting&0x20)  //Hom Min Matk is always the same as Max Matk
  163. -			|| sc->data[SC_RECOGNIZEDSPELL])
  164. -            status->matk_min = status->matk_max;
  165. +		if ((bl->type&BL_HOM && battle_config.hom_setting&0x20)  //Hom Min Matk is always the same as Max Matk
  166. +				|| (sc && sc->data[SC_RECOGNIZEDSPELL]))
  167. +			status->matk_min = status->matk_max;
  168. +		else
  169. +			status->matk_min = status_calc_matk(bl, sc, status->matk_min);
  170.  
  171.  #ifdef RENEWAL
  172.  		if( sd && sd->right_weapon.overrefine > 0){
  173. @@ -4741,37 +4717,37 @@
  174.  		return cap_value(matk,0,USHRT_MAX);
  175.  #ifndef RENEWAL
  176.  	// take note fixed value first before % modifiers
  177. -    if (sc->data[SC_MATKPOTION])
  178. -        matk += sc->data[SC_MATKPOTION]->val1;
  179. -    if (sc->data[SC_MATKFOOD])
  180. -        matk += sc->data[SC_MATKFOOD]->val1;
  181. -    if (sc->data[SC_MANA_PLUS])
  182. -        matk += sc->data[SC_MANA_PLUS]->val1;
  183. -    if (sc->data[SC_AQUAPLAY_OPTION])
  184. -        matk += sc->data[SC_AQUAPLAY_OPTION]->val2;
  185. -    if (sc->data[SC_CHILLY_AIR_OPTION])
  186. -        matk += sc->data[SC_CHILLY_AIR_OPTION]->val2;
  187. -    if (sc->data[SC_WATER_BARRIER])
  188. -        matk -= sc->data[SC_WATER_BARRIER]->val3;
  189. -    if (sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 3)
  190. -        matk += 50;
  191. -    if (sc->data[SC_ODINS_POWER])
  192. -        matk += 40 + 30 * sc->data[SC_ODINS_POWER]->val1; //70 lvl1, 100lvl2
  193. -    if (sc->data[SC_IZAYOI])
  194. -        matk += 50 * sc->data[SC_IZAYOI]->val1;
  195. +	if (sc->data[SC_MATKPOTION])
  196. +		matk += sc->data[SC_MATKPOTION]->val1;
  197. +	if (sc->data[SC_MATKFOOD])
  198. +		matk += sc->data[SC_MATKFOOD]->val1;
  199. +	if (sc->data[SC_MANA_PLUS])
  200. +		matk += sc->data[SC_MANA_PLUS]->val1;
  201. +	if (sc->data[SC_AQUAPLAY_OPTION])
  202. +		matk += sc->data[SC_AQUAPLAY_OPTION]->val2;
  203. +	if (sc->data[SC_CHILLY_AIR_OPTION])
  204. +		matk += sc->data[SC_CHILLY_AIR_OPTION]->val2;
  205. +	if (sc->data[SC_WATER_BARRIER])
  206. +		matk -= sc->data[SC_WATER_BARRIER]->val3;
  207. +	if (sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 3)
  208. +		matk += 50;
  209. +	if (sc->data[SC_ODINS_POWER])
  210. +		matk += 40 + 30 * sc->data[SC_ODINS_POWER]->val1; //70 lvl1, 100lvl2
  211. +	if (sc->data[SC_IZAYOI])
  212. +		matk += 50 * sc->data[SC_IZAYOI]->val1;
  213.  #endif
  214. -    if (sc->data[SC_MAGICPOWER] && sc->data[SC_MAGICPOWER]->val4)
  215. -        matk += matk * sc->data[SC_MAGICPOWER]->val3/100;
  216. -    if (sc->data[SC_MINDBREAKER])
  217. -        matk += matk * sc->data[SC_MINDBREAKER]->val2/100;
  218. -    if (sc->data[SC_INCMATKRATE])
  219. -        matk += matk * sc->data[SC_INCMATKRATE]->val1/100;
  220. -    if (sc->data[SC_MOONLITSERENADE])
  221. -        matk += matk * sc->data[SC_MOONLITSERENADE]->val2/100;
  222. -    if (sc->data[SC_MELODYOFSINK])
  223. -        matk += matk * sc->data[SC_MELODYOFSINK]->val3/100;
  224. -    if (sc->data[SC_BEYONDOFWARCRY])
  225. -        matk -= matk * sc->data[SC_BEYONDOFWARCRY]->val3/100;
  226. +	if (sc->data[SC_MAGICPOWER] && sc->data[SC_MAGICPOWER]->val4)
  227. +		matk += matk * sc->data[SC_MAGICPOWER]->val3/100;
  228. +	if (sc->data[SC_MINDBREAKER])
  229. +		matk += matk * sc->data[SC_MINDBREAKER]->val2/100;
  230. +	if (sc->data[SC_INCMATKRATE])
  231. +		matk += matk * sc->data[SC_INCMATKRATE]->val1/100;
  232. +	if (sc->data[SC_MOONLITSERENADE])
  233. +		matk += matk * sc->data[SC_MOONLITSERENADE]->val2/100;
  234. +	if (sc->data[SC_MELODYOFSINK])
  235. +		matk += matk * sc->data[SC_MELODYOFSINK]->val3/100;
  236. +	if (sc->data[SC_BEYONDOFWARCRY])
  237. +		matk -= matk * sc->data[SC_BEYONDOFWARCRY]->val3/100;
  238.  	if( sc->data[SC_ZANGETSU] )
  239.  		matk += matk * sc->data[SC_ZANGETSU]->val2 / 100;
  240.  
  241. @@ -11341,15 +11317,8 @@
  242.  }
  243.  
  244.  
  245. -/*------------------------------------------
  246. - * DB reading.
  247. - * job_db1.txt    - weight, hp, sp, aspd
  248. - * job_db2.txt    - job level stat bonuses
  249. - * size_fix.txt   - size adjustment table for weapons
  250. - * refine_db.txt  - refining data table
  251. - *------------------------------------------*/
  252. -static bool status_readdb_job1(char* fields[], int columns, int current)
  253. -{// Job-specific values (weight, HP, SP, ASPD)
  254. +//Reading job_db1.txt line, (class,weight,aspd)
  255. +static bool status_readdb_job1(char* fields[], int columns, int current){
  256.  	int idx, class_;
  257.  	unsigned int i;
  258.  
  259. @@ -11363,20 +11332,18 @@
  260.  	idx = pc_class2idx(class_);
  261.  
  262.  	max_weight_base[idx] = atoi(fields[1]);
  263. -	hp_coefficient[idx]  = atoi(fields[2]);
  264. -	hp_coefficient2[idx] = atoi(fields[3]);
  265. -	sp_coefficient[idx]  = atoi(fields[4]);
  266.  #ifdef RENEWAL_ASPD
  267.  	for(i = 0; i <= MAX_WEAPON_TYPE; i++)
  268.  #else
  269.  	for(i = 0; i < MAX_WEAPON_TYPE; i++)
  270.  #endif
  271.  	{
  272. -		aspd_base[idx][i] = atoi(fields[i+5]);
  273. +		aspd_base[idx][i] = atoi(fields[i+2]);
  274.  	}
  275.  	return true;
  276.  }
  277.  
  278. +//Reading job_db2.txt line (class,JobLv1,JobLv2,JobLv3,...)
  279.  static bool status_readdb_job2(char* fields[], int columns, int current)
  280.  {
  281.  	int idx, class_, i;
  282. @@ -11397,6 +11364,78 @@
  283.  	return true;
  284.  }
  285.  
  286. +//Reading job_maxhp.txt line
  287. +static bool status_readdb_maxhp(char* fields[], int columns, int current)
  288. +{
  289. +	int idx, i, maxlvl;
  290. +	int job_id,job_count,jobs[CLASS_COUNT];
  291. +
  292. +	job_count = pc_split_atoi(fields[1],jobs,':',CLASS_COUNT);
  293. +	if (job_count < 1)
  294. +		return false;
  295. +	for (i = 1; i < job_count; i++) {
  296. +		job_id = jobs[i];
  297. +		if(!pcdb_checkid(job_id))
  298. +		{
  299. +			ShowWarning("status_readdb_maxhp: Invalid job class %d specified.\n", job_id);
  300. +			return false;
  301. +		}
  302. +		idx = pc_class2idx(job_id);
  303. +
  304. +		maxlvl = atoi(fields[0]);
  305. +		if(maxlvl > MAX_LEVEL){
  306. +			ShowWarning("status_readdb_maxhp: Invalid maxlevel %d specified.\n", maxlvl);
  307. +			return false;
  308. +		}
  309. +		if(hpsp_info[idx].max_level && hpsp_info[idx].max_level != maxlvl){
  310. +			ShowWarning("status_readdb_maxhp: maxlevel %d was already specified with different value %d.\n",maxlvl,hpsp_info[idx].max_level);
  311. +			return false;
  312. +		}
  313. +		hpsp_info[idx].max_level = maxlvl;
  314. +		for(i = 2; i < maxlvl; i++)
  315. +		{
  316. +			hpsp_info[idx].hp_table[i-1] = atoi(fields[i]);
  317. +		}
  318. +	}
  319. +	return true;
  320. +}
  321. +
  322. +//Reading job_maxsp.txt line
  323. +static bool status_readdb_maxsp(char* fields[], int columns, int current)
  324. +{
  325. +	int idx, i, maxlvl;
  326. +	int job_id,job_count,jobs[CLASS_COUNT];
  327. +
  328. +	job_count = pc_split_atoi(fields[1],jobs,':',CLASS_COUNT);
  329. +	if (job_count < 1)
  330. +		return false;
  331. +	for (i = 1; i < job_count; i++) {
  332. +		job_id = jobs[i];
  333. +		if(!pcdb_checkid(job_id))
  334. +		{
  335. +			ShowWarning("status_readdb_maxhp: Invalid job class %d specified.\n", job_id);
  336. +			return false;
  337. +		}
  338. +		idx = pc_class2idx(job_id);
  339. +
  340. +		maxlvl = atoi(fields[0]);
  341. +		if(maxlvl > MAX_LEVEL){
  342. +			ShowWarning("status_readdb_maxhp: Invalid maxlevel %d specified.\n", maxlvl);
  343. +			return false;
  344. +		}
  345. +		if(hpsp_info[idx].max_level && hpsp_info[idx].max_level != maxlvl){
  346. +			ShowWarning("status_readdb_maxhp: maxlevel %d was already specified with different value %d.\n",maxlvl,hpsp_info[idx].max_level);
  347. +			return false;
  348. +		}
  349. +		hpsp_info[idx].max_level = maxlvl;
  350. +		for(i = 2; i < maxlvl; i++)
  351. +		{
  352. +			hpsp_info[idx].sp_table[i-1] = atoi(fields[i]);
  353. +		}
  354. +	}
  355. +	return true;
  356. +}
  357. +
  358.  static bool status_readdb_sizefix(char* fields[], int columns, int current)
  359.  {
  360.  	unsigned int i;
  361. @@ -11442,34 +11481,33 @@
  362.  	return true;
  363.  }
  364.  
  365. -/*
  366. -* Read status db
  367. -* job1.txt
  368. -* job2.txt
  369. -* size_fixe.txt
  370. -* refine_db.txt
  371. -*/
  372. +
  373. +/*------------------------------------------
  374. + * DB reading.
  375. + * job_db1.txt		- job weight, aspd
  376. + * job_db2.txt		- job level stat bonuses
  377. + * job_maxhp_db.txt	- job max hp
  378. + * job_maxsp_db.txt	- job max sp
  379. + * size_fix.txt		- size adjustment table for weapons
  380. + * refine_db.txt	- refining data table
  381. + *------------------------------------------*/
  382.  int status_readdb(void)
  383.  {
  384.  	int i, j;
  385. -
  386.  	// initialize databases to default
  387.  	//
  388. -
  389.  	// reset job_db1.txt data
  390.  	memset(max_weight_base, 0, sizeof(max_weight_base));
  391. -	memset(hp_coefficient, 0, sizeof(hp_coefficient));
  392. -	memset(hp_coefficient2, 0, sizeof(hp_coefficient2));
  393. -	memset(sp_coefficient, 0, sizeof(sp_coefficient));
  394.  	memset(aspd_base, 0, sizeof(aspd_base));
  395.  	// reset job_db2.txt data
  396.  	memset(job_bonus,0,sizeof(job_bonus)); // Job-specific stats bonus
  397. +	// hp_sptable
  398. +	memset(hpsp_info,0,sizeof(hpsp_info));
  399.  
  400.  	// size_fix.txt
  401.  	for(i=0;i<ARRAYLENGTH(atkmods);i++)
  402.  		for(j=0;j<MAX_WEAPON_TYPE;j++)
  403.  			atkmods[i][j]=100;
  404. -
  405.  	// refine_db.txt
  406.  	for(i=0;i<ARRAYLENGTH(refine_info);i++)
  407.  	{
  408. @@ -11482,17 +11520,17 @@
  409.  	}
  410.  
  411.  	// read databases
  412. -	//
  413. -
  414. -
  415. +	//		path,filename,separator,mincol,maxcol,maxrow,func_parsor
  416.  #ifdef RENEWAL_ASPD
  417. -	sv_readdb(db_path, "re/job_db1.txt",   ',',	6+MAX_WEAPON_TYPE, 6+MAX_WEAPON_TYPE,	-1,		&status_readdb_job1);
  418. +	sv_readdb(db_path, "re/job_db1.txt",',',6+MAX_WEAPON_TYPE,6+MAX_WEAPON_TYPE,-1,&status_readdb_job1);
  419.  #else
  420. -	sv_readdb(db_path, "pre-re/job_db1.txt",   ',',	5+MAX_WEAPON_TYPE, 5+MAX_WEAPON_TYPE,	-1,		&status_readdb_job1);
  421. +	sv_readdb(db_path, "pre-re/job_db1.txt",',',5+MAX_WEAPON_TYPE,5+MAX_WEAPON_TYPE,-1,&status_readdb_job1);
  422.  #endif
  423. -	sv_readdb(db_path, "job_db2.txt",   ',', 1,                 1+MAX_LEVEL,       -1,                            &status_readdb_job2);
  424. -	sv_readdb(db_path, "size_fix.txt",  ',', MAX_WEAPON_TYPE,   MAX_WEAPON_TYPE,    ARRAYLENGTH(atkmods),         &status_readdb_sizefix);
  425. +	sv_readdb(db_path, "job_db2.txt",',',1,1+MAX_LEVEL,-1,&status_readdb_job2);
  426. +	sv_readdb(db_path, "size_fix.txt",',',MAX_WEAPON_TYPE,MAX_WEAPON_TYPE,ARRAYLENGTH(atkmods),&status_readdb_sizefix);
  427.  	sv_readdb(db_path, DBPATH"refine_db.txt", ',', 4+MAX_REFINE, 4+MAX_REFINE, ARRAYLENGTH(refine_info), &status_readdb_refine);
  428. +	sv_readdb(db_path, DBPATH"job_maxhp_db.txt", ',', 3, 1+MAX_LEVEL, -1, &status_readdb_maxhp);
  429. +	sv_readdb(db_path, DBPATH"job_maxsp_db.txt", ',', 3, 1+MAX_LEVEL, -1, &status_readdb_maxsp);
  430.  
  431.  	return 0;
  432.  }
  433. @@ -11508,7 +11546,6 @@
  434.  	initChangeTables();
  435.  	initDummyData();
  436.  	status_readdb();
  437. -	status_calc_sigma();
  438.  	natural_heal_prev_tick = gettick();
  439.  	sc_data_ers = ers_new(sizeof(struct status_change_entry),"status.c::sc_data_ers",ERS_OPT_NONE);
  440.  	add_timer_interval(natural_heal_prev_tick + NATURAL_HEAL_INTERVAL, status_natural_heal_timer, 0, 0, NATURAL_HEAL_INTERVAL);
  441. Index: src/char/char.c
  442. ===================================================================
  443. --- src/char/char.c	(revision 17365)
  444. +++ src/char/char.c	(working copy)
  445. @@ -170,9 +170,9 @@
  446.  int pincode_maxtry = 3;
  447.  bool pincode_force = true;
  448.  
  449. -void pincode_check( int fd, struct char_session_data* sd );
  450. -void pincode_change( int fd, struct char_session_data* sd );
  451. -void pincode_setnew( int fd, struct char_session_data* sd );
  452. +int pincode_check( int fd, struct char_session_data* sd );
  453. +int pincode_change( int fd, struct char_session_data* sd );
  454. +int pincode_setnew( int fd, struct char_session_data* sd );
  455.  void pincode_sendstate( int fd, struct char_session_data* sd, uint16 state );
  456.  void pincode_notifyLoginPinUpdate( int account_id, char* pin );
  457.  void pincode_notifyLoginPinError( int account_id );
  458. @@ -184,7 +184,7 @@
  459.  bool char_movetoused = true;
  460.  bool char_moves_unlimited = false;
  461.  
  462. -void moveCharSlot( int fd, struct char_session_data* sd, unsigned short from, unsigned short to );
  463. +int moveCharSlot( int fd, struct char_session_data* sd);
  464.  void moveCharSlotReply( int fd, struct char_session_data* sd, unsigned short index, short reason );
  465.  
  466.  //Custom limits for the fame lists. [Skotlex]
  467. @@ -222,6 +222,7 @@
  468.  	time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
  469.  	int group_id;
  470.  	unsigned changing_mapservers : 1;
  471. +	int version;
  472.  };
  473.  
  474.  static DBMap* auth_db; // int account_id -> struct auth_node*
  475. @@ -2001,13 +2002,12 @@
  476.  
  477.  void mmo_char_send(int fd, struct char_session_data* sd){
  478.  	ShowInfo("sd->version = %d\n",sd->version);
  479. -#if PACKETVER >= 20130000
  480. +	if(sd->version > 34){
  481.  		mmo_char_send082d(fd,sd);
  482.  		char_charlist_notify(fd,sd);
  483.  		char_block_character(fd,sd);
  484. -#endif
  485. -	//@FIXME dump from kro doesn't show 6b transmission
  486. -	mmo_char_send006b(fd,sd);
  487. +	}
  488. +	mmo_char_send006b(fd,sd); //@FIXME dump from kro doesn't show 6b transmission
  489.  }
  490.  
  491.  int char_married(int pl1, int pl2)
  492. @@ -2280,7 +2280,7 @@
  493.  		break;
  494.  
  495.  		case 0x2717: // account data
  496. -			if (RFIFOREST(fd) < 72)
  497. +			if (RFIFOREST(fd) < 73)
  498.  				return 0;
  499.  
  500.  			// find the authenticated session with this account id
  501. @@ -2300,6 +2300,7 @@
  502.  				safestrncpy(sd->birthdate, (const char*)RFIFOP(fd,52), sizeof(sd->birthdate));
  503.  				safestrncpy(sd->pincode, (const char*)RFIFOP(fd,63), sizeof(sd->pincode));
  504.  				sd->pincode_change = (time_t)RFIFOL(fd,68);
  505. +				sd->version = RFIFOB(fd,72);
  506.  				ARR_FIND( 0, ARRAYLENGTH(server), server_id, server[server_id].fd > 0 && server[server_id].map[0] );
  507.  				// continued from char_auth_ok...
  508.  				if( server_id == ARRAYLENGTH(server) || //server not online, bugreport:2359
  509. @@ -2346,7 +2347,7 @@
  510.  #endif
  511.  				}
  512.  			}
  513. -			RFIFOSKIP(fd,72);
  514. +			RFIFOSKIP(fd,73);
  515.  		break;
  516.  
  517.  		// login-server alive packet
  518. @@ -3620,34 +3621,490 @@
  519.  	WFIFOSET(fd,10);
  520.  }
  521.  
  522. +//For use in packets that depend on an sd being present [Skotlex]
  523. +#define FIFOSD_CHECK(rest) { if(RFIFOREST(fd) < rest) return 0; if (sd==NULL || !sd->auth) { RFIFOSKIP(fd,rest); return 0; } }
  524.  
  525. -static void char_delete2_req(int fd, struct char_session_data* sd)
  526. -{// CH: <0827>.W <char id>.L
  527. +
  528. +// 0065 <account id>.L <login id1>.L <login id2>.L <???>.W <sex>.B
  529. +int char_parse_reqtoconnect(int fd, struct char_session_data* sd,uint32 ipl){
  530. +	if( RFIFOREST(fd) < 17 ) // request to connect
  531. +		return 0;
  532. +	else {
  533. +		struct auth_node* node;
  534. +
  535. +		int account_id = RFIFOL(fd,2);
  536. +		uint32 login_id1 = RFIFOL(fd,6);
  537. +		uint32 login_id2 = RFIFOL(fd,10);
  538. +		int sex = RFIFOB(fd,16);
  539. +		RFIFOSKIP(fd,17);
  540. +
  541. +		ShowInfo("request connect - account_id:%d/login_id1:%d/login_id2:%d\n", account_id, login_id1, login_id2);
  542. +
  543. +		if (sd) {
  544. +			//Received again auth packet for already authentified account?? Discard it.
  545. +			//TODO: Perhaps log this as a hack attempt?
  546. +			//TODO: and perhaps send back a reply?
  547. +			ShowInfo("Already registered break\n");
  548. +			return 0;
  549. +		}
  550. +
  551. +		CREATE(session[fd]->session_data, struct char_session_data, 1);
  552. +		sd = (struct char_session_data*)session[fd]->session_data;
  553. +		sd->account_id = account_id;
  554. +		sd->login_id1 = login_id1;
  555. +		sd->login_id2 = login_id2;
  556. +		sd->sex = sex;
  557. +		sd->auth = false; // not authed yet
  558. +
  559. +		// send back account_id
  560. +		WFIFOHEAD(fd,4);
  561. +		WFIFOL(fd,0) = account_id;
  562. +		WFIFOSET(fd,4);
  563. +
  564. +		if( runflag != CHARSERVER_ST_RUNNING )
  565. +		{
  566. +			WFIFOHEAD(fd,3);
  567. +			WFIFOW(fd,0) = 0x6c;
  568. +			WFIFOB(fd,2) = 0;// rejected from server
  569. +			WFIFOSET(fd,3);
  570. +			return 0;
  571. +		}
  572. +
  573. +		// search authentification
  574. +		node = (struct auth_node*)idb_get(auth_db, account_id);
  575. +		if( node != NULL &&
  576. +		    node->account_id == account_id &&
  577. +			node->login_id1  == login_id1 &&
  578. +			node->login_id2  == login_id2 /*&&
  579. +			node->ip         == ipl*/ )
  580. +		{// authentication found (coming from map server)
  581. +			idb_remove(auth_db, account_id);
  582. +			char_auth_ok(fd, sd);
  583. +		}
  584. +		else
  585. +		{// authentication not found (coming from login server)
  586. +			if (login_fd > 0) { // don't send request if no login-server
  587. +				WFIFOHEAD(login_fd,23);
  588. +				WFIFOW(login_fd,0) = 0x2712; // ask login-server to authentify an account
  589. +				WFIFOL(login_fd,2) = sd->account_id;
  590. +				WFIFOL(login_fd,6) = sd->login_id1;
  591. +				WFIFOL(login_fd,10) = sd->login_id2;
  592. +				WFIFOB(login_fd,14) = sd->sex;
  593. +				WFIFOL(login_fd,15) = htonl(ipl);
  594. +				WFIFOL(login_fd,19) = fd;
  595. +				WFIFOSET(login_fd,23);
  596. +			} else { // if no login-server, we must refuse connection
  597. +				WFIFOHEAD(fd,3);
  598. +				WFIFOW(fd,0) = 0x6c;
  599. +				WFIFOB(fd,2) = 0;
  600. +				WFIFOSET(fd,3);
  601. +			}
  602. +		}
  603. +	}
  604. +	return 1;
  605. +}
  606. +
  607. +int char_parse_charselect(int fd, struct char_session_data* sd,uint32 ipl){
  608. +	FIFOSD_CHECK(3);
  609. +	{
  610. +		struct mmo_charstatus char_dat;
  611. +		struct mmo_charstatus *cd;
  612. +		char* data;
  613. +		int char_id;
  614. +		uint32 subnet_map_ip;
  615. +		struct auth_node* node;
  616. +		int i, map_fd;
  617. +
  618. +		int slot = RFIFOB(fd,2);
  619. +		RFIFOSKIP(fd,3);
  620. +
  621. +		if ( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `char_id` FROM `%s` WHERE `account_id`='%d' AND `char_num`='%d'", char_db, sd->account_id, slot)
  622. +		  || SQL_SUCCESS != Sql_NextRow(sql_handle)
  623. +		  || SQL_SUCCESS != Sql_GetData(sql_handle, 0, &data, NULL) )
  624. +		{	//Not found?? May be forged packet.
  625. +			Sql_ShowDebug(sql_handle);
  626. +			Sql_FreeResult(sql_handle);
  627. +			WFIFOHEAD(fd,3);
  628. +			WFIFOW(fd,0) = 0x6c;
  629. +			WFIFOB(fd,2) = 0; // rejected from server
  630. +			WFIFOSET(fd,3);
  631. +			return 0;
  632. +		}
  633. +
  634. +		char_id = atoi(data);
  635. +		Sql_FreeResult(sql_handle);
  636. +
  637. +		/* set char as online prior to loading its data so 3rd party applications will realise the sql data is not reliable */
  638. +		set_char_online(-2,char_id,sd->account_id);
  639. +		if( !mmo_char_fromsql(char_id, &char_dat, true) ) { /* failed? set it back offline */
  640. +			set_char_offline(char_id, sd->account_id);
  641. +			/* failed to load something. REJECT! */
  642. +			WFIFOHEAD(fd,3);
  643. +			WFIFOW(fd,0) = 0x6c;
  644. +			WFIFOB(fd,2) = 0;
  645. +			WFIFOSET(fd,3);
  646. +			return 0;/* jump off this boat */
  647. +		}
  648. +
  649. +		//Have to switch over to the DB instance otherwise data won't propagate [Kevin]
  650. +		cd = (struct mmo_charstatus *)idb_get(char_db_, char_id);
  651. +		cd->sex = sd->sex;
  652. +
  653. +		if (log_char) {
  654. +			char esc_name[NAME_LENGTH*2+1];
  655. +
  656. +			Sql_EscapeStringLen(sql_handle, esc_name, char_dat.name, strnlen(char_dat.name, NAME_LENGTH));
  657. +			if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`time`, `account_id`,`char_num`,`name`) VALUES (NOW(), '%d', '%d', '%s')",
  658. +				charlog_db, sd->account_id, slot, esc_name) )
  659. +				Sql_ShowDebug(sql_handle);
  660. +		}
  661. +		ShowInfo("Selected char: (Account %d: %d - %s)\n", sd->account_id, slot, char_dat.name);
  662. +
  663. +		// searching map server
  664. +		i = search_mapserver(cd->last_point.map, -1, -1);
  665. +
  666. +		// if map is not found, we check major cities
  667. +		if (i < 0 || !cd->last_point.map) {
  668. +			unsigned short j;
  669. +			//First check that there's actually a map server online.
  670. +			ARR_FIND( 0, ARRAYLENGTH(server), j, server[j].fd >= 0 && server[j].map[0] );
  671. +			if (j == ARRAYLENGTH(server)) {
  672. +				ShowInfo("Connection Closed. No map servers available.\n");
  673. +				WFIFOHEAD(fd,3);
  674. +				WFIFOW(fd,0) = 0x81;
  675. +				WFIFOB(fd,2) = 1; // 01 = Server closed
  676. +				WFIFOSET(fd,3);
  677. +				return 0;
  678. +			}
  679. +			if ((i = search_mapserver((j=mapindex_name2id(MAP_PRONTERA)),-1,-1)) >= 0) {
  680. +				cd->last_point.x = 273;
  681. +				cd->last_point.y = 354;
  682. +			} else if ((i = search_mapserver((j=mapindex_name2id(MAP_GEFFEN)),-1,-1)) >= 0) {
  683. +				cd->last_point.x = 120;
  684. +				cd->last_point.y = 100;
  685. +			} else if ((i = search_mapserver((j=mapindex_name2id(MAP_MORROC)),-1,-1)) >= 0) {
  686. +				cd->last_point.x = 160;
  687. +				cd->last_point.y = 94;
  688. +			} else if ((i = search_mapserver((j=mapindex_name2id(MAP_ALBERTA)),-1,-1)) >= 0) {
  689. +				cd->last_point.x = 116;
  690. +				cd->last_point.y = 57;
  691. +			} else if ((i = search_mapserver((j=mapindex_name2id(MAP_PAYON)),-1,-1)) >= 0) {
  692. +				cd->last_point.x = 87;
  693. +				cd->last_point.y = 117;
  694. +			} else if ((i = search_mapserver((j=mapindex_name2id(MAP_IZLUDE)),-1,-1)) >= 0) {
  695. +				cd->last_point.x = 94;
  696. +				cd->last_point.y = 103;
  697. +			} else {
  698. +				ShowInfo("Connection Closed. No map server available that has a major city, and unable to find map-server for '%s'.\n", mapindex_id2name(cd->last_point.map));
  699. +				WFIFOHEAD(fd,3);
  700. +				WFIFOW(fd,0) = 0x81;
  701. +				WFIFOB(fd,2) = 1; // 01 = Server closed
  702. +				WFIFOSET(fd,3);
  703. +				return 0;
  704. +			}
  705. +			ShowWarning("Unable to find map-server for '%s', sending to major city '%s'.\n", mapindex_id2name(cd->last_point.map), mapindex_id2name(j));
  706. +			cd->last_point.map = j;
  707. +		}
  708. +
  709. +		//Send NEW auth packet [Kevin]
  710. +		//FIXME: is this case even possible? [ultramage]
  711. +		if ((map_fd = server[i].fd) < 1 || session[map_fd] == NULL)
  712. +		{
  713. +			ShowError("parse_char: Attempting to write to invalid session %d! Map Server #%d disconnected.\n", map_fd, i);
  714. +			server[i].fd = -1;
  715. +			memset(&server[i], 0, sizeof(struct mmo_map_server));
  716. +			//Send server closed.
  717. +			WFIFOHEAD(fd,3);
  718. +			WFIFOW(fd,0) = 0x81;
  719. +			WFIFOB(fd,2) = 1; // 01 = Server closed
  720. +			WFIFOSET(fd,3);
  721. +			return 0;
  722. +		}
  723. +
  724. +		//Send player to map
  725. +		WFIFOHEAD(fd,28);
  726. +		WFIFOW(fd,0) = 0x71;
  727. +		WFIFOL(fd,2) = cd->char_id;
  728. +		mapindex_getmapname_ext(mapindex_id2name(cd->last_point.map), (char*)WFIFOP(fd,6));
  729. +		subnet_map_ip = lan_subnetcheck(ipl); // Advanced subnet check [LuzZza]
  730. +		WFIFOL(fd,22) = htonl((subnet_map_ip) ? subnet_map_ip : server[i].ip);
  731. +		WFIFOW(fd,26) = ntows(htons(server[i].port)); // [!] LE byte order here [!]
  732. +		WFIFOSET(fd,28);
  733. +
  734. +		// create temporary auth entry
  735. +		CREATE(node, struct auth_node, 1);
  736. +		node->account_id = sd->account_id;
  737. +		node->char_id = cd->char_id;
  738. +		node->login_id1 = sd->login_id1;
  739. +		node->login_id2 = sd->login_id2;
  740. +		node->sex = sd->sex;
  741. +		node->expiration_time = sd->expiration_time;
  742. +		node->group_id = sd->group_id;
  743. +		node->ip = ipl;
  744. +		node->version = sd->version;
  745. +		idb_put(auth_db, sd->account_id, node);
  746. +
  747. +	}
  748. +	return 1;
  749. +}
  750. +
  751. +// S 0970 <name>.24B <slot>.B <hair color>.W <hair style>.W
  752. +// S 0067 <name>.24B <str>.B <agi>.B <vit>.B <int>.B <dex>.B <luk>.B <slot>.B <hair color>.W <hair style>.W
  753. +int char_parse_createnewchar(int fd, struct char_session_data* sd,int cmd){
  754. +	int i=0, ch;
  755. +
  756. +	if (cmd == 0x970) FIFOSD_CHECK(31) //>=20120307
  757. +	else if (cmd == 0x67) FIFOSD_CHECK(37)
  758. +	else return 0;
  759. +
  760. +	if( !char_new ) //turn character creation on/off [Kevin]
  761. +		i = -2;
  762. +	else {
  763. +		if (cmd == 0x970){
  764. +			i = make_new_char_sql(sd, (char*)RFIFOP(fd,2),RFIFOB(fd,26),RFIFOW(fd,27),RFIFOW(fd,29));
  765. +			RFIFOSKIP(fd,31);
  766. +		}
  767. +		else if(cmd == 0x67){
  768. +#if PACKETVER < 20120307
  769. +			i = make_new_char_sql(sd, (char*)RFIFOP(fd,2),RFIFOB(fd,26),RFIFOB(fd,27),RFIFOB(fd,28),RFIFOB(fd,29),RFIFOB(fd,30),RFIFOB(fd,31),RFIFOB(fd,32),RFIFOW(fd,33),RFIFOW(fd,35));
  770. +			RFIFOSKIP(fd,37);
  771. +#endif
  772. +		}
  773. +	}
  774. +
  775. +	//'Charname already exists' (-1), 'Char creation denied' (-2) and 'You are underaged' (-3)
  776. +	if (i < 0) {
  777. +		WFIFOHEAD(fd,3);
  778. +		WFIFOW(fd,0) = 0x6e;
  779. +		/* Others I found [Ind] */
  780. +		/* 0x02 = Symbols in Character Names are forbidden */
  781. +		/* 0x03 = You are not elegible to open the Character Slot. */
  782. +		switch (i) {
  783. +			case -1: WFIFOB(fd,2) = 0x00; break;
  784. +			case -2: WFIFOB(fd,2) = 0xFF; break;
  785. +			case -3: WFIFOB(fd,2) = 0x01; break;
  786. +			case -4: WFIFOB(fd,2) = 0x03; break;
  787. +		}
  788. +		WFIFOSET(fd,3);
  789. +	} else {
  790. +		int len;
  791. +		// retrieve data
  792. +		struct mmo_charstatus char_dat;
  793. +		mmo_char_fromsql(i, &char_dat, false); //Only the short data is needed.
  794. +
  795. +		// send to player
  796. +		WFIFOHEAD(fd,2+MAX_CHAR_BUF);
  797. +		WFIFOW(fd,0) = 0x6d;
  798. +		len = 2 + mmo_char_tobuf(WFIFOP(fd,2), &char_dat);
  799. +		WFIFOSET(fd,len);
  800. +
  801. +		// add new entry to the chars list
  802. +		ARR_FIND( 0, MAX_CHARS, ch, sd->found_char[ch] == -1 );
  803. +		if( ch < MAX_CHARS )
  804. +			sd->found_char[ch] = i; // the char_id of the new char
  805. +	}
  806. +	return 1;
  807. +}
  808. +
  809. +int char_parse_delchar(int fd,struct char_session_data* sd, int cmd){
  810. +	char email[40];
  811. +	int i, ch;
  812. +
  813. +	if (cmd == 0x68) FIFOSD_CHECK(46)
  814. +	else if (cmd == 0x1fb) FIFOSD_CHECK(56)
  815. +	else return 0;
  816. +
  817. +	{
  818. +		int cid = RFIFOL(fd,2);
  819. +
  820. +		ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, cid);
  821. +		memcpy(email, RFIFOP(fd,6), 40);
  822. +		RFIFOSKIP(fd,( cmd == 0x68) ? 46 : 56);
  823. +
  824. +		// Check if e-mail is correct
  825. +		if(strcmpi(email, sd->email) && //email does not matches and
  826. +		(
  827. +			strcmp("[email protected]", sd->email) || //it is not default email, or
  828. +			(strcmp("[email protected]", email) && strcmp("", email)) //email sent does not matches default
  829. +		)) {	//Fail
  830. +			WFIFOHEAD(fd,3);
  831. +			WFIFOW(fd,0) = 0x70;
  832. +			WFIFOB(fd,2) = 0; // 00 = Incorrect Email address
  833. +			WFIFOSET(fd,3);
  834. +			return 0;
  835. +		}
  836. +
  837. +		// check if this char exists
  838. +		ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid );
  839. +		if( i == MAX_CHARS )
  840. +		{ // Such a character does not exist in the account
  841. +			WFIFOHEAD(fd,3);
  842. +			WFIFOW(fd,0) = 0x70;
  843. +			WFIFOB(fd,2) = 0;
  844. +			WFIFOSET(fd,3);
  845. +			return 0;
  846. +		}
  847. +
  848. +		// remove char from list and compact it
  849. +		for(ch = i; ch < MAX_CHARS-1; ch++)
  850. +			sd->found_char[ch] = sd->found_char[ch+1];
  851. +		sd->found_char[MAX_CHARS-1] = -1;
  852. +
  853. +		/* Delete character */
  854. +		if(delete_char_sql(cid)<0){
  855. +			//can't delete the char
  856. +			//either SQL error or can't delete by some CONFIG conditions
  857. +			//del fail
  858. +			WFIFOHEAD(fd,3);
  859. +			WFIFOW(fd, 0) = 0x70;
  860. +			WFIFOB(fd, 2) = 0;
  861. +			WFIFOSET(fd, 3);
  862. +			return 0;
  863. +		}
  864. +		/* Char successfully deleted.*/
  865. +		WFIFOHEAD(fd,2);
  866. +		WFIFOW(fd,0) = 0x6f;
  867. +		WFIFOSET(fd,2);
  868. +	}
  869. +	return 1;
  870. +}
  871. +
  872. +// R 0187 <account ID>.l
  873. +int char_parse_keepalive(int fd){
  874. +	if (RFIFOREST(fd) < 6)
  875. +		return 0;
  876. +	//int aid = RFIFOL(fd,2);
  877. +	RFIFOSKIP(fd,6);
  878. +	return 1;
  879. +}
  880. +
  881. +// R 08fc <char ID>.l <new name>.24B
  882. +// R 028d <account ID>.l <char ID>.l <new name>.24B
  883. +int char_parse_reqrename(int fd, struct char_session_data* sd, int cmd){
  884. +	if(cmd == 0x8fc) FIFOSD_CHECK(30)
  885. +	if(cmd == 0x28d) FIFOSD_CHECK(34)
  886. +	else return 0;
  887. +
  888. +	{
  889. +		int i, cid=0;
  890. +		char name[NAME_LENGTH];
  891. +		char esc_name[NAME_LENGTH*2+1];
  892. +		safestrncpy(name, (char *)RFIFOP(fd,10), NAME_LENGTH);
  893. +
  894. +		if(cmd == 0x8fc){
  895. +			cid =RFIFOL(fd,2);
  896. +			RFIFOSKIP(fd,30);
  897. +		}
  898. +		else if(cmd == 0x28d) {
  899. +			int aid = RFIFOL(fd,2);
  900. +			cid =RFIFOL(fd,6);
  901. +			if( aid != sd->account_id )
  902. +				return 0;
  903. +			RFIFOSKIP(fd,34);
  904. +		}
  905. +
  906. +		ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid );
  907. +		if( i == MAX_CHARS )
  908. +			return 0;
  909. +
  910. +		normalize_name(name,TRIM_CHARS);
  911. +		Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH));
  912. +		if( !check_char_name(name,esc_name) )
  913. +		{
  914. +			i = 1;
  915. +			safestrncpy(sd->new_name, name, NAME_LENGTH);
  916. +		}
  917. +		else
  918. +			i = 0;
  919. +
  920. +		WFIFOHEAD(fd, 4);
  921. +		WFIFOW(fd,0) = 0x28e;
  922. +		WFIFOW(fd,2) = i;
  923. +		WFIFOSET(fd,4);
  924. +	}
  925. +	return 1;
  926. +}
  927. +
  928. +// 0x28f <char_id>.L
  929. +int char_parse_ackrename(int fd, struct char_session_data* sd){
  930. +	// 0: Sucessfull
  931. +	// 1: This character's name has already been changed. You cannot change a character's name more than once.
  932. +	// 2: User information is not correct.
  933. +	// 3: You have failed to change this character's name.
  934. +	// 4: Another user is using this character name, so please select another one.
  935. +	FIFOSD_CHECK(6)
  936. +
  937. +	{
  938. +		int i;
  939. +		int cid = RFIFOL(fd,2);
  940. +		RFIFOSKIP(fd,6);
  941. +
  942. +		ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid );
  943. +		if( i == MAX_CHARS )
  944. +			return 0;
  945. +		i = rename_char_sql(sd, cid);
  946. +
  947. +		WFIFOHEAD(fd, 4);
  948. +		WFIFOW(fd,0) = 0x290;
  949. +		WFIFOW(fd,2) = i;
  950. +		WFIFOSET(fd,4);
  951. +	}
  952. +	return 1;
  953. +}
  954. +
  955. +// R 07e5 <?>.w <aid>.l
  956. +int char_parse_reqcaptcha(int fd){
  957. +	WFIFOHEAD(fd,5);
  958. +	WFIFOW(fd,0) = 0x7e9;
  959. +	WFIFOW(fd,2) = 5;
  960. +	WFIFOB(fd,4) = 1;
  961. +	WFIFOSET(fd,5);
  962. +	RFIFOSKIP(fd,8);
  963. +	return 1;
  964. +}
  965. +
  966. +// R 07e7 <len>.w <aid>.l <code>.b10 <?>.b14
  967. +int char_parse_chkcaptcha(int fd){
  968. +	WFIFOHEAD(fd,5);
  969. +	WFIFOW(fd,0) = 0x7e9;
  970. +	WFIFOW(fd,2) = 5;
  971. +	WFIFOB(fd,4) = 1;
  972. +	WFIFOSET(fd,5);
  973. +	RFIFOSKIP(fd,32);
  974. +	return 1;
  975. +}
  976. +
  977. +// CH: <0827>.W <char id>.L
  978. +int char_delete2_req(int fd, struct char_session_data* sd)
  979. +{
  980.  	int char_id, i;
  981.  	char* data;
  982.  	time_t delete_date;
  983.  
  984. +	FIFOSD_CHECK(6)
  985. +
  986.  	char_id = RFIFOL(fd,2);
  987. +	RFIFOSKIP(fd,6);
  988.  
  989.  	ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == char_id );
  990.  	if( i == MAX_CHARS )
  991.  	{// character not found
  992.  		char_delete2_ack(fd, char_id, 3, 0);
  993. -		return;
  994. +		return 0;
  995.  	}
  996.  
  997.  	if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `delete_date` FROM `%s` WHERE `char_id`='%d'", char_db, char_id) || SQL_SUCCESS != Sql_NextRow(sql_handle) )
  998.  	{
  999.  		Sql_ShowDebug(sql_handle);
  1000.  		char_delete2_ack(fd, char_id, 3, 0);
  1001. -		return;
  1002. +		return 0;
  1003.  	}
  1004.  
  1005.  	Sql_GetData(sql_handle, 0, &data, NULL); delete_date = strtoul(data, NULL, 10);
  1006.  
  1007.  	if( delete_date ) {// character already queued for deletion
  1008.  		char_delete2_ack(fd, char_id, 0, 0);
  1009. -		return;
  1010. +		return 0;
  1011.  	}
  1012.  
  1013.  /*
  1014. @@ -3674,14 +4131,14 @@
  1015.  	{
  1016.  		Sql_ShowDebug(sql_handle);
  1017.  		char_delete2_ack(fd, char_id, 3, 0);
  1018. -		return;
  1019. +		return 0;
  1020.  	}
  1021.  
  1022.  	char_delete2_ack(fd, char_id, 1, delete_date);
  1023. +	return 1;
  1024.  }
  1025.  
  1026. -
  1027. -static void char_delete2_accept(int fd, struct char_session_data* sd)
  1028. +int char_delete2_accept(int fd, struct char_session_data* sd)
  1029.  {// CH: <0829>.W <char id>.L <birth date:YYMMDD>.6B
  1030.  	char birthdate[8+1];
  1031.  	int char_id, i, k;
  1032. @@ -3689,6 +4146,8 @@
  1033.  	char* data;
  1034.  	time_t delete_date;
  1035.  
  1036. +	FIFOSD_CHECK(12)
  1037. +
  1038.  	char_id = RFIFOL(fd,2);
  1039.  
  1040.  	ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, char_id);
  1041. @@ -3703,19 +4162,20 @@
  1042.  	birthdate[6] = RFIFOB(fd,10);
  1043.  	birthdate[7] = RFIFOB(fd,11);
  1044.  	birthdate[8] = 0;
  1045. +	RFIFOSKIP(fd,12);
  1046.  
  1047.  	ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == char_id );
  1048.  	if( i == MAX_CHARS )
  1049.  	{// character not found
  1050.  		char_delete2_accept_ack(fd, char_id, 3);
  1051. -		return;
  1052. +		return 0;
  1053.  	}
  1054.  
  1055.  	if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `base_level`,`delete_date` FROM `%s` WHERE `char_id`='%d'", char_db, char_id) || SQL_SUCCESS != Sql_NextRow(sql_handle) )
  1056.  	{// data error
  1057.  		Sql_ShowDebug(sql_handle);
  1058.  		char_delete2_accept_ack(fd, char_id, 3);
  1059. -		return;
  1060. +		return 0;
  1061.  	}
  1062.  
  1063.  	Sql_GetData(sql_handle, 0, &data, NULL); base_level = (unsigned int)strtoul(data, NULL, 10);
  1064. @@ -3724,26 +4184,26 @@
  1065.  	if( !delete_date || delete_date>time(NULL) )
  1066.  	{// not queued or delay not yet passed
  1067.  		char_delete2_accept_ack(fd, char_id, 4);
  1068. -		return;
  1069. +		return 0;
  1070.  	}
  1071.  
  1072.  	if( strcmp(sd->birthdate+2, birthdate) )  // +2 to cut off the century
  1073.  	{// birth date is wrong
  1074.  		char_delete2_accept_ack(fd, char_id, 5);
  1075. -		return;
  1076. +		return 0;
  1077.  	}
  1078.  
  1079.  	if( ( char_del_level > 0 && base_level >= (unsigned int)char_del_level ) || ( char_del_level < 0 && base_level <= (unsigned int)(-char_del_level) ) )
  1080.  	{// character level config restriction
  1081.  		char_delete2_accept_ack(fd, char_id, 2);
  1082. -		return;
  1083. +		return 0;
  1084.  	}
  1085.  
  1086.  	// success
  1087.  	if( delete_char_sql(char_id) < 0 )
  1088.  	{
  1089.  		char_delete2_accept_ack(fd, char_id, 3);
  1090. -		return;
  1091. +		return 0;
  1092.  	}
  1093.  
  1094.  	// refresh character list cache
  1095. @@ -3754,20 +4214,24 @@
  1096.  	sd->found_char[MAX_CHARS-1] = -1;
  1097.  
  1098.  	char_delete2_accept_ack(fd, char_id, 1);
  1099. +	return 1;
  1100.  }
  1101.  
  1102. -
  1103. -static void char_delete2_cancel(int fd, struct char_session_data* sd)
  1104. -{// CH: <082b>.W <char id>.L
  1105. +// CH: <082b>.W <char id>.L
  1106. +int char_delete2_cancel(int fd, struct char_session_data* sd)
  1107. +{
  1108.  	int char_id, i;
  1109.  
  1110. +	FIFOSD_CHECK(6)
  1111. +
  1112.  	char_id = RFIFOL(fd,2);
  1113. +	RFIFOSKIP(fd,6);
  1114.  
  1115.  	ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == char_id );
  1116.  	if( i == MAX_CHARS )
  1117.  	{// character not found
  1118.  		char_delete2_cancel_ack(fd, char_id, 2);
  1119. -		return;
  1120. +		return 0;
  1121.  	}
  1122.  
  1123.  	// there is no need to check, whether or not the character was
  1124. @@ -3777,24 +4241,61 @@
  1125.  	{
  1126.  		Sql_ShowDebug(sql_handle);
  1127.  		char_delete2_cancel_ack(fd, char_id, 2);
  1128. -		return;
  1129. +		return 0;
  1130.  	}
  1131.  
  1132.  	char_delete2_cancel_ack(fd, char_id, 1);
  1133. +	return 1;
  1134.  }
  1135.  
  1136. +int char_parse_maplogin(int fd){
  1137. +	int i;
  1138.  
  1139. +	if (RFIFOREST(fd) < 60)
  1140. +		return 0;
  1141. +	else {
  1142. +		char* l_user = (char*)RFIFOP(fd,2);
  1143. +		char* l_pass = (char*)RFIFOP(fd,26);
  1144. +		l_user[23] = '\0';
  1145. +		l_pass[23] = '\0';
  1146. +		ARR_FIND( 0, ARRAYLENGTH(server), i, server[i].fd <= 0 );
  1147. +		if( runflag != CHARSERVER_ST_RUNNING ||
  1148. +			i == ARRAYLENGTH(server) ||
  1149. +			strcmp(l_user, userid) != 0 ||
  1150. +			strcmp(l_pass, passwd) != 0 )
  1151. +		{
  1152. +			WFIFOHEAD(fd,3);
  1153. +			WFIFOW(fd,0) = 0x2af9;
  1154. +			WFIFOB(fd,2) = 3;
  1155. +			WFIFOSET(fd,3);
  1156. +		} else {
  1157. +			WFIFOHEAD(fd,3);
  1158. +			WFIFOW(fd,0) = 0x2af9;
  1159. +			WFIFOB(fd,2) = 0;
  1160. +			WFIFOSET(fd,3);
  1161. +
  1162. +			server[i].fd = fd;
  1163. +			server[i].ip = ntohl(RFIFOL(fd,54));
  1164. +			server[i].port = ntohs(RFIFOW(fd,58));
  1165. +			server[i].users = 0;
  1166. +			memset(server[i].map, 0, sizeof(server[i].map));
  1167. +			session[fd]->func_parse = parse_frommap;
  1168. +			session[fd]->flag.server = 1;
  1169. +			realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
  1170. +			char_mapif_init(fd);
  1171. +		}
  1172. +		RFIFOSKIP(fd,60);
  1173. +	}
  1174. +	return 1;
  1175. +}
  1176. +
  1177.  int parse_char(int fd)
  1178.  {
  1179. -	int i, ch;
  1180. -	char email[40];
  1181. +	int i;
  1182.  	unsigned short cmd;
  1183. -	int map_fd;
  1184. -	struct char_session_data* sd;
  1185. +	struct char_session_data* sd = (struct char_session_data*)session[fd]->session_data;
  1186.  	uint32 ipl = session[fd]->client_addr;
  1187.  
  1188. -	sd = (struct char_session_data*)session[fd]->session_data;
  1189. -
  1190.  	// disconnect any player if no login-server.
  1191.  	if(login_fd < 0)
  1192.  		set_eof(fd);
  1193. @@ -3815,582 +4316,44 @@
  1194.  
  1195.  	while( RFIFOREST(fd) >= 2 )
  1196.  	{
  1197. -		//For use in packets that depend on an sd being present [Skotlex]
  1198. -		#define FIFOSD_CHECK(rest) { if(RFIFOREST(fd) < rest) return 0; if (sd==NULL || !sd->auth) { RFIFOSKIP(fd,rest); return 0; } }
  1199. -
  1200.  		cmd = RFIFOW(fd,0);
  1201.  		switch( cmd )
  1202.  		{
  1203.  
  1204. -		// request to connect
  1205. -		// 0065 <account id>.L <login id1>.L <login id2>.L <???>.W <sex>.B
  1206. -		case 0x65:
  1207. -			if( RFIFOREST(fd) < 17 )
  1208. -				return 0;
  1209. -		{
  1210. -			struct auth_node* node;
  1211. -
  1212. -			int account_id = RFIFOL(fd,2);
  1213. -			uint32 login_id1 = RFIFOL(fd,6);
  1214. -			uint32 login_id2 = RFIFOL(fd,10);
  1215. -			int sex = RFIFOB(fd,16);
  1216. -			RFIFOSKIP(fd,17);
  1217. -
  1218. -			ShowInfo("request connect - account_id:%d/login_id1:%d/login_id2:%d\n", account_id, login_id1, login_id2);
  1219. -
  1220. -			if (sd) {
  1221. -				//Received again auth packet for already authentified account?? Discard it.
  1222. -				//TODO: Perhaps log this as a hack attempt?
  1223. -				//TODO: and perhaps send back a reply?
  1224. -				break;
  1225. -			}
  1226. -
  1227. -			CREATE(session[fd]->session_data, struct char_session_data, 1);
  1228. -			sd = (struct char_session_data*)session[fd]->session_data;
  1229. -			sd->account_id = account_id;
  1230. -			sd->login_id1 = login_id1;
  1231. -			sd->login_id2 = login_id2;
  1232. -			sd->sex = sex;
  1233. -			sd->auth = false; // not authed yet
  1234. -
  1235. -			// send back account_id
  1236. -			WFIFOHEAD(fd,4);
  1237. -			WFIFOL(fd,0) = account_id;
  1238. -			WFIFOSET(fd,4);
  1239. -
  1240. -			if( runflag != CHARSERVER_ST_RUNNING )
  1241. -			{
  1242. -				WFIFOHEAD(fd,3);
  1243. -				WFIFOW(fd,0) = 0x6c;
  1244. -				WFIFOB(fd,2) = 0;// rejected from server
  1245. -				WFIFOSET(fd,3);
  1246. -				break;
  1247. -			}
  1248. -
  1249. -			// search authentification
  1250. -			node = (struct auth_node*)idb_get(auth_db, account_id);
  1251. -			if( node != NULL &&
  1252. -			    node->account_id == account_id &&
  1253. -				node->login_id1  == login_id1 &&
  1254. -				node->login_id2  == login_id2 /*&&
  1255. -				node->ip         == ipl*/ )
  1256. -			{// authentication found (coming from map server)
  1257. -				idb_remove(auth_db, account_id);
  1258. -				char_auth_ok(fd, sd);
  1259. -			}
  1260. -			else
  1261. -			{// authentication not found (coming from login server)
  1262. -				if (login_fd > 0) { // don't send request if no login-server
  1263. -					WFIFOHEAD(login_fd,23);
  1264. -					WFIFOW(login_fd,0) = 0x2712; // ask login-server to authentify an account
  1265. -					WFIFOL(login_fd,2) = sd->account_id;
  1266. -					WFIFOL(login_fd,6) = sd->login_id1;
  1267. -					WFIFOL(login_fd,10) = sd->login_id2;
  1268. -					WFIFOB(login_fd,14) = sd->sex;
  1269. -					WFIFOL(login_fd,15) = htonl(ipl);
  1270. -					WFIFOL(login_fd,19) = fd;
  1271. -					WFIFOSET(login_fd,23);
  1272. -				} else { // if no login-server, we must refuse connection
  1273. -					WFIFOHEAD(fd,3);
  1274. -					WFIFOW(fd,0) = 0x6c;
  1275. -					WFIFOB(fd,2) = 0;
  1276. -					WFIFOSET(fd,3);
  1277. -				}
  1278. -			}
  1279. -		}
  1280. -		break;
  1281. -
  1282. +		case 0x65: char_parse_reqtoconnect(fd,sd,ipl); break;
  1283.  		// char select
  1284. -		case 0x66:
  1285. -			FIFOSD_CHECK(3);
  1286. -		{
  1287. -			struct mmo_charstatus char_dat;
  1288. -			struct mmo_charstatus *cd;
  1289. -			char* data;
  1290. -			int char_id;
  1291. -			uint32 subnet_map_ip;
  1292. -			struct auth_node* node;
  1293. -
  1294. -			int slot = RFIFOB(fd,2);
  1295. -			RFIFOSKIP(fd,3);
  1296. -
  1297. -			if ( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `char_id` FROM `%s` WHERE `account_id`='%d' AND `char_num`='%d'", char_db, sd->account_id, slot)
  1298. -			  || SQL_SUCCESS != Sql_NextRow(sql_handle)
  1299. -			  || SQL_SUCCESS != Sql_GetData(sql_handle, 0, &data, NULL) )
  1300. -			{	//Not found?? May be forged packet.
  1301. -				Sql_ShowDebug(sql_handle);
  1302. -				Sql_FreeResult(sql_handle);
  1303. -				WFIFOHEAD(fd,3);
  1304. -				WFIFOW(fd,0) = 0x6c;
  1305. -				WFIFOB(fd,2) = 0; // rejected from server
  1306. -				WFIFOSET(fd,3);
  1307. -				break;
  1308. -			}
  1309. -
  1310. -			char_id = atoi(data);
  1311. -			Sql_FreeResult(sql_handle);
  1312. -
  1313. -			/* set char as online prior to loading its data so 3rd party applications will realise the sql data is not reliable */
  1314. -			set_char_online(-2,char_id,sd->account_id);
  1315. -			if( !mmo_char_fromsql(char_id, &char_dat, true) ) { /* failed? set it back offline */
  1316. -				set_char_offline(char_id, sd->account_id);
  1317. -				/* failed to load something. REJECT! */
  1318. -				WFIFOHEAD(fd,3);
  1319. -				WFIFOW(fd,0) = 0x6c;
  1320. -				WFIFOB(fd,2) = 0;
  1321. -				WFIFOSET(fd,3);
  1322. -				break;/* jump off this boat */
  1323. -			}
  1324. -
  1325. -			//Have to switch over to the DB instance otherwise data won't propagate [Kevin]
  1326. -			cd = (struct mmo_charstatus *)idb_get(char_db_, char_id);
  1327. -			cd->sex = sd->sex;
  1328. -
  1329. -			if (log_char) {
  1330. -				char esc_name[NAME_LENGTH*2+1];
  1331. -
  1332. -				Sql_EscapeStringLen(sql_handle, esc_name, char_dat.name, strnlen(char_dat.name, NAME_LENGTH));
  1333. -				if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`time`, `account_id`,`char_num`,`name`) VALUES (NOW(), '%d', '%d', '%s')",
  1334. -					charlog_db, sd->account_id, slot, esc_name) )
  1335. -					Sql_ShowDebug(sql_handle);
  1336. -			}
  1337. -			ShowInfo("Selected char: (Account %d: %d - %s)\n", sd->account_id, slot, char_dat.name);
  1338. -
  1339. -			// searching map server
  1340. -			i = search_mapserver(cd->last_point.map, -1, -1);
  1341. -
  1342. -			// if map is not found, we check major cities
  1343. -			if (i < 0 || !cd->last_point.map) {
  1344. -				unsigned short j;
  1345. -				//First check that there's actually a map server online.
  1346. -				ARR_FIND( 0, ARRAYLENGTH(server), j, server[j].fd >= 0 && server[j].map[0] );
  1347. -				if (j == ARRAYLENGTH(server)) {
  1348. -					ShowInfo("Connection Closed. No map servers available.\n");
  1349. -					WFIFOHEAD(fd,3);
  1350. -					WFIFOW(fd,0) = 0x81;
  1351. -					WFIFOB(fd,2) = 1; // 01 = Server closed
  1352. -					WFIFOSET(fd,3);
  1353. -					break;
  1354. -				}
  1355. -				if ((i = search_mapserver((j=mapindex_name2id(MAP_PRONTERA)),-1,-1)) >= 0) {
  1356. -					cd->last_point.x = 273;
  1357. -					cd->last_point.y = 354;
  1358. -				} else if ((i = search_mapserver((j=mapindex_name2id(MAP_GEFFEN)),-1,-1)) >= 0) {
  1359. -					cd->last_point.x = 120;
  1360. -					cd->last_point.y = 100;
  1361. -				} else if ((i = search_mapserver((j=mapindex_name2id(MAP_MORROC)),-1,-1)) >= 0) {
  1362. -					cd->last_point.x = 160;
  1363. -					cd->last_point.y = 94;
  1364. -				} else if ((i = search_mapserver((j=mapindex_name2id(MAP_ALBERTA)),-1,-1)) >= 0) {
  1365. -					cd->last_point.x = 116;
  1366. -					cd->last_point.y = 57;
  1367. -				} else if ((i = search_mapserver((j=mapindex_name2id(MAP_PAYON)),-1,-1)) >= 0) {
  1368. -					cd->last_point.x = 87;
  1369. -					cd->last_point.y = 117;
  1370. -				} else if ((i = search_mapserver((j=mapindex_name2id(MAP_IZLUDE)),-1,-1)) >= 0) {
  1371. -					cd->last_point.x = 94;
  1372. -					cd->last_point.y = 103;
  1373. -				} else {
  1374. -					ShowInfo("Connection Closed. No map server available that has a major city, and unable to find map-server for '%s'.\n", mapindex_id2name(cd->last_point.map));
  1375. -					WFIFOHEAD(fd,3);
  1376. -					WFIFOW(fd,0) = 0x81;
  1377. -					WFIFOB(fd,2) = 1; // 01 = Server closed
  1378. -					WFIFOSET(fd,3);
  1379. -					break;
  1380. -				}
  1381. -				ShowWarning("Unable to find map-server for '%s', sending to major city '%s'.\n", mapindex_id2name(cd->last_point.map), mapindex_id2name(j));
  1382. -				cd->last_point.map = j;
  1383. -			}
  1384. -
  1385. -			//Send NEW auth packet [Kevin]
  1386. -			//FIXME: is this case even possible? [ultramage]
  1387. -			if ((map_fd = server[i].fd) < 1 || session[map_fd] == NULL)
  1388. -			{
  1389. -				ShowError("parse_char: Attempting to write to invalid session %d! Map Server #%d disconnected.\n", map_fd, i);
  1390. -				server[i].fd = -1;
  1391. -				memset(&server[i], 0, sizeof(struct mmo_map_server));
  1392. -				//Send server closed.
  1393. -				WFIFOHEAD(fd,3);
  1394. -				WFIFOW(fd,0) = 0x81;
  1395. -				WFIFOB(fd,2) = 1; // 01 = Server closed
  1396. -				WFIFOSET(fd,3);
  1397. -				break;
  1398. -			}
  1399. -
  1400. -			//Send player to map
  1401. -			WFIFOHEAD(fd,28);
  1402. -			WFIFOW(fd,0) = 0x71;
  1403. -			WFIFOL(fd,2) = cd->char_id;
  1404. -			mapindex_getmapname_ext(mapindex_id2name(cd->last_point.map), (char*)WFIFOP(fd,6));
  1405. -			subnet_map_ip = lan_subnetcheck(ipl); // Advanced subnet check [LuzZza]
  1406. -			WFIFOL(fd,22) = htonl((subnet_map_ip) ? subnet_map_ip : server[i].ip);
  1407. -			WFIFOW(fd,26) = ntows(htons(server[i].port)); // [!] LE byte order here [!]
  1408. -			WFIFOSET(fd,28);
  1409. -
  1410. -			// create temporary auth entry
  1411. -			CREATE(node, struct auth_node, 1);
  1412. -			node->account_id = sd->account_id;
  1413. -			node->char_id = cd->char_id;
  1414. -			node->login_id1 = sd->login_id1;
  1415. -			node->login_id2 = sd->login_id2;
  1416. -			node->sex = sd->sex;
  1417. -			node->expiration_time = sd->expiration_time;
  1418. -			node->group_id = sd->group_id;
  1419. -			node->ip = ipl;
  1420. -			idb_put(auth_db, sd->account_id, node);
  1421. -
  1422. -		}
  1423. -		break;
  1424. -
  1425. -		// create new char
  1426. -#if PACKETVER >= 20120307
  1427. -		// S 0970 <name>.24B <slot>.B <hair color>.W <hair style>.W
  1428. -		case 0x970:
  1429. -			FIFOSD_CHECK(31);
  1430. -#else
  1431. -		// S 0067 <name>.24B <str>.B <agi>.B <vit>.B <int>.B <dex>.B <luk>.B <slot>.B <hair color>.W <hair style>.W
  1432. -		case 0x67:
  1433. -			FIFOSD_CHECK(37);
  1434. -#endif
  1435. -
  1436. -			if( !char_new ) //turn character creation on/off [Kevin]
  1437. -				i = -2;
  1438. -			else
  1439. -#if PACKETVER >= 20120307
  1440. -				i = make_new_char_sql(sd, (char*)RFIFOP(fd,2),RFIFOB(fd,26),RFIFOW(fd,27),RFIFOW(fd,29));
  1441. -#else
  1442. -				i = make_new_char_sql(sd, (char*)RFIFOP(fd,2),RFIFOB(fd,26),RFIFOB(fd,27),RFIFOB(fd,28),RFIFOB(fd,29),RFIFOB(fd,30),RFIFOB(fd,31),RFIFOB(fd,32),RFIFOW(fd,33),RFIFOW(fd,35));
  1443. -#endif
  1444. -
  1445. -			//'Charname already exists' (-1), 'Char creation denied' (-2) and 'You are underaged' (-3)
  1446. -			if (i < 0) {
  1447. -				WFIFOHEAD(fd,3);
  1448. -				WFIFOW(fd,0) = 0x6e;
  1449. -				/* Others I found [Ind] */
  1450. -				/* 0x02 = Symbols in Character Names are forbidden */
  1451. -				/* 0x03 = You are not elegible to open the Character Slot. */
  1452. -				switch (i) {
  1453. -					case -1: WFIFOB(fd,2) = 0x00; break;
  1454. -					case -2: WFIFOB(fd,2) = 0xFF; break;
  1455. -					case -3: WFIFOB(fd,2) = 0x01; break;
  1456. -					case -4: WFIFOB(fd,2) = 0x03; break;
  1457. -				}
  1458. -				WFIFOSET(fd,3);
  1459. -			} else {
  1460. -				int len;
  1461. -				// retrieve data
  1462. -				struct mmo_charstatus char_dat;
  1463. -				mmo_char_fromsql(i, &char_dat, false); //Only the short data is needed.
  1464. -
  1465. -				// send to player
  1466. -				WFIFOHEAD(fd,2+MAX_CHAR_BUF);
  1467. -				WFIFOW(fd,0) = 0x6d;
  1468. -				len = 2 + mmo_char_tobuf(WFIFOP(fd,2), &char_dat);
  1469. -				WFIFOSET(fd,len);
  1470. -
  1471. -				// add new entry to the chars list
  1472. -				ARR_FIND( 0, MAX_CHARS, ch, sd->found_char[ch] == -1 );
  1473. -				if( ch < MAX_CHARS )
  1474. -					sd->found_char[ch] = i; // the char_id of the new char
  1475. -			}
  1476. -#if PACKETVER >= 20120307
  1477. -			RFIFOSKIP(fd,31);
  1478. -#else
  1479. -			RFIFOSKIP(fd,37);
  1480. -#endif
  1481. -		break;
  1482. -
  1483. +		case 0x66: char_parse_charselect(fd,sd,ipl); break;
  1484. +		// createnewchar
  1485. +		case 0x970: char_parse_createnewchar(fd,sd,cmd); break;
  1486. +		case 0x67: char_parse_createnewchar(fd,sd,cmd); break;
  1487.  		// delete char
  1488. -		case 0x68:
  1489. -		// 2004-04-19aSakexe+ langtype 12 char deletion packet
  1490. -		case 0x1fb:
  1491. -			if (cmd == 0x68) FIFOSD_CHECK(46);
  1492. -			if (cmd == 0x1fb) FIFOSD_CHECK(56);
  1493. -		{
  1494. -			int cid = RFIFOL(fd,2);
  1495. -
  1496. -			ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, cid);
  1497. -			memcpy(email, RFIFOP(fd,6), 40);
  1498. -			RFIFOSKIP(fd,( cmd == 0x68) ? 46 : 56);
  1499. -
  1500. -			// Check if e-mail is correct
  1501. -			if(strcmpi(email, sd->email) && //email does not matches and
  1502. -			(
  1503. -				strcmp("[email protected]", sd->email) || //it is not default email, or
  1504. -				(strcmp("[email protected]", email) && strcmp("", email)) //email sent does not matches default
  1505. -			)) {	//Fail
  1506. -				WFIFOHEAD(fd,3);
  1507. -				WFIFOW(fd,0) = 0x70;
  1508. -				WFIFOB(fd,2) = 0; // 00 = Incorrect Email address
  1509. -				WFIFOSET(fd,3);
  1510. -				break;
  1511. -			}
  1512. -
  1513. -			// check if this char exists
  1514. -			ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid );
  1515. -			if( i == MAX_CHARS )
  1516. -			{ // Such a character does not exist in the account
  1517. -				WFIFOHEAD(fd,3);
  1518. -				WFIFOW(fd,0) = 0x70;
  1519. -				WFIFOB(fd,2) = 0;
  1520. -				WFIFOSET(fd,3);
  1521. -				break;
  1522. -			}
  1523. -
  1524. -			// remove char from list and compact it
  1525. -			for(ch = i; ch < MAX_CHARS-1; ch++)
  1526. -				sd->found_char[ch] = sd->found_char[ch+1];
  1527. -			sd->found_char[MAX_CHARS-1] = -1;
  1528. -
  1529. -			/* Delete character */
  1530. -			if(delete_char_sql(cid)<0){
  1531. -				//can't delete the char
  1532. -				//either SQL error or can't delete by some CONFIG conditions
  1533. -				//del fail
  1534. -				WFIFOHEAD(fd,3);
  1535. -				WFIFOW(fd, 0) = 0x70;
  1536. -				WFIFOB(fd, 2) = 0;
  1537. -				WFIFOSET(fd, 3);
  1538. -				break;
  1539. -			}
  1540. -			/* Char successfully deleted.*/
  1541. -			WFIFOHEAD(fd,2);
  1542. -			WFIFOW(fd,0) = 0x6f;
  1543. -			WFIFOSET(fd,2);
  1544. -		}
  1545. -		break;
  1546. -
  1547. +		case 0x68: char_parse_delchar(fd,sd,cmd); break; //
  1548. +		case 0x1fb: char_parse_delchar(fd,sd,cmd); break; // 2004-04-19aSakexe+ langtype 12 char deletion packet
  1549.  		// client keep-alive packet (every 12 seconds)
  1550. -		// R 0187 <account ID>.l
  1551. -		case 0x187:
  1552. -			if (RFIFOREST(fd) < 6)
  1553. -				return 0;
  1554. -			RFIFOSKIP(fd,6);
  1555. -		break;
  1556. -		// char rename request
  1557. -		// R 08fc <char ID>.l <new name>.24B
  1558. -		case 0x8fc:
  1559. -			FIFOSD_CHECK(30);
  1560. -			{
  1561. -				int i, cid =RFIFOL(fd,2);
  1562. -				char name[NAME_LENGTH];
  1563. -				char esc_name[NAME_LENGTH*2+1];
  1564. -				safestrncpy(name, (char *)RFIFOP(fd,6), NAME_LENGTH);
  1565. -				RFIFOSKIP(fd,30);
  1566. -
  1567. -				ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid );
  1568. -				if( i == MAX_CHARS )
  1569. -					break;
  1570. -
  1571. -				normalize_name(name,TRIM_CHARS);
  1572. -				Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH));
  1573. -				if( !check_char_name(name,esc_name) ) {
  1574. -					i = 1;
  1575. -					safestrncpy(sd->new_name, name, NAME_LENGTH);
  1576. -				} else
  1577. -					i = 0;
  1578. -
  1579. -				WFIFOHEAD(fd, 4);
  1580. -				WFIFOW(fd,0) = 0x28e;
  1581. -				WFIFOW(fd,2) = i;
  1582. -				WFIFOSET(fd,4);
  1583. -			}
  1584. -			break;
  1585. -
  1586. -		// char rename request
  1587. -		// R 028d <account ID>.l <char ID>.l <new name>.24B
  1588. -		case 0x28d:
  1589. -			FIFOSD_CHECK(34);
  1590. -			{
  1591. -				int i, aid = RFIFOL(fd,2), cid =RFIFOL(fd,6);
  1592. -				char name[NAME_LENGTH];
  1593. - 				char esc_name[NAME_LENGTH*2+1];
  1594. -				safestrncpy(name, (char *)RFIFOP(fd,10), NAME_LENGTH);
  1595. -				RFIFOSKIP(fd,34);
  1596. -
  1597. -				if( aid != sd->account_id )
  1598. -					break;
  1599. -				ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid );
  1600. -				if( i == MAX_CHARS )
  1601. -					break;
  1602. -
  1603. -				normalize_name(name,TRIM_CHARS);
  1604. -				Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH));
  1605. -				if( !check_char_name(name,esc_name) )
  1606. -				{
  1607. -					i = 1;
  1608. -					safestrncpy(sd->new_name, name, NAME_LENGTH);
  1609. -				}
  1610. -				else
  1611. -					i = 0;
  1612. -
  1613. -				WFIFOHEAD(fd, 4);
  1614. -				WFIFOW(fd,0) = 0x28e;
  1615. -				WFIFOW(fd,2) = i;
  1616. -				WFIFOSET(fd,4);
  1617. -			}
  1618. -			break;
  1619. -		//Confirm change name.
  1620. -		// 0x28f <char_id>.L
  1621. -		case 0x28f:
  1622. -			// 0: Sucessfull
  1623. -			// 1: This character's name has already been changed. You cannot change a character's name more than once.
  1624. -			// 2: User information is not correct.
  1625. -			// 3: You have failed to change this character's name.
  1626. -			// 4: Another user is using this character name, so please select another one.
  1627. -			FIFOSD_CHECK(6);
  1628. -			{
  1629. -				int i;
  1630. -				int cid = RFIFOL(fd,2);
  1631. -				RFIFOSKIP(fd,6);
  1632. -
  1633. -				ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid );
  1634. -				if( i == MAX_CHARS )
  1635. -					break;
  1636. -				i = rename_char_sql(sd, cid);
  1637. -
  1638. -				WFIFOHEAD(fd, 4);
  1639. -				WFIFOW(fd,0) = 0x290;
  1640. -				WFIFOW(fd,2) = i;
  1641. -				WFIFOSET(fd,4);
  1642. -			}
  1643. -			break;
  1644. -
  1645. -		// captcha code request (not implemented)
  1646. -		// R 07e5 <?>.w <aid>.l
  1647. -		case 0x7e5:
  1648. -			WFIFOHEAD(fd,5);
  1649. -			WFIFOW(fd,0) = 0x7e9;
  1650. -			WFIFOW(fd,2) = 5;
  1651. -			WFIFOB(fd,4) = 1;
  1652. -			WFIFOSET(fd,5);
  1653. -			RFIFOSKIP(fd,8);
  1654. -			break;
  1655. -
  1656. -		// captcha code check (not implemented)
  1657. -		// R 07e7 <len>.w <aid>.l <code>.b10 <?>.b14
  1658. -		case 0x7e7:
  1659. -			WFIFOHEAD(fd,5);
  1660. -			WFIFOW(fd,0) = 0x7e9;
  1661. -			WFIFOW(fd,2) = 5;
  1662. -			WFIFOB(fd,4) = 1;
  1663. -			WFIFOSET(fd,5);
  1664. -			RFIFOSKIP(fd,32);
  1665. -		break;
  1666. -
  1667. +		case 0x187: char_parse_keepalive(fd); break;
  1668. +		// char rename
  1669. +		case 0x8fc: char_parse_reqrename(fd,sd,cmd); break; //request <date/version?>
  1670. +		case 0x28d: char_parse_reqrename(fd,sd,cmd); break; //request <date/version?>
  1671. +		case 0x28f: char_parse_ackrename(fd,sd); break; //Confirm change name.
  1672. +		// captcha
  1673. +		case 0x7e5: char_parse_reqcaptcha(fd); break; // captcha code request (not implemented)
  1674. +		case 0x7e7: char_parse_chkcaptcha(fd); break; // captcha code check (not implemented)
  1675.  		// deletion timer request
  1676. -		case 0x827:
  1677. -			FIFOSD_CHECK(6);
  1678. -			char_delete2_req(fd, sd);
  1679. -			RFIFOSKIP(fd,6);
  1680. -		break;
  1681. -
  1682. +		case 0x827: char_delete2_req(fd, sd); break;
  1683.  		// deletion accept request
  1684. -		case 0x829:
  1685. -			FIFOSD_CHECK(12);
  1686. -			char_delete2_accept(fd, sd);
  1687. -			RFIFOSKIP(fd,12);
  1688. -		break;
  1689. -
  1690. +		case 0x829: char_delete2_accept(fd, sd); break;
  1691.  		// deletion cancel request
  1692. -		case 0x82b:
  1693. -			FIFOSD_CHECK(6);
  1694. -			char_delete2_cancel(fd, sd);
  1695. -			RFIFOSKIP(fd,6);
  1696. -		break;
  1697. -
  1698. +		case 0x82b: char_delete2_cancel(fd, sd); break;
  1699.  		// login as map-server
  1700. -		case 0x2af8:
  1701. -			if (RFIFOREST(fd) < 60)
  1702. -				return 0;
  1703. -			else {
  1704. -				char* l_user = (char*)RFIFOP(fd,2);
  1705. -				char* l_pass = (char*)RFIFOP(fd,26);
  1706. -				l_user[23] = '\0';
  1707. -				l_pass[23] = '\0';
  1708. -				ARR_FIND( 0, ARRAYLENGTH(server), i, server[i].fd <= 0 );
  1709. -				if( runflag != CHARSERVER_ST_RUNNING ||
  1710. -					i == ARRAYLENGTH(server) ||
  1711. -					strcmp(l_user, userid) != 0 ||
  1712. -					strcmp(l_pass, passwd) != 0 )
  1713. -				{
  1714. -					WFIFOHEAD(fd,3);
  1715. -					WFIFOW(fd,0) = 0x2af9;
  1716. -					WFIFOB(fd,2) = 3;
  1717. -					WFIFOSET(fd,3);
  1718. -				} else {
  1719. -					WFIFOHEAD(fd,3);
  1720. -					WFIFOW(fd,0) = 0x2af9;
  1721. -					WFIFOB(fd,2) = 0;
  1722. -					WFIFOSET(fd,3);
  1723. -
  1724. -					server[i].fd = fd;
  1725. -					server[i].ip = ntohl(RFIFOL(fd,54));
  1726. -					server[i].port = ntohs(RFIFOW(fd,58));
  1727. -					server[i].users = 0;
  1728. -					memset(server[i].map, 0, sizeof(server[i].map));
  1729. -					session[fd]->func_parse = parse_frommap;
  1730. -					session[fd]->flag.server = 1;
  1731. -					realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
  1732. -					char_mapif_init(fd);
  1733. -				}
  1734. -				RFIFOSKIP(fd,60);
  1735. -			}
  1736. -			return 0; // avoid processing of followup packets here
  1737. -
  1738. -		// checks the entered pin
  1739. -		case 0x8b8:
  1740. -			if( RFIFOREST(fd) < 10 )
  1741. -				return 0;
  1742. -			if( pincode_enabled && RFIFOL(fd,2) == sd->account_id )
  1743. -				pincode_check( fd, sd );
  1744. -			RFIFOSKIP(fd,10);
  1745. -		break;
  1746. -
  1747. -		// request for PIN window
  1748. -		case 0x8c5:
  1749. -			if( RFIFOREST(fd) < 6 )
  1750. -				return 0;
  1751. -			if( pincode_enabled && RFIFOL(fd,2) == sd->account_id ){
  1752. -				if( strlen( sd->pincode ) <= 0 ){
  1753. -					pincode_sendstate( fd, sd, PINCODE_NEW );
  1754. -				}else{
  1755. -					pincode_sendstate( fd, sd, PINCODE_ASK );
  1756. -				}
  1757. -			}
  1758. -			RFIFOSKIP(fd,6);
  1759. -		break;
  1760. -
  1761. -		// pincode change request
  1762. -		case 0x8be:
  1763. -			if( RFIFOREST(fd) < 14 )
  1764. -				return 0;
  1765. -
  1766. -			if( pincode_enabled && RFIFOL(fd,2) == sd->account_id )
  1767. -				pincode_change( fd, sd );
  1768. -
  1769. -			RFIFOSKIP(fd,14);
  1770. -		break;
  1771. -
  1772. -		// activate PIN system and set first PIN
  1773. -		case 0x8ba:
  1774. -			if( RFIFOREST(fd) < 10 )
  1775. -				return 0;
  1776. -			if( pincode_enabled && RFIFOL(fd,2) == sd->account_id )
  1777. -				pincode_setnew( fd, sd );
  1778. -			RFIFOSKIP(fd,10);
  1779. -		break;
  1780. -
  1781. +		case 0x2af8: char_parse_maplogin(fd); return 0; // avoid processing of followup packets here
  1782. +		//pincode
  1783. +		case 0x8b8: pincode_check( fd, sd ); break; // checks the entered pin
  1784. +		case 0x8c5: char_parse_reqpincode_window(fd,sd); break; // request for PIN window
  1785. +		case 0x8be: pincode_change( fd, sd ); break; // pincode change request
  1786. +		case 0x8ba: pincode_setnew( fd, sd ); break; // activate PIN system and set first PIN
  1787.  		// character movement request
  1788. -		case 0x8d4:
  1789. -			if( RFIFOREST(fd) < 8 )
  1790. -				return 0;
  1791. +		case 0x8d4: moveCharSlot(fd,sd); break;
  1792.  
  1793. -			moveCharSlot( fd, sd, RFIFOW(fd, 2), RFIFOW(fd, 4) );
  1794. -			mmo_char_send(fd, sd);
  1795. -			RFIFOSKIP(fd,8);
  1796. -		break;
  1797. -
  1798.  		case 0x9a1:
  1799.  			if( RFIFOREST(fd) < 2 )
  1800.  				return 0;
  1801. @@ -4598,18 +4561,37 @@
  1802.  //------------------------------------------------
  1803.  //Pincode system
  1804.  //------------------------------------------------
  1805. -void pincode_check( int fd, struct char_session_data* sd ){
  1806. +int char_parse_reqpincode_window(int fd, struct char_session_data* sd){
  1807. +	if( RFIFOREST(fd) < 6 )
  1808. +		return 0;
  1809. +	if( pincode_enabled && RFIFOL(fd,2) == sd->account_id ){
  1810. +		if( strlen( sd->pincode ) <= 0 ){
  1811. +			pincode_sendstate( fd, sd, PINCODE_NEW );
  1812. +		}else{
  1813. +			pincode_sendstate( fd, sd, PINCODE_ASK );
  1814. +		}
  1815. +	}
  1816. +	RFIFOSKIP(fd,6);
  1817. +	return 1;
  1818. +}
  1819. +
  1820. +int pincode_check( int fd, struct char_session_data* sd ){
  1821.  	char pin[PINCODE_LENGTH+1];
  1822.  
  1823. +	if( RFIFOREST(fd) < 10 )
  1824. +		return 0;
  1825. +	if( pincode_enabled==0 || RFIFOL(fd,2) != sd->account_id )
  1826. +		return 0;
  1827. +
  1828.  	memset(pin,0,PINCODE_LENGTH+1);
  1829. -
  1830.  	strncpy((char*)pin, (char*)RFIFOP(fd, 6), PINCODE_LENGTH);
  1831. +	RFIFOSKIP(fd,10);
  1832.  
  1833.  	pincode_decrypt(sd->pincode_seed, pin );
  1834. -
  1835.  	if( pincode_compare( fd, sd, pin ) ){
  1836.  		pincode_sendstate( fd, sd, PINCODE_PASSED );
  1837.  	}
  1838. +	return 1;
  1839.  }
  1840.  
  1841.  int pincode_compare( int fd, struct char_session_data* sd, char* pin ){
  1842. @@ -4627,34 +4609,46 @@
  1843.  	}
  1844.  }
  1845.  
  1846. -void pincode_change( int fd, struct char_session_data* sd ){
  1847. +int pincode_change( int fd, struct char_session_data* sd ){
  1848.  	char oldpin[PINCODE_LENGTH+1];
  1849.  	char newpin[PINCODE_LENGTH+1];
  1850.  
  1851. +	if( RFIFOREST(fd) < 14 )
  1852. +		return 0;
  1853. +	if( pincode_enabled==0 || RFIFOL(fd,2) != sd->account_id )
  1854. +		return 0;
  1855. +
  1856.  	memset(oldpin,0,PINCODE_LENGTH+1);
  1857.  	memset(newpin,0,PINCODE_LENGTH+1);
  1858. +	strncpy(oldpin, (char*)RFIFOP(fd,6), PINCODE_LENGTH);
  1859. +	strncpy(newpin, (char*)RFIFOP(fd,10), PINCODE_LENGTH);
  1860. +	RFIFOSKIP(fd,14);
  1861.  
  1862. -	strncpy(oldpin, (char*)RFIFOP(fd,6), PINCODE_LENGTH);
  1863.  	pincode_decrypt(sd->pincode_seed,oldpin);
  1864. -
  1865.  	if( !pincode_compare( fd, sd, oldpin ) )
  1866. -		return;
  1867. -
  1868. -	strncpy(newpin, (char*)RFIFOP(fd,10), PINCODE_LENGTH);
  1869. +		return 0;
  1870.  	pincode_decrypt(sd->pincode_seed,newpin);
  1871.  
  1872.  	pincode_notifyLoginPinUpdate( sd->account_id, newpin );
  1873.  	strncpy(sd->pincode, newpin, sizeof(newpin));
  1874.  
  1875.  	pincode_sendstate( fd, sd, PINCODE_PASSED );
  1876. +	return 1;
  1877.  }
  1878.  
  1879. -void pincode_setnew( int fd, struct char_session_data* sd ){
  1880. +int pincode_setnew( int fd, struct char_session_data* sd ){
  1881.  	char newpin[PINCODE_LENGTH+1];
  1882.  
  1883.  	memset(newpin,0,PINCODE_LENGTH+1);
  1884.  
  1885. +	if( RFIFOREST(fd) < 10 )
  1886. +		return 0;
  1887. +
  1888. +	if( pincode_enabled==0 || RFIFOL(fd,2) != sd->account_id )
  1889. +		return 0;
  1890.  	strncpy( newpin, (char*)RFIFOP(fd,6), PINCODE_LENGTH );
  1891. +	RFIFOSKIP(fd,10);
  1892. +
  1893.  	pincode_decrypt( sd->pincode_seed, newpin );
  1894.  
  1895.  	pincode_notifyLoginPinUpdate( sd->account_id, newpin );
  1896. @@ -4724,17 +4718,26 @@
  1897.  //------------------------------------------------
  1898.  //Add On system
  1899.  //------------------------------------------------
  1900. -void moveCharSlot( int fd, struct char_session_data* sd, unsigned short from, unsigned short to ){
  1901. +int moveCharSlot( int fd, struct char_session_data* sd){
  1902. +	uint16 from, to;
  1903. +
  1904. +	if( RFIFOREST(fd) < 8 )
  1905. +		return 0;
  1906. +	from = RFIFOW(fd,2);
  1907. +	to = RFIFOW(fd,4);
  1908. +	//Cnt = RFIFOW(fd,6); //how many time we have left to change (client.. lol we don't trust him)
  1909. +	RFIFOSKIP(fd,8);
  1910. +
  1911.  	// Have we changed to often or is it disabled?
  1912.  	if( !char_move_enabled || ( !char_moves_unlimited && sd->char_moves[from] <= 0 ) ){
  1913.  		moveCharSlotReply( fd, sd, from, 1 );
  1914. -		return;
  1915. +		return 0;
  1916.  	}
  1917.  
  1918.  	// We dont even have a character on the chosen slot?
  1919.  	if( sd->found_char[from] <= 0 ){
  1920.  		moveCharSlotReply( fd, sd, from, 1 );
  1921. -		return;
  1922. +		return 0;
  1923.  	}
  1924.  
  1925.  	if( sd->found_char[to] > 0 ){
  1926. @@ -4749,7 +4752,7 @@
  1927.  				moveCharSlotReply( fd, sd, from, 1 );
  1928.  				Sql_ShowDebug(sql_handle);
  1929.  				Sql_QueryStr(sql_handle,"ROLLBACK");
  1930. -				return;
  1931. +				return 0;
  1932.  			}
  1933.  		}else{
  1934.  			// Admin doesnt allow us to
  1935. @@ -4759,7 +4762,7 @@
  1936.  	}else if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_num`='%d' WHERE `char_id`='%d'", char_db, to, sd->found_char[from] ) ){
  1937.  		Sql_ShowDebug(sql_handle);
  1938.  		moveCharSlotReply( fd, sd, from, 1 );
  1939. -		return;
  1940. +		return 0;
  1941.  	}
  1942.  
  1943.  	if( !char_moves_unlimited ){
  1944. @@ -4770,6 +4773,7 @@
  1945.  	// We successfully moved the char - time to notify the client
  1946.  	moveCharSlotReply( fd, sd, from, 0 );
  1947.  	mmo_char_send(fd, sd);
  1948. +	return 1;
  1949.  }
  1950.  
  1951.  // reason
  1952. Index: src/common/socket.c
  1953. ===================================================================
  1954. --- src/common/socket.c	(revision 17365)
  1955. +++ src/common/socket.c	(working copy)
  1956. @@ -637,7 +637,7 @@
  1957.  /// advance the RFIFO cursor (marking 'len' bytes as processed)
  1958.  int RFIFOSKIP(int fd, size_t len)
  1959.  {
  1960. -    struct socket_data *s;
  1961. +	struct socket_data *s;
  1962.  
  1963.  	if ( !session_isActive(fd) )
  1964.  		return 0;
  1965. Index: db/packet_db.txt
  1966. ===================================================================
  1967. --- db/packet_db.txt	(revision 17365)
  1968. +++ db/packet_db.txt	(working copy)
  1969. @@ -1416,7 +1416,7 @@
  1970.  
  1971.  //2009-08-18aRagexeRE
  1972.  0x07e3,6
  1973. -0x07e4,-1,itemlistwindowselected,2:4:8
  1974. +0x07e4,-1,itemlistwindowselected,2:4:8:12
  1975.  0x07e6,8
  1976.  
  1977.  //2009-08-25aRagexeRE
  1978. @@ -1612,7 +1612,7 @@
  1979.  
  1980.  //2010-11-24aRagexeRE
  1981.  packet_ver: 26
  1982. -0x0288,-1,cashshopbuy,2:4:8:10
  1983. +0x0288,-1,cashshopbuy,2:4:6:10
  1984.  0x0436,19,wanttoconnection,2:6:10:14:18
  1985.  0x035f,5,walktoxy,2
  1986.  0x0360,6,ticksend,2
  1987. @@ -1658,7 +1658,7 @@
  1988.  0x083c,19,wanttoconnection,2:6:10:14:18
  1989.  0x08aa,7,actionrequest,2:6
  1990.  0x02c4,10,useskilltoid,2:4:6
  1991. -0x0811,-1,itemlistwindowselected,2:4:8
  1992. +0x0811,-1,itemlistwindowselected,2:4:8:12
  1993.  0x890,8
  1994.  0x08a5,18,bookingregreq,2:4:6
  1995.  0x0835,-1,reqopenbuyingstore,2:4:8:9:89
  1996. @@ -1689,7 +1689,7 @@
  1997.  0x0929,26,partyinvite2,2
  1998.  0x0885,7,actionrequest,2:6
  1999.  0x0889,10,useskilltoid,2:4:6
  2000. -0x0870,-1,itemlistwindowselected,2:4:8
  2001. +0x0870,-1,itemlistwindowselected,2:4:8:12
  2002.  //0x0926,18,bookingregreq,2:4:6
  2003.  0x0815,-1,reqopenbuyingstore,2:4:8:9:89
  2004.  0x0817,2,reqclosebuyingstore,0
  2005. @@ -1707,13 +1707,13 @@
  2006.  0x089c,26,friendslistadd,2
  2007.  0x0885,5,hommenu,2:4
  2008.  0x0961,36,storagepassword,2:4:20
  2009. -0x0288,-1,cashshopbuy,2:4:8:10
  2010. +0x0288,-1,cashshopbuy,2:4:6:10
  2011.  0x091c,26,partyinvite2,2
  2012.  0x094b,19,wanttoconnection,2:6:10:14:18
  2013.  0x0369,7,actionrequest,2:6
  2014.  0x083c,10,useskilltoid,2:4:6
  2015.  0x0439,8,useitem,2:4
  2016. -0x0945,-1,itemlistwindowselected,2:4:8
  2017. +0x0945,-1,itemlistwindowselected,2:4:8:12
  2018.  0x0815,-1,reqopenbuyingstore,2:4:8:9:89
  2019.  0x0817,2,reqclosebuyingstore,0
  2020.  0x0360,6,reqclickbuyingstore,2
  2021. @@ -1769,7 +1769,7 @@
  2022.  0x08A8,36,storagepassword,2:4:20
  2023.  0x0802,26,partyinvite2,2
  2024.  0x022D,19,wanttoconnection,2:6:10:14:18
  2025. -0x0281,-1,itemlistwindowselected,2:4:8
  2026. +0x0281,-1,itemlistwindowselected,2:4:8:12
  2027.  0x035F,6,ticksend,2
  2028.  0x0202,5,changedir,2:4
  2029.  0x07E4,6,takeitem,2
  2030. @@ -1808,7 +1808,7 @@
  2031.  packet_ver: 34
  2032.  0x014f,6,guildrequestinfo,2
  2033.  0x01fd,15,repairitem,2:4:6:7:9:11:13
  2034. -//0x0281,-1,itemlistwindowselected,2:4:8
  2035. +//0x0281,-1,itemlistwindowselected,2:4:8:12
  2036.  0x035f,6,reqclickbuyingstore,2
  2037.  0x0363,6,ticksend,2
  2038.  0x0365,12,searchstoreinfolistitemclick,2:6:10
  2039. @@ -1821,7 +1821,7 @@
  2040.  0x084b,19 //fallitem4
  2041.  0x085a,90,useskilltoposinfo,2:4:6:8:10
  2042.  0x085d,18,bookingregreq,2:4:6
  2043. -0x0868,-1,itemlistwindowselected,2:4:8
  2044. +0x0868,-1,itemlistwindowselected,2:4:8:12
  2045.  0x086d,26,partyinvite2,2
  2046.  0x086f,26,friendslistadd,2
  2047.  0x0874,8,movefromkafra,2:4
  2048. @@ -1891,7 +1891,7 @@
  2049.  0x0815,-1,reqopenbuyingstore,2:4:8:9:89
  2050.  0x092D,18,bookingregreq,2:4:6
  2051.  //0x08AA,8 CZ_JOIN_BATTLE_FIELD
  2052. -0x0963,-1,itemlistwindowselected,2:4:8
  2053. +0x0963,-1,itemlistwindowselected,2:4:8:12
  2054.  0x0943,19,wanttoconnection,2:6:10:14:18
  2055.  0x0947,26,partyinvite2,2
  2056.  //0x0862,4 CZ_GANGSI_RANK
  2057. @@ -1923,7 +1923,7 @@
  2058.  0x0874,-1,reqopenbuyingstore,2:4:8:9:89
  2059.  0x089B,18,bookingregreq,2:4:6
  2060.  //0x0965,8 CZ_JOIN_BATTLE_FIELD
  2061. -0x086A,-1,itemlistwindowselected,2:4:8
  2062. +0x086A,-1,itemlistwindowselected,2:4:8:12
  2063.  0x08A9,19,wanttoconnection,2:6:10:14:18
  2064.  0x0950,26,partyinvite2,2
  2065.  //0x08AC,4 CZ_GANGSI_RANK
  2066. @@ -1955,7 +1955,7 @@
  2067.  0x0869,-1,reqopenbuyingstore,2:4:8:9:89
  2068.  0x0874,41,bookingregreq,2,4:6
  2069.  // 0x088E,8); // CZ_JOIN_BATTLE_FIELD
  2070. -0x0958,-1,itemlistwindowselected,2:4:8
  2071. +0x0958,-1,itemlistwindowselected,2:4:8:12
  2072.  0x0919,19,wanttoconnection,2:6:10:14:18
  2073.  0x08A8,26,partyinvite2,2
  2074.  // 0x0888,4); // CZ_GANGSI_RANK
  2075. @@ -1987,7 +1987,7 @@
  2076.  0x0815,-1,reqopenbuyingstore,2:4:8:9:89
  2077.  0x0365,41,bookingregreq,2:4:6
  2078.  // 0x0363,8 // CZ_JOIN_BATTLE_FIELD
  2079. -0x0281,-1,itemlistwindowselected,2:4:8
  2080. +0x0281,-1,itemlistwindowselected,2:4:8:12
  2081.  0x022D,19,wanttoconnection,2:6:10:14:18
  2082.  0x0802,26,partyinvite2,2
  2083.  // 0x0436,4 // CZ_GANGSI_RANK
  2084. @@ -2019,7 +2019,7 @@
  2085.  0x0815,-1,reqopenbuyingstore,2:4:8:9:89
  2086.  0x0365,18,bookingregreq,2:4:6
  2087.  // 0x0363,8 CZ_JOIN_BATTLE_FIELD
  2088. -0x0281,-1,itemlistwindowselected,2:4:8
  2089. +0x0281,-1,itemlistwindowselected,2:4:8:12
  2090.  0x0919,19,wanttoconnection,2:6:10:14:18
  2091.  0x0802,26,partyinvite2,2
  2092.  // 0x0436,4 CZ_GANGSI_RANK
  2093.  
Viewed 1149 times, submitted by lighta.