Browse Source

* Updated "Calyon" NPC in El Dicastes quests, fixing an incorrect condition.

> Hercules merges:
* 2bc8562, 126225b:
Skills granted through scripts are now permanent, until this date they were not relog persistent. (bugreport:5018)
Note that you will need to execute /sql-files/upgrades/upgrade_svn17136.sql for this change.

* b8379d2:
@skillid now supports partial search.

* d7ce0c1:
Character's online states are now updated as soon as they attempt a char select, instead of at the end of the procedure. This improves reliability with 3rd party software e.g. control panels. (bugreport:7269)

* d828000:
Login and Char servers will now exit when failing to bind to the port (as map server has always done).

* 003ed2c:
Moved "Honeymoon Helper" and "Odgnalam" NPCs to official RE coordinates.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@17136 54d463be-8e91-2dee-dedb-b68131a5f0ec
euphyy 12 years ago
parent
commit
f3e4ef5067

+ 4 - 1
conf/msg_athena.conf

@@ -1013,7 +1013,7 @@
 
 // @skillid
 1163: Please enter a skill name to look up (usage: @skillid <skill name>).
-1164: skill %d: %s
+1164: skill %d: %s (%s)
 
 // @useskill
 1165: Usage: @useskill <skill ID> <skill level> <target>
@@ -1406,5 +1406,8 @@
 1396: You do not have a cart to be cleaned.
 1397: Your cart was cleaned.
 
+// @skillid (extension)
+1398: -- Displaying first %d partial matches:
+
 //Custom translations
 import: conf/import/msg_conf.txt

+ 2 - 1
npc/re/cities/jawaii.txt

@@ -10,6 +10,7 @@
 //= Jawaii town NPCs.
 //===== Additional Comments: =================================
 //= 1.0 First Version. Renewal coordinates by Masao.
+//= 1.1 Moved "Honeymoon Helper" NPC.
 //============================================================
 
-izlude,102,150,6	duplicate(Honeymoon_Helper_Izlude)	Honeymoon Helper#Izlude	71
+izlude,180,224,6	duplicate(Honeymoon_Helper_Izlude)	Honeymoon Helper#Izlude	71

+ 4 - 4
npc/re/cities/malangdo.txt

@@ -3,7 +3,7 @@
 //===== By: ================================================== 
 //= Muad_Dib
 //===== Current Version: ===================================== 
-//= 1.1
+//= 1.2
 //===== Compatible With: ===================================== 
 //= rAthena SVN
 //===== Description: ========================================= 
@@ -11,6 +11,7 @@
 //===== Additional Comments: ================================= 
 //= 1.0 First version. [Euphy]
 //= 1.1 Added entrance scripts.
+//= 1.2 Moved "Odgnalam" NPC.
 //============================================================
 
 // Entrance :: malangdo_go
@@ -150,9 +151,8 @@ rachel,121,126,4	duplicate(Dolangmal)	Dolangmal#7	553
 lighthalzen,254,83,5	duplicate(Dolangmal)	Dolangmal#8	553
 mora,57,150,4	duplicate(Dolangmal)	Dolangmal#9	553
 
-// Unofficial coordinates.
-// Original pre-re: izlude,182,192,4
-izlude,197,213,4	script	Odgnalam#iz	554,{
+//Pre-RE: izlude (182,192)
+izlude,182,218,4	script	Odgnalam#iz	554,{
 	if (strnpcinfo(4) == "izlude")
 		mes "Receiving the warm sun of Izlude, the cat is sleeping.";
 	else if (strnpcinfo(4) == "alberta")

+ 1 - 1
npc/re/guides/guides_izlude.txt

@@ -128,7 +128,7 @@
 					mes "^8B4513Jawaii^000000, the paradise of newlyweds,";
 					mes "please speak to the ^B9062FNewlywed Helper^000000.";
 					mes "Would you like to check any other locations?";
-					viewpoint 1,102,150,9,0xFF0000;
+					viewpoint 1,180,224,9,0xFF0000;
 					next;
 					break;
 				case 4:

+ 168 - 151
npc/re/quests/quests_dicastes.txt

@@ -3,7 +3,7 @@
 //===== By: ==================================================
 //= Gennosuke Kouga, Muad_Dib
 //===== Current Version: =====================================
