GmOcean
-
Content Count
371 -
Joined
-
Last visited
-
Days Won
8
Posts posted by GmOcean
-
-
Scripting Tutorials and Guides
I'm going to attempt to help everyone here with their scripts while not being directly involved in helping you with them xD.
This will also help future/current scripters get some fresh info and maybe inspire innovative ideas towards scripting.
So that we can prove that us " Scripters " are the superior ragnarok emulation race! Take that Source Code writers!! Jk lol, we need you too .
What I'm going to do, is write detailed tutorials on how to write a few scripts. Starting from the basics to more advanced scripts.
This way everyone can follow along. And hopefully this will help everyone understand how to write a few scripts and even troubleshoot their own scripts.Also please read: Scripting Standards.
It will help you understand how to read some of the syntax and way people script things.
// A list of <sprite id>s can be found here: Sprite_IDs Credits: Ai4rei
Scripting Tutorials & Guides
In this section you will learn how to write scripts ranging from Complete Begginer Level Scripts ( Me and Some of you ) -> Expert Level Scripts ( Think, Developer Status O.o; )
- Beginner Scripts -
Scripts for complete beginners and novice scripters.
Basic Healer & Buffer Script ( 5 Parts )
A Basic Healer Script. Here we will cover most, if not all of the basics of scripting.
Basic Item Trader Script ( 2 Parts )
A basic item trader script. Here we will learn how to give players an item in exchange for other items.
Basic Floating Rates Script - Complete ( 2 Parts )
Here we will create a " floating " npc. And have it adjust base & job experience rates.
Basic Player vs Player Script - Complete ( 1 Part )
A Player vs Player script to introduce you to the basics needed to make them work.
- Intermediate Scripts -
Scripts for intermediate level scripters. If you completed my beginner script series, then you are ready for this section.
Intermediate Healer & Buffer Script - Complete ( 2 Parts )
An Intermediate version of the Basic Healer & Buffer script.
Custom AtCommand @buff - Complete ( 2 Parts )
A custom @command, that will buff the player with preset buffs, have a cast time, cost zeny, have a cooldown time, and will unlock more buffs the more they use it !!
Bounty Hunting PvP Script - Complete ( 2 Parts )
An intermediate level PvP script. This script is intended to help improve your scripting abilities, while also making you feel more comfortable about PvP scripts.
- Advanced Scripts -
Scripts for advanced level scripters. If you completed my intermediate script series and have made a few of your own intermediate scripts, then you are ready for this section.
The idea behind this topic, is for new users, and current ones, to have a (second)place they can go to for reference when trying to write a script if they can't figure it out with script_commands.txt file. It will also help people learn how to write scripts. While hopefully, keeping script writing techniques to a ' very ' similar structure!
*Read Me* - I have updated the links on this post to link to the oldboard so these guides can be viewed. However, do note that the script_commands.txt links within those guides are no longer accurate. Enjoy your scripting.
-
This looks amazing. How far along would you say it is towards completion? 20%? 50%? 99% (I hope)? lol.
Edit: @Mysterious ( below ) - Yeah, I meant the main page lol. And glad to hear it's so far along
-
@Zephyr - See, your situation is a matter of just scripting flaw. Instead of determining whether or not to give a player based on whether the quest is active or not, you should be deciding whether or not to give the player the quest depending on whether or not it's complete.
for( set @i, 50009; @i <= 50036; set @i, @i +1 ) { if( !checkquest( @i ) && getd("quest_limit"+@i+"") <= 10 ) { // Hasn't obtained quest mes "Do you want to obtain this quest?"; if( select("Yes:No") == 2 ) { close; } setquest @i; } else if( checkquest( @i ) != 2 ) { // Has quest but is unfinished. mes "Do you want to abandon this quest?"; if( select("Yes:No") == 2 ) { close; } erasequest @i; } else if( getd("quest_limit"+@i+"") > 10 ) { mes "You can't do this quest anymore times today."; } else { mes "Congratulations! You fished the quest. Did you want to turn it in?"; if( select("Yes:No") == 2 ) { close; } setd "quest_limit"+@i+"", getd("quest_limit"+@i+"") - 1; // Obtain Reward. erasequest @i; //Erase quest again. if( !getd("quest_limit"+@i+"") ) { setd "quest_limit"+@i+"", gettimetick(2) + (3600 * 24 ); } mes "Quest turned in."; } close;}OnPCLoginEvent:for( @i = 50009; @i <= 50036; @i++ ) { if( gettimetick(2) > getd("quest_limit"+@i+"") ) { setd "quest_limit"+@i+"", 10; }}end;
-
3 ways of doing this.
1. Use bindatcmd in combination with Sql table. ( Recommended & Permanent ).
2. Use bindatcmd in combination with NPC variables. ( Temporary & Not-Recommended ).
3. Use bindatcmd in combination with Per-Global variables. ( Permanent & Not-Recommended ).
- script playtime -1,{OnInit:bindatcmd "playtime",strnpcinfo(3)+"::OnPlayTime";// 1 = TempVariable | 2 = PermVariable | 3 = PermSQL// Default: 3.mode = 3;end;OnPlayTime:switch( .mode ) { case 1: if( .@atcmd_parameters$[0] == "" ) { .@atcmd_parameters$[0] = strcharinfo(0); } if( (.@size = query_sql( "SELECT char_id FROM char WHERE name= "+ .@atcmd_parameters$[0] +"",.@char_id ) ) ) { query_sql "SELECT lastlogin FROM login WHERE char_id="+ .@char_id[0] +"",.@login$; mes "-------- "+ .@atcmd_parameters$[0] +" --------", ""+ getd(".idlehours"+.@atcmd_parameters$[0]+"") +"hours "+ getd(".idleminutes"+.@atcmd_parameters$[0]+"") +"minutes idle.", ""+ getd(".activehours"+.@atcmd_parameters$[0]+"") +"hours "+ getd(".activeminutes"+.@atcmd_parameters$[0]+"") +"minutes active.", "Last Time Online: "+ .@login$ +"; close; } case 2: if( .@atcmd_parameters$[0] == "" ) { .@atcmd_parameters$[0] = strcharinfo(0); } if( (.@size = query_sql( "SELECT name,char_id FROM char WHERE name= "+ .@atcmd_parameters$[0] +"",.@name$,.@char_id ) ) ) { query_sql "SELECT lastlogin FROM login WHERE char_id="+ .@char_id[0] +"",.@login$; mes "-------- "+ .@name$ +" --------", ""+ getd("$idlehours"+.@atcmd_parameters$[0]+"") +"hours "+ getd("$idleminutes"+.@atcmd_parameters$[0]+"") +"minutes idle.", ""+ getd("$activehours"+.@atcmd_parameters$[0]+"") +"hours "+ getd("$activeminutes"+.@atcmd_parameters$[0]+"") +"minutes active.", "Last Time Online: "+ .@login$[0] +""; close; } case 3: if( .@atcmd_parameters$[0] == "" ) { .@atcmd_parameters$[0] = strcharinfo(0); } if( (.@size = query_sql( "SELECT char_id,idle_hour,idle_minute,active_hour,active_minute FROM playtime WHERE name="+ .@atcmd_parameters$[0] +"", .@char_id, .@idleh, .@idem, .@activeh, .@activem ) ) ) { query_sql "SELECT lastlogin FROM login WHERE char_id="+ .@char_id[0] +"",.@login$; mes "-------- "+ .@atcmd_parameters$[0] +" --------", ""+ .@idelh[0] +"hours "+ .@idlem[0] +"minutes idle.", ""+ .@activeh[0] +"hours "+ .@activem[0] +"minutes active.", "Last Time Online: "+ .@login$[0] +""; close; }}end;OnPCLoginEvent: @login = gettimetick(2); freeloop(1); while(1) { if( checkidle ) { @idle++; } else { @active++; } sleep2 1000; }end;OnPCLogoutEvent:.@idleh = @idle / 3600;.@idlem = @idle % 3600;.@activeh = @active / 3600;.@activem = @active % 3600;switch( .mode ) { case 1: setd ".idleh"+strcharinfo(0)+"", getd(".idleh"+strcharinfo(0)+"") + .@idleh; setd ".idlem"+strcharinfo(0)+"", getd(".idlem"+strcharinfo(0)+"") + .@idlem; setd ".activeh"+strcharinfo(0)+"", getd(".activeh"+strcharinfo(0)+"") + .@activeh; setd ".activem"+strcharinfo(0)+"", getd(".activem"+strcharinfo(0)+"") + .@activem; end; case 2: setd "$idleh"+strcharinfo(0)+"", getd("$idleh"+strcharinfo(0)+"") + .@idleh; setd "$idlem"+strcharinfo(0)+"", getd("$idlem"+strcharinfo(0)+"") + .@idlem; setd "$activeh"+strcharinfo(0)+"", getd("$activeh"+strcharinfo(0)+"") + .@activeh; setd "$activem"+strcharinfo(0)+"", getd("$activem"+strcharinfo(0)+"") + .@activem; end; case 3: if( query_sql( "SELECT * FROM playtime WHERE char_id="+getcharid(0)+"",.@char_id,.@name$,.@ihours,.@imins,.@ahours,.@amins) ) { query_sql "UPDATE playtime SET(idle_hours,idle_minutes,active_hours,active_minutes) VALUES("+ (.@ihours + .@idleh) +","+ (.@iminutes + .@idlem) +","+ (.@ahours + .@activeh) +","+ (.@aminutes + .@activem) +")"; } else { query_sql "INSERT INTO playtime char_id="+getcharid(0)+",name="+strcharinfo(0)+",idle_hours="+.@idleh+",idle_minutes="+.@idlem+",active_hours="+.@activeh+",active_minutes="+.@activem+""; } end;}end;}
*NOTE - Completely untested. Just going off of what I can remember. unfortunately I have work, so you may have to rely on someone else to help you if there are bugs *
-
if( gettimetick(2) < lastTimeTalked ) {mes "You talked recently";close;} else {set lastTimeTalked, gettimetick(2) + ( 3600 * 24 );mes "You may not talk to me again for 24 hours.";close;}
I'm assuming you mean something like this?
If so, then your problem is you didn't actually set ' lastTimeTalked ' to anything. So, you were trying to check if gettimetick(2) - 0 would be greater than ( 60 * 60 * 24 ) [24 hours]. Which of course it will be since it's a number that goes up every second since 1950? 1960?. At anyrate, as long as you set the variable to current time ( gettimetick(2) ) plus 24 hours, then you won't have an issue.
-
You, mean uses the same window as Kafra Storage, but doesn't share the same inventory? Like how Storage and Guild Storage work? If so then yes. Since Guild Storage is just a clone of regular storage. It's possible to make a unique storage for each individual character, a storage depending on whether or not you have a variable set to 1 or not. And assuming you have a faction system, you could even create a storage depending on what faction they are in.
-
That would probably a well bought service.
-
O.o What!? They even changed the buttons for Inventory, Party, Booking, Equipment, Skills and such !? Or is that just your skin >.>?
Also, yay, lucky roulette button is there. Guess gotta wait longer till we can find the RoDex one D: (Pokedex O.o)
-
I just wanna suggest that the *explode script command, should push the array size of the one it creates. So that things like this are possible:
.@a = 10;while( .@b != .@a ) { .@menu$ = .@menu$ +""+ .@b +":"; .@b++;}.@menu$ = .@menu$ +"Last Option";if( select( .@menu$ ) == ( .@size = explode( .@temp$, .@menu$, ":" ) ) ) { close; } // Clicked Last Option in list.
vs what we have to do now:
.@a = 10;while( .@b != .@a ) { .@menu$ = .@menu$ +""+ .@b +":"; .@b++;}.@menu$ = .@menu$ +"last Option";explode( .@temp$, .@menu$, ":" );if( select( .@menu$ ) == getarraysize( .@temp$ ) ){ close; } // Clicked Last Option in list.
It's not really " needed " more of just a feature I think it should have since commands like query_sql have it. I figure why not give it the extra feature since it's not a downgrade nor does it break backwards compatibility.
-
Yeah, sorry, that's my fault, I just copy pasted the table from my sql, and that's what my test server's sql_db table is called.
-
You mean, have it shout out random headgear names, and then players just type it out as fast as they can? This can be done, but I think i can make it more entertaining or rather more appealing by use of <ITEMLINK> if I can figure out why it doesn't work :/
-
I completely agree with the removal of those extra values. It's really not needed. Because, I only need to know 2 things, 1) Does Player have quest? Yes/No 2) Is quest Done? Yes/No.
Everything else, is a waste of time imo. It doesn't really matter to me if they obtained the quest but aren't tracking it. Because to me, that is purely for their ease.
It's like this in almost every MMO ever...
1. You obtain a quest.
2. You either choose to track it ( active ) or remove it from your tracking bar since it's not that important ( inactive ).
3. You kill monsters, talk to npcs, etc..
4. Your quest get's updated whether your tracking it or not (active or inactive).
5. You turn it in whether your tracking it or not (active or inactive).
So again, let's just remove it, not needed D:
-
Well, i'm assuming you meant, how to make it so only party leader can run the warp. Since there was a line of code having to deal with @leader and such.
prontera,192,176,5 script Çöó½Ã¾ÆÀÇ Àü·É 4_M_SAKRAYROYAL,{ if (getareausers("prontera",197,178,207,167) < 2) {// if (getareausers("prontera",197,178,207,167) < 2) { mes "[ºí·¹µå]"; mes "Àü Çöó½Ã¾ÆÀÇ Àü·ÉÀ¸·Î"; mes "¿ëÀÇ ´øÀü Åä¹ú´ë¸¦ ¸ðÁý ÇÏ°í ÀÖ½À´Ï´Ù."; mes "Çöó½Ã¾ÆÀÇ ±àÁö·Î"; mes "4´ë ¿ëµéÀ» ¹°¸®ÃÄ ÁֽʽÿÀ."; next; menu "Åä¹ú´ë ±¸¼º ¹× Ãâ¹ß",D_go,"Ãë¼Ò",Cancel;Cancel: mes "[ºí·¹µå]"; mes "¾î¿¼ö ¾ø±º¿ä."; close; D_go: mes "[ºí·¹µå]"; mes "µå·¡°ï µÕÁö·Î °¡±âÀ§Çؼ´Â 20¸í ÀÌ»óÀÇ Åä¹ú´ë°¡ ÀÖ¾î¾ß ÇÕ´Ï´Ù."; mes "ÇöÀç ½ÅÀü¿¡ "+getareausers("prontera",197,178,207,167)+ " ¸íÀÌ ´ë±âÁßÀ̱º¿ä.."; next; mes "[ºí·¹µå]"; mes "ÀοøÀ» ´õ ¸ðÁý ÇϽðųª"; mes "½ÅÀüÀ¸·Î ÀοøÀ» ¸ð¾Æ ÁֽʽÿÀ."; close; } mes "[ºí·¹µå]"; mes "Ãâ¹ß ÇϽðڽÀ´Ï±î?"; next; switch(select("Ãâ¹ß ÇÏ°Ú½À´Ï´Ù.:Ãë¼Ò")) { case 1: mes "[ºí·¹µå]"; mes "¹«¿îÀ» º÷´Ï´Ù."; close2; if( getpartyleader(getcharid(3),1) == -1){ mes "Only party leader can use this."; close; } areawarp "prontera",197,178,207,167,"1@eom",95,123,101,117; warp "1@eom",93,120; case 2: close; } }}
-
Creating a pearl expression to identify upper/lowercase/numbers/symbols is hard, atleast I didn't wanna bother with it. That's why my disguise event accepts lowercase or all upper case when giving the answer.
-
- script autocart -1,{OnPCLoginEvent:if( !checkcart() ) { setcart 1;}end;}
This just gives them a cart, can't really say which one. Also, I'm against this sort of thing, because what if the player doesn't wanna wear a cart for looks D:
*Note - Documentation says this wont work for class' besides merchant class ( unless they have MC_PUSHCART skill ), so should be fine without checks *
-
If you're not getting any points, then it's highly likely I got the killerrid and killedrid backwards. If that is the simply add this after OnPCKillEvent:
attachrid( killedrid ) ;
-
Well, this is a very basic script, doing just the bare minimum of what you requested. Just the bones, no flesh =P
prontera,160,180,4 script PVP ROOMS 123,{mes "Welcome, what PVP room do you want to enter?";switch( select("Normal PVP Room [ Unranked ]"+ (lolpvprank?":["+ .ranknames$[lolpvprank] +"] PVP Room:No Division Limit":"::") +":Close") ) { case 1: explode( .@w$, .warplocations$[0], ":" ); warp .@w$[0], atoi( .@w$[1] ), atoi( .@w$[2] ); end; case 2: explode( .@w$, .warplocations$[lolpvprank], ":" ); warp .@w$[0], atoi( .@w$[1] ), atoi( .@w$[2] ); end; case 3: explode( .@w$, .warplocations$[getarraysize(.warplocations$)], ":" ); warp .@w$[0], atoi( .@w$[1] ), atoi( .@w$[2] ); end; case 4: close;}OnPCKillEvent:for( .@i = 0; .@i< getarraysize( .warplocations ); .@i++ ) { explode( .@w$, .warplocations$[.@i], ":" ); if( strcharinfo(3) == .@w$[0] ) { .@a = 1; }}if( !.@a ) { end; } // Only Count Kills from maps in Ranked/Non-Ranked PVP rooms.lolpvpkills--; // Minus Points on death, even if it was a suicide.if( lolpvpkills == -1 ){ lolpvprank--; lolpvpkills = .lolpvpkillsrank[lolpvprank] - 1; // De-rank players and set them to 1 kill away from promotion again. announce "Ouch~! You've been deranked, back to "+ .ranknames$[lolpvprank] +"~!",bc_self | bc_blue;}if( killedrid == killerrid ){ end; } // Was a suicide so end.attachrid( killerrid );if( lolpvprank == ( getarraysize( .lolpvpkillsrank ) - 1 ) ){ end; } // Reached Max Rank already.lolpvpkills++;if( lolpvpkills >= .lolpvpkillsrank[lolpvprank +1] && .lolpvpkillsrank[lolpvprank+2] >= lolpvpkills ) { lolpvprank++; announce "Congratulations~! You are now "+ .ranknames$[lolpvprank] +"~!",bc_self | bc_blue; lolpvpkills = 0;}end;OnInit:// Warp Locations// eg: "prontera:150:180", <--- Will warp you to Prontera 150,180.setarray .warplocations$[0],"MapName:X:Y", // Unranked Warp Location ( Always make this one first ). "MapName:X:Y", // Bronze V "MapName:X:Y", // Bronze IV "MapName:X:Y", // Bronze III "MapName:X:Y", // Bronze II "MapName:X:Y", // Bronze I "MapName:X:Y", // Silver V "MapName:X:Y", // Silver IV "MapName:X:Y", // Silver III "MapName:X:Y", // Silver II "MapName:X:Y", // Silver I "MapName:X:Y", // Gold V "MapName:X:Y", // Gold IV "MapName:X:Y", // Gold III "MapName:X:Y", // Gold II "MapName:X:Y", // Gold I "MapName:X:Y", // Platinum V "MapName:X:Y", // Platinum IV "MapName:X:Y", // Platinum III "MapName:X:Y", // Platinum II "MapName:X:Y", // Platinum I "MapName:X:Y", // Challenger V "MapName:X:Y", // Challenger IV "MapName:X:Y", // Challenger III "MapName:X:Y", // Challenger II "MapName:X:Y", // Challenger I "MapName:X:Y"; // No Division Limit ( Always keep this one last ).setarray .ranknames$[0],"Unranked", "Bronze V", "Bronze IV", "Bronze III", "Bronze II", "Bronze I", "Silver V", "Silver IV", "Silver III", "Silver II", "Silver I", "Gold V", "Gold IV", "Gold III", "Gold II", "Gold I", "Platinum V", "Platinum IV", "Platinum III", "Platinum II", "Platinum I", "Diamond V", "Diamond IV", "Diamond III", "Diamond II", "Diamond I", "Challenger V", "Challenger IV", "Challenger III", "Challenger II", "Challenger I";setarray .lolpvpkillsrank[0],00, // Unranked 10,10,15,20,25, // Bronze 30,35,40,45,50, // Silver 55,60,65,70,75, // Gold 80,85,90,95,100, // Platinum 105,110,115,120,125, // Diamond 130,135,140,145,150; // Challengerend;}
-
Well, incases like WZ_Waterball, it checks to see if the cell type your standing on is water type.
if( src->type != BL_PC || map->getcell(src->m,x,y,CELL_CHKWATER) ) // non-players bypass the water requirement count++; // natural water cell else if( (su = map->find_skill_unit_oncell(src,x,y,SA_DELUGE,NULL,1)) != NULL || (su = map->find_skill_unit_oncell(src,x,y,NJ_SUITON,NULL,1)) != NULL ) { count++; // skill-induced water cell skill->delunit(su); // consume cell }
However, with AL_HOLYWATER and AB_ANCILLA, there isn't a check atleast, not one directly correlated with it's titles. It just says to produce them at 100%.
case AL_HOLYWATER: /** * Arch Bishop **/ case AB_ANCILLA: make_per = 100000; //100% success break;
There isn't a check in skill.c for water type, it might be else where but I don't know where to look.
-
It'd probably just be better to create a " third " storage for characters. Much like we did for guildstorage. Although, that would take up alot of storage space on server's since, now there'd be a storage for every character, account and guild.
On average thats about:
Every 20 accounts = 1 Guild storage
Every 1 Account = 1 Account Storage
Every 1 Account = 3-9 Character Storage.
It'll be alot of data added in but better in the long run.
Also, an alternative would be to store the ID inside of a data space which we add it items. So instead of it saying item.bound = 1->4. We can have it check against character ID / Account id if not then bound type.
if( item.bound == 2 ){ guild bound; }
else if( item.bound == 3 ){ party bound; }
else if( item.bound >= 150000 && item.bound <= 1999999 ) { char bound; }
else if( item.bound >= 2000000 ){ account bound; }
else { not bound; }
But, thats meh. Just my thoughts.
-
I"d write a plugin for it if I could but I'm not that skilled at src lol. But yeah, I understand what the bound types do, it's just I think in some cases servers bind items to indivisual characters so as to make the quest or process of aquiring that item, not a 1 time thing. Making them have to redo it to gear out their other characters. I myself use this sort of tactic to add replay value for my players.
-
-
Yes it would but i'd have to look up the storage info to see how it's blocked first.
Edit: Okay it seems that the clif_storageitemadded to add items, doesn't support bound item types in it's packet.
However, I can't seem to find that actual code that limits or performs the check on whether or not a bound item can be placed or not.
Edit2: Okay I found it, but understand that without further modifications you'd be able to effectively: store a bound item into storage -> grab it on a different character and then equip it. Making Character Bound type items useless. Your going to need to modify the way bound items work as whole.
Because you see currently all bound items check is for a number 0->4. If it's 1->4 it's bound, 0 it's not. Each number determines what TYPE of bound item it is. But nothing is stored to check WHO the item is bound to.
We just decided it'd be simpler to just say, " hey your item is character bound, you can't remove it from your inventory.".
At anyrate here is the code that deals with storage. Find it and then comment out the section regarding bound items.
/*========================================== * Internal add-item function. *------------------------------------------*/int storage_additem(struct map_session_data* sd, struct item* item_data, int amount) { struct storage_data* stor = &sd->status.storage; struct item_data *data; int i; if( item_data->nameid <= 0 || amount <= 0 ) return 1; data = itemdb->search(item_data->nameid); if( data->stack.storage && amount > data->stack.amount ) {// item stack limitation return 1; } if( !itemdb_canstore(item_data, pc_get_group_level(sd)) ) { //Check if item is storable. [Skotlex] clif->message (sd->fd, msg_txt(264)); return 1; } if( item_data->bound > IBT_ACCOUNT && !pc_can_give_bound_items(sd) ) { clif->message(sd->fd, msg_txt(294)); return 1; } if( itemdb->isstackable2(data) ) {//Stackable for( i = 0; i < MAX_STORAGE; i++ ) { if( compare_item(&stor->items[i], item_data) ) {// existing items found, stack them if( amount > MAX_AMOUNT - stor->items[i].amount || ( data->stack.storage && amount > data->stack.amount - stor->items[i].amount ) ) return 1; stor->items[i].amount += amount; clif->storageitemadded(sd,&stor->items[i],i,amount); return 0; } } } // find free slot ARR_FIND( 0, MAX_STORAGE, i, stor->items[i].nameid == 0 ); if( i >= MAX_STORAGE ) return 1; // add item to slot memcpy(&stor->items[i],item_data,sizeof(stor->items[0])); stor->storage_amount++; stor->items[i].amount = amount; clif->storageitemadded(sd,&stor->items[i],i,amount); clif->updatestorageamount(sd, stor->storage_amount, MAX_STORAGE); return 0;}
Comment out this section:
// if( item_data->bound > IBT_ACCOUNT && !pc_can_give_bound_items(sd) ) {// clif->message(sd->fd, msg_txt(294));// return 1;// }
-
Maybe not -1 sprite, but you could go with the ( i think 111? or 139 *think this is the hidden warp portal* ). But the difference would be your hiding it to ALL players by just simply changing the sprite. With the masking it'd be only certain players.
But yes, it would be possible to simulate this effect somewhat using sprite id 111 and variable check to just end the script.
Edit: Oh lol, i see your asking about using the sprite in combination with the plugin (you just didn't install it yet -.-; feel like an idiot now lol !!) but the same methods should still apply by simply using 111 as the sprite id if -1 doesn't work.
-
If you mean from the { script }, { OnEquip Script }, { UnEquip Script } part of an item, then currently no. Atleast not without the use of a custom command to return those as a string you can compare against. This also applies to whether or not your checking to see if a person can equip it based on Class or required level.
For the latter 2 you could just do something like:
if( equip(itemid) ) { unequip(itemid); do this; do that; end;} else { you can't wear this item. close;}
R> @mvptimer bindactmd
in Script Requests
Posted
Can't be done unless we know EXACTLY when the monster is going to respawn.
In other words you need to edit your monster spawn files so they always spawn on a fixed rate. Then once you provide that information a working command can be written.
But i suggest just going the src route and having a command hook into the MVP tomb/graveyard code.