Jump to content

Utility: [SQL] Mission Board


Emistry

Recommended Posts


  • Group:  Forum Moderator
  • Topic Count:  93
  • Topics Per Day:  0.02
  • Content Count:  10015
  • Reputation:   2354
  • Joined:  10/28/11
  • Last Seen:  

File Name:

 Mission Board

[b]File Submitter[/b]: [url=http://rathena.org/board/user/241-emistry/]Emistry[/url]

[b]File Submitted[/b]: 01 Jan 2014

[b]File Category[/b]: [url=http://rathena.org/board/files/category/142-utilities/]Utilities[/url]

[b]Content Author[/b]: Emistry / AnnieRuru



original topic : [url="http://www.eathena.ws/board/index.php?showtopic=242306"]http://www.eathena.ws/board/index.php?showtopic=242306[/url]

this is actually a quite old topic , anyway i will just borrow the information written by Annieruru ..
it's one of my favourite script back in eAthena,[quote]
i know that there are serveral server out there who "manage" to make it to save "permanent" quest by using permanent global variable , well ... all i can say is that the method they are currently using are not really a good way ...[/quote][quote]
[size=3]ok ... this script allow admins to setup quests on the server[/size]
1 npc allow 40 missions, and allow up to 127 npc's, means total of 5080 quests can be created

best use on low rate and medium rate servers
server that likes to create lots of quests to keep players busy[/quote]

[size=4][background=rgb(255,255,255)]Credit to AnnieRuru and any other contributors from the pass....[/background][/size]
[hr]

[size=5][b]Installation :[/b][/size]
Just a basic simple instruction ...[list]
[*]download the NPC script and install into your server
[*]download the [url="http://pastebin.com/raw.php?i=misZD8cf"][ SQL Table ][/url] and load into youe mysql or phpmyadmin server.
[/list]
[size=5][b]Basic Configuration :[/b][/size][code=auto:1021] // gm level to access panel .gm_level = 90; // max no. of required monster .max_required_monster = 10; // max no. of required item .max_required_item = 10; // max no. of required mission ( un-implement yet ) .max_required_mission = 10; // max no. of available mission .max_mission_available = 50; // max value of integer input .max_integer_value = 30000; // max amount of mission per page .max_page_size = 30; // max mission per npc take by character .max_mission_per_char = 4; [/code]


[b][size=5]NPC Duplication :[/size][/b]

[code=auto:1447] // the number behind the NPC name must be NUMBER with range of ( 1 ~ 500 ) // the number should stay the same for eternity, if you change it frequently, it might affect your missions for each NPC. // ( to conclude, once you assigned the number, dont change it for the sake of your mission board ... ) prontera,151,171,4 duplicate(mission_board) Mission A#1 837 prontera,154,174,4 duplicate(mission_board) Mission B#2 837 prontera,156,176,4 duplicate(mission_board) Mission C#3 837 prontera,159,179,4 duplicate(mission_board) Mission D#4 837[/code]


take note the number behind the NPC is the index of each NPC ....
[color=#ff0000][b]once you assigned an index to a NPC, try not to change it in the future[/b][/color], since missions are assigned based on these index number.



[size=5][b]What's New in this Version :[/b][/size]
each npc probably can have more than 40 missions.
each NPC can have their own quests....or a quest that can share among any other NPCs.

  • 1 NPC can have many individual quests.
  • All / Certain NPCs share the same quests.
  • Only certains classes[i] ( include inherited classes ) [/i]may do the quests. However, base classes are alway able to pick the quests.


All the Quests will not be removed upon server restart / @reloadscript, which mean you dont have to re-setup all the quests everytime server restarted / reloaded.

** You may edit the required monsters for each mission, but will end up remove all the killing progress of each players who have taken the missions.

[size=5][b]Future TODO List :[/b][/size]

  • support party-assist , guild-assist to completing the quests .
  • pre-requisite mission or so-called chain missions.
  • custom variable as rewards.
  • etc


[i]( you may tell me if you have any ideas to improve this script )[/i]



[size=5][b]Screenshots :[/b][/size]
http://imgur.com/9zPLLab,LeCTXWI,iAMODwY,uM0G9b7,PtfRQU9,CzIDSja,LWeafsQ,WLcDMaW,Dx3y3fw,7UukU0t#0

uWNbLrD.gif

[hr]

just a scratching script and havent spent really much time to debug every single lines ...overall it still work fine ...[i]( still on holiday mood + school started again )[/i]
the structure of the scripts might look messy and hard to read .. >.< ... didnt really plan well on the structure of the scripts.[i] ( Emistry suck on planning )[/i]

There are some bugs i guess ... but i not really so sure is it come from this script or will it really bring big effect to the servers..
when playing with this script .... i think my char will failed to connect to server everytime I relog , does any of you facing this problem when using this script ??

AnnieRuru and other member who good at scripts, time for lecturers ... /gg


[b]SQL Mission file sharing ....[/b]
if anyone of you willing to share the SQL Mission Table with some quests inside , let me know =)


Click here to download this file

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  18
  • Topics Per Day:  0.00
  • Content Count:  2044
  • Reputation:   682
  • Joined:  10/09/12
  • Last Seen:  

I asked you to do this since 21 Dec .. means took you around 11 days

not so bad, around the same amount of time I took to write this 3 years ago

1st obvious bug

the menu

if I input the title name with the ":" symbol, the menu becomes 2 lines when players want to choose a quest

and the menu option number become mess up

2nd, the job limitation should default to everyone on, not everyone off

my way is use to limit certain jobs, but your way is force everyone to enable all jobs

3rd,

I have never complete the custom variable stuffs ...

means, the reward with a custom variable, can be use with achievement system or custom point currency

I plan to do that but I couldn't do it that time, thinking that you can do though

PS... I try dig as many bugs as I can until nobody wants to use this script /gg

4th

http://www.eathena.ws/board/index.php?s=&showtopic=241133&view=findpost&p=1318425

your script is able to hit string limitation when the menu is too long, cause client crash

seems your way of saving the variable is different than mine

can tell that immediately you are using SQL table instead of setarray

it also means your script would probably break the 5080 mission limit,

but still limited to the string length that a menu can gives

5th

Mission Offered by use wrong color, Red<=>Green is opposite

nvm seems like need to go through the .@check_progress variable once to get it done

a weird way though

Edited by AnnieRuru
Link to comment
Share on other sites


  • Group:  Forum Moderator
  • Topic Count:  93
  • Topics Per Day:  0.02
  • Content Count:  10015
  • Reputation:   2354
  • Joined:  10/28/11
  • Last Seen:  

btw ... thinking this should be remain at here...or script support section ... >.,

 

 

 

I asked you to do this since 21 Dec .. means took you around 11 days
not so bad, around the same amount of time I took to write this 3 years ago

actually it's not 11 days.... but around 3~4 days only ...( with the help of reference from the old eAthena topic of yours )

i was travel around...playing....partying for the past 2 week during the semester holiday ~ xD

so the script i believe isnot really good enough yet ..><

but i was planned to release it in public during new year ... so that can get more and more feedback to improve it instead of squeeze my brain for it..

 

 

 

if I input the title name with the ":" symbol, the menu becomes 2 lines when players want to choose a quest
and the menu option number become mess up

I see .... never thought of this ...xD  nice for reminding ... will keep this in mind.

 

 

 

my way is use to limit certain jobs, but your way is force everyone to enable all jobs

xP ..let them pick themselve ~ 

 

 

 

means, the reward with a custom variable, can be use with achievement system or custom point currency
I plan to do that but I couldn't do it that time, thinking that you can do though

ya ... i have added it into the TODO list of mine .. =)

and ...i forget to write it at above..LOL..

 

 

 

PS... I try dig as many bugs as I can until nobody wants to use this script

try /gg  haha ~

 

 

 

http://www.eathena.w...dpost&p=1318425
your script is able to hit string limitation when the menu is too long, cause client crash 

i see ...seem like i was mistaken about the limitation of menu .. my mind only telling me the client will fail if menu exist more than 100 option ..and it never remind me of the string limitation ...LOL..

 

erm..wait..i have added the "pagination" for the mission list ...

	// max amount of mission per page
	.max_page_size = 30;

i think this should be able to encounter this problem ?

 

still the script isnt fully added all the features like yours yet ~ will working on it after my university stuff done for the next few weeks...slowly dig some time for this..

>.<  my university just started their class at 31st december .. >.<

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  18
  • Topics Per Day:  0.00
  • Content Count:  2044
  • Reputation:   682
  • Joined:  10/09/12
  • Last Seen:  

btw ... thinking this should be remain at here...or script support section ... >.,

should get me review in PM 1st ...

you already bomb my pm so much

whats the difference having 1 more :ani_swt3:

 

 

erm..wait..i have added the "pagination" for the mission list ...

	// max amount of mission per page
	.max_page_size = 30;
i think this should be able to encounter this problem ?
yeah x.x

I only test by create 2 missions, so haven't try up above 30

 

still the script isnt fully added all the features like yours yet ~ will working on it after my university stuff done for the next few weeks...slowly dig some time for this..

already noticed that

like player couldn't drop a mission after they have picked

and swap mission order to make the npc looks more organized etc

actually you know, your sql way makes me re-think ... probably can go unlimited ... so its not limited by any script engine anymore

just now I look at the script too much

5th ...

I can't pick a mission <.<

[SQL]: DB error - Incorrect integer value: 'AnnieRuru' for column 'name' at row
1
[Debug]: at d:\rathena\src\map\script.c:14885 - INSERT INTO `player_mission` VAL
UES ( 444132381,62120,2000000,150000,'AnnieRuru','',1388568855,NOW(),'0000-00-00
 00:00:00' );
.... please ....

why are you using gettimetick(0), but not gettimetick(2) ?

Edited by AnnieRuru
Link to comment
Share on other sites


  • Group:  Forum Moderator
  • Topic Count:  93
  • Topics Per Day:  0.02
  • Content Count:  10015
  • Reputation:   2354
  • Joined:  10/28/11
  • Last Seen:  

 

 

you already bomb my pm so much

whats the difference having 1 more 

bomb more then ...xD  just like how your bunshin bomb my house ..

 

 

 

I only test by create 2 missions, so haven't try up above 30

i also create a few only ... but thinking that each title only 30character...+ around 10 character for level display .. + 30 quests per page..

the menu length ...probably around 1300 characters only .. hopefully enough ..

** anyone created alot missions..and willing to share it...pm me ...

 

 

 

like player couldn't drop a mission after they have picked

and swap mission order to make the npc looks more organized etc

/omg ?? what happened ...LOL ..

i was able to drop mission and pick mission as i recall .. >.< maybe i will try one more times ...

btw..i didnt do the mission swap ....because the doesnt look useful in quest mission... ??

maybe shall recheck this part ...probably i added some new column in sql and forget to add in the required data...

 

 

 

actually you know, your sql way makes me re-think ... probably can go unlimited ... so its not limited by any script engine anymore

probably can unlimit ... but not sure how it will affect the perfomance or maybe sql storage size etc..xD

but definitely can store really alot ...

 

 

 

why are you using gettimetick(0), but not gettimetick(2) ? 

i just random pick between 0 ~ 2 xD

just used to create an id to differentiate the value in sql ...

xP

anyway i think shouldnt be 0 ....the value should be 1 ~ 2 ...since 0 will lead to repeating same number after some time ...

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  9
  • Topics Per Day:  0.00
  • Content Count:  187
  • Reputation:   7
  • Joined:  09/04/12
  • Last Seen:  

Future TODO List :

  • support party-assist , guild-assist to completing the quests .
  • pre-requisite mission or so-called chain missions.
  • etc

 

Great!Bravo!

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  154
  • Topics Per Day:  0.03
  • Content Count:  493
  • Reputation:   46
  • Joined:  01/24/12
  • Last Seen:  

i want to suggest a custom variable reward settings

 

for example #pvppoints + 10

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  0
  • Topics Per Day:  0
  • Content Count:  6
  • Reputation:   0
  • Joined:  10/22/12
  • Last Seen:  

Stuck on "Edit NPC Limitation", last step.

not shown NPC are available, somebody can fix this?

 

i am used last svn rathena.

 

But nice work :)

Link to comment
Share on other sites


  • Group:  Forum Moderator
  • Topic Count:  93
  • Topics Per Day:  0.02
  • Content Count:  10015
  • Reputation:   2354
  • Joined:  10/28/11
  • Last Seen:  

Stuck on "Edit NPC Limitation", last step.

not shown NPC are available, somebody can fix this?

 

i am used last svn rathena.

 

But nice work :)