-//= 1.8a
+//= 1.8b
 //===== Compatible With: =====================================
 //= rAthena SVN
 //===== Description: =========================================
@@ -25,6 +25,7 @@
 //= 1.7 Updated to match the official script. [Joseph]
 //= 1.8 Optimized and fixed invalid checkquest. [Joseph]
 //= 1.8a Disabled "Fish Tails" until Izlude RE coordinates are found. [Euphy]
+//= 1.8b Updated "Calyon" NPC and fixed a check. [Euphy]
 //============================================================
 
 // Entrance
@@ -2279,159 +2280,175 @@ dic_in01,158,188,3	script	Jarute HesLanta#ep133_2	451,{
 }
 
 dicastes01,223,190,1	script	Calyon#pa8029	453,{
+	if (checkweight(1201,1) == 0) {
+		mes "You have too many kinds of items. Let's try again after you reduce the number of items.";
+		close;
+	}
+	if (MaxWeight - Weight < 1000) {
+		mes "Cannot proceed because the weight of your items is too heavy. Let's try again after you get rid of some weight.";
+		close;
+	}
+	if (!isequipped(2782)) {
+		mes "□ⅲ◆";
+		mes "■▲◇ ⅲ ■●★ ※ ○⒉ⅲ";
+		next;
+		mes "I don't feel confident in talking since you wouldn't understand anything.";
+		close;
+	}
+	if (ep13_3_invite < 6) {
+		mes "Sapha keeps a distance from you even when you try to talk. Looks like he called on Guard Galten. Time to go.";
+		close;
+	}
 	mes "[Calyon]";
