* 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
This commit is contained in:
euphyy 2013-02-17 21:13:33 +00:00
parent cd382be6ab
commit f3e4ef5067
14 changed files with 265 additions and 198 deletions

View File

@ -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

View File

@ -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

View File

@ -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")

View File

@ -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:

View File

@ -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,36 +2280,62 @@ 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; }
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; }
close;
}
mes "Welcome.";
mes "What brings you here?";
next;
if(select("Please explain the request to me.", "Please give me a request.")==1) {
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.";
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 key departments that obtains the rich supplies mostly from the Midgard Continent.";
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 once you are ready.";
mes "Please see me any time";
mes "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;
set .@calyonrequest,rand(1,11);
mes "[Calyon]";
if (.@calyonrequest == 1) {
setquest 12139;
@ -2419,19 +2446,9 @@ dicastes01,223,190,1 script Calyon#pa8029 453,{
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 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;
}
mes "□ⅲ◆";
mes "■▲◇ ⅲ ■●★ ※ ○⒉ⅲ";
next;
mes "- I can't understand him... -";
close;
}

View File

@ -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;

View File

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

View File

@ -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,12 +1275,15 @@ 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);
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 )

View File

@ -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;
}

View File

@ -5379,25 +5379,46 @@ 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;

View File

@ -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);
}

View File

@ -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) )

View File

@ -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

View File

@ -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
{