follow the way how duplicated npc are named.

// the number behind the NPC name must be above 1000 ( if you had not changed another )
// you can have 127 npcs.
 
prontera,151,171,4	duplicate(mission_board)	Prontera Mission::1001	837
prontera,155,171,4	duplicate(mission_board)	Byalan Mission::1002	837
prontera,159,171,4	duplicate(mission_board)	Payon Cave Mission::1003	837

1001 ~ 1127

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  0
  • Topics Per Day:  0
  • Content Count:  6
  • Reputation:   0
  • Joined:  10/22/12
  • Last Seen:  

I have same result, i am add this for end script:

// the number behind the NPC name must be above 1000 ( if you had not changed another )
// you can have 127 npcs.

prontera,151,171,4	duplicate(mission_board)	Prontera Mission::1001	837
prontera,155,171,4	duplicate(mission_board)	Byalan Mission::1002	837
prontera,159,171,4	duplicate(mission_board)	Payon Cave Mission::1003	837
//prontera,159,175,4	duplicate(mission_board)	Mission 1::1003	837
//prontera,159,171,4	duplicate(mission_board)	Mission 2::1004	837
//prontera,159,171,4	duplicate(mission_board)	Mission 3::1005	837
//prontera,159,171,4	duplicate(mission_board)	Mission 4::1006	837
prontera,155,175,4	duplicate(mission_board)	Prontera Mission::1007	837

u2ERH1m.jpg

 

  • Running script is well, not have error, just debug from your script
  • MySQL have done imported
  • Last have done add duplicate NPC with same name, but different ID ( 1007 ), still not shown.

Thanks for advice Emistry

 

:D

Edited by Code Hunter
Link to comment
Share on other sites


  • Group:  Forum Moderator
  • Topic Count:  93
  • Topics Per Day:  0.02
  • Content Count:  10015
  • Reputation:   2354
  • Joined:  10/28/11
  • Last Seen:  

post your full script.

 

is this setup quest step ??

did you added any npc to offer this quest when you setup the quest ??

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  0
  • Topics Per Day:  0
  • Content Count:  6
  • Reputation:   0
  • Joined:  10/22/12
  • Last Seen:  

This full script

/*

DROP TABLE IF EXISTS `mission_board`;
CREATE TABLE IF NOT EXISTS `mission_board` (
`id` int(11) unsigned NOT NULL,
`title` varchar(30) NOT NULL default '',
`desc` varchar(255) NOT NULL default '',
`mob_list` varchar(50) NOT NULL default '',
`mob_qty` varchar(50) NOT NULL default '',
`item_list` varchar(50) NOT NULL default '',
`item_qty` varchar(50) NOT NULL default '',
`class_limitation` int(11) unsigned NOT NULL default '0',
`class_branch` int(11) unsigned NOT NULL default '0',
`min_lv` smallint(6) unsigned NOT NULL default '1',
`max_lv` smallint(6) unsigned NOT NULL default '99',
`repeat` smallint(6) unsigned NOT NULL default '0',
`duration` int(11) unsigned NOT NULL default '0',
`reward_list` varchar(50) NOT NULL default '',
`reward_qty` varchar(50) NOT NULL default '',
`base_exp` int(11) unsigned NOT NULL default '0',
`job_exp` int(11) unsigned NOT NULL default '0',
`zeny` int(11) unsigned NOT NULL default '0',
`cash` int(11) unsigned NOT NULL default '0',
`aid` int(11) unsigned NOT NULL default '0',
`name` varchar(30) NOT NULL default '',
`time_update` datetime NOT NULL default '0000-00-00 00:00:00',
`npc_id` varchar(255) NOT NULL default '',
`redo_delay` smallint(6) unsigned NOT NULL default '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;


DROP TABLE IF EXISTS `player_mission`;
CREATE TABLE IF NOT EXISTS `player_mission` (
`id` int(11) unsigned NOT NULL,
`mission_id` int(11) unsigned NOT NULL,
`aid` int(11) unsigned NOT NULL default '0',
`cid` int(11) unsigned NOT NULL default '0',
`name` varchar(30) NOT NULL default '',
`mob_hunt` varchar(50) NOT NULL default '',
`expire` int(11) unsigned NOT NULL default '0',
`starting` datetime NOT NULL default '0000-00-00 00:00:00',
`completion` datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

*/



