Jump to content

GmOcean

Community Contributors
  • Content Count

    371
  • Joined

  • Last visited

  • Days Won

    8

Posts posted by GmOcean


  1. 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.


  2. 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 :D


  3. @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;

  4. 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 *


  5. 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.


  6. 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.


  7. 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.


  8. 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:


  9. 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;		}	}}

  10. -	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 *


  11. 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;}

     


  12. 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.


  13. 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.


  14. 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.


  15. Currently, no one knows how to change that. It's a client limitation until we can find the proper hex code and make a diff for it. For now people will just have to drag the corner of the window to increase it's size or maximize it :/


  16. 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;//	}

  17. 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.


  18. 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;}
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.