-	if (isequipped(2782)) {
-		if (ep13_3_invite == 5) {
-			if (BaseLevel < 80) {
-				mes "Sorry, a minimum base level of 80 or higher is required to obtain my request.";
-				close; }
-			if (checkquest(12163,PLAYTIME) == 2) {
-				mes "Calculate your request activities with the ^800080Transport Dept. 1 Manager^000000 at Operations and then come back.";
-				close;
-			} else if (checkquest(12163,PLAYTIME) != -1) {
-				mes "We're done for the day. You can report back to the ^800080Transport Dept. 1 Manager^000000 at Operations. Good luck.";
-				close; }
-			mes "Welcome.";
-			mes "What brings you here?";
-			next;
-			if(select("Please explain the request to me.", "Please give me a request.")==1) {
-				mes "[Calyon]";
-				mes "The Transport Dept. 1 and 2 brings in rare items that are not available here.";
-				next;
-				mes "[Calyon]";
-				mes "It is one of the key departments that obtains the rich supplies mostly from the Midgard Continent.";
-				next;
-				mes "[Calyon]";
-				mes "Please see me any time once you are ready.";
-				close; 
-			}
-			set .@calyonrequest,rand(1,11);
-			mes "[Calyon]";
-			mes "Finally, I have a request for you. It is an important one so I need you to be focused.";
-			next;
-			mes "[Calyon]";
-			if (.@calyonrequest == 1) {
-				setquest 12139;
-				setquest 12163;
-				mes "The high minister is looking for the Midgard product, Witherless Roses these days.";
-				mes "Not sure if it's a good gift but some have seen him with it on his head and showing it off.";
-				next;
-				mes "[Calyon]";
-				mes "So... I know this is difficult to ask for but please bring me 1 Witherless Rose. This is just between you and me.";
-				next;
-				mes "You have received a request named ^800080Respect for Taste^000000.";
-			} else if (.@calyonrequest == 2) {
-				setquest 12137;
-				setquest 12163;
-				mes "The industrial research center researches ways of refining Bradium efficiently but they are always short on test materials.";
-				next;
-				mes "[Calyon]";
-				mes "I heard there is a merchant in the adventurer's city who sells Glass Tubes. I will need 4 of them.";
-				next;
-				mes "You have received a request named ^800080Tools for Experiment^000000.";
-			} else if (.@calyonrequest == 3) {
-				setquest 12138;
-				setquest 12163;
-				mes "The pub owner said he wants to give a gift to all his regular Sapha customers.";
-				next;
-				mes "[Calyon]";
-				mes "But doesn't know what to give. If you see any interesting gifts in Midgard, can bring back 5 of them?";
-				next;
-				mes "You have received a request named ^800080Fine Gift Samples^000000.";
-			} else if (.@calyonrequest == 4) {
-				setquest 12140;
-				setquest 12163;
-				mes "A request from the pub owner. He says he can't use disposable leaf plates for regular customers.";
-				next;
-				mes "[Calyon]";
-				mes "He is asking for 15 solid, white chinas from Midgard.";
-				next;
-				mes "You have received a request named ^800080Courtesy for Regular^000000.";
-			} else if (.@calyonrequest == 5) {
-				setquest 12141;
-				setquest 12163;
-				mes "I have a personal request. I heard there is a round transparent handicraft in Midgard.";
-				mes "I think they are called Glass Beads.";
-				next;
-				mes "[Calyon]";
-				mes "We have similar manufactured items here but nothing compared to the elaborate sphere there.";
-				mes "Please get me 10 of them.";
-				next;
-				mes "You have received a request named ^800080Special Package^000000.";
-			} else if (.@calyonrequest == 6) {
-				setquest 12142;
-				setquest 12163;
-				mes "Hmm... I don't know how to start. The high minister is requesting for puppets from Midgard.";
-				mes "I don't know what it is but since the high minister is asking for it, it must be used for a very important purpose.";
-				next;
-				mes "[Calyon]";
-				mes "Please bring 15 of them.";
-				next;
-				mes "You have received a request named ^800080Dangerous Request^000000.";
-			} else if (.@calyonrequest == 7) {
-				setquest 12143;
-				setquest 12163;
-				mes "I heard there is a trend among many of my colleagues here about a musical accessory made from a Bill of Birds from Midgard.";
-				next;
-				mes "[Calyon]";
-				mes "I'm thinking of distributing them within the Operations building.";
-				mes "Can you buy and bring back 50 of them?";
-				next;
-				mes "You have received a request named ^800080Strange Trend^000000.";
-			} else if (.@calyonrequest == 8) {
-				setquest 12144;
-				setquest 12163;
-				mes "The pub owner said he wanted to decorate the pub with something called Clam Shells.";
-				mes "Please bring back about 50 of them.";
-				next;
-				mes "[Calyon]";
-				mes "I have no idea how he will use them but I think he has a very unique taste after being acquainted with many adventurers.";
-				next;
-				mes "You have received a request named ^800080Unknown Usage^000000.";
-			} else if (.@calyonrequest == 9) {
-				setquest 12145;
-				setquest 12163;
-				mes "We don't have cuisine for ourselves but many adventurers seem to enjoy the art of eating.";
-				mes "So the pub owner needs a plate for his new cuisine.";
-				next;
-				mes "[Calyon]";
-				mes "He asked for 20 Crab Shells.";
-				mes "I have no idea where you can get them but... good luck.";
-				next;
-				mes "You have received a request named ^800080Other World Cuisine^000000.";
-			} else if (.@calyonrequest == 10) {
-				setquest 12146;
-				setquest 12163;
-				mes "I think the most useful Midgard item is Scells.";
-				next;
-				mes "[Calyon]";
-				mes "Use Scells to fill any crack or holes in a building and then mix and plaster grinded Garlet to it and the building is maintained quick and simple.";
-				mes "Can you bring back 30 of them?";
-				next;
-				mes "You have received a request named ^800080Filling in Cracks^000000.";
-			} else if (.@calyonrequest == 11) {
-				setquest 12147;
-				setquest 12163;
-				mes "Garlets are an element in building maintenance.";
-				mes "It is one of the most important materials in buildings.";
-				next;
-				mes "[Calyon]";
-				mes "Before Garlets were available, we crushed and used Zargons but they have become difficult to come by.";
-				mes "Please bring back 40 of them.";
-				next;
-				mes "You have received a request named ^800080Adhesive Material^000000."; }
-			mes "You can check details of the request and who to report back to by opening the ^800080Quest Window^000000.";
-			mes "You have 23 hours to complete this mission.";
-			close; 
-		}
-		mes "- The Sapha keeps a distance from you even when you try to talk.";
-		mes "It looks like he is calling for a Galten. Time to go. -";
-		close; 
+	if (BaseLevel < 80) {
+		mes "Ha ha, come back again after you are trained more. I have no request that fits you.";
+		close;
+	}
+	if (checkquest(12163,PLAYTIME) == 2) {
+		mes "Calculate your request activities with the ^800080Transport Dept. 1 Manager^000000 at Operations and then come back.";
+		close;
+	} else if (checkquest(12163,PLAYTIME) != -1) {
+		mes "We're done for the day. You can report back to the ^800080Transport Dept. 1 Manager^000000 at Operations. Good luck.";
+		close;
 	}
-	mes "□ⅲ◆";
-	mes "■▲◇ ⅲ ■●★ ※ ○⒉ⅲ";
+	mes "Welcome.";
+	mes "What brings you here?";
 	next;
-	mes "- I can't understand him... -";
+	if(select("Please explain the request to me.", "Please give me a request.") == 1) {
+		mes "[Calyon]";
+		mes "The Transport Dept. 1 and 2";
+		mes "brings in rare items";
+		mes "that are not available";
+		mes "here.";
+		next;
+		mes "[Calyon]";
+		mes "It is one of the";
+		mes "key departments that";
+		mes "obtains the rich supplies";
+		mes "mostly from the Midgard Continent.";
+		next;
+		mes "[Calyon]";
+		mes "Please see me any time";
+		mes "once you are ready.";
+		close;
+	}
+	mes "[Calyon]";
+	mes "Finally, I have a request for you. It is an important one so I need you to be focused.";
+	next;
+	set .@calyonrequest,rand(1,11);
+	mes "[Calyon]";
+	if (.@calyonrequest == 1) {
+		setquest 12139;
+		setquest 12163;
+		mes "The high minister is looking for the Midgard product, Witherless Roses these days.";
+		mes "Not sure if it's a good gift but some have seen him with it on his head and showing it off.";
+		next;
+		mes "[Calyon]";
+		mes "So... I know this is difficult to ask for but please bring me 1 Witherless Rose. This is just between you and me.";
+		next;
+		mes "You have received a request named ^800080Respect for Taste^000000.";
+	} else if (.@calyonrequest == 2) {
+		setquest 12137;
+		setquest 12163;
+		mes "The industrial research center researches ways of refining Bradium efficiently but they are always short on test materials.";
+		next;
+		mes "[Calyon]";
+		mes "I heard there is a merchant in the adventurer's city who sells Glass Tubes. I will need 4 of them.";
+		next;
+		mes "You have received a request named ^800080Tools for Experiment^000000.";
+	} else if (.@calyonrequest == 3) {
+		setquest 12138;
+		setquest 12163;
+		mes "The pub owner said he wants to give a gift to all his regular Sapha customers.";
+		next;
+		mes "[Calyon]";
+		mes "But doesn't know what to give. If you see any interesting gifts in Midgard, can bring back 5 of them?";
+		next;
+		mes "You have received a request named ^800080Fine Gift Samples^000000.";
+	} else if (.@calyonrequest == 4) {
+		setquest 12140;
+		setquest 12163;
+		mes "A request from the pub owner. He says he can't use disposable leaf plates for regular customers.";
+		next;
+		mes "[Calyon]";
+		mes "He is asking for 15 solid, white chinas from Midgard.";
+		next;
+		mes "You have received a request named ^800080Courtesy for Regular^000000.";
+	} else if (.@calyonrequest == 5) {
+		setquest 12141;
+		setquest 12163;
+		mes "I have a personal request. I heard there is a round transparent handicraft in Midgard.";
+		mes "I think they are called Glass Beads.";
+		next;
+		mes "[Calyon]";
+		mes "We have similar manufactured items here but nothing compared to the elaborate sphere there.";
+		mes "Please get me 10 of them.";
+		next;
+		mes "You have received a request named ^800080Special Package^000000.";
+	} else if (.@calyonrequest == 6) {
+		setquest 12142;
+		setquest 12163;
+		mes "Hmm... I don't know how to start. The high minister is requesting for puppets from Midgard.";
+		mes "I don't know what it is but since the high minister is asking for it, it must be used for a very important purpose.";
+		next;
+		mes "[Calyon]";
+		mes "Please bring 15 of them.";
+		next;
+		mes "You have received a request named ^800080Dangerous Request^000000.";
+	} else if (.@calyonrequest == 7) {
+		setquest 12143;
+		setquest 12163;
+		mes "I heard there is a trend among many of my colleagues here about a musical accessory made from a Bill of Birds from Midgard.";
+		next;
+		mes "[Calyon]";
+		mes "I'm thinking of distributing them within the Operations building.";
+		mes "Can you buy and bring back 50 of them?";
+		next;
+		mes "You have received a request named ^800080Strange Trend^000000.";
+	} else if (.@calyonrequest == 8) {
+		setquest 12144;
+		setquest 12163;
+		mes "The pub owner said he wanted to decorate the pub with something called Clam Shells.";
+		mes "Please bring back about 50 of them.";
+		next;
+		mes "[Calyon]";
+		mes "I have no idea how he will use them but I think he has a very unique taste after being acquainted with many adventurers.";
+		next;
+		mes "You have received a request named ^800080Unknown Usage^000000.";
+	} else if (.@calyonrequest == 9) {
+		setquest 12145;
+		setquest 12163;
+		mes "We don't have cuisine for ourselves but many adventurers seem to enjoy the art of eating.";
+		mes "So the pub owner needs a plate for his new cuisine.";
+		next;
+		mes "[Calyon]";
+		mes "He asked for 20 Crab Shells.";
+		mes "I have no idea where you can get them but... good luck.";
+		next;
+		mes "You have received a request named ^800080Other World Cuisine^000000.";
+	} else if (.@calyonrequest == 10) {
+		setquest 12146;
+		setquest 12163;
+		mes "I think the most useful Midgard item is Scells.";
+		next;
+		mes "[Calyon]";
+		mes "Use Scells to fill any crack or holes in a building and then mix and plaster grinded Garlet to it and the building is maintained quick and simple.";
+		mes "Can you bring back 30 of them?";
+		next;
+		mes "You have received a request named ^800080Filling in Cracks^000000.";
+	} else if (.@calyonrequest == 11) {
+		setquest 12147;
+		setquest 12163;
+		mes "Garlets are an element in building maintenance.";
+		mes "It is one of the most important materials in buildings.";
+		next;
+		mes "[Calyon]";
+		mes "Before Garlets were available, we crushed and used Zargons but they have become difficult to come by.";
+		mes "Please bring back 40 of them.";
+		next;
+		mes "You have received a request named ^800080Adhesive Material^000000.";
+	}
+	mes "You can check details of the request and who to report back to by opening the ^800080Quest Window^000000.";
 	close;
 }
 