- script mission_board -1,{
.@gm_level = getgmlevel();
.@npc_name$ = strnpcinfo(1);
.@mission_npc_num = ( atoi( strnpcinfo(3) ) - .name_offset_num );


query_sql( "SELECT COUNT(`id`) FROM `mission_board` WHERE `npc_id` LIKE '%|"+.@mission_npc_num+"|%' ",.@mission_count );
query_sql( "SELECT `id`,`mission_id`,`mob_hunt`,`expire` FROM `player_mission` WHERE `mission_id` IN ( SELECT `id` FROM `mission_board` WHERE `npc_id` LIKE '%|"+.@mission_npc_num+"|%' ) AND `cid` = "+getcharid(0)+" AND `completion` = '0000-00-00 00:00:00' ",.@id,.@mission_id,.@mob_hunt$,.@expire );
.@current_mission_size = getarraysize( .@id );

mes "^0055FF[ "+.@npc_name$+" ]^000000";
mes "A mission board may provide various missions for adventures. Each players may pick ";
mes " ^FF0000"+.max_mission_per_char+" missions^000000";
mes "from each mission npc.";
next;
switch( select( ( .@current_mission_size )?"Submit Mission":"",
( .@current_mission_size < .max_mission_per_char )?"Pick Mission":"",
( .@current_mission_size )?"Drop Mission":"",
( .@gm_level < .gm_level || !.@mission_count )?"":"^FF0000[GM] Update Mission^000000",
( .@gm_level < .gm_level )?"":"^FF0000[GM] Setup Mission^000000",
( .@gm_level < .gm_level || !.@mission_count )?"":"^FF0000[GM] Delete Mission^000000" ) ){
Case 1:
.@current_time = gettimetick(2);
query_sql( "SELECT `id`,`title`,`min_lv`,`max_lv` FROM `mission_board` WHERE `npc_id` LIKE '%|"+.@mission_npc_num+"|%' AND `id` IN ( SELECT `mission_id` FROM `player_mission` WHERE `cid` = "+getcharid(0)+" AND `completion` = '0000-00-00 00:00:00' )",.@mission_id,.@title$,.@min_lv,.@max_lv );
.@size = getarraysize( .@mission_id );
for( .@i = 0; .@i < .@size; .@i++ ){
if( .@expire[.@i] < .@current_time )
.@submit_menu$ = .@submit_menu$ + "^FF0000[Expired]^000000";
.@submit_menu$ = .@submit_menu$ + "["+.@min_lv[.@i]+"~"+.@max_lv[.@i]+"] "+.@title$[.@i] +":";
}
.@i = select( .@submit_menu$ ) - 1;

if( .@expire[.@i] < .@current_time ){
dispbottom " ~ Mission expired "+callsub( OnTime2Str,( gettimetick(2) + ( .@current_time - .@expire[.@i] ) ) )+" ago.";
dispbottom " ~ You may drop this mission.";
close;
}

// get mission data from sql
query_sql( "SELECT * FROM `mission_board` WHERE `id` = "+.@mission_id[.@i]+" LIMIT 1",
.@mission_id,
.@title$,
.@description$,
.@mob_list$,
.@mob_qty$,
.@item_list$,
.@item_qty$,
.@base_job_bitmask,
.@job_branch_bitmask,
.@min_lv,
.@max_lv,
.@repeatable,
.@timelimit,
.@reward_list$,
.@reward_qty$,
.@baseexp,
.@jobexp,
.@zeny,
.@cash,
.@aid,
.@name$,
.@time_update$,
.@npc_id$,
.@redo_delay
);

// explode all saved strings to array value.
.@monster_size = callsub( OnExplodeArray,.@mob_list$,.@monster_list,0 );
if( .@monster_size )
callsub( OnExplodeArray,.@mob_qty$,.@monster_qty,0 );

.@item_size = callsub( OnExplodeArray,.@item_list$,.@item_list,0 );
if( .@item_size )
callsub( OnExplodeArray,.@item_qty$,.@item_qty,0 );

.@reward_size = callsub( OnExplodeArray,.@reward_list$,.@reward_list,0 );
if( .@reward_size )
callsub( OnExplodeArray,.@reward_qty$,.@reward_qty,0 );

.@selected_npc_size = callsub( OnExplodeArray,.@npc_id$,.@selected_npc_array$,1 );

setarray .@level_range,.@min_lv,.@max_lv;

// display the information of mission
.@result = callsub( OnDisplayMissionInfo,
.@mission_id,
.@title$,
.@description$,
.@level_range,
.@repeatable,
.@expire[.@i],
.@monster_list,
.@monster_qty,
.@item_list,
.@item_qty,
.@base_job_bitmask,
.@job_branch_bitmask,
.@baseexp,
.@jobexp,
.@cash,
.@zeny,
.@reward_list,
.@reward_qty,
.@selected_npc_array$,
.@time_update$,
.@redo_delay,
1|2|4|8
);

// submit mission or not
if( .@result ){
message strcharinfo(0),"Failed to submit this mission.";
}else{
next;
if( select( "Submit Completed Mission","Cancel" ) == 1 ){
for( .@ms = ( @ms_size - 1 ); .@ms >= 0; .@ms-- )
if( @ms_list$[.@ms] == ""+.@mission_id ){
mes "^0055FF[ "+.@npc_name$+" ]^000000";
query_sql( "UPDATE `player_mission` SET `completion` = NOW() WHERE `cid` = "+getcharid(0)+" AND `mission_id` = "+.@mission_id );
mes "Mission accomplished.";
@ms_size--;

// clear requirement.
setd( "@ms_"+.@mission_id+"_expire" ),0;
deletearray getd( "@ms_"+.@mission_id+"_list" );
deletearray getd( "@ms_"+.@mission_id+"_qty" );
deletearray getd( "@ms_"+.@mission_id+"_hunt" );
if( .@item_size )
for( .@i = 0; .@i < .@item_size; .@i++ ){
debugmes getitemname( .@item_list[.@i] )+" - "+.@item_qty[.@i];
}
// delitem .@item_list[.@i],.@item_qty[.@i];

mes "Gained some mission's rewards.";
// rewards
getexp .@baseexp,.@jobexp;
if( .@reward_size )
for( .@i = 0; .@i < .@reward_size; .@i++ )
getitem .@reward_list[.@i],.@reward_qty[.@i];
#CASHPOINTS += .@cash;
Zeny += .@zeny;
break;
}
mes "Something went wrong ..";
}
}
break;
Case 2:
// get info from SQL.
do{
mes "^0055FF[ "+.@npc_name$+" ]^000000";
deletearray .@id;
query_sql( "SELECT `id`,`title`,`min_lv`,`max_lv` FROM `mission_board` WHERE `npc_id` LIKE '%|"+.@mission_npc_num+"|%' AND `id` NOT IN ( SELECT `mission_id` FROM `player_mission` WHERE `cid` = "+getcharid(0)+" AND `completion` = '0000-00-00 00:00:00' ) LIMIT "+.max_page_size+" OFFSET "+.@offset,.@id,.@title$,.@min_lv,.@max_lv );
.@offset += .max_page_size;
.@size = getarraysize( .@id );
if( !.@size ){
mes "There are no other available missions to pick.";
close;

}else{
mes "Pick a mission.";
.@mission_menu$ = "";
for( .@i = 0; .@i < .@size; .@i++ )
.@mission_menu$ = .@mission_menu$ + "["+.@min_lv[.@i]+"~"+.@max_lv[.@i]+"] "+.@title$[.@i] +":";
}
next;
.@i = select( .@mission_menu$+"- next page" ) - 1;
}while( .@i == .@size );

query_sql( "SELECT * FROM `mission_board` WHERE `id` = "+.@id[.@i]+" LIMIT 1",
.@mission_id,
.@title$,
.@description$,
.@mob_list$,
.@mob_qty$,
.@item_list$,
.@item_qty$,
.@base_job_bitmask,
.@job_branch_bitmask,
.@min_lv,
.@max_lv,
.@repeatable,
.@timelimit,
.@reward_list$,
.@reward_qty$,
.@baseexp,
.@jobexp,
.@zeny,
.@cash,
.@aid,
.@name$,
.@time_update$,
.@npc_id$,
.@redo_delay
);

// explode all saved strings to array value.
.@monster_size = callsub( OnExplodeArray,.@mob_list$,.@monster_list,0 );
.@monster_size = callsub( OnExplodeArray,.@mob_qty$,.@monster_qty,0 );

.@item_size = callsub( OnExplodeArray,.@item_list$,.@item_list,0 );
.@item_size = callsub( OnExplodeArray,.@item_qty$,.@item_qty,0 );

.@reward_size = callsub( OnExplodeArray,.@reward_list$,.@reward_list,0 );
.@reward_size = callsub( OnExplodeArray,.@reward_qty$,.@reward_qty,0 );

.@selected_npc_size = callsub( OnExplodeArray,.@npc_id$,.@selected_npc_array$,1 );

setarray .@level_range,.@min_lv,.@max_lv;

// display the information of mission
.@result = callsub( OnDisplayMissionInfo,
.@mission_id,
.@title$,
.@description$,
.@level_range,
.@repeatable,
( .@timelimit + gettimetick(2) ),
.@monster_list,
.@monster_qty,
.@item_list,
.@item_qty,
.@base_job_bitmask,
.@job_branch_bitmask,
.@baseexp,
.@jobexp,
.@cash,
.@zeny,
.@reward_list,
.@reward_qty,
.@selected_npc_array$,
.@time_update$,
.@redo_delay,
1|8
);

// check completed how many times.
if( .@repeatable[.@i] ){
query_sql( "SELECT COUNT(`id`),TIMESTAMPDIFF( HOUR,`completion`,NOW() ),DATE_ADD( `completion`, INTERVAL "+.@redo_delay+" HOUR) FROM `player_mission` WHERE `mission_id` = "+.@id[.@i]+" AND `completion` <> '0000-00-00 00:00:00'",.@mission_completed,.@diff_delay,.@day$ );
if( .@repeatable[.@i] && ( ( .@mission_completed >= .@repeatable[.@i] ) || ( .@diff_delay && .@diff_delay <= .@redo_delay ) ) ){
next;
mes "^0055FF[ "+.@npc_name$+" ]^000000";
mes " ";
if( .@mission_completed >= .@repeatable[.@i] ){
mes "You cant pick this mission, you have mission completion reach the max repeatable attempt of "+.@mission_completed+" times.";
close;
}
if( .@diff_delay && .@diff_delay <= .@redo_delay ){
mes "You cant pick this mission, you have mission redo delay isnt finish yet.";
mes "Approximate : ^FF0000"+.@day$+"^000000";
close;
}
}
}

if( .@result ){
message strcharinfo(0),"Failed to pick this mission.";
}else{
if( select( "Pick Mission","Cancel" ) == 1 ){
mes "^0055FF[ "+.@npc_name$+" ]^000000";
mes " ";
query_sql( "INSERT INTO `player_mission` VALUES ( "+gettimetick(2)+","+.@mission_id+","+getcharid(3)+","+getcharid(0)+",'"+escape_sql( strcharinfo(0) )+"','',"+( .@timelimit + gettimetick(2) )+",NOW(),'0000-00-00 00:00:00' );" );
mes "Picked ^0055FFMission # "+.@mission_id+"^000000";

@ms_list$[ @ms_size ] = ""+.@mission_id;
@ms_size++;

setd( "@ms_"+.@mission_id+"_expire" ),( .@timelimit + gettimetick(2) );
copyarray getd( "@ms_"+.@mission_id+"_list[0]" ),.@monster_list[0],.@monster_size;
copyarray getd( "@ms_"+.@mission_id+"_qty[0]" ),.@monster_qty[0],.@monster_size;
deletearray getd( "@ms_"+.@mission_id+"_hunt" );
addtimer ( .@timelimit * 1000 ),.npc_name$+"::OnTimeCheck";
}
}
break;
Case 3:
query_sql( "SELECT `id`,`title`,`min_lv`,`max_lv` FROM `mission_board` WHERE `npc_id` LIKE '%|"+.@mission_npc_num+"|%' AND `id` IN ( SELECT `mission_id` FROM `player_mission` WHERE `cid` = "+getcharid(0)+" AND `completion` = '0000-00-00 00:00:00' )",.@id,.@title$,.@min_lv,.@max_lv );
.@id_size = getarraysize( .@id );
for( .@i = 0; .@i < .@id_size; .@i++ )
.@mission_menu$ = .@mission_menu$ + "["+.@min_lv[.@i]+"~"+.@max_lv[.@i]+"] "+.@title$[.@i] +":";
mes "^0055FF[ "+.@npc_name$+" ]^000000";
mes "Pick a Mission to remove.";
next;
.@i = select( .@mission_menu$ ) - 1;
mes "^0055FF[ "+.@npc_name$+" ]^000000";
mes "Confirm remove ^0055FFMission # "+.@id[.@i]+"^000000?";
mes "Title : ^0055FF"+.@title$[.@i]+"^000000";
mes "^777777( this cant be un-done )^000000";
if( select( "nope","Confirm" ) == 2 ){
mes "^0055FF[ "+.@npc_name$+" ]^000000";
mes "Done removed.";
query_sql( "DELETE FROM `player_mission` WHERE `mission_id` = "+.@id[.@i]+" AND `cid` = "+getcharid(0)+" AND `completion` = '0000-00-00 00:00:00'" );
setd( "@ms_"+.@id[.@i]+"_expire" ),0;
deletearray getd( "@ms_"+.@id[.@i]+"_list" );
deletearray getd( "@ms_"+.@id[.@i]+"_qty" );
deletearray getd( "@ms_"+.@id[.@i]+"_hunt" );
for( .@ms = 0; .@ms < @ms_size; .@ms++ )
if( ""+.@id[.@i] == @ms_list$[.@ms] ){
deletearray @ms_list$[.@ms],1;
@ms_size--;
break;
}
}
break;
Case 4:
// get info from SQL.
do{
mes "^0055FF[ "+.@npc_name$+" ]^000000";
deletearray .@id;
query_sql( "SELECT `id`,`title`,`min_lv`,`max_lv` FROM `mission_board` WHERE `npc_id` LIKE '%|"+.@mission_npc_num+"|%' LIMIT "+.max_page_size+" OFFSET "+.@offset,.@id,.@title$,.@min_lv,.@max_lv );
.@offset += .max_page_size;
.@size = getarraysize( .@id );
if( !.@size ){
mes "There are no available mission to update.";
close;

}else{
mes "Pick a mission.";
.@mission_menu$ = "";
for( .@i = 0; .@i < .@size; .@i++ )
.@mission_menu$ = .@mission_menu$ + "["+.@min_lv[.@i]+"~"+.@max_lv[.@i]+"] "+.@title$[.@i] +":";
}
next;
.@i = select( .@mission_menu$+"- next page" ) - 1;
}while( .@i == .@size );
query_sql( "SELECT * FROM `mission_board` WHERE `id` = "+.@id[.@i],
.@new_mission_id,
.@title$,
.@description$,
.@mob_list$,
.@mob_qty$,
.@item_list$,
.@item_qty$,
.@base_job_bitmask,
.@job_branch_bitmask,
.@min_lv,
.@max_lv,
.@repeatable,
.@timelimit,
.@reward_list$,
.@reward_qty$,
.@baseexp,
.@jobexp,
.@zeny,
.@cash,
.@aid,
.@name$,
.@time_update$,
.@npc_id$,
.@redo_delay
);
// explode all saved strings to array value.
.@monster_size = callsub( OnExplodeArray,.@mob_list$,.@monster_list,0 );
.@monster_size = callsub( OnExplodeArray,.@mob_qty$,.@monster_qty,0 );

.@item_size = callsub( OnExplodeArray,.@item_list$,.@item_list,0 );
.@item_size = callsub( OnExplodeArray,.@item_qty$,.@item_qty,0 );

.@reward_size = callsub( OnExplodeArray,.@reward_list$,.@reward_list,0 );
.@reward_size = callsub( OnExplodeArray,.@reward_qty$,.@reward_qty,0 );

.@selected_npc_size = callsub( OnExplodeArray,.@npc_id$,.@selected_npc_array$,1 );

setarray .@level_range,.@min_lv,.@max_lv;

Case 5:
do{
mes "^0055FF[ "+.@npc_name$+" ]^000000";
// display the information of mission
callsub( OnDisplayMissionInfo,
.@new_mission_id,
.@title$,
.@description$,
.@level_range,
.@repeatable,
( .@timelimit + gettimetick(2) ),
.@monster_list,
.@monster_qty,
.@item_list,
.@item_qty,
.@base_job_bitmask,
.@job_branch_bitmask,
.@baseexp,
.@jobexp,
.@cash,
.@zeny,
.@reward_list,
.@reward_qty,
.@selected_npc_array$,
.@time_update$,
.@redo_delay,
0
);

// check if required info complete for setup mission
.@incomplete = 0;
if( .@title$ == "" ) .@incomplete |= 1;
if( .@description$ == "" ) .@incomplete |= 2;
if( !.@monster_size && !.@item_size ) .@incomplete |= 4;
if( getarraysize( .@level_range ) != 2 || !.@base_job_bitmask || !.@job_branch_bitmask ) .@incomplete |= 8;
if( !.@reward_size && !.@baseexp && !.@jobexp && !.@cash && !.@zeny ) .@incomplete |= 16;
if( !.@selected_npc_size ) .@incomplete |= 32;

.@main_option = select( "Edit Title "+(( .@incomplete & 1 )?"^FF0000-incomplete-^000000":"" ),
"Edit Description "+(( .@incomplete & 2 )?"^FF0000-incomplete-^000000":"" ),
"Edit Monster List "+(( .@incomplete & 4 )?"^FF0000-incomplete-^000000":( ( !.@monster_size )?"^777777-none-^000000":"" )),
"Edit Item List "+(( .@incomplete & 4 )?"^FF0000-incomplete-^000000":( ( !.@item_size )?"^777777-none-^000000":"" )),
"Edit Class/Level Limitation "+(( .@incomplete & 8 )?"^FF0000-incomplete-^000000":"" ),
"Edit Time/Repeat/Mission Limitation ",
"Edit Reward List "+(( .@incomplete & 16 )?"^FF0000-incomplete-^000000":"" ),
"Edit NPC Limitation "+(( .@incomplete & 32 )?"^FF0000-incomplete-^000000":"" ),
( .@incomplete )?"":"^0055FF - Complete Setup Mission^000000" );
next;
switch( .@main_option ){
Case 1:
mes "^0055FF[ "+.@npc_name$+" ]^000000";
mes "Enter Title";
mes "^777777( Length: 4 ~ 30 )^000000";
while( input( .@title$,4,30 ) );
.@input_result = replacestr( .@title$,":"," " );
break;
Case 2:
.@description$ = "";
do{
mes "^0055FF[ "+.@npc_name$+" ]^000000";
mes "Enter Description";
mes "^777777( Length: 4 ~ 255 )^000000";
mes " ";
mes "^0055FF"+.@description$+"^000000";
.@length = getstrlen( .@description$ );
do{
.@input_result = input( .@temp_input$,4,255 );
if( .@input_result )
message strcharinfo(0),"Input length must between 4 ~ 255";
}while( .@input_result );
.@description$ = .@description$ + " "+ .@temp_input$;
mes "^0055FF"+.@temp_input$+"^000000";
.@length = getstrlen( .@description$ );
next;
}while( select( ( .@length >= 255 )?"":"add more ^777777( left "+( 255 - .@length )+" words )^000000","-back" ) == 1 );
.@description$ = replacestr( .@description$,":"," " );
break;
Case 3:
if( .@new_mission_id ){
dispbottom "Editing monster list might caused unwanted behaviours of scripts. Which may included :";
dispbottom " > Script/Missions isnt working properly.";
dispbottom " > Deletion of player mission's progress.";
dispbottom " > etc.";
dispbottom "Overall it's not suggested to edit monster list that you have set early.";
dispbottom "( Recommend for Re-Adding mission, if needed )";
}
do{
mes "^0055FF[ "+.@npc_name$+" ]^000000";
mes "Monster List:";
if( .@monster_size ){
.@mob_menu$ = "";
deletearray .@current_mob$;
for( .@i = 0; .@i < .@monster_size; .@i++ ){
.@mob_name$ = getmonsterinfo( .@monster_list[.@i],MOB_NAME );
.@mob_menu$ = .@mob_menu$ + .@monster_qty[.@i] +" x "+.@mob_name$ +":";
.@current_mob$[.@i] = .@mob_name$;
mes " ^777777 ~ "+.@monster_qty[.@i]+" x "+.@mob_name$+"^000000";
}
.@current_mob_list$ = implode( .@current_mob$,"|" );
}else{
mes " ^777777 ~ none ^000000";
}
mes " ";
.@option = select( ( .@monster_size >= .max_required_monster )?"":"Add Monster",( .@monster_size )?"Delete Monster":"","- Back" );
switch( .@option ){
Case 1:
mes "^0055FF[ "+.@npc_name$+" ]^000000";
mes "Enter Monster ID";
do{
input .@mob_id;
if( !.@mob_id ) break;
.@mob_name$ = getmonsterinfo( .@mob_id,MOB_NAME );
}while( .@mob_name$ == "null" );
if( .@mob_name$ != "null" ){
mes "How many "+.@mob_name$+" need to hunt ?";
input .@amount,0,30000;
if( .@amount ){
if( compare( "|"+.@current_mob_list$+"|","|"+.@mob_name$+"|" ) ){
for( .@i = 0; .@i < .@monster_size; .@i++ )
if( .@monster_list[.@i] == .@mob_id ){
.@monster_qty[.@i] += .@amount;
break;
}

}else{
.@monster_list[.@monster_size] = .@mob_id;
.@monster_qty[.@monster_size] = .@amount;
.@monster_size++;
}
}
}
break;
Case 2:
mes "^0055FF[ "+.@npc_name$+" ]^000000";
mes "Pick a Monster to Remove.";
.@i = select( .@mob_menu$ ) - 1;
deletearray .@monster_list[.@i],1;
deletearray .@monster_qty[.@i],1;
.@monster_size--;
default: break;
}
if( .@option < 3 ) next;
}while( .@option < 3 );
break;
Case 4:
do{
mes "^0055FF[ "+.@npc_name$+" ]^000000";
mes "Required Item List: ";
if( .@item_size ){
.@item_menu$ = "";
deletearray .@current_item$;
for( .@i = 0; .@i < .@item_size; .@i++ ){
.@item_name$ = getitemname( .@item_list[.@i] );
.@item_menu$ = .@item_menu$ + .@item_qty[.@i] +"x "+.@item_name$ +":";
.@current_item$[.@i] = .@item_name$;
mes " ^777777 ~ "+.@item_qty[.@i]+" x "+.@item_name$+"^000000";
}
.@current_item_list$ = implode( .@current_item$,"|" );

}else{
mes " ^777777 ~ none ^000000";
}
mes " ";
.@option = select( ( .@item_size >= .max_required_item )?"":"Add Item",( .@item_size )?"Delete Item":"","- Back" );
switch( .@option ){
Case 1:
mes "^0055FF[ "+.@npc_name$+" ]^000000";
mes "Enter Item ID";
do{
input .@item_id;
if( !.@item_id ) break;
.@item_name$ = getitemname( .@item_id );
}while( .@item_name$ == "null" || .@item_name$ == "" );
if( .@item_id && .@item_name$ != "null" && .@item_name$ != "" ){
mes "How many "+.@item_name$+" need to collect ?";
input .@amount,0,30000;
if( .@amount ){
if( compare( "|"+.@current_item_list$+"|","|"+.@item_name$+"|" ) ){
for( .@i = 0; .@i < .@item_size; .@i++ )
if( .@item_list[.@i] == .@item_id ){
.@item_qty[.@i] += .@amount;
break;
}
}else{
.@item_list[.@item_size] = .@item_id;
.@item_qty[.@item_size] = .@amount;
.@item_size++;
}
}
}
break;
Case 2:
mes "^0055FF[ "+.@npc_name$+" ]^000000";
mes "Pick an Item to Remove.";
.@i = select( .@item_menu$ ) - 1;
mes "Removed "+.@item_qty[.@i]+" x "+getitemname( .@item_list[.@i] );
deletearray .@item_list[.@i],1;
deletearray .@item_qty[.@i],1;
.@item_size--;
default: break;
}
if( .@option < 3 ) next;
}while( .@option < 3 );
break;
Case 5: // class limitation
do{
mes "^0055FF[ "+.@npc_name$+" ]^000000";
mes "Level Range : "+( ( .@level_range[1] )? "^777777"+.@level_range[0]+" ~ "+.@level_range[1]:"^FF0000-incomplete-" )+"^000000";
mes "Available Job Setting";
if( .@base_job_bitmask ){
for( .@i = 0; .@i < .base_job_size; .@i++ )
if( .@base_job_bitmask & ( 1 << .@i ) )
mes " ^777777 ~ "+jobname( roclass( .base_job[.@i] ) )+" ^000000";
}else{
mes " ^FF0000 -incomplete-^000000";
}
mes " ";
mes "Inherited Branch Setting";
if( .@job_branch_bitmask ){
for( .@i = 0; .@i < .job_branch_size; .@i++ )
if( .@job_branch_bitmask & ( 1 << .@i ) )
mes " ^777777 ~ "+.job_branch_name$[.@i]+" ^000000";
}else{
mes " ^FF0000 -incomplete-^000000";
}
next;
.@option = select( "Edit Base Job","Edit Job Branch","Edit Level Range","- Back" );
switch( .@option ){
Case 1:
do{
mes "^0055FF[ "+.@npc_name$+" ]^000000";
mes "Available Job List:";
.@base_job_menu$ = "";
for( .@i = 0; .@i < .base_job_size; .@i++ ){
.@job_name$ = jobname( roclass( .base_job[.@i] ) );
if( .@base_job_bitmask & ( 1 << .@i ) )
mes " ^777777 ~ "+.@job_name$+" ^000000";
.@base_job_menu$ = .@base_job_menu$ + (( .@base_job_bitmask & ( 1 << .@i ) )?"^4EEE94":"^FF0000" ) + .@job_name$ +"^000000:";
}
next;
.@i = select( .@base_job_menu$+" -Back" ) - 1;
if( .@i < .base_job_size ){
.@bitmask_value = ( 1 << .@i );
if( .@base_job_bitmask & .@bitmask_value )
.@base_job_bitmask -= .@bitmask_value;
else
.@base_job_bitmask |= .@bitmask_value;
}
}while( .@i < .base_job_size );
break;
Case 2:
do{
mes "^0055FF[ "+.@npc_name$+" ]^000000";
mes "Inherited Job Branch List:";
.@job_branch_menu$ = "";
for( .@i = 0; .@i < .job_branch_size; .@i++ ){
if( .@job_branch_bitmask & ( 1 << .@i ) )
mes " ^777777 ~ "+.job_branch_name$[.@i]+" ^000000";
.@job_branch_menu$ = .@job_branch_menu$ + (( .@job_branch_bitmask & ( 1 << .@i ) )?"^4EEE94":"^FF0000" ) + .job_branch_name$[.@i] +"^000000:";
}
next;
.@i = select( .@job_branch_menu$+" - Back" ) - 1;
if( .@i < .job_branch_size ){
.@bitmask_value = ( 1 << .@i );
if( .@job_branch_bitmask & .@bitmask_value )
.@job_branch_bitmask -= .@bitmask_value;
else
.@job_branch_bitmask |= .@bitmask_value;
}
}while( .@i < .job_branch_size );
break;
Case 3:
mes "^0055FF[ "+.@npc_name$+" ]^000000";
mes "Minimum Level";
input .@level_range[0],1,.server_max_level ;
mes "Maximum Level";
input .@level_range[1],.@level_range[0],.server_max_level;
default: break;
}
next;
if( .@option < 4 ) next;
}while( .@option < 4 );
break;
Case 6: // mission limitation
do{
mes "^0055FF[ "+.@npc_name$+" ]^000000";
mes "Repeatable: ^777777"+( ( !.@repeatable )?"unlimit":""+.@repeatable )+" time^000000";
mes "Redo Delay: ^777777"+( ( !.@redo_delay )?"none":callsub( OnTime2Str,( ( .@redo_delay * 3600 ) + gettimetick(2) ) ))+"^000000";
mes "Time Limit: ^777777"+( ( !.@timelimit )?"none":callsub( OnTime2Str,( .@timelimit + gettimetick(2) ) ) )+"^000000";
.@option = select( "Edit Repeatable Status","Edit Time Limit","Edit Re-do Delay","Edit Required Mission","- Back" );
switch( .@option ){
Case 1:
mes "How many time can this mission repeat ??";
mes "^777777( 0 = unlimited )^000000";
input .@repeatable,0,100;
break;
Case 2:
mes "Time Limit of mission";
mes " 1 = 1 minute";
mes " 60 = 1 hour";
mes "1440 = 1 day";
input .@timelimit,0,50000;
.@timelimit *= 60;
break;
Case 3:
mes "Time Delay to re-take the mission";
mes " 1 = 1 hour";
mes " 24 = 1 day";
mes " 720 = 30 day";
input .@redo_delay,0,50000;
break;
Case 4:
mes "This is not fully implemented yet.. still in beta test";
break;

do{
mes "Required Mission:";
if( .@required_mission_size ){
for( .@i = 0; .@i < .@required_mission_size; .@i++ ){
mes " ^777777 ~ "+.@required_mission$[.@i]+"^000000";
.@required_mission_menu$ = .@required_mission_menu$ + .@required_mission$[.@i] +":";
}

}else{
mes "^777777 none ^000000";
}
next;
.@sub_option = select( ( .@required_mission_size < .max_required_mission )?"Add required mission":"",
( .@required_mission_size )?"Remove required mission":"",
"- Back");
switch( .@sub_option ){
Case 1:
mes "Enter mission ID";
mes "^777777( enter 0 to cancel )^000000";
do{
input .@mission_id$;
if( .@mission_id$ == "0" ) break;
}while( compare( "|"+.@required_mission_menu$+"|","|"+.@mission_id$+"|" ) );
.@mission_id$ = replacestr( .@mission_id$,":","" );
if( .@mission_id$ != "0" ){
.@required_mission$[.@required_mission_size] = .@mission_id$;
.@required_mission_size++;
}
break;
Case 2:
mes "Select a mission to remove.";
.@i = select( .@required_mission_menu$ ) - 1;
deletearray .@required_mission$[.@i],1;
default: break;
}
}while( .@sub_option < 3 );
default: break;
}
if( .@option < 5 ) next;
}while( .@option < 5 );
break;
Case 7: // reward list
do{
mes "^0055FF[ "+.@npc_name$+" ]^000000";
mes " ";
mes "Cash : ^777777"+( ( .@cash )? .@cash:"none" )+"^000000";
mes "Zeny : ^777777"+( ( .@zeny )? .@zeny:"none" )+"^000000";
mes "Reward Item List: ";
if( .@reward_size ){
.@reward_menu$ = "";
deletearray .@current_reward$;
for( .@i = 0; .@i < .@reward_size; .@i++ ){
.@reward_name$ = getitemname( .@reward_list[.@i] );
.@reward_menu$ = .@item_menu$ + .@reward_qty[.@i] +"x "+.@reward_name$ +":";
.@current_reward$[.@i] = .@reward_name$;
mes " ^777777 ~ "+.@reward_qty[.@i]+" x "+.@reward_name$+"^000000";
}
.@current_reward_list$ = implode( .@current_reward$,"|" );

}else{
mes " ^777777 ~ none ^000000";
}
mes "Base EXP : ^777777"+( ( .@baseexp )? .@baseexp:"none" )+"^000000";
mes "Job EXP : ^777777"+( ( .@jobexp )? .@jobexp:"none" )+"^000000";
mes " ";
next;
.@option = select( ( .@reward_size >= .max_required_item )?"":"Add Item Reward",
( .@reward_size )?"Delete Item Reward":"",
"Edit Cash Reward",
"Edit Zeny Reward",
"Edit Base EXP Reward",
"Edit Job EXP Reward",
"- Back" );
mes "^0055FF[ "+.@npc_name$+" ]^000000";
switch( .@option ){
Case 1:
mes "Enter Reward Item ID";
do{
input .@reward_id;
if( !.@reward_id ) break;
.@reward_name$ = getitemname( .@reward_id );
}while( .@reward_name$ == "null" || .@reward_name$ == "" );
if( .@reward_id && .@reward_name$ != "null" && .@reward_name$ != "" ){
mes "How many "+.@reward_name$+" will be rewarded ?";
input .@amount,0,30000;
if( .@amount ){
if( compare( "|"+.@current_reward_list$+"|","|"+.@reward_name$+"|" ) ){
for( .@i = 0; .@i < .@reward_size; .@i++ )
if( .@reward_list[.@i] == .@item_id ){
.@reward_qty[.@i] += .@amount;
break;
}
}else{
.@reward_list[.@reward_size] = .@reward_id;
.@reward_qty[.@reward_size] = .@amount;
.@reward_size++;
}
}
}
break;
Case 2:
mes "Pick an Reward to Remove.";
.@i = select( .@reward_menu$ ) - 1;
mes "Removed "+.@reward_qty[.@i]+"x "+getitemname( .@reward_list[.@i] );
deletearray .@reward_list[.@i],1;
deletearray .@reward_qty[.@i],1;
.@reward_size--;
break;
Case 3:
mes "How many Cash will be given ?";
mes "^777777( value: 0 ~ "+.max_integer_value+" )^000000";
input .@cash,0,.max_integer_value;
break;
Case 4:
mes "How many Zeny will be given ?";
mes "^777777( value: 0 ~ "+.max_integer_value+" )^000000";
input .@zeny,0,.max_integer_value;
break;
Case 5:
mes "How many Base EXP reward ?";
mes "^777777( value: 0 ~ "+.max_integer_value+" )^000000";
input .@baseexp,0,.max_integer_value;
break;
Case 6:
mes "How many Job EXP reward ?";
mes "^777777( value: 0 ~ "+.max_integer_value+" )^000000";
input .@jobexp,0,.max_integer_value;
default: break;
}
next;
}while( .@option < 7 );
break;
Case 8: // npc limitation
mes "^0055FF[ "+.@npc_name$+" ]^000000";
mes "By default, the mission will be available from each mission board npc ^FF0000unless you have specified which NPC may offer this mission.^000000";
mes " ";
mes "Just pick all the NPC that may offer this mission if you wish.";
next;
if( !getarraysize( .@selected_npc_array$ ) )
for( .@i = 1; .@i <= .mission_npc_count; .@i++ ){
.@selected_npc_array$[.@i-1] = ""+.@i;
.@selected_npc_size++;
}
do{
mes "^0055FF[ "+.@npc_name$+" ]^000000";
mes "Mission offered by: ";
.@selected_npc_menu$ = "";
if( .@selected_npc_size >= 2 ){
.@selected_npc$ = "|"+implode( .@selected_npc_array$,"|" )+"|";
}else{
.@selected_npc$ = "|"+.@selected_npc_array$+"|";
}
for( .@i = 1; .@i <= .mission_npc_count; .@i++ ){
getmapxy( .@map$,.@x,.@y,1,( .name_offset_num + .@i ) );
.@sub_npc_name$ = "^777777("+.@map$+") ";
.@sub_npc_name$ = .@sub_npc_name$ + ( ( compare( "|"+.@selected_npc$+"|","|"+.@i+"|" ) )?"^44EE00":"^FF0000" );
// .@sub_npc_name$ = .@sub_npc_name$ + "["+.@map$+","+.@x+","+.@y+"]";
.@sub_npc_name$ = .@sub_npc_name$ + .npc_name_list$[.@i] + "^000000";
mes ""+.@sub_npc_name$;
.@selected_npc_menu$ = .@selected_npc_menu$ + .@sub_npc_name$ +":";
}
next;
.@option = select( .@selected_npc_menu$+"-Back" );
if( .@option <= .mission_npc_count ){
if( compare( "|"+.@selected_npc$+"|","|"+.@option+"|" ) )
.@selected_npc_array$[.@option-1] = "";
else
.@selected_npc_array$[.@option-1] = ""+.@option;
.@selected_npc_size = getarraysize( .@selected_npc_array$ );
}
}while( .@option <= .mission_npc_count );
break;
default: break;
}
next;
}while( .@main_option < 9 );

// finalise all variable
if( .@monster_size ){
.@final_mob_list$ = "|";
.@final_mob_qty$ = "|";
for( .@i = 0; .@i < .@monster_size; .@i++ ){
.@final_mob_list$ = .@final_mob_list$ + .@monster_list[.@i] +"|";
.@final_mob_qty$ = .@final_mob_qty$ + .@monster_qty[.@i] +"|";
}
}

if( .@item_size ){
.@final_item_list$ = "|";
.@final_item_qty$ = "|";
for( .@i = 0; .@i < .@item_size; .@i++ ){
.@final_item_list$ = .@final_item_list$ + .@item_list[.@i] +"|";
.@final_item_qty$ = .@final_item_qty$ + .@item_qty[.@i] +"|";
}
}

if( .@reward_size ){
.@final_reward_list$ = "|";
.@final_reward_qty$ = "|";
for( .@i = 0; .@i < .@reward_size; .@i++ ){
.@final_reward_list$ = .@final_reward_list$ + .@reward_list[.@i] +"|";
.@final_reward_qty$ = .@final_reward_qty$ + .@reward_qty[.@i] +"|";
}
}

if( .@selected_npc_size ){
.@final_npc_list$ = "|";
for( .@i = 0; .@i < .@selected_npc_size; .@i++ )
.@final_npc_list$ = .@final_npc_list$ + .@selected_npc_array$[.@i] +"|";
}

if( !.@new_mission_id ){
.@new_mission_id = gettimetick(1);
message strcharinfo(0),"Mission # "+.@new_mission_id+" has been added.";
}else{
message strcharinfo(0),"Mission # "+.@new_mission_id+" has been updated.";
// attach and inform other online players.
callsub( OnRemoveMission,.@new_mission_id,"A GM updated Mission # "+.@new_mission_id );
}

// add new mission into SQL
query_sql(
"REPLACE INTO `mission_board` VALUES ( " +
.@new_mission_id+", " +
"'"+escape_sql( .@title$ )+"', " +
"'"+escape_sql( .@description$ )+"', " +
"'"+escape_sql( .@final_mob_list$ )+"', " +
"'"+escape_sql( .@final_mob_qty$ )+"', " +
"'"+escape_sql( .@final_item_list$ )+"', " +
"'"+escape_sql( .@final_item_qty$ )+"', " +
.@base_job_bitmask+", " +
.@job_branch_bitmask+", " +
.@level_range[0]+", " +
.@level_range[1]+", " +
.@repeatable+", " +
.@timelimit+", " +
"'"+escape_sql( .@final_reward_list$ )+"', " +
"'"+escape_sql( .@final_reward_qty$ )+"', " +
.@baseexp+", " +
.@jobexp+", " +
.@zeny+", " +
.@cash+", " +
getcharid(3)+", " +
"'"+escape_sql( strcharinfo(0) )+"', " +
"NOW(), " +
"'"+escape_sql( .@final_npc_list$ )+"', " +
.@redo_delay +
" ); "
);
break;
Case 6: // delete mission
do{
mes "^0055FF[ "+.@npc_name$+" ]^000000";
deletearray .@id;
query_sql( "SELECT `id`,`title`,`min_lv`,`max_lv` FROM `mission_board` WHERE `npc_id` LIKE '%|"+.@mission_npc_num+"|%' LIMIT "+.max_page_size+" OFFSET "+.@offset,.@id,.@title$,.@min_lv,.@max_lv );
.@offset += .max_page_size;
.@size = getarraysize( .@id );
if( !.@size ){
mes "There are no available mission to update.";
close;

}else{
mes "Pick a mission.";
for( .@i = 0; .@i < .@size; .@i++ )
.@mission_menu$ = .@mission_menu$ + "["+.@min_lv[.@i]+"~"+.@max_lv[.@i]+"] "+.@title$[.@i] +":";
}
next;
.@i = select( .@mission_menu$+"- next page" ) - 1;
}while( .@i == .@size );
.@mission_id = .@id[.@i];
mes "^0055FF[ "+.@npc_name$+" ]^000000";
mes "Are you sure to remove this mission ?";
if( select( "nope","Delete Mission" ) == 2 ){
query_sql( "DELETE FROM `mission_board` WHERE `id` = "+.@mission_id+" LIMIT 1" );
mes "Removed mission from mission list.";

// attach other online players and remove the missions.
callsub( OnRemoveMission,.@mission_id,"A GM removed Mission # "+.@mission_id );
query_sql( "DELETE FROM `player_mission` WHERE `completion` = '0000-00-00 00:00:00' AND `mission_id` = "+.@mission_id );
mes "Removed mission from all players.";
}
default: break;
}
close;

OnInit:
.name_offset_num = 1000;
// initialize settings
if( strnpcinfo(0) == "mission_board" ){

// gm level to access panel
.gm_level = 90;
// max no. of required monster
.max_required_monster = 10;
// max no. of required item
.max_required_item = 10;
// max no. of required mission ( un-implement yet )
.max_required_mission = 10;
// max no. of available mission
.max_mission_available = 50;
// max value of integer input
.max_integer_value = 2000000000;
// max amount of mission per page
.max_page_size = 30;
// max mission per npc take by character
.max_mission_per_char = 4;

// predefined values.
.npc_name$ = strnpcinfo(0);
.server_max_level = getbattleflag( "max_lv" );
setarray .base_job,
EAJ_SWORDMAN,
EAJ_MAGE,
EAJ_ARCHER,
EAJ_ACOLYTE,
EAJ_MERCHANT,
EAJ_THIEF,
EAJ_TAEKWON,
EAJ_GUNSLINGER,
EAJ_NINJA;
.base_job_size = getarraysize( .base_job );
setarray .job_branch_name$,
"2-1 Classes",
"2-2 Classes",
"Rebirth Classes",
"Baby Classes",
"Third Classes";
setarray .job_branch,
EAJL_2_1,
EAJL_2_2,
EAJL_UPPER,
EAJL_BABY,
EAJL_THIRD;
.job_branch_size = getarraysize( .job_branch );
sleep 1000;
debugmes "[ Mission Board ] NPC Loaded : "+.mission_npc_count+" ...";

}else{
.mission_npc_count++;
// save correct npc name to each index based on unique name
.@index = ( atoi( strnpcinfo(3) ) - .name_offset_num );
.npc_name_list$[ .@index ] = strnpcinfo(1);
// debugmes "["+.@index+"]"+.npc_name_list$[ .@index ];
}
end;


// OnWhisperGlobal:
OnPCLoginEvent:
if( strnpcinfo(0) == .npc_name$ ){
.@timetick = gettimetick(2);
query_sql( "SELECT `mission_id`,`expire`,`mob_hunt` FROM `player_mission` WHERE `completion` = '0000-00-00 00:00:00' AND `cid` = "+getcharid(0),@ms_list$,.@expire,.@mob_hunt$ );
@ms_size = getarraysize( @ms_list$ );
if( @ms_size )
for( .@i = 0; .@i < @ms_size; .@i++ ){
if( .@timetick < .@expire[.@i] ){
.@timeleft = ( .@expire[.@i] - .@timetick );
addtimer ( .@timeleft * 1000 ),.npc_name$+"::OnTimeCheck";
dispbottom "[ Mission Progress : "+@ms_list$[.@i]+" , expire in "+callsub( OnTime2Str,( .@timeleft + .@timetick ) )+" ]";
query_sql( "SELECT `mob_list`,`mob_qty` FROM `mission_board` WHERE `id` = "+@ms_list$[.@i],.@mob_list$,.@mob_qty$ );

setd( "@ms_"+@ms_list$[.@i]+"_expire" ),.@expire[.@i];
if( callsub( OnExplodeArray,.@mob_list$[.@i],getd( "@ms_"+@ms_list$[.@i]+"_list" ),0 ) ){
callsub( OnExplodeArray,.@mob_hunt$[.@i],getd( "@ms_"+@ms_list$[.@i]+"_qty" ),0 );
.@monster_size = callsub( OnExplodeArray,.@mob_hunt$[.@i],getd( "@ms_"+@ms_list$[.@i]+"_hunt" ),0 );
// for( .@mob = 0; .@mob < .@monster_size; .@mob++ )
// dispbottom " ~ killed "+getd( "@ms_"+@ms_list$[.@i]+"_hunt["+.@mob+"]" )+"/"+getd( "@ms_"+@ms_list$[.@i]+"_qty["+.@mob+"]" )+" x "+getmonsterinfo( getd( "@ms_"+@ms_list$[.@i]+"_list["+.@mob+"]" ),MOB_NAME );
}
}
}
}
end;

OnPCLogoutEvent:
if( strnpcinfo(0) == .npc_name$ ){
if( @ms_size )
for( .@ms = 0; .@ms < @ms_size; .@ms++ ){
debugmes "Saving "+@ms_list$[.@ms];
.@mob_size = getarraysize( getd( "@ms_"+@ms_list$[.@ms]+"_list" ) );
if( .@mob_size ){
copyarray .@temp_array[0],getd( "@ms_"+@ms_list$[.@ms]+"_list[0]" ),.@mob_size;
.@mob_hunt$ = "|";
for( .@mob = 0; .@mob < .@mob_size; .@mob++ )
.@mob_hunt$ = .@mob_hunt$ + getd( "@ms_"+@ms_list$[.@ms]+"_hunt["+.@mob+"]" ) +"|";
query_sql( "UPDATE `player_mission` SET `mob_hunt` = '"+escape_sql( .@mob_hunt$ )+"' WHERE `mission_id` = "+@ms_list$[.@ms]+" AND `completion` = '0000-00-00 00:00:00' AND `cid` = "+getcharid(0) );
}
}
}
end;

OnNPCKillEvent:
if( strnpcinfo(0) == .npc_name$ ){
if( @ms_size ){
.@timetick = gettimetick(2);
for( .@ms = ( @ms_size - 1 ); .@ms >= 0; .@ms-- ){
if( getd( "@ms_"+@ms_list$[.@ms]+"_expire" ) < .@timetick ){
setd( "@ms_"+@ms_list$[.@ms]+"_expire" ),0;
deletearray getd( "@ms_"+@ms_list$[.@ms]+"_list" );
deletearray getd( "@ms_"+@ms_list$[.@ms]+"_qty" );
deletearray getd( "@ms_"+@ms_list$[.@ms]+"_hunt" );
dispbottom "[Mission # "+@ms_list$[.@ms]+"] Mission removed due to expired. ";
deletearray @ms_list$[.@ms],1;
@ms_size--;

}else{
.@mob_size = getarraysize( getd( "@ms_"+@ms_list$[.@ms]+"_list" ) );
if( .@mob_size ){
copyarray .@temp_array[0],getd( "@ms_"+@ms_list$[.@ms]+"_list[0]" ),.@mob_size;
for( .@mob = 0; .@mob_size; .@mob++ )
if( .@temp_array[.@mob] == killedrid ){
.@value = getd( "@ms_"+@ms_list$[.@ms]+"_hunt["+.@mob+"]" ) + 1;
setd( "@ms_"+@ms_list$[.@ms]+"_hunt["+.@mob+"]" ),.@value;
// dispbottom "[Mission # "+@ms_list$[.@ms]+" Progress] Hunted "+.@value+" x "+getmonsterinfo( .@temp_array[.@mob],MOB_NAME );
break;
}
deletearray .@temp_array;
}
}
}
}
}
end;

OnTimeCheck:
if( @ms_size ){
.@timetick = gettimetick(2);
for( .@i = ( @ms_size - 1 ); .@i >= 0; .@i-- ){
if( getd( "@ms_"+@ms_list$[.@i]+"_expire" ) <= .@timetick ){
setd( "@ms_"+@ms_list$[.@i]+"_expire" ),0;
deletearray getd( "@ms_"+@ms_list$[.@i]+"_list" );
deletearray getd( "@ms_"+@ms_list$[.@i]+"_qty" );
deletearray getd( "@ms_"+@ms_list$[.@i]+"_hunt" );
dispbottom "[Mission # "+@ms_list$[.@i]+"] Mission removed due to expired. ";
deletearray @ms_list$[.@i],1;
@ms_size--;
}
}
}
end;

OnRemoveMission:
.@mission_id = getarg(0);
.@message$ = getarg(1);

query_sql( "SELECT `aid`,`cid` FROM `player_mission` WHERE `cid` IN ( SELECT `char_id` FROM `char` WHERE `online` = 1 ) AND `mission_id` = "+.@mission_id+" AND `completion` = '0000-00-00 00:00:00' LIMIT 128",.@aid,.@cid );
.@aid_size = getarraysize( .@aid );
.@i = 0;
.@origin_aid = getcharid(3);
while( .@i < .@aid_size ){
if( isloggedin( .@aid[.@i],.@cid[.@i] ) ){
attachrid( .@aid[.@i] );
for( .@i = @ms_size; .@i >= 0; .@i-- )
if( @ms_list$[.@i] == ""+.@mission_id ){
message strcharinfo(0),.@message$;
dispbottom "Please visit Mission NPC to gain latest information.";
setd( "@ms_"+@ms_list$[.@i]+"_expire" ),0;
deletearray getd( "@ms_"+@ms_list$[.@i]+"_list" );
deletearray getd( "@ms_"+@ms_list$[.@i]+"_qty" );
deletearray getd( "@ms_"+@ms_list$[.@i]+"_hunt" );
deletearray @ms_list$[.@i],1;
@ms_size--;
break;
}
detachrid;
.@count++;
}
.@i++;
}
attachrid( .@origin_aid );
dispbottom "Total "+.@count+" online players affected.";
return;

// usage :
// .@timeleft = callsub( OnTime2Str,<time> );
OnTime2Str:
.@time = getarg(0);
.@left = ( .@time - gettimetick(2) );
.@hour = ( .@left / 3600 );
.@min = ( .@left % 3600 / 60 );
.@sec = ( .@left % 60 );
if( !.@left )
return "none";
else
return "^777777"+( ( .@hour )? .@hour+" hr ":"" ) + ( ( .@hour || .@min )? .@min+" min ":"" ) +.@sec+" sec^000000";


// usage :
// .@new_array_size = callsub( OnExplodeArray,<old string variable>,<new array variable>,<save '0'> );
OnExplodeArray:
.@type = getarg(2);
explode( getarg(0),getarg(0),"|" );
.@size = getarraysize( getarg(0) );
while( .@i < .@size ){
if( !.@type ){
.@value = atoi( getelementofarray( getarg(0),.@i ) );
if( .@value ){
set getelementofarray( getarg(1),.@new_size ),.@value;
.@new_size++;
}
}else{
set getelementofarray( getarg(1),.@new_size ),getelementofarray( getarg(0),.@i );
.@new_size++;
}
.@i++;
}

return .@new_size;


// display mission information + optional progress checking
OnDisplayMissionInfo:
.@mission_id = getarg(0);
.@title$ = getarg(1);
.@description$ = getarg(2);
.@repeatable = getarg(4);
.@timelimit = getarg(5);
.@monster_size = getarraysize( getarg(6) );
.@item_size = getarraysize( getarg(8) );
.@base_job_bitmask = getarg(10);
.@job_branch_bitmask = getarg(11);
.@baseexp = getarg(12);
.@jobexp = getarg(13);
.@cash = getarg(14);
.@zeny = getarg(15);
.@reward_size = getarraysize( getarg(16) );
.@selected_npc_size = getarraysize( getarg(18) );
.@time_update$ = getarg(19);
.@redo_delay = getarg(20);
.@check_progress = getarg(21);

if( .@check_progress & 8 )
.@eac = eaclass();

// display mission info
mes ""+(( .@mission_id )? "^FF0000Mission ID # "+.@mission_id:" " )+"^000000";
mes "Title : "+( ( .@title$ != "" )?"^777777"+.@title$:"^FF0000-incomplete-" )+"^000000";
mes "Description : "+( ( .@description$ != "" )?"^777777"+.@description$:"^FF0000-incomplete-" )+"^000000";
mes "Level Range : "+( ( getelementofarray( getarg(3),0 ) )? "^777777"+getelementofarray( getarg(3),0 )+" ~ "+getelementofarray( getarg(3),1 ):"^FF0000-incomplete-" )+"^000000";
if( .@check_progress & 1 )
if( BaseLevel >= getelementofarray( getarg(3),0 ) && BaseLevel <= getelementofarray( getarg(3),1 ) )
.@lv_progress = 1;

mes "Repeatable: ^777777"+( ( !.@repeatable )?"unlimit":.@repeatable+" time" )+"^000000";
mes "Redo Delay: ^777777"+( ( !.@redo_delay )?"none":callsub( OnTime2Str,( ( .@redo_delay * 3600 ) + gettimetick(2) ) ) )+"^000000";
mes "Expire in: ^777777"+( ( !.@timelimit )?"none":callsub( OnTime2Str,.@timelimit ) )+"^000000";
mes " ";

.@word$ = (( !.@monster_size && !.@item_size )?"^FF0000incomplete":"^777777none" );
mes "Monster List : "+( ( .@monster_size )?"":.@word$ )+"^000000";
if( .@monster_size )
for( .@i = 0; .@i < .@monster_size; .@i++ ){
.@mob_id = getelementofarray( getarg(6),.@i );
.@quantity = getelementofarray( getarg(7),.@i );
if( .@check_progress & 2 ){
.@killed_count = getd( "@ms_"+.@mission_id+"_hunt["+.@i+"]" );
if( .@killed_count >= .@quantity ){
.@monster_progress++;
.@temp_color$ = "44EE99";
}else{
.@temp_color$ = "FF0000";
}
}
mes " ^777777"+.@quantity+" x "+getmonsterinfo( .@mob_id,MOB_NAME )+" "+( ( .@check_progress & 2 )?"^"+.@temp_color$+"(killed "+.@killed_count+")":"" )+"^000000";
}
mes "Item List : "+( ( .@item_size )?"":.@word$ )+"^000000";
if( .@item_size )
for( .@i = 0; .@i < .@item_size; .@i++ ){
.@item_id = getelementofarray( getarg(8),.@i );
.@quantity = getelementofarray( getarg(9),.@i );
.@item_type = getiteminfo( .@item_id,2 );
if( .@check_progress & 4 ){
.@item_count = countitem( .@item_id );
if( .@item_count >= .@quantity ){
.@item_progress++;
.@temp_color$ = "44EE99";
}else{
.@temp_color$ = "FF0000";
}
}
mes " ^777777"+.@quantity+" x "+getitemname( .@item_id )+" "+( ( .@item_type == 4 || .@item_type == 5 )?"["+getitemslots( .@item_id )+"]":"" )+" "+( ( .@check_progress & 4 )?"^"+.@temp_color$+"(have "+.@item_count+")":"" )+"^000000";
}
mes " ";
mes "Available Job Classes :";
if( .@base_job_bitmask ){
deletearray .@available_job$;
deletearray .@available_branch$;
.@available_job_size = 0;
.@available_branch_size = 0;
for( .@i = 0; .@i < .base_job_size; .@i++ )
if( .@base_job_bitmask & ( 1 << .@i ) ){
.@class = roclass( .base_job[.@i] );
.@available_job$[.@available_job_size] = jobname( .@class );
if( .@check_progress & 8 && BaseClass == .@class )
.@class_progress = 1;
.@available_job_size++;
}
mes " ^777777"+implode( .@available_job$,"," )+" ^000000";
if( .@job_branch_bitmask ){
for( .@i = 0; .@i < .job_branch_size; .@i++ )
if( .@job_branch_bitmask & ( 1 << .@i ) ){
if( .@check_progress & 8 && ( .@eac & .job_branch[.@i] ) )
.@branch_progress++;
.@available_branch$[.@available_branch_size] = .job_branch_name$[.@i];
.@available_branch_size++;
}
mes "Inherited: ^777777"+implode( .@available_branch$,", " )+" ^000000";
}
}else{
mes " ^FF0000-incomplete^000000";
}

mes " ";
mes "Reward List : ";
mes "^777777 ~ Base EXP: "+( ( .@baseexp )? .@baseexp:"none" )+"^000000";
mes "^777777 ~ Job EXP: "+( ( .@jobexp )? .@jobexp:"none" )+"^000000";
mes "^777777 ~ Cash: "+( ( .@cash )? .@cash:"none" )+"^000000";
mes "^777777 ~ Zeny: "+( ( .@zeny )? .@zeny:"none" )+"^000000";
mes "Reward Item List: "+( ( .@reward_size )?"":"^777777none" )+"^000000";
if( .@reward_size )
for( .@i = 0; .@i < .@reward_size; .@i++ ){
.@item_id = getelementofarray( getarg(16),.@i );
.@item_type = getiteminfo( .@item_id,2 );
mes " ^777777 ~ "+getelementofarray( getarg(17),.@i )+" x "+getitemname( .@item_id )+" "+( ( .@item_type == 4 || .@item_type == 5 )?"["+getitemslots( .@item_id )+"]":"" )+"^000000";
}
mes " ";

mes "Mission Offered by: "+( ( .@selected_npc_size )?"":"^FF0000-incomplete" )+"^000000";
if( .@selected_npc_size ){
if( .@selected_npc_size >= 2 )
.@selected_npc$ = "|"+implode( getarg(18),"|" )+"|";
else
.@selected_npc$ = "|"+getarg(18)+"|";
for( .@i = 1; .@i <= .mission_npc_count; .@i++ )
if( ( compare( "|"+.@selected_npc$+"|","|"+.@i+"|" ) ) ){
getmapxy( .@map$,.@x,.@y,1,( .name_offset_num + .@i ) );
.@sub_npc_name$ = "^777777("+.@map$+") ";
// .@sub_npc_name$ = .@sub_npc_name$ + "["+.@map$+","+.@x+","+.@y+"]";
.@sub_npc_name$ = .@sub_npc_name$ + .npc_name_list$[.@i] + "^000000";
mes " ~ "+.@sub_npc_name$;
}



mes " ";
}
if( .@time_update$ != "0000-00-00 00:00:00" && .@time_update$ != "" ){
mes "Last Mission Update:";
mes "^777777"+.@time_update$+"^000000";
}

if( .@check_progress ){
if( .@check_progress & 1 && !.@lv_progress ){
dispbottom "[Failed] Your level didnt meet the requirements.";
.@check_result |= 1;
}
if( .@check_progress & 2 && .@monster_size != .@monster_progress ){
dispbottom "[Failed] Your Monsters Hunt didnt meet the requirements.";
.@check_result |= 2;
}
if( .@check_progress & 4 && .@item_size != .@item_progress ){
dispbottom "[Failed] Your Items collecting didnt meet the requirements.";
.@check_result |= 4;
}
if( .@check_progress & 8 && ( !.@branch_progress || !.@class_progress ) ){
dispbottom "[Failed] Your Class didnt meet the requirements.";
.@check_result |= 8;
}
}
return .@check_result;


}


