-
Posts
51 -
Joined
-
Last visited
-
Days Won
6
Content Type
Profiles
Forums
Downloads
Jobs Available
Server Database
Third-Party Services
Top Guides
Store
Posts posted by Nyaniverse
-
-
1. Unlimited Chain Quest - Monster Hunting / Item Collection in 1 NPC
Spoiler/* !!! SQL TABLE DEFINITIONS !!! !!! Run in your MySQL tool before using the NPC !!! -- Monthly leaderboard (resets monthly) CREATE TABLE IF NOT EXISTS `quest_monthly_ranking` ( `account_id` INT NOT NULL, `char_name` VARCHAR(30) NOT NULL, `completed` INT DEFAULT 0, PRIMARY KEY (`account_id`) ); -- Overall leaderboard (never resets) CREATE TABLE IF NOT EXISTS `quest_overall_ranking` ( `account_id` INT NOT NULL, `char_name` VARCHAR(30) NOT NULL, `completed` INT DEFAULT 0, PRIMARY KEY (`account_id`) ); -- Reward claim storage CREATE TABLE IF NOT EXISTS `quest_monthly_rewards` ( `account_id` INT NOT NULL, `char_name` VARCHAR(30) NOT NULL, `claim_flag` TINYINT(1) DEFAULT 0, `rewards` TEXT NOT NULL, PRIMARY KEY (`account_id`) ); */ /* Author: Nyani Version 1.0 ---------------------------------------------- Features - Unlimited Chain Quest (Randomized Kill/Collection Quest) - Automatic Quest submission - unless Collection Quest (Must turn in) - Automatic Quest Acquisition - Does not repeat previous quest (shuffles the quest provided) - Cancel Current Quest (Must talk to NPC) - Monthly Ranking - Automated Monthly Reward distribution - Chance to obtain rewards for quest submissions - Milestone Rewards every 100 quests finished ---------------------------------------------- Changelogs v1.0 - Initial Release Notice: No support will be provided - unless it is a bug on the current script */ // ========================== // NPC SCRIPT START // ========================== prontera,155,180,5 script Quest Board 857,{ function AddProgress; function displayQuestProgress; function AssignNewQuest; //============================= // MAIN INTERACTION //============================= if (BaseLevel < 99) { message strcharinfo(0), "You must be at least level 99 to take a quest."; end; } // Auto-complete gather quests if ready if (#DailyQuestType == 2 && countitem(#DailyQuestTarget) >= #DailyQuestAmount) { callsub OnComplete; end; } // Auto-assign new quest if none exists if (#DailyQuestType == 0) { callsub OnQuest; end; } displayQuestProgress(); .@menu$ = "Abandon Current Quest"; if (.reward_mode == 0) { .@menu$ += ":Claim Monthly Rewards"; } if (getgmlevel() >= 99) { .@menu$ += ":[GM] Trigger Rewards"; } .@menu$ += ":Close"; switch(select(.@menu$)) { case 1: callsub OnReset; end; case 2: if (.reward_mode == 0) callsub OnClaimReward; else if (getgmlevel() >= 99) callsub OnGMDistribute; end; case 3: if (.reward_mode == 0 && getgmlevel() >= 99) { callsub OnGMDistribute; } end; default: end; } end; OnClaimReward: .@aid = getcharid(3); .@name$ = strcharinfo(0); query_sql("SELECT 1 FROM quest_monthly_rewards WHERE account_id = " + .@aid, .@found); if (!.@found) { message strcharinfo(0),"You have no unclaimed rewards."; end; } for (.@i = 0; .@i < getarraysize(.MonthlyReward); .@i++) { getitem .MonthlyReward[.@i], .MonthlyRewardAmount[.@i]; } query_sql("DELETE FROM quest_monthly_rewards WHERE account_id = " + .@aid); message strcharinfo(0),"Your monthly rewards have been claimed successfully!"; end; OnQuest: if (#DailyQuestType > 0) { displayQuestProgress(); menu "Complete Quest", OnComplete, "Abandon Quest", OnReset, "Close", -; end; } .@roll = rand(2); // 0 = kill, 1 = gather if (.@roll == 0) { .@index = rand(getarraysize(.MobList)); #DailyQuestType = 1; #DailyQuestTarget = .MobList[.@index]; #DailyQuestAmount = .MobAmount[.@index]; #DailyQuestProgress = 0; } else { .@index = rand(getarraysize(.ItemList)); #DailyQuestType = 2; #DailyQuestTarget = .ItemList[.@index]; #DailyQuestAmount = .ItemAmount[.@index]; #DailyQuestProgress = 0; } message strcharinfo(0),"A new quest has been assigned to you!"; displayQuestProgress(); end; OnComplete: if (#DailyQuestType == 1) { message strcharinfo(0),"This quest will be completed once you've killed enough mobs."; end; } else if (#DailyQuestType == 2) { if (countitem(#DailyQuestTarget) >= #DailyQuestAmount) { delitem #DailyQuestTarget, #DailyQuestAmount; // Begin quest completion logic (normally inside AddProgress) #DailyQuestProgress = 0; #DailyQuestTarget = 0; #DailyQuestAmount = 0; #DailyQuestType = 0; #DailyQuestCompleted++; message strcharinfo(0), "You have completed a quest!"; if (rand(1, 10000) <= .RewardChance) { .@r = rand(getarraysize(.RewardList)); getitem .RewardList[.@r], .RewardAmount[.@r]; } if (#DailyQuestCompleted % 100 == 0) { if (rand(1, 10000) <= .SpecialRewardChance) { .@s = rand(getarraysize(.SpecialRewardList)); getitem .SpecialRewardList[.@s], .SpecialRewardAmount[.@s]; } } query_sql("INSERT INTO quest_monthly_ranking (account_id, char_name, completed) VALUES (" + getcharid(3) + ", '" + escape_sql(strcharinfo(0)) + "', 1) ON DUPLICATE KEY UPDATE completed = completed + 1"); query_sql("INSERT INTO quest_overall_ranking (account_id, char_name, completed) VALUES (" + getcharid(3) + ", '" + escape_sql(strcharinfo(0)) + "', 1) ON DUPLICATE KEY UPDATE completed = completed + 1"); message strcharinfo(0), "Quest Completed!"; message strcharinfo(0), "You have now completed " + #DailyQuestCompleted + " quests."; AssignNewQuest(); end; } else { message strcharinfo(0),"You haven't collected all required items yet."; end; } } end; end; OnReset: mes "Are you sure you want to abandon the current quest?"; menu "Yes", OnResetConfirm, "No", -; close; OnResetConfirm: #DailyQuestTarget = 0; #DailyQuestAmount = 0; #DailyQuestProgress = 0; #DailyQuestType = 0; message strcharinfo(0),"Quest abandoned."; end; OnNPCKillEvent: if (#DailyQuestType == 1 && killedrid == #DailyQuestTarget) AddProgress(); end; function AddProgress { #DailyQuestProgress++; // Kill count message strcharinfo(0), "[Kill Quest] " + strmobinfo(1, #DailyQuestTarget) + ": " + #DailyQuestProgress + "/" + #DailyQuestAmount; if (#DailyQuestProgress >= #DailyQuestAmount) { #DailyQuestProgress = 0; #DailyQuestTarget = 0; #DailyQuestAmount = 0; #DailyQuestType = 0; #DailyQuestCompleted++; // Roll for reward chance if (rand(1, 10000) <= .RewardChance) { .@r = rand(getarraysize(.RewardList)); getitem .RewardList[.@r], .RewardAmount[.@r]; } if (#DailyQuestCompleted % 100 == 0) { if (rand(1, 10000) <= .SpecialRewardChance) { .@s = rand(getarraysize(.SpecialRewardList)); getitem .SpecialRewardList[.@s], .SpecialRewardAmount[.@s]; } } query_sql("INSERT INTO quest_monthly_ranking (account_id, char_name, completed) VALUES (" + getcharid(3) + ", '" + escape_sql(strcharinfo(0)) + "', 1) ON DUPLICATE KEY UPDATE completed = completed + 1"); query_sql("INSERT INTO quest_overall_ranking (account_id, char_name, completed) VALUES (" + getcharid(3) + ", '" + escape_sql(strcharinfo(0)) + "', 1) ON DUPLICATE KEY UPDATE completed = completed + 1"); message strcharinfo(0), "Quest Completed!"; message strcharinfo(0), "You have now completed " + #DailyQuestCompleted + " quests."; AssignNewQuest(); return; } return; } function AssignNewQuest { .@roll = rand(2); // 0 = kill, 1 = gather if (.@roll == 0) { .@tries = 0; .@last_target = #DailyQuestTarget; // store previous target do { .@index = rand(getarraysize(.MobList)); } while (.MobList[.@index] == .@last_target && .@tries++ < 5); // retry if same mob #DailyQuestType = 1; #DailyQuestTarget = .MobList[.@index]; #DailyQuestAmount = .MobAmount[.@index]; message strcharinfo(0), "[Kill Quest] Target: " + strmobinfo(1, #DailyQuestTarget) + " | Progress: 0/" + #DailyQuestAmount; } else { .@tries = 0; .@last_target = #DailyQuestTarget; // store previous target do { .@index = rand(getarraysize(.ItemList)); } while (.ItemList[.@index] == .@last_target && .@tries++ < 5); // retry if same item #DailyQuestType = 2; #DailyQuestTarget = .ItemList[.@index]; #DailyQuestAmount = .ItemAmount[.@index]; message strcharinfo(0), "[Gather Quest] Item: " + getitemname(#DailyQuestTarget) + " | Required: " + #DailyQuestAmount; } #DailyQuestProgress = 0; return; } function displayQuestProgress { if (#DailyQuestType == 1) { message strcharinfo(0), "[Kill Quest] Target: " + strmobinfo(1,#DailyQuestTarget) + " | Progress: " + #DailyQuestProgress + "/" + #DailyQuestAmount; } else if (#DailyQuestType == 2) { message strcharinfo(0), "[Gather Quest] Item: " + getitemname(#DailyQuestTarget) + " | Progress: " + countitem(#DailyQuestTarget) + "/" + #DailyQuestAmount; } else { message strcharinfo(0), "You currently have no active quest."; } return; } OnGMDistribute: if (getgmlevel() < 99) end; callsub OnMonthlyDistribute; message strcharinfo(0),"GM distribution manually triggered."; end; OnDay0101: callsub OnMonthlyDistribute; end; OnMonthlyDistribute: // Configure Rerward Message - Applicable for RoDEX only .@title$ = "Quest Monthly Rewards"; .@body$ = "Congrats on ranking in the Top 10! This mail will be deleted in 14 days."; .@sender$ = "Quest Board"; .@reward_count = getarraysize(.MonthlyReward); //Ensures that if rewards are more than 5 items, switches to manual distribution (talk to npc) if (.@reward_count > 5) set .reward_mode, 0; query_sql("TRUNCATE TABLE quest_monthly_rewards"); query_sql("SELECT account_id, char_name FROM quest_monthly_ranking ORDER BY completed DESC LIMIT 10", .@aid, .@name$); for (.@i = 0; .@i < getarraysize(.@aid); .@i++) { if (.reward_mode == 0) { .@reward_string$ = ""; for (.@j = 0; .@j < .@reward_count; .@j++) { .@reward_string$ += .MonthlyReward[.@j]+":"+.MonthlyRewardAmount[.@j]; if (.@j < .@reward_count - 1) .@reward_string$ += ","; } query_sql("INSERT INTO quest_monthly_rewards (account_id, char_name, rewards) VALUES (" + .@aid[.@i] + ", '" + escape_sql(.@name$[.@i]) + "', '" + escape_sql(.@reward_string$) + "')"); } else { for (.@j = 0; .@j < 5; .@j++) { .@item_id[.@j] = .MonthlyReward[.@j]; .@amount[.@j] = .MonthlyRewardAmount[.@j]; } .@title$ = "Quest Monthly Rewards"; .@body$ = "Congrats on ranking in the Top 10! This mail will be deleted in 14 days."; .@sender$ = "Quest Board"; .@cid = getcharid(0, .@name$[.@i]); if (.@cid) { mail .@cid, .@sender$, .@title$, .@body$, 0, .@item_id, .@amount; } else { debugmes "Mail failed: Char ID not found for " + .@name$[.@i]; } } } query_sql("TRUNCATE TABLE quest_monthly_ranking"); announce "Monthly Quest Leaderboard has been reset! Take on new quests and rise to the top!", bc_all; end; OnInit: // ========================== // CONFIGURATION // ========================== // 0 = NPC Claim Mode, 1 = RoDEX Mode .reward_mode = 1; // Mob and kill amounts setarray .MobList[0], 1002,1004,1010; setarray .MobAmount[0], 30,40,50; setarray .ItemList[0], 705, // Orcish Voucher 1015, // Garlet 1021, // Tooth of Bat 719, // Bear’s Footskin 729, // Coal 744, // Witherless Rose 746, // Evil Horn 728, // Cyfar 938, // Golem Fragment 1058, // Cactus Needle 1009, // Claw of Desert Wolf 1038, // Emveretarcon 1042, // Worm Peelings 1044, // Flame Heart 1046, // Mystic Frozen 1047, // Great Nature 1049; // Red Blood setarray .ItemAmount[0], 5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5; // Completion reward pool setarray .RewardList[0], 607, 608, 609; setarray .RewardAmount[0], 1, 2, 1; // 100-completion reward pool setarray .SpecialRewardList[0], 7711, 7712; setarray .SpecialRewardAmount[0], 1, 1; // Monthly rewards for top 10 setarray .MonthlyReward[0], 607, 501, 504, 505, 506,909,910; setarray .MonthlyRewardAmount[0], 5, 2, 1, 3, 2,5,10; // Reward chance settings (1-10000 scale) .RewardChance = 10000; // 100% chance by default .SpecialRewardChance = 10000; // 100% for 100-completion }
2. Music Player - Just for fun
Spoiler/* Author: Nyani Version 1.0 ---------------------------------------------- Autoplay System ---------------------------------------------- Changelogs 1.0 - Initial Release Note: !!! Make sure you have your BGMs ready in your BGM folder !!! BGM files must be 128kbps, client will not play unless it is not 128kbps Website: https://www.xconvert.com/unit-converter/milliseconds-to-minutes */ - script BGM_Playlist -1,{ end; function isPlaylistMap; OnInit: setarray .bgmList$[0], "714", "716", "712", "808"; setarray .bgmDuration[0], 336000, 251000, 252000, 246000; .bgmsize = getarraysize(.bgmList$); setarray .playlistMap$[0], "hakurei", "izlude", "alberta"; end; OnPCLoginEvent: if (isPlaylistMap(strcharinfo(3))) { callsub OnStartPlaylist; } end; OnStartPlaylist: .@count = .bgmsize; for (.@i = 0; .@i < .@count; .@i++) { .@tempOrder[.@i] = .@i; } for (.@i = .@count - 1; .@i > 0; .@i--) { .@j = rand(.@i + 1); .@swap = .@tempOrder[.@i]; .@tempOrder[.@i] = .@tempOrder[.@j]; .@tempOrder[.@j] = .@swap; } copyarray @BGM_Order[0], .@tempOrder[0], .bgmsize; @BGM_Size = .bgmsize; @BGM_Index = 0; doevent strnpcinfo(3)+"::OnPlayNextBGM"; end; OnPlayNextBGM: if (!isPlaylistMap(strcharinfo(3))) { stopnpctimer; end; } if (@BGM_Index >= @BGM_Size) { @BGM_Index = 0; } .@track_id = @BGM_Order[@BGM_Index]; .@bgm$ = .bgmList$[.@track_id]; .@duration = .bgmDuration[.@track_id]; playBGM .@bgm$; @BGM_Index++; addtimer .@duration, strnpcinfo(3)+"::OnPlayNextBGM"; end; function isPlaylistMap { .@map$ = getarg(0); for (.@i = 0; .@i < getarraysize(.playlistMap$); .@i++) { if (.playlistMap$[.@i] == .@map$) return 1; } return 0; } } hakurei mapflag loadevent
3. Race to Max Level - Perfect for single-time race events!
Spoiler/* Make sure you implement this table in your database If you dont, this script will not work CREATE TABLE IF NOT EXISTS `race_to_99` ( `aid` INT(11) UNSIGNED NOT NULL, `name` VARCHAR(30) NOT NULL, `class` INT(11) UNSIGNED NOT NULL, `time` VARCHAR(30) NOT NULL, PRIMARY KEY (`aid`) ) ENGINE=MyISAM; */ /* Author: Nyani Version 2.9 Changelogs v1.0 - Initial Release v1.1 - Added dynamic settings for easier configuration v1.2 - Slightly improved stylistic look for npc dialogue v1.3 - Added dynamic reward list v1.4 - Added support for time stamp v1.5 - Added class selection for checking race v1.6 - Fixed time stamp issue v1.7 - Fixed rewards bug v1.8 - Added proper spacing to winners list v1.9 - Added proper message when no winners to display v2.0 - Optimized script algorithm v2.1 - Added Registration Requirement v2.2 - Removed usage of global map variable v2.3 - Added color indication for available/contested/filled slots v2.4 - Optimized check for classes in the race v2.5 - Automated the checking of who got to max level first v2.6 - Added GM Options v2.7 - Fixed a bug with showscript remaining even if npc is hidden v2.8 - Fixed an exploit with registration NPC v2.9 - Fixed some bugs and added fall backs and clean up */ new_1-1,64,122,3 script Race Event#main 864,{ if(getgmlevel() > 10) .@gm = 1; .@menu$ = "> ^83B939View Slots^000000:> ^83B939Claim Reward^000000"; if(.@gm) .@menu$ += ":>[ ^ff0000GM^000000 ] ^D8A0FFStart new Race^000000:>[ ^ff0000GM^000000 ] ^D8A0FFCancel Race^000000"; switch(select(.@menu$)){ case 1: for(.@i = 1; .@i < getarraysize(.class); .@i++){ query_sql( "SELECT COUNT(`Class`) FROM `race_to_99` WHERE `class` = "+.class[.@i],.@job); if(.@job >= 2) .@j_menu$ += "> ^B9396B"+jobname(.class[.@i])+"^000000:"; else if(.@job == 1) .@j_menu$ += "> ^FA8415"+jobname(.class[.@i])+"^000000:"; else .@j_menu$ += "> ^83B939"+jobname(.class[.@i])+"^000000:"; } .@s = select(.@j_menu$); .@selection = .class[.@s]; mes "[ ^9d3ad3Race to Max Event^000000 ]"; query_sql( "SELECT `name`,`class`,`time` FROM `race_to_99` WHERE `class` = '"+.@selection+"' ORDER BY `time` DESC LIMIT 25",.@name$,.@class,.@date$); if(.@name$[0] == ""){ mes "No winners yet for ^876A3B"+jobname(.@selection)+"^000000."; close; } for(.@i = 0; .@i < getarraysize(.@name$); .@i++){ mes "- ^876A3B"+jobname(.@class[.@i])+"^000000 -"; mes .@name$[.@i]+" - "+.@date$[.@i]; mes "******************************"; } close; case 2: if(.active == 0){ mes "[ ^9d3ad3Race to Max Event^000000 ]"; mes "Sorry, there's no on-going race at the moment."; close; } if(inarray(.class[0],Class) == -1){ mes "[ ^9d3ad3Race to Max Event^000000 ]"; mes "I'm sorry, but "+jobname(Class)+" Class is not included in the race."; close; } query_sql( "SELECT `class`,`aid` FROM `race_to_99` WHERE `aid` = "+getcharid(3),.@class,.@aid); if(.@aid != 0 && #race_claim == 2){ mes "[ ^9d3ad3Race to Max Event^000000 ]"; mes "It seems your account already won before."; mes "You are unable to participate further."; if(#register == 1) #register = 0; //removing registered status close; } if(#race_claim == 1){ .@s = select(.menu$); for(.@i = 0; .@i < getarraysize(getd(".rewards"+.@s)); .@i++){ if(.bound) getitembound getd(".rewards"+.@s+"["+.@i+"]"),getd(".rwd_amt"+.@s+"["+.@i+"]"),.bound; else getitem getd(".rewards"+.@s+"["+.@i+"]"),getd(".rwd_amt"+.@s+"["+.@i+"]"); } #race_claim = 2; } else{ mes "[ ^9d3ad3Race to Max Event^000000 ]"; mes "I'm sorry, but it seems that you do not have any pending rewards."; close; } break; case 3: mes "[ ^9d3ad3Race to Max Event^000000 ]"; mes "Hello "+strcharinfo(0)+"."; mes "Would you like to remove current race data?"; menu "Yes, remove data",-; clear; query_sql("TRUNCATE `race_to_99`",.@aid); mes "[ ^9d3ad3Race to Max Event^000000 ]"; mes "Race records have been removed."; mes "Would you like start a new race?"; menu "Yes, start a new one",-; clear; .active = 1; mes "[ ^9d3ad3Race to Max Event^000000 ]"; mes "Alright, I've arranged the race event for you."; hideoffnpc "Race Event Registration#reg"; announce "[ Race to Max ]: "+strcharinfo(0)+" has started a new race. All older race data have been removed! Please talk to the Race Event Registration NPC!",0; close2; addrid(1); if(!#register) end; #register = 0; detachrid; query_sql("UPDATE `acc_reg_num` SET `value`='0' WHERE `value` >= '1' AND `key` = '#register'"); donpcevent "Race Event Registration#reg::OnHideOff"; break; case 4: if(!.active){ mes "[ ^9d3ad3Race to Max Event^000000 ]"; mes "There is currently no active event as of right now."; close; } mes "[ ^9d3ad3Race to Max Event^000000 ]"; mes "Hello "+strcharinfo(0)+"."; mes "Would you like to cancel the current race?"; menu "Yes, please cancel.",-; .active = 0; hideonnpc "Race Event Registration#reg"; clear; mes "[ ^9d3ad3Race to Max Event^000000 ]"; mes "Alright, it's been canceled."; announce "[ Race to Max ]: "+strcharinfo(0)+" has stopped the race. Please wait for a new one to start.",0; close2; addrid(1); if(!#register) end; #register = 0; detachrid; query_sql("TRUNCATE `race_to_99`",.@aid); query_sql("UPDATE `acc_reg_num` SET `value`='0' WHERE `value` >= '1' AND `key` = '#register'"); donpcevent "Race Event Registration#reg::OnHideOff"; break; } end; OnPCBaseLvUpEvent: if(!#register) end; if(!.active) end; if(BaseLevel < .base_level) end; if(query_sql("SELECT COUNT(*) FROM `race_to_99` WHERE `aid` = "+getcharid(3)); if (.@exists > 0) end; query_sql( "SELECT COUNT(`Class`) FROM `race_to_99` WHERE `class` = "+Class,.@job); if(.@job >= .class_limit) end; if(BaseLevel >= .base_level && JobLevel >= .job_level){ query_sql( "INSERT INTO `race_to_99` ( `aid`,`name`,`class`,`time`) VALUES ( "+getcharid(3)+",'"+escape_sql( strcharinfo(0))+"',"+Class+", '"+gettimestr("%m/%d %H:%M:%S",21)+"' )" ); announce "Congratulations to [ "+strcharinfo(0)+" ] for being one of the first [ "+jobname(Class)+" ] to reach max level!",1; message strcharinfo(0),"Please talk to the Race Event NPC for your reward."; #race_claim = 1; if(#register == 1) #register = 0; //removing registered status } end; OnPCJobLvUpEvent: if(!#register) end; if(!.active) end; if(JobLevel < .job_level && BaseLevel < .base_level) end; if(query_sql("SELECT COUNT(*) FROM `race_to_99` WHERE `aid` = "+getcharid(3)); if (.@exists > 0) end; query_sql( "SELECT COUNT(`Class`) FROM `race_to_99` WHERE `class` = "+Class,.@job); if(.@job >= .class_limit) end; if(BaseLevel >= .base_level && JobLevel >= .job_level){ query_sql( "INSERT INTO `race_to_99` ( `aid`,`name`,`class`,`time`) VALUES ( "+getcharid(3)+",'"+escape_sql( strcharinfo(0))+"',"+Class+", '"+gettimestr("%m/%d %H:%M:%S",21)+"' )" ); announce "Congratulations to [ "+strcharinfo(0)+" ] for being one of the first [ "+jobname(Class)+" ] to reach max level!",1; message strcharinfo(0),"Please talk to the Race Event NPC for your reward."; #race_claim = 1; if(#register == 1) #register = 0; //removing registered status } end; OnInit: .active = 1; .class_limit = 2; //how many players can claim for that particular class .base_level = 99; //max base level .job_level = 70; //max job level .bound = 1; //1 = account, 2 = guild, 3 = party, 4 = character, 0 = not bound //class number, check using @job in-game / these are the jobs/classes who can win prizes setarray .class[1], 4008, 4009, 4010, 4011, 4012, 4013, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 23; //name of your reward set .menu$ = "Reward Set 1:Reward Set 2:Reward Set 3"; //reward id,quantity,reward id,quantity setarray .rewards1, 501,502,503; setarray .rwd_amt1, 1 ,1 ,1; setarray .rewards2, 504,505,506; setarray .rwd_amt2, 1 ,1 ,1; setarray .rewards3, 507,508,509; setarray .rwd_amt3, 1 ,1 ,1; while(1){ sleep 1000; showscript "Race to MAX!"; } end; } new_1-1,64,118,3 script Race Event Registration#reg 864,{ .@i = getvariableofnpc(.active,"Race Event#main"); if(!.@i){ mes "[ ^9d3ad3Race to Max Event^000000 ]"; mes "There is currently no active event as of right now."; close; } if(#race_claim == 2){ mes "[ ^9d3ad3Race to Max Event^000000 ]"; mes "Your account can only win once per race."; } if(Class != 0 || BaseLevel > 5){ mes "[ ^9d3ad3Race to Max Event^000000 ]"; mes "I'm sorry, but I can only speak with Level 1 Novices."; close; } query_sql( "SELECT `aid` FROM `race_to_99` WHERE `aid` = "+getcharid(3),.@aid); if(.@aid != 0){ mes "[ ^9d3ad3Race to Max Event^000000 ]"; mes "It seems your account already won before."; mes "You are unable to participate further."; if(#register == 1) #register = 0; //removing registered status close; } if(#register == 1){ mes "[ ^9d3ad3Race to Max Event^000000 ]"; mes "You are already registered."; close; } mes "[ ^9d3ad3Race to Max Event^000000 ]"; mes "Hello "+strcharinfo(0)+"!"; mes "We have an on-going ^ff0000Race Event^000000 that is on-going right now."; mes "Would you like to join?"; menu "Yes, sign me up.",-; clear; mes "[ ^9d3ad3Race to Max Event^000000 ]"; mes "Alright, I have "+strcharinfo(0)+" in my records now!"; mes "Good luck on the race!"; close2; announce "[ Race to 99 ]: "+strcharinfo(0)+" has joined the race! We wish everyone the best of luck!",0; #register = 1; end; OnHideOff: OnInit: sleep 5000; .@i = getvariableofnpc(.active,"Race Event#main"); if(!.@i) hideonnpc strnpcinfo(0); while(.@i == 1){ sleep 1000; showscript "Race Registration"; .@i = getvariableofnpc(.active,"Race Event#main"); } end; }
4. Beta Registration NPC - Easy handing out rewards
Spoiler/* Make sure you implement this table on your database If you do not implement this, this will not function CREATE TABLE IF NOT EXISTS `beta_registration` ( `aid` INT(11) UNSIGNED NOT NULL DEFAULT '0', `claimed` INT(11) NOT NULL DEFAULT '0', PRIMARY KEY (`aid`) ) ENGINE=MyISAM; */ /* Author: Nyani Version 2.8 Changelogs v1.0 - Initial Release */ prontera,166,88,3 script Beta Registration 10146,{ query_sql( "SELECT `aid` FROM `beta_registration` WHERE `aid` = "+getcharid(3),.@aid); if(.@aid == 0){ mes "[ Beta Registration ]"; mes "Thank you for participating in our Beta!"; mes "You can claim your rewards on our official release~"; close2; query_sql( "INSERT INTO `beta_registration` ( `aid`) VALUES ( "+getcharid(3)+" )" ); debugmes "Successfully registered: "+getcharid(3); end; } mes "[ Beta Registration ]"; mes "Thank you for registering~"; close; OnInit: set .message$, " Beta Registration"; freeloop(1); while (1) { set .message$, delchar(.message$+charat(.message$,0),0); delwaitingroom; waitingroom .message$, 0; sleep 300; } freeloop(0); end; } prontera,166,90,3 script Beta Claim 831,{ query_sql( "SELECT `aid` FROM `beta_registration` WHERE `aid` = "+getcharid(3),.@aid); query_sql( "SELECT `claimed` FROM `beta_registration` WHERE `aid` = "+getcharid(3),.@claim); if(.@aid == getcharid(3)){ if(.@claim == 0){ mes "[ Beta Claim ]"; mes "Thank you for participating in our beta test!"; close2; getitembound 49000,1,1; query_sql( "UPDATE `beta_registration` SET `claimed` = 1 WHERE `aid` = "+getcharid(3)); end; } mes "[ Beta Claim ]"; mes "You have already claimed your reward."; close; } mes "[ Beta Claim ]"; mes "I'm sorry but I could not find records of you."; mes "Please check with an administrator if you did participate in the beta"; close; OnInit: set .message$, " Beta Rewards"; freeloop(1); while (1) { set .message$, delchar(.message$+charat(.message$,0),0); delwaitingroom; waitingroom .message$, 0; sleep 300; } freeloop(0); end; }
NOTE: No support will be provided - unless it's a bug in the script itselfBugs? Reply to this thread and I'll fix it right up.
-
2
-
-
On 4/11/2025 at 2:39 AM, Emanda said:
Thank you for your topic, I have the same problem!
Just use the same script, but rename the shops and functions accordingly.
- shop qshop1 -1,909:-1
to
- shop bshop1 -1,909:-1
function script qshop {
to
function script bshop {
dispbottom "Select one item at a time."; callshop "qshop"+@shop_index,1; npcshopattach "qshop"+@shop_index;
to
dispbottom "Select one item at a time."; callshop "bshop"+@shop_index,1; npcshopattach "bshop"+@shop_index;
npcshopdelitem "qshop"+.@i,909;
to
npcshopdelitem "bshop"+.@i,909;
- script quest_shop -1,{
to
- script bquest_shop -1,{
and lastly
payon,148,222,5 script Headgear List 123,{ callfunc "qshop"; }
to
payon,148,222,5 script Headgear List 123,{ callfunc "bshop"; }
This is the lazy method that I manage to come up with, really easy to do.
-
Here's my own version of an Hourly Point System
- Simple and easy to configure
- Makes use of Account Variable to track time
- Records player's playtime every 5 minutes, allowing continuous tracking even if they log off in between*
- Provides detailed time when they last received their reward/bonus/hourly point
- Removes Vendors from the system automatically
No support will be provided, unless it's a bug issue.
/* Author: Nyani Version 1.0 ---------------------------------------------- Playtime System ---------------------------------------------- Changelogs 1.0 - Initial Release */ - script PlaytimeCount -1,{ end; OnPCLoginEvent: //if(BaseLevel < 30) end; @starttime$ = gettimestr("%Y-%m-%d %H:%M:%S", 21); message strcharinfo(0),"Playtime Point System is now enabled. Please note that vending will disqualify you from gaining points."; addtimer 300000,"PlaytimeCount::OnPointUpdate"; // 5 minutes dispbottom "Play Point System start time: "+@starttime$; dispbottom "[ "+#playtimepts+"0/60 ] minutes completed."; end; OnPointUpdate: if ( checkvending(strcharinfo(0)) == 2 ){ dispbottom "You have been removed from the Playtime Point System. Please re-log to opt-in again."; deltimer strnpcinfo(3)+"::OnPointUpdate"; end; } @playtime += 1; if(@playtime == 2){ @playtime = 0; #playtimepts += 1; if(#playtimepts == 6){ #playtimepts = 0; #YourPtsHere += 1; @playtime = 0; message strcharinfo(0),"[Playtime Points]: You have received your Playtime Reward at "+gettimestr("%Y-%m-%d %H:%M:%S", 21)+"."; @prevtime$ = gettimestr("%Y-%m-%d %H:%M:%S", 21); } } deltimer "PlaytimeCount::OnPointUpdate"; addtimer 300000,"PlaytimeCount::OnPointUpdate"; end; OnPlaytimeCheck: dispbottom "Last Reward: "+@prevtime$; dispbottom "Minutes: "+#playtimepts+"0/60"; dispbottom "Current points: "+#YourPtsHere; end; OnInit: bindatcmd "playtime",strnpcinfo(0)+"::OnPlaytimeCheck"; end; }
-
2
-
On 9/13/2024 at 10:00 PM, GM Winter said:
hello sir ive tried it and its not working theres no hourly reward every minute
If you don't mind using a different script for an hourly reward system. Here's one that I made.
Spoiler/* Author: Nyani Version 1.0 ---------------------------------------------- Playtime System ---------------------------------------------- Changelogs 1.0 - Initial Release */ - script PlaytimeCount -1,{ end; OnPCLoginEvent: //if(BaseLevel < 30) end; @starttime$ = gettimestr("%Y-%m-%d %H:%M:%S", 21); message strcharinfo(0),"Playtime Point System is now enabled. Please note that vending will disqualify you from gaining points."; addtimer 300000,"PlaytimeCount::OnPointUpdate"; // 5 minutes dispbottom "Play Point System start time: "+@starttime$; dispbottom "[ "+#playtimepts+"0/60 ] minutes completed."; end; OnPointUpdate: if ( checkvending(strcharinfo(0)) == 2 ){ dispbottom "You have been removed from the Playtime Point System. Please re-log to opt-in again."; deltimer strnpcinfo(3)+"::OnPointUpdate"; end; } @playtime += 1; if(@playtime == 2){ @playtime = 0; #playtimepts += 1; if(#playtimepts == 6){ #playtimepts = 0; #valkafkpts += 1; @playtime = 0; message strcharinfo(0),"[Playtime Points]: You have received your Playtime Reward at "+gettimestr("%Y-%m-%d %H:%M:%S", 21)+"."; @prevtime$ = gettimestr("%Y-%m-%d %H:%M:%S", 21); } } deltimer "PlaytimeCount::OnPointUpdate"; addtimer 300000,"PlaytimeCount::OnPointUpdate"; end; OnPlaytimeCheck: dispbottom "Last Reward: "+@prevtime$; dispbottom "Minutes: "+#playtimepts+"0/60"; dispbottom "Current points: "+#valkafkpts; end; OnInit: bindatcmd "playtime",strnpcinfo(0)+"::OnPlaytimeCheck"; end; }
-
8 hours ago, Seller said:
the npc doesnt appear at all in my game when i reload it.
What is the console error?
For one, I downloaded it but I'm not adding it to my server since I don't have access to it right now. But a quick glance I can tell the tab spacing on the NPC header is not correct. Post your console error and I can help you out. -
9 hours ago, GM Winter said:
no sorry im looking for a script with sql also so that i can also trace the characters who changes their names i also try the item Character Name Change Coupon Item ID# 12790
but nothing change im using pre renewal i only import it in pre re, i need the change name script because i want to implement the character selling system and i want them to allow to change the name of it anyways ty budsIf you're not being picky, just use logmes and it should work.
*logmes "<message>"; This command will write the message given to the map server NPC log file, as specified in 'conf/log_athena.conf'. In the TXT version of the server, the log file is 'log/npclog.log' by default. In the SQL version, if SQL logging is enabled, the message will go to the 'npclog' table, otherwise, it will go to the same log file. If logs are not enabled, nothing will happen.
-
On 1/13/2024 at 11:00 AM, Gidz Cross said:
WOW. Maybe add remarks to sellers like "Character already completed Kiel Hyre Quest. Already completed LHZ quest etc etc."
This is actually a good idea, I might add it as a separate information query on the NPC. I'm slightly busy at the moment, so might take some time for me to add it. But this is very do-able.
-
Good day everynyan~
I'm here again to showcase a newly finish system for a server that I am helping out with~
It's a simple Sell Character system, much like Shakto's but also not quite the exact same.
Feature:- Preview character information (Status/Equipment)
- Sold characters are categorized based on their Class
- Checks if character/account is online (in-game or in the server select/character select screen)
- Blocks usage of character that is being sold - will be prompted to either remove the character from Sell List or will be blocked from moving indefinitely
- Sellers can receive their earnings via the same NPC
- Logs buyer ID, seller ID, character ID and time of purchase
- Logs earnings and time of claim for earnings
- Lots of configuration options, such as to check for Bound items (account,party,guild) and more\
Credit to @Cydhfor making this script possible via:
-
1
-
2
-
2
-
if (.@fake_icon_time_ms = 0) {
Try changing that line to this one
if (.@fake_icon_time_ms == 0) {
-
*summon "monster name",<monster id>{,<Time Out>{,"event label"}}; This command will summon a monster. (see also 'monster') Unlike monsters spawned with other commands, this one will set up the monster to fight to protect the invoking character. Monster name and mob id obey the same rules as the one given at the beginning of this document for permanent monster spawns with the exceptions mentioned when describing 'monster' command. The effect for the skill 'Call Homunculus' will be displayed centered on the invoking character. Timeout is the time in milliseconds the summon lives, and is set default to 60000 (1 minute). Note that also the value 0 will set the timer to default, and it is not possible to create a spawn that lasts forever. If an event label is given, upon the monster being killed, the event label will run as if by 'donpcevent'. Returned value is the game ID of the spawned monster. // Will summon a dead branch-style monster to fight for the character. summon "--ja--",-1;
Just add an OnEvent label, set it so that a character variable is set, something like
summon_avail = 1;
And when you kill another monster that can be "summoned", check if summo_avail is 1, if it's not, summon, if its 1, ignore -
Note, your solution only displays the first item on the list. If they bought multiple cards, then it won't announce the rest.
Example: Player A bought Poring, Drops and Fabre Card - the only one that will be showed on announce is Poring Card -
-
Hello everynyan!
I am very intrigued with Ragnarok Landverse's core systems and features, and I wanted to try to see if I can try to even get close to replicating their Gear Score system. And this is what I have done so far.
This feature is based off of what's available on their wiki/information pages, here.Features:
- Gear Score rating is updated upon logout and when issuing @gscore command in-game
- Ranking buff is based off server-time, Ranker buff will always expire at 00:00 server time
- Weapon on L-HAND does not count towards Gear Score rating
- Reads Upper Headgear, Body, Garment, Footgear, R-Hand and L-Hand (shields only)
- Reads cards, number of cards, number of options and equipment slots
Note: This will never be as complex or as intricate as Ragnarok Landverse, more so, this is only made to see if I can replicate what they have done to and I guess to practice my scripting knowledge.
Any feedback, criticism or ideas are all welcome~
-
1
-
Solved.
Resolved by using a combination of getequipweaponlv and getequipcardcnt, in conjunction with adding a function to the card upon Equip and UnEquip to identify that it's been equipped on L-Hand. -
Hi, I'm somewhat familiar with scripting already with rAthena, however, there is one issue I am facing that I haven't figured out at all or any other way to do the checks properly.
It's on how to figure out if the card is being equipped on the L-Hand side or R-Hand side of equipment (specifically, Assassin dual wielding and such)
This is what I came up with, but looking at it more, it doesn't really do what I need it to do.
if(getarg(3) == 1 && Class == 12 || Class == 4013){ .@right = getequipid(EQI_HAND_R); .@left = getequipid(EQI_HAND_L) for(.@i = 0; .@i < 4; .@i++){ .@rc[.@i] = getequipcardid(EQI_HAND_R,.@i); .@lc[.@i] = getequipcardid(EQI_HAND_R,.@i); if(inarray(.@rc[0], .@lc[@i]) == -1)
Is there any other method that can be used to check if card is in the left-hand or right-hand?
-
This auto-lootfeature was requested by RagnaVerse and exclusive to their server. I have been given permission to showcase the system with the caveat to add their logo on the video. If this is in violation to any rules, please feel free to remove the showcase video.
Features- Limit VIP Autoloot (alootid) based off their VIP Tier
- Easily add/update/remove items on their existing loot list
- Loot list is saved account-wide, so you don't have to keep entering the same IDs over and over again
- Display your autoloot list on demand (using @command)
- Loot list is carried over even if player changes their VIP tier (add / reduce number of aloot id slots)
Note: The bug at the end of the video where it spams aloot id is already fxied, but is not represented on this video showcase
Spoiler -
Update:
New Features:- Added previous week/month ranking on options
- Added option for GM to reset weekly/monthly rankings or both
If anyone has any ideas that might be good to add to this NPC, please feel free to comment and I'll see if I can add that said feature~
-
Update!!
- Fixed an issue wherein players can pre-register, level up a novice to max level and wait for the next race (this removes the race variiable from everyone)
- Fixed an issue that can reset race data when restarting server or reloading script
-
Both of your requests have been asked in the forum already years past, I would suggest trying the search feature, it should give you similar scripts you can try to implement to your script.
-
I advice looking at the regular refiner and basing your script off of it.
-
Hello everynyan~
This script is an identical copy of Ragnarok Landverse's Pet Combine System. Just wanted to see if I could make it work on older clients without the newer UI~ and apparently it can be done as you can see, albeit it's pretty weird using the sell window.
Of course, I added my own twist to the combining process~ Can't be Nyani without a lil' bit of sprinkle of Nyani.
Comments, suggestions and feedback are so appreciated!
-
1
-
-
Update:
New Features
- Username searching feature
- Additional option to wipe all supplies sent to streamers (can be configured what IDs that will be removed)
- Daily supply distribution with automatic reset at X time, available logs to check when stream/supply was claimed
- Separate supply list for 'Casual' and 'Official' streamers
- Has streamer ranking that settles every week for weekly, and every 1st of the month for monthly, keeps a record for all-time ranking as well
- When streamer is removed, data will not show on rankings, but ranking information is preserved, so if streamer is added back, they will go back to their previous rank/point
New feature video (updated initial post as well)
Spoiler -
Solved.
For anyone looking the solution, it's using INNER JOIN on SQL.@sql$ = " SELECT `acc_reg_num`.`value`,`streamer_db`.`name`" + " FROM `acc_reg_num`" + " INNER JOIN `streamer_db`" + " ON `acc_reg_num`.`account_id` = `streamer_db`.`aid`" + " WHERE `acc_reg_num`.`key` = '#s_alltime' " + " AND `acc_reg_num`.`value` >= 1" + " ORDER BY `acc_reg_num`.`value` DESC LIMIT 20";
-
I'm trying to match the points to their names and aid on another table, but somehow the points are not going to their assigned aid, any clues on how to properly set it?
.@sql$ = " SELECT `account_id`,`value` " + " FROM `acc_reg_num`" + " WHERE `key` = '#s_alltime' " + " AND `value` >= 1" + " ORDER BY `value` DESC LIMIT 20"; query_sql(.@sql$,.@aid,.@total); query_sql("SELECT `aid`,`name` FROM `test_db`",.@said,.@name$); //comparing who's going to be in the ranking for(.@i = 0; .@i < getarraysize(.@aid); .@i++) if(inarray(.@said[0],.@aid[.@i]) != -1){ .@all_time$[.@i] = .@name$[inarray(.@aid[0],.@said[.@i])]; .@all_time[.@i] = .@total[inarray(.@aid[0],.@said[.@i])]; }
Quests, Games: Nyani's Unlimited Quest NPC
in Game, Event, Quest Script Releases
Posted
View File
Nyani's Unlimited Quest NPC
Author: Nyani Version 1.0 ---------------------------------------------- Features - Unlimited Chain Quest (Randomized Kill/Collection Quest) - Automatic Quest submission - unless Collection Quest (Must turn in) - Automatic Quest Acquisition - Does not repeat previous quest (shuffles the quest provided) - Cancel Current Quest (Must talk to NPC) - Monthly Ranking - Automated Monthly Reward distribution - Chance to obtain rewards for quest submissions - Milestone Rewards every 100 quests finished ---------------------------------------------- Changelogs v1.0 - Initial Release Notice: No support will be provided - unless it is a bug on the current script
Config
// ========================== // CONFIGURATION // ========================== // 0 = NPC Claim Mode, 1 = RoDEX Mode .reward_mode = 1; // Mob and kill amounts setarray .MobList[0], 1002,1004,1010; setarray .MobAmount[0], 30,40,50; setarray .ItemList[0], 705, // Orcish Voucher 1015, // Garlet 1021, // Tooth of Bat 719, // Bear’s Footskin 729, // Coal 744, // Witherless Rose 746, // Evil Horn 728, // Cyfar 938, // Golem Fragment 1058, // Cactus Needle 1009, // Claw of Desert Wolf 1038, // Emveretarcon 1042, // Worm Peelings 1044, // Flame Heart 1046, // Mystic Frozen 1047, // Great Nature 1049; // Red Blood setarray .ItemAmount[0], 5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5; // Completion reward pool setarray .RewardList[0], 607, 608, 609; setarray .RewardAmount[0], 1, 2, 1; // 100-completion reward pool setarray .SpecialRewardList[0], 7711, 7712; setarray .SpecialRewardAmount[0], 1, 1; // Monthly rewards for top 10 setarray .MonthlyReward[0], 607, 501, 504, 505, 506,909,910; setarray .MonthlyRewardAmount[0], 5, 2, 1, 3, 2,5,10; // Reward chance settings (1-10000 scale) .RewardChance = 10000; // 100% chance by default .SpecialRewardChance = 10000; // 100% for 100-completion
Make sure to run SQL queries!
No support provided, unless it's a bug in the script's core features.