+ 1 - 0
sql-files/main.sql

@@ -618,6 +618,7 @@ CREATE TABLE IF NOT EXISTS `skill` (
   `char_id` int(11) unsigned NOT NULL default '0',
   `id` smallint(11) unsigned NOT NULL default '0',
   `lv` tinyint(4) unsigned NOT NULL default '0',
+  `flag` TINYINT(1) UNSIGNED NOT NULL default 0,
   PRIMARY KEY  (`char_id`,`id`)
 ) ENGINE=MyISAM;
 

+ 1 - 0
sql-files/upgrades/upgrade_svn17136.sql

@@ -0,0 +1 @@
+ALTER TABLE `skill` ADD COLUMN `flag` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0;

+ 34 - 16
src/char/char.c

@@ -595,19 +595,20 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
 		}
 
 		StringBuf_Clear(&buf);
-		StringBuf_Printf(&buf, "INSERT INTO `%s`(`char_id`,`id`,`lv`) VALUES ", skill_db);
+		StringBuf_Printf(&buf, "INSERT INTO `%s`(`char_id`,`id`,`lv`,`flag`) VALUES ", skill_db);
 		//insert here.
-		for( i = 0, count = 0; i < MAX_SKILL; ++i )
-		{
-			if( p->skill[i].id != 0 && p->skill[i].flag != SKILL_FLAG_TEMPORARY )
-			{
-				if( p->skill[i].flag == SKILL_FLAG_PERMANENT && p->skill[i].lv == 0 )
+		for( i = 0, count = 0; i < MAX_SKILL; ++i ) {
+			if( p->skill[i].id != 0 && p->skill[i].flag != SKILL_FLAG_TEMPORARY ) {
+
+				if( p->skill[i].lv == 0 && ( p->skill[i].flag == SKILL_FLAG_PERM_GRANTED || p->skill[i].flag == SKILL_FLAG_PERMANENT ) )
 					continue;
-				if( p->skill[i].flag != SKILL_FLAG_PERMANENT && (p->skill[i].flag - SKILL_FLAG_REPLACED_LV_0) == 0 )
+				if( p->skill[i].flag != SKILL_FLAG_PERMANENT && p->skill[i].flag != SKILL_FLAG_PERM_GRANTED && (p->skill[i].flag - SKILL_FLAG_REPLACED_LV_0) == 0 )
 					continue;
 				if( count )
 					StringBuf_AppendStr(&buf, ",");
-				StringBuf_Printf(&buf, "('%d','%d','%d')", char_id, p->skill[i].id, (p->skill[i].flag == SKILL_FLAG_PERMANENT ? p->skill[i].lv : p->skill[i].flag - SKILL_FLAG_REPLACED_LV_0));
+				StringBuf_Printf(&buf, "('%d','%d','%d','%d')", char_id, p->skill[i].id,
+								 ( (p->skill[i].flag == SKILL_FLAG_PERMANENT || p->skill[i].flag == SKILL_FLAG_PERM_GRANTED) ? p->skill[i].lv : p->skill[i].flag - SKILL_FLAG_REPLACED_LV_0),
+								 p->skill[i].flag == SKILL_FLAG_PERM_GRANTED ? p->skill[i].flag : 0);/* other flags do not need to be saved */
 				++count;
 			}
 		}
@@ -1274,13 +1275,16 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
 
 	//read skill
 	//`skill` (`char_id`, `id`, `lv`)
-	if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `id`, `lv` FROM `%s` WHERE `char_id`=? LIMIT %d", skill_db, MAX_SKILL)
+	if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `id`, `lv`,`flag` FROM `%s` WHERE `char_id`=? LIMIT %d", skill_db, MAX_SKILL)
 	||	SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0)
 	||	SQL_ERROR == SqlStmt_Execute(stmt)
-	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_USHORT, &tmp_skill.id, 0, NULL, NULL)
-	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 1, SQLDT_USHORT, &tmp_skill.lv, 0, NULL, NULL) )
+	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_USHORT, &tmp_skill.id  , 0, NULL, NULL)
+	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 1, SQLDT_UCHAR , &tmp_skill.lv  , 0, NULL, NULL)
+	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 2, SQLDT_UCHAR , &tmp_skill.flag, 0, NULL, NULL) )
 		SqlStmt_ShowDebug(stmt);