// the number behind the NPC name must be above 1000 ( if you had not changed another )
// you can have 127 npcs.

prontera,151,171,4 duplicate(mission_board) Prontera Mission::1001 837
prontera,155,171,4 duplicate(mission_board) Byalan Mission::1002 837
prontera,159,171,4 duplicate(mission_board) Payon Cave Mission::1003 837
//prontera,159,175,4 duplicate(mission_board) Mission 1::1003 837
//prontera,159,171,4 duplicate(mission_board) Mission 2::1004 837
//prontera,159,171,4 duplicate(mission_board) Mission 3::1005 837
//prontera,159,171,4 duplicate(mission_board) Mission 4::1006 837
prontera,155,175,4 duplicate(mission_board) Prontera Mission::1007 837
I am not modify some codes, just add end line for duplicate NPC,

 

 

post your full script.

 

is this setup quest step ??

did you added any npc to offer this quest when you setup the quest ??

 

yes, screen shoot is a setup quest

not, i am not add any script.

 

Thanks Emistry

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  127
  • Topics Per Day:  0.03
  • Content Count:  1445
  • Reputation:   163
  • Joined:  08/17/13
  • Last Seen:  

for me it was working fine, players wera able to drop a mission after the picked up one

 

huh i got a lil. problem here

 

when adding gold acidus and blue acidus to the hunt quest, they weren't counted, they appeared like 1

