//===== rAthena Script ======================================= //= MvP Ranker with Shop //===== By =================================================== //= llchrisll //===== Version ============================================== //= 1.0 - Initial Version //= 1.1 - Fixed Ranking Display // - Exchanged .mvp_ with $@mvp_ variables // - Modified OnMvPCardUnlock to be a function // - Added freeloop(); to prevent infinite loop <<----- DON'T NEED ANY freeloop //= 1.2 - Improved by AnnieRuru <3 //= rAthena 03/26/2018 Revision //= GIT Hash: 333f0dddc8353663eacba0423751988c9bc38e34 //===== Description ========================================== //= MvP Ranking with MvP Card Shop as soon as the Goal Points of // respective MvP has been reached. //= Automatic detection of MvPs hunting state and addition of MvP Card // into the Shop. //= Top 10 Ranking //= List of MvP Goals //= Price per MvP Card = Goal Points/4 //===== Request ============================================== //= by Radian (https://rathena.org/board/profile/27689-radian/) //= Topic: https://rathena.org/board/topic/115216-mvp-ranker-w-rewards/ //===== SQL Tables =========================================== /* SQL Tables: CREATE TABLE `mvp_rank` ( `char_id` int(11) unsigned NOT NULL, `char_name` varchar(30) NOT NULL default 'Unknown', `mvp_points` int(11) default '0', PRIMARY KEY ( `char_id` ), KEY (`mvp_points`) ) ENGINE = MyISAM; CREATE TABLE `mvp_goal` ( `mvp_id` smallint(5) unsigned NOT NULL, `goal_points` int(11) default '4', `goal_needed` int(11) default '4', `mvp_card` smallint(5) unsigned NOT NULL, PRIMARY KEY ( `mvp_id` ) ) ENGINE = InnoDB; */ //============================================================ poring_w01,100,100,4 script MvP Ranker 102,{ mes .n$; mes "How can I help you?"; next; switch(select("- Server Ranking","- MVP Goals","- Open MVP Shop:- Nevermind")) { case 1: mes .n$; mes "I will now list the Top 10 MvP Hunters:"; next; mes "[ Top 10 MvP Hunters ]"; if ( !( .@nb = query_sql( "SELECT `char_name` , `mvp_points` FROM `mvp_rank` ORDER BY `mvp_points` DESC LIMIT 10;", .@c_name$, .@mvp_pts ) ) ) { mes "There is currently no player ranked."; mes "Come back later."; close; } for ( .@i = 0; .@i < .@nb; ++.@i ) mes ( .@i +1 )+". "+ .@c_name$[.@i] +" - "+ .@mvp_pts[.@i] +" Points"; close; case 2: mes .n$; mes "Here is the list of the MvP's with their needed Goal Points:"; mes " "; mes "> MvP / Required / Current"; .@nb = query_sql( "SELECT `mvp_id` , `goal_points`, `goal_needed` FROM `mvp_goal`", .@mvp_id, .@goal_pts, .@need_goal ); for ( .@i = 0; .@i < .@nb; ++.@i ) mes "> "+ getmonsterinfo(.@mvp_id[.@i], MOB_NAME) +" / "+ .@need_goal[.@i] +" / "+( .@goal_pts[.@i] ? .@goal_pts[.@i] : "UNLOCKED" ); close; case 3: mes .n$; if(!MVPPOINTS) { mes "I'm sorry, but you have to kill at least 1 MvP to gain access to the MvP Shop"; close; } mes "Your current MvP Points: "+MVPPOINTS; if(!.shop_card_total) { // Prevent opening an empty shop mes "I'm sorry, but there is no card yet available."; mes "Kill one of the MvP's first until their goal has been reached!"; close; } mes "I will now open the Shop."; close2; callshop "MvPRankShop",1; npcshopattach "MvPRankShop"; end; case 4: close; } end; OnInit: set .n$,"["+strnpcinfo(1)+"]"; // MvP ID's to Hunt: // Put every MvP ID here, which should be hunted setarray .mvp_id[0], 1511, // Amonra 1785, // Atroce 1630, // Bacsojin 1039, // Baphomet 1272, // Dark Lord 1719, // Detale 1046, // Doppelganger 1389, // 1112, 1115, 1418, 1871, 1252, 1768, 1086, 1832, 1492, 1734, 1251, 1779, 1688, 1373, 1147, 1059, 1087, 1190, 1038, 1157, 1159, 1623, 1583, 1708, 1312, 1751, 1685, 1658; // MvP Card ID's // magically built with SQL commands ~ set .mvp_id_size, getarraysize( .mvp_id ); // Goal Points required // setarray .mvp_goal[0],4,4,4,4,4; cleararray .mvp_goal, 4, .mvp_id_size; // change back to setarray // Automatic check for existing database entries for ( .@i = 0; .@i < .mvp_id_size; ++.@i ) .@values$[.@i] = "SELECT "+ .mvp_id[.@i] +" AS MVPID, "+ .mvp_goal[.@i] +", "+ .mvp_goal[.@i] +", ( SELECT `DropCardid` FROM `"+( checkre(0)? "mob_db_re" : "mob_db" )+"` where ID = MVPID )"; if ( .mvp_id_size ) query_sql "INSERT IGNORE INTO `mvp_goal` ( `mvp_id`, `goal_points`, `goal_needed`, `mvp_card` ) "+ implode( .@values$, " UNION " ); // Automatic check if MvP will not be hunted anymore: // It checks if the MvP is in the .mvp_id array, if not remove it from the database // Note: Be aware that the acquired goal points will not be saved anywhere for later usage! for ( .@i = 0; .@i < .mvp_id_size; ++.@i ) .@where_clause$[.@i] = "`mvp_id` != "+ .mvp_id[.@i]; if ( .mvp_id_size ) query_sql "DELETE FROM `mvp_goal` WHERE "+ implode( .@where_clause$, " AND " ); else query_sql "TRUNCATE TABLE `mvp_goal`"; npcshopdelitem "MvPRankShop", 501; if ( ( .shop_card_total = query_sql( "SELECT `mvp_card`, `goal_needed` FROM `mvp_goal` WHERE `goal_points` = 0", .@mvpcard, .@need_goal ) ) ) { for ( .@i = 0; .@i < .shop_card_total; ++.@i ) { npcshopadditem "MvPRankShop", .@mvpcard[.@i], .@need_goal[.@i] /4; .shop_card_id[.@i] = .@mvpcard[.@i]; .shop_goal[.@i] = .@need_goal[.@i] /4; } } end; OnNPCKillEvent: if ( !getmonsterinfo( killedrid, MOB_MVPEXP ) ) end; if ( !query_sql( "SELECT `goal_points`, `goal_needed`, `mvp_card` FROM `mvp_goal` WHERE `mvp_id` = "+ killedrid, .@goal, .@need_goal, .@mvpcard ) ) end; // if the killedrid is MVP but not a mvp_goal ... if ( .@goal ) query_sql "UPDATE `mvp_goal` SET `goal_points` = `goal_points` - 1 WHERE `mvp_id` = "+ killedrid; if ( .@goal -1 == 0 ) { announce "[ MVP Ranker ]: "+ strcharinfo(0) +" has fullfilled the last kill of ["+ getmonsterinfo( killedrid, MOB_NAME ) +"], the Monster Card can now be purchased in the Shop!", bc_all; npcshopadditem "MvPRankShop", .@mvpcard, .@need_goal /4; .shop_card_id[.shop_card_total] = .@mvpcard[.@i]; .shop_goal[.shop_card_total] = .@need_goal[.@i] /4; ++.shop_card_total; } if ( !getcharid(1) ) { ++MVPPOINTS; query_sql "INSERT INTO `mvp_rank` ( `char_id`, `char_name`, `mvp_points` ) VALUES ( "+ getcharid(0) +", '"+ escape_sql( strcharinfo(0) ) +"', 1 ) ON DUPLICATE KEY UPDATE `mvp_points` = `mvp_points` +1;"; } else { // *addrid is evil XD .@map$ = strcharinfo(3); .@killedrid = killedrid; getpartymember getcharid(1), 1; getpartymember getcharid(1), 2; for ( .@i = 0; .@i < $@partymembercount; ++.@i ) { if ( isloggedin( $@partymemberaid[.@i], $@partymembercid[.@i] ) ) { attachrid $@partymemberaid[.@i]; if ( strcharinfo(3) == .@map$ ) { // only those in the same map ++MVPPOINTS; message strcharinfo(0), .n$ +": You have recieved 1 MvP Point for slaying "+ getmonsterinfo( .@killedrid, MOB_NAME ) +"!"; .@cid[.@count] = $@partymembercid[.@i]; .@name$[.@count] = strcharinfo(0); ++.@count; } } } for ( .@i = 0; .@i < .@count; ++.@i ) .@values$[.@i] = "( "+ .@cid[.@i] +", '"+ escape_sql( .@name$[.@i] ) +"', 1 )"; query_sql "INSERT INTO `mvp_rank` ( `char_id`, `char_name`, `mvp_points` ) VALUES "+ implode( .@values$, ", " ) +" ON DUPLICATE KEY UPDATE `mvp_points` = `mvp_points` +1;"; } end; OnBuyItem: if ( checkweight2( @bought_nameid, @bought_quantity ) == false ) { dispbottom .n$+": I'm sorry, but you don't have enough space in inventory to take these items."; end; } .@item_bought = getarraysize( @bought_nameid ); for ( .@i = 0; .@i < .@item_bought; ++.@i ) for ( .@j = 0; .@j < .shop_card_total; ++.@j ) if ( @bought_nameid[.@i] == .shop_card_id[.@j] ) .@total += .shop_goal[.@j] * @bought_quantity[.@i]; if ( .@total > MVPPOINTS ) { dispbottom .n$+": I'm sorry, but you don't enough MvP Points to purchase these cards."; end; } MVPPOINTS -= .@total; for ( .@i = 0; .@i < .@item_bought; ++.@i ) getitem @bought_nameid[.@i], @bought_quantity[.@i]; end; } - shop MvPRankShop -1,501:-1