-	tmp_skill.flag = SKILL_FLAG_PERMANENT;
+
+	if( tmp_skill.flag != SKILL_FLAG_PERM_GRANTED )
+		tmp_skill.flag = SKILL_FLAG_PERMANENT;
 
 	for( i = 0; i < MAX_SKILL && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i )
 	{
@@ -3764,7 +3768,18 @@ int parse_char(int fd)
 
 			char_id = atoi(data);
 			Sql_FreeResult(sql_handle);
-			mmo_char_fromsql(char_id, &char_dat, true);
+
+			/* set char as online prior to loading its data so 3rd party applications will realise the sql data is not reliable */
+			set_char_online(-2,char_id,sd->account_id);
+			if( !mmo_char_fromsql(char_id, &char_dat, true) ) { /* failed? set it back offline */
+				set_char_offline(char_id, sd->account_id);
+				/* failed to load something. REJECT! */
+				WFIFOHEAD(fd,3);
+				WFIFOW(fd,0) = 0x6c;
+				WFIFOB(fd,2) = 0;
+				WFIFOSET(fd,3);
+				break;/* jump off this boat */
+			}
 
 			//Have to switch over to the DB instance otherwise data won't propagate [Kevin]
 			cd = (struct mmo_charstatus *)idb_get(char_db_, char_id);
@@ -3863,8 +3878,6 @@ int parse_char(int fd)
 			node->ip = ipl;
 			idb_put(auth_db, sd->account_id, node);
 
-			set_char_online(-2,node->char_id,sd->account_id);
-
 		}
 		break;
 