same for green ferus and red ferus

 

i had to separate the quest, one for gold acidus and green ferus and another one for blue acidus and red ferus

 

any idea D:?!

 

Edit:

The script i have not changed it at all D:!

Link to comment
Share on other sites


  • Group:  Forum Moderator
  • Topic Count:  93
  • Topics Per Day:  0.02
  • Content Count:  10015
  • Reputation:   2354
  • Joined:  10/28/11
  • Last Seen:  

@Code Hunter

seem fine for me ......

17oTxto.jpg

 

btw...the number behind NPC should not jump ..

 

 

@kido

could it be you added wrong mob id ? some monster are used for event only.

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  0
  • Topics Per Day:  0
  • Content Count:  6
  • Reputation:   0
  • Joined:  10/22/12
  • Last Seen:  

/hmm

 

or maybe your script need some specify requirement?

 

i am try using last svn linux compiled with sql, then i am try using windows precompiled rAthena Revision 16797, it same, still not shown.

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  18
  • Topics Per Day:  0.00
  • Content Count:  2044
  • Reputation:   682
  • Joined:  10/09/12
  • Last Seen:  

http://www.eathena.ws/board/index.php?autocom=bugtracker&showbug=1260

gold acidus = 1713

blue acidus = 1716

abyss_02,0,0,0,0 monster Acidus 1713,10,600000,0,0

