astralprojection 35 Posted February 20, 2021 (edited) //===== Hercules Script ====================================== // MVP Spawn Controller //===== By: ================================================== // astralprojektion //===== Current Version: ===================================== // 1.3 //===== Description: ========================================= // Control MVP Spawn with script. MVP will not respawn on server start or reload using flag. // Delete or Comment all MVP and mini boss spawn at npc/pre-re/mobs/dungeons/ or /fields. // Make sure set at NifInvasion to make it work. // OnLoDDead: // // Set LOD as dead ang next respawn is 5580sec // $S11373 = 2; $T11373 = (gettimetick(2) + 5580); // //===== Additional Comments: ================================= // 1.0 Initial Release // 1.1 Use TimeStamp when mvp is killed // Fixed typo on MVP_Map array. // 1.2 Set Variables to Global. // 1.3 Include some Mini Boss on the controller // Added PvP On/Off MvP is alive // Integrate LOD invasion // Added @mvpcontroller command to reset all or a specific mvp and other settings. //============================================================ /* Credits to Meko https://herc.ws/board/files/file/326-array-manipulation-functions/ */ function script array_find { .@size = getarraysize(getarg(0)); .@neq = getarg(2, false); freeloop(true); for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) { if ((.@neq && (getelementofarray(getarg(0), .@i) != getarg(1))) || (!(.@neq) && (getelementofarray(getarg(0), .@i) == getarg(1)))) { freeloop(false); return .@i; } } freeloop(false); return -1; } - script mvpcontroller FAKE_NPC,{ end; OnNPCKillEvent: if(array_find(.mvpid, killedrid) >= 0 ){ for( .@i = 0; .@i < getarraysize(.mvpid); .@i++ ) { if( killedrid == .mvpid[.@i] && strcharinfo(PC_MAP) == .mvpmaps$[.@i]) { // 1 - Alive 2 - Dead setd("$S"+.mvpa[.@i]+.mvpid[.@i], 2); // current time + respawn time (seconds) setd("$T"+.mvpa[.@i]+.mvpid[.@i],gettimetick(2)+(.mvptime[.@i]*60)); setd("$P"+.mvpa[.@i]+.mvpid[.@i]+"$", strcharinfo(PC_NAME)); if( killedrid == 1120 || killedrid == 1096 || killedrid == 1388 ) { if(.announce) announce "A mini boss monster [ "+strmobinfo(1,killedrid)+" ] at "+strcharinfo(PC_MAP)+" has been slain.",bc_all; } else { if(.announce) announce "A boss monster [ "+strmobinfo(1,killedrid)+" ] at "+strcharinfo(PC_MAP)+" has been slain.",bc_all; if(.pvp){ removemapflag .mvpmaps$[.@i], mf_pvp_nocalcrank; pvpoff .mvpmaps$[.@i]; } } break; } } } end; OnSettings: while(1){ switch(select( " ~ PvP On Map [ "+((.pvp)?"^28bf00Yes^000000":"^ff0000No^000000")+" ]:"+ " ~ Announce [ "+((.announce)?"^28bf00Yes^000000":"^ff0000No^000000")+" ]:"+ " ~ Reset All MvP:"+ " ~ Reset Specific MvP:"+ " ~ ^777777Close^000000" )) { case 1: .pvp =! .pvp; for( .@i = 0; .@i < getarraysize(.mvpid); .@i++ ) { if ( getd("$S"+.mvpa[.@i]+.mvpid[.@i]) < 2 || getd("$T"+.mvpa[.@i]+.mvpid[.@i]) <= gettimetick(2) ) { // if mini boss, just ignore pvp if(.pvp){ if(.mvpid[.@i] == 1120 || .mvpid[.@i] == 1096 || .mvpid[.@i] == 1388 ){ //PASS THROUGH } else { setmapflag .mvpmaps$[.@i], mf_pvp_nocalcrank; pvpon .mvpmaps$[.@i]; } } else { removemapflag .mvpmaps$[.@i], mf_pvp_nocalcrank; pvpoff .mvpmaps$[.@i]; } } } break; case 2: .announce =! .announce; break; case 3: freeloop(1); for( .@i = 0; .@i < getarraysize(.mvpid); .@i++ ) { setd("$S"+.mvpa[.@i]+.mvpid[.@i], 1); setd("$T"+.mvpa[.@i]+.mvpid[.@i], 0); setd("$P"+.mvpa[.@i]+.mvpid[.@i]+"$",""); killmonsterall .mvpmaps$[.@i]; } for( .@i = 0; .@i < getarraysize(.mvpid); .@i++ ) { if( compare( .mvpmaps$[.@i], "prt_maze03" ) && .mvpid[.@i] == 1039 ) { // Baphomet monster .mvpmaps$[.@i],100,100,"--ja--",.mvpid[.@i],1; } else if( compare( .mvpmaps$[.@i], "treasure02" ) && .mvpid[.@i] == 1112 ) { // Drake monster .mvpmaps$[.@i],101,151,"--ja--",.mvpid[.@i],1; } else if( compare( .mvpmaps$[.@i], "pay_dun04" ) && .mvpid[.@i] == 1150 ) { // moonlight monster .mvpmaps$[.@i],120,115,"--ja--",.mvpid[.@i],1; } else if( compare( .mvpmaps$[.@i], "tur_dun04" ) && .mvpid[.@i] == 1312 ) { // turtle monster .mvpmaps$[.@i],99,93,"--ja--",.mvpid[.@i],1; } else if( compare( .mvpmaps$[.@i], "moc_pryd06" ) && .mvpid[.@i] == 1511 ) { // amon monster .mvpmaps$[.@i],102,166,"--ja--",.mvpid[.@i],1; } else if( compare( .mvpmaps$[.@i], "ayo_dun02" ) && .mvpid[.@i] == 1688 ) { // lady monster .mvpmaps$[.@i],150,90,"--ja--",.mvpid[.@i],1; } else if( compare( .mvpmaps$[.@i], "niflheim" ) && .mvpid[.@i] == 1373 ) { // LOD donpcevent("NifInvasion::OnSpawn"); } else { monster .mvpmaps$[.@i],0,0,"--ja--",.mvpid[.@i],1; } if(.pvp){ if(.mvpid[.@i] == 1120 || .mvpid[.@i] == 1096 || .mvpid[.@i] == 1388 ){ //PASS THROUGH } else { setmapflag .mvpmaps$[.@i], mf_pvp_nocalcrank; pvpon .mvpmaps$[.@i]; } } else { removemapflag .mvpmaps$[.@i], mf_pvp_nocalcrank; pvpoff .mvpmaps$[.@i]; } } freeloop(0); dispbottom "All MVP has been reset."; break; case 4: set .@menu$,""; freeloop(1); for( .@i = 0; .@i < getarraysize(.mvpid); .@i++ ) set .@menu$, .@menu$+getmonsterinfo(.mvpid[.@i],0)+" - ("+.mvpmaps$[.@i]+"):"; set .@menu$, .@menu$+" ~ ^777777Cancel^000000"; freeloop(0); set .@i, select(.@menu$)-1; setd("$S"+.mvpa[.@i]+.mvpid[.@i], 1); setd("$T"+.mvpa[.@i]+.mvpid[.@i], 0); setd("$P"+.mvpa[.@i]+.mvpid[.@i]+"$",""); killmonsterall .mvpmaps$[.@i]; monster .mvpmaps$[.@i],0,0,"--ja--",.mvpid[.@i],1; if(.pvp){ if(.mvpid[.@i] == 1120 || .mvpid[.@i] == 1096 || .mvpid[.@i] == 1388 ){ //PASS THROUGH } else { setmapflag .mvpmaps$[.@i], mf_pvp_nocalcrank; pvpon .mvpmaps$[.@i]; } } else { removemapflag .mvpmaps$[.@i], mf_pvp_nocalcrank; pvpoff .mvpmaps$[.@i]; } dispbottom "Monster [ "+strmobinfo(1,.mvpid[.@i])+" ] at "+.mvpmaps$[.@i]+" has been reset."; break; default: close; } } close; OnTimer60000: // Let recheck after a minute. for( .@i = 0; .@i < getarraysize(.mvpid); .@i++ ) { /* $S 1 - Alive $S 2 - Dead */ // If MvP status is not yet set if ( getd("$S"+.mvpa[.@i]+.mvpid[.@i]) == 2 && getd("$T"+.mvpa[.@i]+.mvpid[.@i]) <= gettimetick(2) ) { // check if MvP has fixed spawn location in the map. if( compare( .mvpmaps$[.@i], "prt_maze03" ) && .mvpid[.@i] == 1039 ) { // Baphomet monster .mvpmaps$[.@i],100,100,"--ja--",.mvpid[.@i],1; } else if( compare( .mvpmaps$[.@i], "treasure02" ) && .mvpid[.@i] == 1112 ) { // Drake monster .mvpmaps$[.@i],101,151,"--ja--",.mvpid[.@i],1; } else if( compare( .mvpmaps$[.@i], "pay_dun04" ) && .mvpid[.@i] == 1150 ) { // moonlight monster .mvpmaps$[.@i],120,115,"--ja--",.mvpid[.@i],1; } else if( compare( .mvpmaps$[.@i], "tur_dun04" ) && .mvpid[.@i] == 1312 ) { // turtle monster .mvpmaps$[.@i],99,93,"--ja--",.mvpid[.@i],1; } else if( compare( .mvpmaps$[.@i], "moc_pryd06" ) && .mvpid[.@i] == 1511 ) { // amon monster .mvpmaps$[.@i],102,166,"--ja--",.mvpid[.@i],1; } else if( compare( .mvpmaps$[.@i], "ayo_dun02" ) && .mvpid[.@i] == 1688 ) { // lady monster .mvpmaps$[.@i],150,90,"--ja--",.mvpid[.@i],1; // Initiate LOD invasion at Niflheim } else if( compare( .mvpmaps$[.@i], "niflheim" ) && .mvpid[.@i] == 1373 ) { // LOD donpcevent("NifInvasion::OnSpawn"); } else { // Spawn the MvP at random location. monster .mvpmaps$[.@i],0,0,"--ja--",.mvpid[.@i],1; } if(.announce) announce "Monster [ "+strmobinfo(1,.mvpid[.@i])+" ] at "+.mvpmaps$[.@i]+" has been spawned.",bc_all; // set status of MvP as ALIVE! setd("$S"+.mvpa[.@i]+.mvpid[.@i], 1); // reset killer name. setd("$P"+.mvpa[.@i]+.mvpid[.@i]+"$", ""); if(.pvp){ // if mini boss, just ignore pvp if(.mvpid[.@i] == 1120 || .mvpid[.@i] == 1096 || .mvpid[.@i] == 1388 ){ //PASS THROUGH } else { setmapflag .mvpmaps$[.@i], mf_pvp_nocalcrank; pvpon .mvpmaps$[.@i]; } } else { removemapflag .mvpmaps$[.@i], mf_pvp_nocalcrank; pvpoff .mvpmaps$[.@i]; } } } initnpctimer(); end; OnCheck: OnPCLoginEvent: .@rank = 0; query_sql "SELECT DATABASE()", .@rag_db$; query_logsql "SELECT DATABASE()", .@log_db$; query_sql( "SELECT COUNT(`monster_id`) AS `total`,`char`.`name`,`kill_char_id` FROM "+.@log_db$+".`mvplog`"+" LEFT JOIN "+.@rag_db$+".`char` ON `char`.`char_id` = `mvplog`.`kill_char_id` WHERE `map` <> 'guild_vs5' AND DATE_FORMAT( `mvp_date`, '%Y-%m-%d') = DATE_FORMAT( now(), '%Y-%m-%d') GROUP BY `kill_char_id` ORDER BY `total` DESC LIMIT 10",.@mvptotal,.@mvpname$,.@kill_char_id ); for( .@i = 0; .@i < getarraysize(.@kill_char_id); .@i++ ) { if(getcharid(CHAR_ID_CHAR) == .@kill_char_id[.@i]){ .@rank = .@i+1; .@total = .@mvptotal[.@i]; } } if ( .@rank > 0 && .@rank < 4 ) { if(countitem(.topreward) == 0){ dispbottom "Congratulations you ranked as #"+.@rank+" MvP Hunter for today. Total kill "+.@total; getitembound .topreward,1,4; equip(.topreward); } } else { if(countitem(.topreward) > 0){ delitem .topreward,countitem(.topreward); dispbottom "Sorry you have lost your rank as Top 3 MvP Hunter of the day."; } } addtimer 300000,strnpcinfo(0) + "::OnCheck"; end; OnInit: .topreward = 31488; // top mvp daily reward .toprange = 3; // Only Top 3 gets the reward .announce = 1; // shall we announce mvp kills and spawn? (yes = 1 no = 0) .pvp = 1; // shall will make the map pvp? (yes = 1 no = 0) bindatcmd("mvpcontroller","mvpcontroller::OnSettings",99,99); // Mvp ids setarray .mvpid[0],1511,1096,1096,1388,1039,1272,1272,1046,1046,1389,1112,1115,1115,1418,1252,1120,1120,1120,1120,1086,1492,1251,1147,1147,1059,1150,1087,1190,1038,1157,1159,1312,1373,1630,1688; // Mvp Index is used because there are same mvp that spawn on different maps. setarray .mvpa[0],1,1,2,1,1,1,2,1,2,1,1,1,2,1,1,1,2,3,4,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1; // MvP maps setarray .mvpmaps$[0],"moc_pryd06","pay_fild04","xmas_dun01","yuno_fild02","prt_maze03","gl_chyard","gld_dun04","gef_dun02","gld_dun02","gef_dun01","treasure02","gld_dun01","pay_fild11","gon_dun03","xmas_fild01","gld_dun04","pay_fild04","prt_maze03","treasure02","prt_sewb4","ama_dun03","xmas_dun02","anthell02","gld_dun03","mjolnir_04","pay_dun04","gef_fild14","gef_fild10","moc_pryd04","in_sphinx5","moc_fild15","tur_dun04","niflheim","lou_dun03","ayo_dun02"; // How many minutes to respawn? setarray .mvptime[0],60,60,60,60,120,60,480,120,480,60,120,480,120,95,120,240,60,114,32,60,91,60,120,480,120,60,60,120,60,60,120,60,93,117,420; freeloop(1); for( .@i = 0; .@i < getarraysize(.mvpid); .@i++ ) { // If MvP status is not yet set if ( getd("$S"+.mvpa[.@i]+.mvpid[.@i]) < 2 || getd("$T"+.mvpa[.@i]+.mvpid[.@i]) <= gettimetick(2) ) { // check if MvP has fixed spawn location in the map. if( compare( .mvpmaps$[.@i], "prt_maze03" ) && .mvpid[.@i] == 1039 ) { // Baphomet monster .mvpmaps$[.@i],100,100,"--ja--",.mvpid[.@i],1; } else if( compare( .mvpmaps$[.@i], "treasure02" ) && .mvpid[.@i] == 1112 ) { // Drake monster .mvpmaps$[.@i],101,151,"--ja--",.mvpid[.@i],1; } else if( compare( .mvpmaps$[.@i], "pay_dun04" ) && .mvpid[.@i] == 1150 ) { // moonlight monster .mvpmaps$[.@i],120,115,"--ja--",.mvpid[.@i],1; } else if( compare( .mvpmaps$[.@i], "tur_dun04" ) && .mvpid[.@i] == 1312 ) { // turtle monster .mvpmaps$[.@i],99,93,"--ja--",.mvpid[.@i],1; } else if( compare( .mvpmaps$[.@i], "moc_pryd06" ) && .mvpid[.@i] == 1511 ) { // amon monster .mvpmaps$[.@i],102,166,"--ja--",.mvpid[.@i],1; } else if( compare( .mvpmaps$[.@i], "ayo_dun02" ) && .mvpid[.@i] == 1688 ) { // lady monster .mvpmaps$[.@i],150,90,"--ja--",.mvpid[.@i],1; // Initiate LOD invasion at Niflheim } else if( compare( .mvpmaps$[.@i], "niflheim" ) && .mvpid[.@i] == 1373 ) { // LOD donpcevent("NifInvasion::OnSpawn"); } else { // Spawn the MvP at random location. monster .mvpmaps$[.@i],0,0,"--ja--",.mvpid[.@i],1; } // set status of MvP as ALIVE! setd("$S"+.mvpa[.@i]+.mvpid[.@i], 1); // status is alive (1) // reset killer name. setd("$P"+.mvpa[.@i]+.mvpid[.@i]+"$", ""); // killer name reset if(.pvp){ // if mini boss, just ignore pvp if(.mvpid[.@i] == 1120 || .mvpid[.@i] == 1096 || .mvpid[.@i] == 1388 ){ //PASS THROUGH } else { setmapflag .mvpmaps$[.@i], mf_pvp_nocalcrank; pvpon .mvpmaps$[.@i]; } } else { removemapflag .mvpmaps$[.@i], mf_pvp_nocalcrank; pvpoff .mvpmaps$[.@i]; } } } freeloop(0); initnpctimer(); end; } /* If you want your player have access to spawn time, you can use this function to display status of each MvP and who killed them { Id: 501 AegisName: "Red_Potion" Name: "Red Potion" Type: "IT_HEALING" Buy: 50 Weight: 70 Script: <" callfunc "F_MVPTime"; "> }, */ function script F_MVPTime { mes "^FF0000MvP Status^000000"; for( .@i = 0; .@i < getarraysize(getvariableofnpc(.mvpid,"mvpcontroller")); .@i++ ) { .@time = getd("$T" +getvariableofnpc(.mvpindex[.@i],"mvpcontroller") + getvariableofnpc(.mvpid[.@i],"mvpcontroller")); .@alive = getd("$S" +getvariableofnpc(.mvpindex[.@i],"mvpcontroller") + getvariableofnpc(.mvpid[.@i],"mvpcontroller")); set .@hours, (.@time - gettimetick(2)) / 3600; set .@mins, (.@time - gettimetick(2))%3600/60; set .@secs, (.@time - gettimetick(2))%60; set .@mobname$,getmonsterinfo( getvariableofnpc(.mvpid[.@i], "mvpcontroller"),0 ); set .@map$,getvariableofnpc(.mvpmaps$[.@i], "mvpcontroller"); set .@player$,getd("$P"+getvariableofnpc(.mvpindex[.@i], "mvpcontroller") + getvariableofnpc(.mvpid[.@i], "mvpcontroller") +"$"); mes ((.@alive == 1) ? "[ ^01DF01+^000000 ]" : "[ ^FF0000x^000000 ]")+((getstrlen( .@mobname$ ) > 10 ) ? " ^0055FF"+substr(.@mobname$,0, 10)+"^000000" : " ^0055FF"+.@mobname$+"^000000")+" ^777777"+.@map$+"^000000 "; if( .@alive == 2 ) { mes "^FF0000"+((.@hours) ? .@hours +"h" : "")+" "+((.@mins) ? .@mins +"m" : "")+" "+((.@secs) ? .@secs +"s" : "")+"^000000 "+"^777777 kiiled by "+.@player$+"^000000"; } } close; } What does it do? - prevents spawn of mvp on each server starts or reload. - spawns mvp or mini only at specific time based when it was killed + spawn time - reward x top mvp killers. Cons: - you can not use convex mirrors to show mvp in the map - you can not find mvp using @whereis. How to use: - Delete or Comment target MVP and mini boss spawn from your npc/pre-re/mobs/dungeons/ or /fields. - Add these mvps to array. FAQ: #Q1 What the heck is this? setarray .mvpa[0],1,1,2,1,1,1,2,1,2,1,1,1,2,1,1,1,2,3,4,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1; #A1: since there are same kind of MVP spawn on multile map (i.e Angeling spawns at pay_fild04, xmas_dun01, yuno_fild03) those numbers are the unique identifiers. if there is only 1 spawn, then just write 1. succeeding spawn is 2 then 3 .... All other suggestions to simplify and improve @AnnieRuru yohoo! my master. Edited February 21, 2021 by astralprojection 1 Caspian reacted to this Quote Share this post Link to post Share on other sites
Eternity 1 Posted February 28, 2021 What's the replacement for getarrayindex on rAthena? Quote Share this post Link to post Share on other sites