@@ -4817,7 +4830,12 @@ int do_init(int argc, char **argv)
 		Sql_ShowDebug(sql_handle);
 
 	set_defaultparse(parse_char);
-	char_fd = make_listen_bind(bind_ip, char_port);
+
+	if( (char_fd = make_listen_bind(bind_ip,char_port)) == -1 ) {
+		ShowFatalError("Failed to bind to port '"CL_WHITE"%d"CL_RESET"'\n",char_port);
+		exit(EXIT_FAILURE);
+	}
+
 	ShowStatus("The char-server is "CL_GREEN"ready"CL_RESET" (Server is listening on the port %d).\n\n", char_port);
 
 	if( runflag != CORE_ST_STOP )

+ 6 - 5
src/login/login.c

@@ -1862,16 +1862,17 @@ int do_init(int argc, char** argv)
 		}
 	}
 
-	if( login_config.console )
-	{
+	if( login_config.console ) {
 		//##TODO invoke a CONSOLE_START plugin event
 	}
 
 	// server port open & binding
-	login_fd = make_listen_bind(login_config.login_ip, login_config.login_port);
+	if( (login_fd = make_listen_bind(login_config.login_ip,login_config.login_port)) == -1 ) {
+		ShowFatalError("Failed to bind to port '"CL_WHITE"%d"CL_RESET"'\n",login_config.login_port);
+		exit(EXIT_FAILURE);
+	}
 	
-	if( runflag != CORE_ST_STOP )
-	{
+	if( runflag != CORE_ST_STOP ) {
 		shutdown_callback = do_shutdown;
 		runflag = LOGINSERVER_ST_RUNNING;
 	}

+ 29 - 8
src/map/atcommand.c

@@ -5379,27 +5379,48 @@ ACMD_FUNC(clearcart)
  * @skillid by [MouseJstr]
  * lookup a skill by name
  *------------------------------------------*/
+#define MAX_SKILLID_PARTIAL_RESULTS 5
+#define MAX_SKILLID_PARTIAL_RESULTS_LEN 74 // "skill " (6) + "%d:" (up to 5) + "%s" (up to 30) + " (%s)" (up to 33)
 ACMD_FUNC(skillid)
 {
-	int skillen, idx;
+	int skillen, idx, i, found = 0;
+	DBIterator* iter;
+	DBKey key;
+	DBData *data;
+	char partials[MAX_SKILLID_PARTIAL_RESULTS][MAX_SKILLID_PARTIAL_RESULTS_LEN];
+
 	nullpo_retr(-1, sd);
 
-	if (!message || !*message)
-	{
+	if (!message || !*message) {
 		clif_displaymessage(fd, msg_txt(1163)); // Please enter a skill name to look up (usage: @skillid <skill name>).
 		return -1;
 	}
 
 	skillen = strlen(message);
 
-	for (idx = 0; idx < MAX_SKILL_DB; idx++) {
-		if (strnicmp(skill_db[idx].name, message, skillen) == 0 || strnicmp(skill_db[idx].desc, message, skillen) == 0)
-		{
-			sprintf(atcmd_output, msg_txt(1164), idx, skill_db[idx].desc); // skill %d: %s
+	iter = db_iterator(skilldb_name2id);
+	
+	for( data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key) ) {
+		idx = skill_get_index(db_data2i(data));
+		if (strnicmp(key.str, message, skillen) == 0 || strnicmp(skill_db[idx].desc, message, skillen) == 0) {
+			sprintf(atcmd_output, msg_txt(1164), db_data2i(data), skill_db[idx].desc, key.str); // skill %d: %s (%s)
 			clif_displaymessage(fd, atcmd_output);
+		} else if ( found < MAX_SKILLID_PARTIAL_RESULTS && ( stristr(key.str,message) || stristr(skill_db[idx].desc,message) ) ) {
+			snprintf(partials[found++], MAX_SKILLID_PARTIAL_RESULTS_LEN, msg_txt(1164), db_data2i(data), skill_db[idx].desc, key.str);
 		}
 	}
-
+	
+	dbi_destroy(iter);
+	
+	if( found ) {
+		sprintf(atcmd_output, msg_txt(1398), found); // -- Displaying first %d partial matches
+		clif_displaymessage(fd, atcmd_output);
+	}
+	
+	for(i = 0; i < found; i++) { /* partials */
+		clif_displaymessage(fd, partials[i]);
+	}
+	
 	return 0;
 }
 

+ 1 - 1
src/map/clif.c

@@ -17135,7 +17135,7 @@ int do_init_clif(void) {
 
 	set_defaultparse(clif_parse);
 	if( make_listen_bind(bind_ip,map_port) == -1 ) {
-		ShowFatalError("can't bind game port\n");
+		ShowFatalError("Failed to bind to port '"CL_WHITE"%d"CL_RESET"'\n",map_port);
 		exit(EXIT_FAILURE);
 	}
 

+ 10 - 7
src/map/pc.c

@@ -1254,7 +1254,7 @@ static int pc_calc_skillpoint(struct map_session_data* sd)
 				if(sd->status.skill[i].flag == SKILL_FLAG_PERMANENT)
 					skill_point += skill;
 				else
-				if(sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0)
+				if(sd->status.skill[i].flag == SKILL_FLAG_REPLACED_LV_0)
 					skill_point += (sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0);
 			}
 		}
@@ -1284,13 +1284,13 @@ int pc_calc_skilltree(struct map_session_data *sd)
 
 	for( i = 0; i < MAX_SKILL; i++ )
 	{
-		if( sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED ) //Don't touch plagiarized skills
+		if( sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED ) //Don't touch these
 			sd->status.skill[i].id = 0; //First clear skills.
 	}
 
 	for( i = 0; i < MAX_SKILL; i++ )
 	{
-		if( sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED )
+		if( sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED )
 		{ // Restore original level of skills after deleting earned skills.
 			sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0;
 			sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
@@ -1510,7 +1510,7 @@ int pc_clean_skilltree(struct map_session_data *sd)
 			sd->status.skill[i].flag = 0;
 		}
 		else
-		if (sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0){
+		if (sd->status.skill[i].flag == SKILL_FLAG_REPLACED_LV_0){
 			sd->status.skill[i].lv = sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0;
 			sd->status.skill[i].flag = 0;
 		}
@@ -3431,7 +3431,7 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag)
 	case 0: //Set skill data overwriting whatever was there before.
 		sd->status.skill[id].id   = id;
 		sd->status.skill[id].lv   = level;
-		sd->status.skill[id].flag = SKILL_FLAG_PERMANENT;
+		sd->status.skill[id].flag = SKILL_FLAG_PERM_GRANTED;
 		if( level == 0 ) //Remove skill.
 		{
 			sd->status.skill[id].id = 0;
@@ -6045,7 +6045,7 @@ int pc_allskillup(struct map_session_data *sd)
 	nullpo_ret(sd);
 
 	for(i=0;i<MAX_SKILL;i++){
-		if (sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED) {
+		if (sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED) {
 			sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0;
 			sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
 			if (sd->status.skill[i].lv == 0)
@@ -6318,6 +6318,9 @@ int pc_resetskill(struct map_session_data* sd, int flag)
 		if( i == NV_BASIC && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE )
 			continue;
 
+		if( sd->status.skill[i].flag == SKILL_FLAG_PERM_GRANTED )
+			continue;
+
 		if( flag&4 && !skill_ischangesex(i) )
 			continue;
 
@@ -6333,7 +6336,7 @@ int pc_resetskill(struct map_session_data* sd, int flag)
 		if( sd->status.skill[i].flag == SKILL_FLAG_PERMANENT )
 			skill_point += lv;
 		else
-		if( sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0 )
+		if( sd->status.skill[i].flag == SKILL_FLAG_REPLACED_LV_0 )
 			skill_point += (sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0);
 
 		if( !(flag&2) )

+ 0 - 2
src/map/skill.c

@@ -62,8 +62,6 @@ static struct eri *skill_timer_ers = NULL; //For handling skill_timerskills [Sko
 
 DBMap* skillunit_db = NULL; // int id -> struct skill_unit*
 
-DBMap* skilldb_name2id = NULL;
-
 /**
  * Skill Cool Down Delay Saving
  * Struct skill_cd is not a member of struct map_session_data

+ 3 - 0
src/map/skill.h

@@ -5,6 +5,7 @@
 #define _SKILL_H_
 
 #include "../common/mmo.h" // MAX_SKILL, struct square
+#include "../common/db.h"
 #include "map.h" // struct block_list
 struct map_session_data;
 struct homun_data;
@@ -22,6 +23,8 @@ struct status_change_entry;
 
 #define MAX_SKILL_LEVEL 100
 
+DBMap* skilldb_name2id;
+
 //Constants to identify the skill's inf value:
 enum e_skill_inf
 {