abyss_02,0,0,0,0 monster Acidus 1716,60,300000,0,0

areamonster .@map$,93,96,103,132,"Acidus",1716,10,.@label$;

areamonster .@map$,93,96,103,132,"Acidus",1713,10,.@label$;

apparently, the monster in abyss_02 can add the count, but if kill inside endless tower, its not

perhaps you should tell that ... this npc shouldn't setup outside instance npc ?

since all instance script has monster labels

@Code Hunter

I think his script doesn't have protection against skipping a npc ID

means, 1001,1002,1003,1004,1005,1006 ... must be in order ..

you can't do 1001,1005,1020,1030 ... it will bug

my old one, can jump ID, can detect which npc ID has fault and report it on that npc itself even

I think most people here ... doesn't read the error on map-server.exe console ... that might be the problem

that's why my script, if setup just slightly a little bug, the whole npc will down

Edited by AnnieRuru
Link to comment
Share on other sites


  • Group:  Forum Moderator
  • Topic Count:  93
  • Topics Per Day:  0.02
  • Content Count:  10015
  • Reputation:   2354
  • Joined:  10/28/11
  • Last Seen:  

I think his script doesn't have protection against skipping a npc ID

means, 1001,1002,1003,1004,1005,1006 ... must be in order ..

you can't do 1001,1005,1020,1030 ... it will bug

