Jump to content

GmOcean

Community Contributors
  • Content Count

    371
  • Joined

  • Last visited

  • Days Won

    8

Posts posted by GmOcean


  1. Oh this would be very useful for quest type scripts where a player completes a certain phase and such. Like also making a player have access to a shop based on whether or not the did X or Y. Instead of just having the NPC be unresponsive or say something like you can't use this. Nice work.


  2. I thought about it. But decided to save it for a future version just to see how this and my monster search sits well with users D: these 2 scripts were mainly just a test of the hyperlink uses anyways lol. Along with some experimental looping for future scripts =p. Learned a few things too, like apparently even if the loop isn't technically an infinite loop, it'll still throw an error if it's somewhere around 1000+ so. Thats why you see freeloop() being used.


  3. File Name: Item Search

    File Submitter: GmOcean

    File Submitted: 13 Oct 2014

    File Category: Utility

     

    =============================================================

    Description

    =============================================================

    This script will allow users to search information about an

    item in-game. Supports both renewal/non-renewal items. It

    will show the exact item if using the search directory

    function. If however using the input method, this script will

    will run a broadened search, or pull up the exact item if an

    item ID is given instead of a name.

    =============================================================

    Features

    =============================================================

    Choose between what website you want your server to use.

    Or simply leave that upto your players by enabling all sites.

    =============================================================

    NOTE - Requires a client from 2011-10-10aRagexe.exe onwards.

    NOTE2 - RateMyServer Link does not support custom items.

    =============================================================

     

    Click here to download this file


  4. I can't reproduce your problem. Something else must be going on. Also it seems your original script was charging the owner zeny even if they were just changing the settings. This included collecting zeny. Resulting in getting 1 payment less. I cleaned that issue up.

    prontera,155,181,5	script	Healer#rent	757,{	// item to rent NPC	.@item_id = 7539;	// rent NPC for how many days	.@rent_day = 30;		.@aid = getcharid(3);	if ( getd(".rent_aid"+strnpcinfo(3)+"") && getd(".rent_duration"+strnpcinfo(3)+"") > gettimetick(2) ) {			if ( getd(".rent_aid"+strnpcinfo(3)+"") == .@aid ) {			if ( select( "Continue","Set Healer Cost","Collect Zeny" ) == 2 ) {				input .@rental_cost;				setd ".rental_cost"+strnpcinfo(3)+"", .@rental_cost;			}			else if ( @menu == 3 ) {				Zeny += getd(".rental_accumulate"+strnpcinfo(3)+"");				dispbottom "Collected "+getd(".rental_accumulate"+strnpcinfo(3)+"")+" Zeny";				setd ".rental_accumulate"+strnpcinfo(3)+"", 0;			close;			}		}				if ( getd(".rental_cost"+strnpcinfo(3)+"") ) {			dispbottom "Healing Cost: "+getd(".rental_cost"+strnpcinfo(3)+"")+" Zeny";			if ( Zeny < getd(".rental_cost"+strnpcinfo(3)+"") ) close;						Zeny -= getd(".rental_cost"+strnpcinfo(3)+"");			setd ".rental_accumulate"+strnpcinfo(3)+"", getd(".rental_accumulate"+strnpcinfo(3)+"") + getd(".rental_cost"+strnpcinfo(3)+"");		}				percentheal 100,100;		// your desired buff heres			}	else if ( countitem( .@item_id ) ) {		mes "Rent Healer NPC ?";		mes "Rental Cost: 1 x "+getitemname( .@item_id );				if ( select( "Yes","No" ) == 1 ) {			delitem .@item_id,1;			setd ".rent_aid"+strnpcinfo(3)+"", .@aid;			setd ".rent_duration"+strnpcinfo(3)+"", gettimetick(2) + ( .@rent_day * 86400 ); 			mes "NPC belong to you.";		}	}	else {		mes "NPC isnt available.";		mes "Rental Cost: 1 x "+getitemname( .@item_id );	}	close;}prontera,155,181,5	duplicate(rent)	Healer#rent1	757

     

    As for duplicates check the bottom of the script for the syntax.


  5. Infinityloop... must mean theres too much being requested at one time. I'll add a fix....

     

    Edit: This should fix it. Just added freeloop(1) at the begining and freeloop(0) at the end.

    -	script	at_sameip	-1,{OnInit:bindatcmd "sameip",strnpcinfo(3)+"::OnAtSameIP";//,99,99,0; // 0 = No log, 1 = Log usageend;OnAtSameIP:freeloop(1);.@size = query_sql("SELECT `account_id` FROM `char` WHERE `online` = '1' AND `last_map` = '"+ strcharinfo(3) +"'",.@acct_id);.@size2 = query_sql("SELECT `account_id`, `last_ip` FROM `login` WHERE `account_id` != '1'", .@aid, .@ip$);while( .@a < .@size ) {	for( .@i = 0; .@i < getarraysize(.@aid); .@i++ ) {		if( .@aid[.@i] == .@acct_id[.@a] ) {			.@tempaid$[.@a] = ""+ .@aid[.@i] +"";			.@tempaip$[.@a] = .@ip$[.@i];			}		}	.@a++;}.@size3 = getarraysize(.@tempaid$);while( .@c != .@size3 ) {	for( .@i = 0; .@i < getarraysize( .@usedaids$ ); .@i++ ) {		if( .@usedaids$[.@i] == .@tempaid$[.@c] ) { //Account ID already in array.		.@used = 1;		}	}	if( !.@used ) {		.@usedaids$[( getarraysize( .@usedaids$ ) + 1 )] = .@tempaid$[.@c];		.@duplicateaid$[.@c] = "Account IDs: "+ .@tempaid$[.@c] +"";		.@duplicaterid2name$[.@c] = "Character Names: "+ rid2name( atoi( .@tempaid$[.@c] ) ) +"";		.@duplicateaip$[.@c] = "IP Address: "+ .@tempaip$[.@c] +"";				for( .@i = 0; .@i < getarraysize( .@tempaid$ ); .@i++ ) {			if( .@tempaip$[.@c] == .@tempaip$[.@i] && .@tempaid$[.@c] != .@tempaid$[.@i] ) {				.@duplicateaid$[.@c] = .@duplicateaid$[.@c] +", "+ .@tempaid$[.@i] +"";				.@duplicaterid2name$[.@c] = .@duplicaterid2name$[.@c] +", "+ rid2name( atoi( .@tempaid$[.@i] ) ) +"";				.@usedaids$[( getarraysize( .@usedaids$ ) + 1 )] = .@tempaid$[.@i];				}			}		}	.@used = 0;	.@c++;	}dispbottom "---------------- List of Same IP User ----------------";dispbottom "---------------------- "+ setchar( strcharinfo(3), strtoupper(charat(strcharinfo(3),0)), 0 ) +" ----------------------";for( .@i = 0; .@i < getarraysize(.@duplicateaid$); .@i++ ) {	if( .@duplicateaid$[.@i] != "" ) {		dispbottom " ";		dispbottom .@duplicateaip$[.@i];		dispbottom .@duplicateaid$[.@i];		dispbottom .@duplicaterid2name$[.@i];		}	}freeloop(0);end;}

  6. prontera,155,181,5	script	Healer#rent	757,{	// item to rent NPC	.@item_id = 7539;	// rent NPC for how many days	.@rent_day = 30;		.@aid = getcharid(3);	if ( getd(".rent_aid"+strnpcinfo(3)+"") && getd(".rent_duration"+strnpcinfo(3)+"") > gettimetick(2) ) {			if ( getd(".rent_aid"+strnpcinfo(3)+"") == .@aid ) {			if ( select( "Continue","Set Healer Cost","Collect Zeny" ) == 2 ) {				input .@rental_cost;				setd ".rental_cost"+strnpcinfo(3)+"", .@rental_cost;			}			else if ( @menu == 3 ) {				Zeny += getd(".rental_accumulate"+strnpcinfo(3)+"");				dispbottom "Collected "+getd(".rental_accumulate"+strnpcinfo(3)+"")+" Zeny";				setd ".rental_accumulate"+strnpcinfo(3)+"", 0;			}		}				if ( getd(".rental_cost"+strnpcinfo(3)+"") ) {			dispbottom "Healing Cost: "+getd(".rental_cost"+strnpcinfo(3)+"")+" Zeny";			if ( Zeny < getd(".rental_cost"+strnpcinfo(3)+"") ) close;						Zeny -= getd(".rental_cost"+strnpcinfo(3)+"");			$rental_accumulate += getd(".rental_cost"+strnpcinfo(3)+"");		}				percentheal 100,100;		// your desired buff heres			}	else if ( countitem( .@item_id ) ) {		mes "Rent Healer NPC ?";		mes "Rental Cost: 1 x "+getitemname( .@item_id );				if ( select( "Yes","No" ) == 1 ) {			delitem .@item_id,1;			setd ".rent_aid"+strnpcinfo(3)+"", .@aid;			setd ".rent_duration"+strnpcinfo(3)+"", gettimetick(2) + ( .@rent_day * 86400 ); 			mes "NPC belong to you.";		}	}	else {		mes "NPC isnt available.";		mes "Rental Cost: 1 x "+getitemname( .@item_id );	}	close;}

  7. Requires a src edit.

    Open CLIF.C & find:

    /// Presents list of items, that can be sold to an NPC shop (ZC_PC_SELL_ITEMLIST)./// 00c7 <packet len>.W { <index>.W <price>.L <overcharge price>.L }*void clif_selllist(struct map_session_data *sd){	int fd,i,c=0,val;	nullpo_retv(sd);	fd=sd->fd;	WFIFOHEAD(fd, MAX_INVENTORY * 10 + 4);	WFIFOW(fd,0)=0xc7;	for( i = 0; i < MAX_INVENTORY; i++ )	{		if( sd->status.inventory[i].nameid > 0 && sd->inventory_data[i] )		{			if( !itemdb_cansell(&sd->status.inventory[i], pc_get_group_level(sd)) )				continue;			if( sd->status.inventory[i].expire_time )				continue; // Cannot Sell Rental Items 			if( sd->status.inventory[i].bound && !pc_can_give_bound_items(sd))				continue; // Don't allow sale of bound items			val=sd->inventory_data[i]->value_sell;			if( val < 0 )				continue;			WFIFOW(fd,4+c*10)=i+2;			WFIFOL(fd,6+c*10)=val;			WFIFOL(fd,10+c*10)=pc->modifysellvalue(sd,val);			c++;		}	}	WFIFOW(fd,2)=c*10+4;	WFIFOSET(fd,WFIFOW(fd,2));}

     

    Comment out these lines: ( e.g: // This is commented.

    			if( sd->status.inventory[i].bound && !pc_can_give_bound_items(sd))				continue; // Don't allow sale of bound items

     

    Should look like this:

    /// Presents list of items, that can be sold to an NPC shop (ZC_PC_SELL_ITEMLIST)./// 00c7 <packet len>.W { <index>.W <price>.L <overcharge price>.L }*void clif_selllist(struct map_session_data *sd){	int fd,i,c=0,val;	nullpo_retv(sd);	fd=sd->fd;	WFIFOHEAD(fd, MAX_INVENTORY * 10 + 4);	WFIFOW(fd,0)=0xc7;	for( i = 0; i < MAX_INVENTORY; i++ )	{		if( sd->status.inventory[i].nameid > 0 && sd->inventory_data[i] )		{			if( !itemdb_cansell(&sd->status.inventory[i], pc_get_group_level(sd)) )				continue;			if( sd->status.inventory[i].expire_time )				continue; // Cannot Sell Rental Items //			if( sd->status.inventory[i].bound && !pc_can_give_bound_items(sd))//				continue; // Don't allow sale of bound items			val=sd->inventory_data[i]->value_sell;			if( val < 0 )				continue;			WFIFOW(fd,4+c*10)=i+2;			WFIFOL(fd,6+c*10)=val;			WFIFOL(fd,10+c*10)=pc->modifysellvalue(sd,val);			c++;		}	}	WFIFOW(fd,2)=c*10+4;	WFIFOSET(fd,WFIFOW(fd,2));}

     

    Save and Recompile. All done. you can now sell bound items.


  8. You mean this? in battle/skill.conf

    // Grandcross Settings (Don't mess with these)// If set to no, hit interval is increased based on the amount of mobs standing on the same cell// (means that when there's stacked mobs in the same cell, they won't receive all hits)gx_allhit: no// Grandcross display type (Default 1)// 0: Yellow character// 1: White charactergx_disptype: 1

    ??


  9. Hmm, since paladin's were designed around being a supportive/tank class. I'd suggest their heal amount being determined by amount of player's in party as an additional argument.

     

    Regular Heal formula +  100 * amount of party members = Crusader heal amount.

     

    By default that'd be an increased 1200 heal since I believe 12 party members are by default so meh.


  10. That is part of the client as far as I know. If you want to disable it ( not make it show up ). Then you can do a very tedious work around, but I wouldn't recommend it as it's VERY annoying to do.

     

    What you'd have to do is basically make custom jobs in a sense. You'd be making these jobs with the 3rd class sprites, 3rd class skills + 2nd class skills and then making the client think they are 2nd classes.

     

    This way you'd still get to keep the benefit of going: Rebirth Novice -> High Class -> Trans Class -> 3rd Class. Since it'd have the skills of the trans, but only appear in the 2nd class window.

     

    Next you'd need to edit the statuspoint db file so that these classes get the appropriate status points for their respective class.

     

    Next you'd need to create a custom job changer. This job changer would do the following:

    1. Copy player's Trans skills and skill level.

    2. Change Job into custom 3rd classes we created above.

    3. Give those skills to the player permanently.

     

    Then you'd need to create a custom stat/skillpoint reseter ( if your using one ). This reseter would do the following:

    1. Reset Status points like normal.

    2. Reset skill points AND THEN subtract the skill points needed to get all the trans skills to the level's they were at.

     

    Then lastly, you'd need to either make the script for giving them skills on an infiniteloop OR edit several src files to NOT do a skill-reset upon status point update, change map, unequip/re-equip, etc....

     

    So yeah, like I said, not worth it. Just stick with the 3rd class window =P


  11. Here, this is done using bindatcmd. ( @sameip )

    It displays in this format:

    ---------------- List of Same IP User -------------------------------------- Prontera ----------------------IP Address: 127.0.0.1Account ID: 2000001, 2000002, 2000003Character Names: Name1, Name2, Name3IP Address: 192.168.1.1Account ID: 2000004, 2000011Character Names: Name4, Name11etc...

    It won't show duplicate account ids. Meaning, it will only show 1 IP address and then all the account ids using that IP address and then the names of those characters currently online. So if Player 1 has same IP address as Player2. And Player3 has same IP address as Player 1. It will only show 1 entry to make it neater.

    -	script	at_sameip	-1,{OnInit:bindatcmd "sameip",strnpcinfo(3)+"::OnAtSameIP";//,99,99,0; // 0 = No log, 1 = Log usageend;OnAtSameIP:.@size = query_sql("SELECT `account_id` FROM `char` WHERE `online` = '1' AND `last_map` = '"+ strcharinfo(3) +"'",.@acct_id);.@size2 = query_sql("SELECT `account_id`, `last_ip` FROM `login` WHERE `account_id` != '1'", .@aid, .@ip$);while( .@a < .@size ) {	for( .@i = 0; .@i < getarraysize(.@aid); .@i++ ) {		if( .@aid[.@i] == .@acct_id[.@a] ) {			.@tempaid$[.@a] = ""+ .@aid[.@i] +"";			.@tempaip$[.@a] = .@ip$[.@i];			}		}	.@a++;}.@size3 = getarraysize(.@tempaid$);while( .@c != .@size3 ) {	for( .@i = 0; .@i < getarraysize( .@usedaids$ ); .@i++ ) {		if( .@usedaids$[.@i] == .@tempaid$[.@c] ) { //Account ID already in array.		.@used = 1;		}	}	if( !.@used ) {		.@usedaids$[( getarraysize( .@usedaids$ ) + 1 )] = .@tempaid$[.@c];		.@duplicateaid$[.@c] = "Account IDs: "+ .@tempaid$[.@c] +"";		.@duplicaterid2name$[.@c] = "Character Names: "+ rid2name( atoi( .@tempaid$[.@c] ) ) +"";		.@duplicateaip$[.@c] = "IP Address: "+ .@tempaip$[.@c] +"";				for( .@i = 0; .@i < getarraysize( .@tempaid$ ); .@i++ ) {			if( .@tempaip$[.@c] == .@tempaip$[.@i] && .@tempaid$[.@c] != .@tempaid$[.@i] ) {				.@duplicateaid$[.@c] = .@duplicateaid$[.@c] +", "+ .@tempaid$[.@i] +"";				.@duplicaterid2name$[.@c] = .@duplicaterid2name$[.@c] +", "+ rid2name( atoi( .@tempaid$[.@i] ) ) +"";				.@usedaids$[( getarraysize( .@usedaids$ ) + 1 )] = .@tempaid$[.@i];				}			}		}	.@used = 0;	.@c++;	}dispbottom "---------------- List of Same IP User ----------------";dispbottom "---------------------- "+ setchar( strcharinfo(3), strtoupper(charat(strcharinfo(3),0)), 0 ) +" ----------------------";for( .@i = 0; .@i < getarraysize(.@duplicateaid$); .@i++ ) {	if( .@duplicateaid$[.@i] != "" ) {		dispbottom " ";		dispbottom .@duplicateaip$[.@i];		dispbottom .@duplicateaid$[.@i];		dispbottom .@duplicaterid2name$[.@i];		}	}end;}

     

    Enjoy D:


  12. Okay, well this is all you need to do:

    1. Open up script.c & Find: BUILDIN(mes

    2. Above that add in:

    // PickUp Item Effect// pickupitem();BUILDIN(pickupitem) {        struct block_list tbl;        TBL_PC* sd = script->rid2sd(st);        if( sd == NULL )            return true;        tbl.id = 0;        clif->takeitem(&sd->bl,&tbl);        return true;}

    3. Find: BUILDIN_DEF(mes

    4. Above that add:

    BUILDIN_DEF(pickupitem,""),

    Save & Recompile.

     

    Then make a script that tells the player to use it. *Note - Player must be attached to the script for it to work (talking to it or otherwise).*

     

    Example NPC:

    prontera,150,170,4    script    npc_name    123,{mes "I command you to pick up an item !!";pickupitem;close;}

    In that example as soon as they click the NPC, a MES window will pop up and they will bend over to pick up an item (wont get an item though just the animation).


  13. Okay, so adding items via itemdb.conf is really easy now, since you essentially only need to input 3 fields to get an item to exist in game. However, on the SQL side for those of us who use it, you still need to add all the information or it'll be buggy and could cause issues. Since default is either NULL or 0.

     

    #1. I suggest we update this to take on the same parameters as itemdb.conf when not filling them in. It only makes sense in my opinion. (Yes I know I can easily do this myself by editing the main.sql file. But this is a suggestion so that we won't have to in the future).

     

    #2. of the suggestion is about the inherit feature. While looking in itemdb.c you'll notice that it does some PRE-checks before adding the data to the *db. It reads the sql entries -> checks to see if it's valid -> changes information so that it is valid in the instance where it is incorrect.

    /** * Processes one itemdb entry from the sql backend, loading and inserting it * into the item database. * * @param *handle MySQL connection handle. It is expected to have data *                available (i.e. already queried) and it won't be freed (it *                is care of the caller to do so) * @param n       Ordinal number of the entry, to be displayed in case of *                validation errors. * @param *source Source of the entry (table name), to be displayed in case of *                validation errors. * @return Nameid of the validated entry, or 0 in case of failure. */int itemdb_readdb_sql_sub(Sql *handle, int n, const char *source) {	struct item_data id = { 0 };	char *data = NULL;	/*	 * `id`              smallint(5)   unsigned NOT NULL DEFAULT '0'	 * `name_english`    varchar(50)            NOT NULL DEFAULT ''	 * `name_japanese`   varchar(50)            NOT NULL DEFAULT ''	 * `type`            tinyint(2)    unsigned NOT NULL DEFAULT '0'	 * `price_buy`       mediumint(10)                   DEFAULT NULL	 * `price_sell`      mediumint(10)                   DEFAULT NULL	 * `weight`          smallint(5)   unsigned          DEFAULT NULL	 * `atk`             smallint(5)   unsigned          DEFAULT NULL	 * `matk`            smallint(5)   unsigned          DEFAULT NULL	 * `defence`         smallint(5)   unsigned          DEFAULT NULL	 * `range`           tinyint(2)    unsigned          DEFAULT NULL	 * `slots`           tinyint(2)    unsigned          DEFAULT NULL	 * `equip_jobs`      int(12)       unsigned          DEFAULT NULL	 * `equip_upper`     tinyint(8)    unsigned          DEFAULT NULL	 * `equip_genders`   tinyint(2)    unsigned          DEFAULT NULL	 * `equip_locations` smallint(4)   unsigned          DEFAULT NULL	 * `weapon_level`    tinyint(2)    unsigned          DEFAULT NULL	 * `equip_level_min` smallint(5)   unsigned          DEFAULT NULL	 * `equip_level_max` smallint(5)   unsigned          DEFAULT NULL	 * `refineable`      tinyint(1)    unsigned          DEFAULT NULL	 * `view`            smallint(3)   unsigned          DEFAULT NULL	 * `bindonequip`     tinyint(1)    unsigned          DEFAULT NULL	 * `buyingstore`     tinyint(1)             NOT NULL DEFAULT NULL	 * `delay`           mediumint(9)           NOT NULL DEFAULT NULL	 * `trade_flag`      smallint(4)            NOT NULL DEFAULT NULL	 * `trade_group`     smallint(4)            NOT NULL DEFAULT NULL	 * `nouse_flag`      smallint(4)            NOT NULL DEFAULT NULL	 * `nouse_group`     smallint(4)            NOT NULL DEFAULT NULL	 * `stack_amount`    mediumint(6)           NOT NULL DEFAULT NULL	 * `stack_flag`      smallint(2)            NOT NULL DEFAULT NULL	 * `sprite`          mediumint(6)           NOT NULL DEFAULT NULL	 * `script`          text	 * `equip_script`    text	 * `unequip_script`  text	 */	SQL->GetData(handle,  0, &data, NULL); id.nameid = (uint16)atoi(data);	SQL->GetData(handle,  1, &data, NULL); safestrncpy(id.name, data, sizeof(id.name));	SQL->GetData(handle,  2, &data, NULL); safestrncpy(id.jname, data, sizeof(id.jname));	SQL->GetData(handle,  3, &data, NULL); id.type = atoi(data);	SQL->GetData(handle,  4, &data, NULL); id.value_buy = data ? atoi(data) : -1; // Using invalid price -1 when missing, it'll be validated later	SQL->GetData(handle,  5, &data, NULL); id.value_sell = data ? atoi(data) : -1;	SQL->GetData(handle,  6, &data, NULL); id.weight = data ? atoi(data) : 0;	SQL->GetData(handle,  7, &data, NULL); id.atk = data ? atoi(data) : 0;	SQL->GetData(handle,  8, &data, NULL); id.matk = data ? atoi(data) : 0;	SQL->GetData(handle,  9, &data, NULL); id.def = data ? atoi(data) : 0;	SQL->GetData(handle, 10, &data, NULL); id.range = data ? atoi(data) : 0;	SQL->GetData(handle, 11, &data, NULL); id.slot = data ? atoi(data) : 0;	SQL->GetData(handle, 12, &data, NULL); itemdb->jobid2mapid(id.class_base, data ? (unsigned int)strtoul(data,NULL,0) : UINT_MAX);	SQL->GetData(handle, 13, &data, NULL); id.class_upper = data ? (unsigned int)atoi(data) : ITEMUPPER_ALL;	SQL->GetData(handle, 14, &data, NULL); id.sex = data ? atoi(data) : 2;	SQL->GetData(handle, 15, &data, NULL); id.equip = data ? atoi(data) : 0;	SQL->GetData(handle, 16, &data, NULL); id.wlv = data ? atoi(data) : 0;	SQL->GetData(handle, 17, &data, NULL); id.elv = data ? atoi(data) : 0;	SQL->GetData(handle, 18, &data, NULL); id.elvmax = data ? atoi(data) : 0;	SQL->GetData(handle, 19, &data, NULL); id.flag.no_refine = data && atoi(data) ? 0 : 1;	SQL->GetData(handle, 20, &data, NULL); id.look = data ? atoi(data) : 0;	SQL->GetData(handle, 21, &data, NULL); id.flag.bindonequip = data && atoi(data) ? 1 : 0;	SQL->GetData(handle, 22, &data, NULL); id.flag.buyingstore = data && atoi(data) ? 1 : 0;	SQL->GetData(handle, 23, &data, NULL); id.delay = data ? atoi(data) : 0;	SQL->GetData(handle, 24, &data, NULL); id.flag.trade_restriction = data ? atoi(data) : ITR_NONE;	SQL->GetData(handle, 25, &data, NULL); id.gm_lv_trade_override = data ? atoi(data) : 0;	SQL->GetData(handle, 26, &data, NULL); id.item_usage.flag = data ? atoi(data) : INR_NONE;	SQL->GetData(handle, 27, &data, NULL); id.item_usage.override = data ? atoi(data) : 0;	SQL->GetData(handle, 28, &data, NULL); id.stack.amount = data ? atoi(data) : 0;	SQL->GetData(handle, 29, &data, NULL);	if (data) {		int stack_flag = atoi(data);		id.stack.inventory = (stack_flag&1)!=0;		id.stack.cart = (stack_flag&2)!=0;		id.stack.storage = (stack_flag&4)!=0;		id.stack.guildstorage = (stack_flag&8)!=0;	}	SQL->GetData(handle, 30, &data, NULL);	if (data) {		id.view_id = atoi(data);		if (id.view_id)			id.flag.available = 1;	}	SQL->GetData(handle, 31, &data, NULL); id.script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;	SQL->GetData(handle, 32, &data, NULL); id.equip_script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;	SQL->GetData(handle, 33, &data, NULL); id.unequip_script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;	return itemdb->validate_entry(&id, n, source);}

    Knowing this we could add an INHERIT column in our sql itemdb entries to allow for the option of making an item inherit that of another item. Which leads to my third suggestion.

     

     

    #3. While inherit is useful in some cases, it's fairly if not vastly limited, since it's a boolean option. Meaning either YES inherit or NO don't inherit. This should be changed to an item_id entry. So that we can specify WHAT item it inherits its information from. That way were not limited to re-making an existing item just to change or add a feature.

     

    Example of current inherit:

    {    Id: 501    AegisName: "Red_Potion"    Name: "Red Potion"    Buy: 1200    Weight: 150    Script: <" itemheal rand(325,405),0; ">    Inherit: true},

    This will make a red potion inherit all of it's information from itemdb.conf but make it act like a White Potion in terms of buy/sell price, weight and heal power.

     

    Example of suggested inherit:

    {	Id: 501	AegisName: "Red_Potion"	Name: "Red Potion"	Inherit: 504},

    This would effectively do the same thing as above should we decide to add it. BUT more importantly, i wouldn't be limited to using an existing item ID.

    {	Id: 32000	AegisName: "New_Potion"	Name: "New Potion"	Inherit: 504},

    Thusly allowing us to add new items in and inherit information without the need to overwrite an item already in existence. ( I'm repeating myself xD ).

     

    Naturally this could be applied to the SQL side as well and rightfully should if there aren't any underlying compatibility issues.

     

    For those who don't know what I'm talking about in relation to the src here is the section in question:

    	if( (t = libconfig->setting_get_member(it, "Inherit")) && (inherit = libconfig->setting_get_bool(t)) ) {		if( !itemdb->exists(id.nameid) ) {			ShowWarning("itemdb_readdb_libconfig_sub: Trying to inherit nonexistent item %d, default values will be used instead.n", id.nameid);			inherit = false;		} else {			// Use old entry as default			struct item_data *old_entry = itemdb->load(id.nameid);			memcpy(&id, old_entry, sizeof(struct item_data));		}	}

    It would be a simple change to: *Note - would also need to change   bool inherit = false   to int inherit = false

       	 if( (inherit = libconfig->setting_lookup_int(it, "Inherit", &i32 )) ) {            if( !itemdb->exists(id.nameid) && inherit == 1 || !itemdb->exists(inherit) && inherit != 1 ) {            ShowWarning("itemdb_readdb_libconfig_sub: Trying to inherit nonexistent item %d, default values will be used instead.n", inherit);            inherit = false;        } else {            // Use old entry as default            if( inherit = 1 ) {                struct item_data *old_entry = itemdb->load(id.nameid);                memcpy(&id, old_entry, sizeof(struct item_data));            } else {                struct item_data *old_entry = itemdb->load(inherit);                memcpy(&id, old_entry, sizeof(struct item_data));            }        }    }

     

    From my limited knowledge on the src code ( and coding in general ), this would let it lookup the item specified rather than a boolean option and then use that information as the default, else go to the default paramters given in itemdb.conf


  14. In CLIF.C find:

    /// Request to add an item to the action (CZ_AUCTION_ADD_ITEM)./// 024c <index>.W <count>.Lvoid clif_parse_Auction_setitem(int fd, struct map_session_data *sd){	int idx = RFIFOW(fd,2) - 2;	int amount = RFIFOL(fd,4); // Always 1	struct item_data *item;	if( !battle_config.feature_auction )		return;	if( sd->auction.amount > 0 )		sd->auction.amount = 0;	if( idx < 0 || idx >= MAX_INVENTORY ) {		ShowWarning("Character %s trying to set invalid item index in auctions.n", sd->status.name);		return;	}	if( amount != 1 || amount > sd->status.inventory[idx].amount ) { // By client, amount is always set to 1. Maybe this is a future implementation.		ShowWarning("Character %s trying to set invalid amount in auctions.n", sd->status.name);		return;	}	if( (item = itemdb->exists(sd->status.inventory[idx].nameid)) != NULL && !(item->type == IT_ARMOR || item->type == IT_PETARMOR || item->type == IT_WEAPON || item->type == IT_CARD || item->type == IT_ETC) )	{ // Consumable or pets are not allowed		clif->auction_setitem(sd->fd, idx, true);		return;	}	if( !pc_can_give_items(sd) || sd->status.inventory[idx].expire_time ||			!sd->status.inventory[idx].identify ||				!itemdb_canauction(&sd->status.inventory[idx],pc_get_group_level(sd)) || // Quest Item or something else					(sd->status.inventory[idx].bound && !pc_can_give_bound_items(sd)) ) { 		clif->auction_setitem(sd->fd, idx, true);		return;	}	sd->auction.index = idx;	sd->auction.amount = amount;	clif->auction_setitem(fd, idx + 2, false);}

    Change this part:

    	if( (item = itemdb->exists(sd->status.inventory[idx].nameid)) != NULL && !(item->type == IT_ARMOR || item->type == IT_PETARMOR || item->type == IT_WEAPON || item->type == IT_CARD || item->type == IT_ETC) )	{ // Consumable or pets are not allowed		clif->auction_setitem(sd->fd, idx, true);		return;	}

    INTO

    	clif->auction_setitem(sd->fd, idx, true);	return;

    This will allow you to post ALL type of items in the auction. Or SHOULD allow you to. Don't know how the client will act upon doing this, but I do know that I am able to put RedPotions in my auction house so yeah. ( I did not make these changes, I was already able to do it, don't know why D: ).

     

    As always make a back-up copy of your src files before making these changes. And don't forget to recompile after making the changes.

     

    *Note - This clif packet currently has amount set to 1 by default. Not sure if this can be changed as I currently can't test this. But keep in mind that placing a large stack of consumables may be reduced to just 1 while listed in the auction. This could cause a loss of items or it might just take 1 away. Would be a pain to have to list 100 Ygg berries 1by1.


  15. Edit: Okay, I see your problem. I'm sorry, but ATM i'm not able to properly test these things.... You'll just have to continue to use the zeny mode until I can get a working client system setup at my computer at work. Or until I fix my personal comp (work station).

     

    Sorry :/


  16. Oh sorry lol. I put the parenthesis in the wrong spot... I always do that when using variable? I don't know why, it just looks better that way. I updated my previous post. Should work, but again, untested. Work station still broken T.T


  17. This is untested as my work station is down atm. But this should do what you want. Just follow the annotations under OnInit label to make it work with items instead of zeny. When my work station is up and running i'll post an update to allow for a more hybrid version and written in better code ( right now it's all smushed together, and is unnessecarily complicated ).

    /* =============================================================/* Slot Machine - Triple Slot Machine/* =============================================================/* Version: v0.2a/* v0.1 - Original Script Created./* v0.2 - Added Option for Triple Slot Machine with animations./* v0.2a - Added option for item price instead of zeny.Untested./* =============================================================/* Description/* =============================================================/* This script will allow users to spend zeny for a chance to/* win a prize from the slot machine. Currently there are 2/* versions. First is a Single Slot Machine, where only 1 slot/* is rolled. Second is the Triple Slot machine, where 3 slots/* are rolled. For either version, SUCCESS must be the only/* thing displayed in order to win./* =============================================================/* Created By: GmOcean/* ===========================================================*/prontera,152,176,4	script	SlotMachine	563,{switch( .mode ){	case 0: // Single Slot machine mode.		mes "Do you want to play a game?","It costs: "+ .price[1] +" "+ (.price[2]?"zeny":""+getitemname(.price[0])+"") +" to play.";		if( select("YES:NO") == 2 || Zeny < .price[0] && !.price[2] || ( countitem( .price[0] ) < .price[1] ) && .price[2] ){ close; }		while( @menu == 1 ){		if( !.price[2] ){ Zeny -= .price[0]; } else { delitem .price[0],.price[1]; }		.@a = rand(1,100);		if( .@a < atoi(.1animate$[0]) ){ .@a = 1; } else { .@a = 2; }		.@b = 1;		while( .@b < atoi(.1animate$[.@a]) ) {			cutin .1animate$[3] + .@b,4; sleep2 ( ( atoi(.1animate$[4]) * 1000 ) / atoi(.1animate$[.@a]) ); .@b++;			}		if( .@a == 1 ){ 			cutin .1animate$[3] + atoi(.1animate$[.@a]),4;			dispbottom "Failed";			} 		else {			cutin .1animate$[3] + atoi(.1animate$[.@a]),4;			getitem .1prize[0], .1prize[1];			}		if( select("Another Round:I'm done") == 2 || Zeny < .price[0] && !.price[2] || ( countitem( .price[0] ) < .price[1] ) && .price[2] ){ cutin "",255; close; }		}	end;	case 1: // Triple Slot machine mode.		mes "Do you want to play a game?","It costs: "+ .price[1] +" "+ (.price[2]?"zeny":""+getitemname(.price[0])+"") +" to play.";		if( select("YES:NO") == 2 || Zeny < .price[0] && !.price[2] || countitem( .price[0] ) < .price[1] && .price[2] ){ close; }		while( @menu == 1 ){			if( !.price[2] ){ Zeny -= .price[0]; } else { delitem .price[0],.price[1]; }			// Slot 1 = 100% Chance for success. (Because I didn't make a fail animation for it.			.@2 = rand(1,100); //Rolls dice for Slot 2			.@3 = rand(1,100); //Rolls dice for Slot 3				if( .@2 <= atoi(.3animate$[0]) && .@3 <= atoi(.3animate$[1]) ){ .@a = 8; }				else if( .@2 <= atoi(.3animate$[0]) && .@3 > atoi(.3animate$[1]) ){ .@a = 6; }				else if( .@2 > atoi(.3animate$[0]) && .@3 <= atoi(.3animate$[1]) ){ .@a = 4; }				else { .@a = 2; }			.@b = 1;			while( .@b < atoi(.3animate$[.@a+1]) ) {				cutin .3animate$[.@a] + .@b,4; sleep2 ( ( atoi(.3animate$[10]) * 1000 ) / atoi(.3animate$[.@a+1]) ); .@b++;				}			cutin .3animate$[.@a] + atoi(.3animate$[.@a+1]),4;				if( .@a == 2 ){ getitem .3prize[0], .3prize[1]; }				else { dispbottom "Failed"; }			if( select("Another Round:I'm done") == 2 || Zeny < .price[1] ){ cutin "",255; close; }			}		end;	}OnInit://[ 0 = Single Slot Machine Mode ]_[ 1 = Triple Slot Machine Mode ].mode = 1;//[0] = Fail Rate//[1] = Fail (Do not change)//[2] = Success (Do not change)//[3] = File Name (Do not change)//[4] = Animation Time (Do not change, for best results )setarray .1animate$[0],"30","29","33","slot_","3";//[0] = Fail Rate "Slot 2"//[1] = Fail Rate "Slot 3"//[2] = SSS (Do not change)//[3] = SSS_Count (Do not change)//[4] = SSF (Do not change)//[5] = SSF_Count (Do not change)//[6] = SFS (Do not change)//[7] = SFS_Count (Do not change)//[8] = SFF (Do not change)//[9] = SFF_Count (Do not change)//[10] = Animation Time (Do not change, for best results )setarray .3animate$[0],"30","30","SSS_","41","SSF_","37","SFS_","41","SFF_","45","3";setarray .1prize[0],501,10;setarray .3prize[0],501,30;// [ 0 = SSM Zeny / Item Req ]  |  [ 1 = TSM Zeny / Item Amt ]  |  [  2 = Enable/Disable Item Requirements ( 0 = Disable, 1 = Enable ).// e.g of zeny mode:  setarray .price[0], 100, 300, 0;  <--- SSM costs 100z, TSM costs 300z to play.// e.g of item mode:  setarray .price[0], 501, 10, 1; <---- SSM & TSM costs 10 RedPotions to play.setarray .price[0],100,300,0;end;}
×
×
  • Create New...

Important Information

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