ya...just noticed it ...xD

but his problem seem like different ... in his screenshot, he cant see any npc name..O__O  but i can view the npc name..

weird..

 

anyway...detected a few possible bug ..xD 

gonna fix it when i have time ...

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  0
  • Topics Per Day:  0
  • Content Count:  6
  • Reputation:   0
  • Joined:  10/22/12
  • Last Seen:  

@Code Hunter

I think his script doesn't have protection against skipping a npc ID

means, 1001,1002,1003,1004,1005,1006 ... must be in order ..

you can't do 1001,1005,1020,1030 ... it will bug

my old one, can jump ID, can detect which npc ID has fault and report it on that npc itself even

I think most people here ... doesn't read the error on map-server.exe console ... that might be the problem

that's why my script, if setup just slightly a little bug, the whole npc will down

 

 

Yes, i have to it. but still same, NPC not snown, thanks AnnieRuru

 

 

I think his script doesn't have protection against skipping a npc ID

means, 1001,1002,1003,1004,1005,1006 ... must be in order ..

you can't do 1001,1005,1020,1030 ... it will bug

ya...just noticed it ...xD

but his problem seem like different ... in his screenshot, he cant see any npc name..O__O  but i can view the npc name..

weird..

 

anyway...detected a few possible bug ..xD 

gonna fix it when i have time ...

 

 

Last try, i am insert manually quest to sql table "mission_board", still same the quest not shown to NPC.

 

Okey Emistry, thanks once again for advice.

 

:)

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  127
  • Topics Per Day:  0.03
  • Content Count:  1445
  • Reputation:   163
  • Joined:  08/17/13
  • Last Seen:  

@Emistry @AnnieRuru

 

that's what i'm saying D: i added the different IDs, for example:

kill 100 gold acidus 1713

and 100 blue acidus 1716

 

then this appears, like it was only 1 same mob D:

*see the video*

http://youtu.be/Nq4LflypE6g

Link to comment
Share on other sites


  • Group:  Forum Moderator
  • Topic Count:  93
  • Topics Per Day:  0.02
  • Content Count:  10015
  • Reputation:   2354
  • Joined:  10/28/11
  • Last Seen:  

New Updates :

 Mission Board 1.2
  • Fixed mob/item adding bugs
  • Change how mission NPC naming
  • Enable All Classes by default when setup mission
  • Shorten some menu length
  • Auto remove NPC if it's named wrongly or max NPC reached.
 
feel free to report if you found any potential bugs / exploits..
  • Upvote 1
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  127
  • Topics Per Day:  0.03
  • Content Count:  1445
  • Reputation:   163
  • Joined:  08/17/13
  • Last Seen:  

woa excellente o:!!!

 

may i ask

should i deleted the sql table and re-add it?

with an @reloadscript by replacing the script file, should be make the changes too o:?

 

thankies emistry o:!!

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  18
  • Topics Per Day:  0.00
  • Content Count:  2044
  • Reputation:   682
  • Joined:  10/09/12
  • Last Seen:  

I think there's still a bug

the job branch doesn't enable a 1-1 job branch

if I'm a swordsman/archer/magician, I couldn't do any quest

@Kido

as long as the data structure has been planned out nicely .. there is no need to modify the sql table ..

though, I can kinda tell if emistry wants to add a custom variable as reward ... then need to do alter table in the future

Link to comment
Share on other sites


  • Group:  Forum Moderator
  • Topic Count:  93
  • Topics Per Day:  0.02
  • Content Count:  10015
  • Reputation:   2354
  • Joined:  10/28/11
  • Last Seen:  

I think there's still a bug

the job branch doesn't enable a 1-1 job branch

if I'm a swordsman/archer/magician, I couldn't do any quest

erm...i remember that it's enabled for all 1-1 job by default ... i didnt add any settings to limit 1-1 job ...the job limitation work after 1-1 job.

 

 

woa excellente o:!!!

 

may i ask

should i deleted the sql table and re-add it?

with an @reloadscript by replacing the script file, should be make the changes too o:?

 

thankies emistry o:!!

just as annie stated, dont need to change it.  the only things that you might need to change is just the npc column. ( might affected when changing NPC number )

 

 

and if there are any changes regarding SQL table, normally i will inform it during the updates =)

 

though, I can kinda tell if emistry wants to add a custom variable as reward ... then need to do alter table in the future

yes... will have to alter the table to add this.. =)

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  127
  • Topics Per Day:  0.03
  • Content Count:  1445
  • Reputation:   163
  • Joined:  08/17/13
  • Last Seen:  

can't wait for it < 3 ty both

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  18
  • Topics Per Day:  0.00
  • Content Count:  2044
  • Reputation:   682
  • Joined:  10/09/12
  • Last Seen:  

I think there's still a bug

the job branch doesn't enable a 1-1 job branch

if I'm a swordsman/archer/magician, I couldn't do any quest

erm...i remember that it's enabled for all 1-1 job by default ... i didnt add any settings to limit 1-1 job ...the job limitation work after 1-1 job.
no ... its not

 

if( .@check_progress & 8 && ( .@eac & .job_branch[.@i] ) )
.@branch_progress++;
your script doesn't have 1-1 enable

when .@eac if ( eaclass() & .job_branch ), 1-1 classes doesn't meet the requirement, thus .@branch_progress becomes 0

thus it meet this condition

			if( .@check_progress & 8 && ( !.@branch_progress || !.@class_progress ) ){
				dispbottom "[Failed] Your Class didnt meet the requirements.";
				.@check_result |= 8;
			}
I have tested in-game before I post, of course

I have debug your script with

			announce .@check_progress +" "+ .@branch_progress +" "+ .@class_progress, 0;
			if( .@check_progress & 8 && ( !.@branch_progress || !.@class_progress ) ){
				dispbottom "[Failed] Your Class didnt meet the requirements.";
				.@check_result |= 8;
			}
@job 0 -> novice, 9 0 0

@job 1 -> swordsman, 9 0 1

@job super novice, 9 1 0

Edited by AnnieRuru
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...