Jump to content
Sign in to follow this  
keitenai

Costume Converter

Recommended Posts

I saw some people asking to make the costume converter compatible with 3ceam.
So i look upon it and just so happen to caught my interest even though i'm not fond
of costume system.
 
so without further ado!
Here's a patch i made for you guys.
 
EDIT: 
 
   V2 Fixed missing script.c dependencies

   V3 Removed the relocation of ammo as informed by 15peaces that rytech moved it to the last for ammo-fix.

        sorry, i was not aware about it.

 
3CEAM_COSTUME_CONVERTER_V3.patch
 
 

Index: conf/battle/battle.conf
===================================================================
--- conf/battle/battle.conf	(revision 801)
+++ conf/battle/battle.conf	(working copy)
@@ -171,3 +171,9 @@
 // range. For example, Sonic Blow requires a 2 cell distance before autocasting is allowed.
 // This setting also affects autospellwhenhit.
 autospell_check_range: no
+
+// ****************************************
+// Reserved Costume ID's
+// ****************************************
+// Reserved Char ID for costume converted items.
+reserved_costume_id: 999998
\ No newline at end of file
Index: npc/custom/costume.txt
===================================================================
--- npc/custom/costume.txt	(nonexistent)
+++ npc/custom/costume.txt	(working copy)
@@ -0,0 +1,146 @@
+//===== Hercules Script ======================================
+//= Headgear to Costume converter >> Costume to Headgear converter
+//===== By: ==================================================
+//= Rebel, Zephyrus [rAthena]
+//= Mhalicot [Hercules]
+//===== Current Version: =====================================
+//= 1.1
+//===== Compatible With: =====================================
+//= Hercules
+//===== Description: =========================================
+//= Allows a user to convert the equipped headgear 
+//	(on Top, Mid or Low) into a costume item. 
+//	It will remove any card and refine of the Item.
+//= Allows a user to restore the equipped costume headgear 
+//	(on Top, Mid or Low) into its original form. 
+//	It will not return any card or refine of the item.
+//===== Additional Comments: =================================
+//= 1.0 Initial script [All of this script are credit to
+//	Rebel, Zephyrus of [rAthena] and revised by [Mhalicot]
+//	to make it compatible in Hercules.]
+//= 1.1 Denied if Headgear is rental, has refine,
+//	or has card[Mhalicot]
+//	Note: You must apply the patch in order to use this script
+//============================================================
+-	script	Costume Clown	-1,{
+	mes "[Clown]";
+	mes "Here you can convert your headgears into a Costume Headgear or restore to its Original form.";
+	switch(select("I want to convert.:I want to restore.:No thanks.")) {
+	case 1:
+			next;
+			mes "[Clown]";
+			mes "Please, select what to convert.";
+			mes "Remember, cards and refine will be removed.";
+			next;
+				setarray .@Position$[1],"Top","Mid","Low";
+				setarray .@Position[1],     1,    9,   10;
+				set .@Menu$,"";
+			for( set .@i, 1; .@i < 5; set .@i, .@i + 1 )
+			{
+				if( getequipisequiped(.@Position[.@i]) )
+				set .@Menu$, .@Menu$ + .@Position$[.@i] + "-" + "[" + getequipname(.@Position[.@i]) + "]";
+				set .@Menu$, .@Menu$ + ":";
+			}
+			set .@Part, .@Position[ select(.@Menu$) ];
+			set .@id, getequipid(.@Part);
+			set .@ref, getequiprefinerycnt(.@Part);
+			if( !getequipisequiped(.@Part) )
+			{
+				mes "[Clown]";
+				mes "Your not wearing anything there...";
+				close;
+			}
+			mes "[Clown]";
+			mes "You want to Costume your " + getitemname(getequipid(.@Part)) + "?";
+			next;
+			if( select("Yes, proceed:No, I am sorry.") == 2 )
+			{
+				mes "[Clown]";
+				mes "Need some time to think about it, huh?";
+				mes "Alright, I can understand.";
+				close;
+			}
+			for(set .@i,0; .@i<4; set .@i,.@i+1)
+				set .@slot[.@i], getequipcardid(.@Part,.@i);
+			if (.@slot[0]>4000 && .@slot[0]<5000) { // If it has card don't convert
+				mes "[Clown]";
+				mes "A card? Here?!";
+				mes "As I said before, I don't convert headgear with cards.";
+				emotion e_hmm;
+				close;
+			}
+			getinventorylist;
+			for(set .@i,0; .@i<@inventorylist_count; set .@i,.@i+1)
+				if (@inventorylist_expire[.@i] != 0 && @inventorylist_equip[.@i] != 0) { // If rental don't convert
+				mes "[Clown]";
+				mes "Sorry, I don't convert a rental headgear!";
+				emotion e_hmm;
+				close;
+				}
+				if (.@ref > 0) { // If refine don't convert
+				mes "[Clown]";
+				mes "Sorry please keep in mind.";
+				mes "I don't convert headgear with refine.";
+				emotion e_hmm;
+				close;
+				}
+			if (!countitem(.@id)) { 
+				mes "[Clown]";
+				mes "Where is "+getitemname(@id)+"...?";
+				npctalk "You're a snoozy cheater!";
+				logmes "CHEATER: Tried to sign an item not having it: "+getitemname(@id);
+				emotion e_wah;
+				close;
+			}
+			costume .@Part; // Convert the Headgear
+			mes "[Clown]";
+			mes "Done, enjoy your costume headgear.";
+			close;
+	case 2:
+			next;
+			mes "Please, select what to restore.";
+			mes "Remember, I will only restore it back without refine and cards.";
+			next;
+				setarray .@Position$[1],"Top","Mid","Low";
+				setarray .@Position[1],     13,    12,   11;
+				set .@Menu$,"";
+			for( set .@i, 1; .@i < 5; set .@i, .@i + 1 )
+			{
+				if( getequipisequiped(.@Position[.@i]) )
+				set .@Menu$, .@Menu$ + .@Position$[.@i] + "-" + "[" + getequipname(.@Position[.@i]) + "]";
+				set .@Menu$, .@Menu$ + ":";
+			}
+			set .@Part, .@Position[ select(.@Menu$) ];
+			if( !getequipisequiped(.@Part) )
+			{
+				mes "[Clown]";
+				mes "Your not wearing anything there...";
+				close;
+			}
+			mes "[Clown]";
+			mes "You want to restore your " + getitemname(getequipid(.@Part)) + "?";
+			next;
+			if( select("Yes, proceed:No, I am sorry.") == 2 )
+			{
+				mes "[Clown]";
+				mes "Need some time to think about it, huh?";
+				mes "Alright, I can understand.";
+				close;
+			}
+			a = getequipid(.@Part);			
+			delitem a,1;
+			getitem a,1;
+			
+			mes "[Clown]";
+			mes "Done, enjoy your restored headgear.";
+			close;
+	case 3:
+		mes "[Clown]";
+		mes "Very well. Return at once if you seek my services.";
+		close;
+	}
+}
+// --------------------------------------------------------------------------
+// Use duplicates to put your npc on different cities
+// --------------------------------------------------------------------------
+prontera,155,181,4	duplicate(Costume Clown)	Costume Clown#1	715
\ No newline at end of file
Index: npc/scripts_custom.conf
===================================================================
--- npc/scripts_custom.conf	(revision 801)
+++ npc/scripts_custom.conf	(working copy)
@@ -9,6 +9,7 @@
 //                     Your scripts go here!!
 // --------------------------------------------------------------
 // ----------------------- Basic  Scripts -----------------------
+npc: npc/custom/costume.txt
 // -- Card Remover
 //npc: npc/custom/card_remover.txt
 // -- Write your name on your equipment/weapon (mini-quest)
Index: src/map/atcommand.c
===================================================================
--- src/map/atcommand.c	(revision 801)
+++ src/map/atcommand.c	(working copy)
@@ -1679,7 +1679,7 @@
 ACMD_FUNC(item)
 {
 	char item_name[100];
-	int number = 0, item_id, flag;
+	int number = 0, item_id, flag = 0, costume = 0;
 	struct item item_tmp;
 	struct item_data *item_data;
 	int get_count, i;
@@ -1704,6 +1704,27 @@
 		clif_displaymessage(fd, msg_txt(19)); // Invalid item ID or name.
 		return -1;
 	}
+	
+	
+	if( !strcmpi(command+1,"costumeitem") )
+	{
+		if( !battle_config.reserved_costume_id )
+		{
+			clif_displaymessage(fd, "Costume convertion is disable. Set a value for reserved_cosutme_id on your battle.conf file.");
+			return -1;
+		}
+		if( !(item_data->equip&EQP_HEAD_LOW) &&
+			!(item_data->equip&EQP_HEAD_MID) &&
+			!(item_data->equip&EQP_HEAD_TOP) &&
+			!(item_data->equip&EQP_COSTUME_HEAD_LOW) &&
+			!(item_data->equip&EQP_COSTUME_HEAD_MID) &&
+			!(item_data->equip&EQP_COSTUME_HEAD_TOP) )
+		{
+			clif_displaymessage(fd, "You cannot costume this item. Costume only work for headgears.");
+			return -1;
+		}
+		costume = 1;
+	}
 
 	item_id = item_data->nameid;
 	get_count = number;
@@ -1718,6 +1739,13 @@
 			item_tmp.nameid = item_id;
 			item_tmp.identify = 1;
 
+			if( costume == 1 )
+			{ // Costume Item
+				item_tmp.card[0] = CARD0_CREATE;
+				item_tmp.card[2] = GetWord(battle_config.reserved_costume_id, 0);
+				item_tmp.card[3] = GetWord(battle_config.reserved_costume_id, 1);
+			}
+
 			if ((flag = pc_additem(sd, &item_tmp, get_count)))
 				clif_additem(sd, 0, 0, flag);
 		}
@@ -9218,6 +9246,7 @@
 	{ "kamic",             40,40,     atcommand_kami },
 	{ "heal",              40,60,     atcommand_heal },
 	{ "item",              60,60,     atcommand_item },
+	{ "costumeitem",       99,99,     atcommand_item },
 	{ "item2",             60,60,     atcommand_item2 },
 	{ "itemreset",         40,40,     atcommand_itemreset },
 	{ "blvl",              60,60,     atcommand_baselevelup },
Index: src/map/battle.c
===================================================================
--- src/map/battle.c	(revision 801)
+++ src/map/battle.c	(working copy)
@@ -5848,6 +5848,7 @@
 	{ "buyer_name",                         &battle_config.buyer_name,                      1,      0,      1,              },
 	{ "skill_wall_check",                   &battle_config.skill_wall_check,                1,      0,      1,              },
 	{ "cell_stack_limit",                   &battle_config.cell_stack_limit,                1,      1,      255,            },
+	{ "reserved_costume_id",                &battle_config.reserved_costume_id,             999998, 0,      INT_MAX,        },
 // eAthena additions
 	{ "item_logarithmic_drops",             &battle_config.logarithmic_drops,               0,      0,      1,              },
 	{ "item_drop_common_min",               &battle_config.item_drop_common_min,            1,      1,      10000,          },
Index: src/map/battle.h
===================================================================
--- src/map/battle.h	(revision 801)
+++ src/map/battle.h	(working copy)
@@ -540,6 +540,9 @@
 	int oktoberfest_ignorepalette;
 	int summer2_ignorepalette;
 
+	// Costume System
+	int reserved_costume_id;
+
 	// Homunculus Limits
 	int max_homunculus_hp;
 	int max_homunculus_sp;
Index: src/map/map.c
===================================================================
--- src/map/map.c	(revision 801)
+++ src/map/map.c	(working copy)
@@ -1677,6 +1677,12 @@
 
 	nullpo_retv(sd);
 
+	if( battle_config.reserved_costume_id && battle_config.reserved_costume_id == charid )
+	{
+		clif_solved_charname(sd->fd, charid, "Costume");
+		return;
+	}
+
 	tsd = map_charid2sd(charid);
 	if( tsd )
 	{
Index: src/map/pc.c
===================================================================
--- src/map/pc.c	(revision 801)
+++ src/map/pc.c	(working copy)
@@ -845,7 +845,7 @@
 
 int pc_equippoint(struct map_session_data *sd,int n)
 {
-	int ep = 0;
+	int ep = 0, char_id = 0;
 
 	nullpo_ret(sd);
 
@@ -863,6 +863,15 @@
 			(sd->class_&MAPID_UPPERMASK) == MAPID_KAGEROUOBORO))//Kagerou and Oboro can dual wield daggers. [Rytech]
 			return EQP_ARMS;
 	}
+	
+	if( battle_config.reserved_costume_id &&
+		sd->status.inventory[n].card[0] == CARD0_CREATE &&
+		(char_id = MakeDWord(sd->status.inventory[n].card[2],sd->status.inventory[n].card[3])) == battle_config.reserved_costume_id )
+	{ // Costume Item - Converted
+		if( ep&EQP_HEAD_TOP ) { ep &= ~EQP_HEAD_TOP; ep |= EQP_COSTUME_HEAD_TOP; }
+		if( ep&EQP_HEAD_LOW ) { ep &= ~EQP_HEAD_LOW; ep |= EQP_COSTUME_HEAD_LOW; }
+		if( ep&EQP_HEAD_MID ) { ep &= ~EQP_HEAD_MID; ep |= EQP_COSTUME_HEAD_MID; }
+	}
 	return ep;
 }
 
@@ -2082,8 +2091,8 @@
 				if( autobonus[i].bonus_script )
 				{
 					int j;
-					ARR_FIND( 0, EQI_MAX-1, j, sd->equip_index[j] >= 0 && sd->status.inventory[sd->equip_index[j]].equip == autobonus[i].pos );
-					if( j < EQI_MAX-1 )
+					ARR_FIND( 0, EQI_MAX_BONUS, j, sd->equip_index[j] >= 0 && sd->status.inventory[sd->equip_index[j]].equip == autobonus[i].pos );
+					if( j < EQI_MAX_BONUS )
 						script_run_autobonus(autobonus[i].bonus_script,sd->bl.id,sd->equip_index[j]);
 				}
 				continue;
@@ -2113,8 +2122,8 @@
 	if( autobonus->other_script )
 	{
 		int j;
-		ARR_FIND( 0, EQI_MAX-1, j, sd->equip_index[j] >= 0 && sd->status.inventory[sd->equip_index[j]].equip == autobonus->pos );
-		if( j < EQI_MAX-1 )
+		ARR_FIND( 0, EQI_MAX_BONUS, j, sd->equip_index[j] >= 0 && sd->status.inventory[sd->equip_index[j]].equip == autobonus->pos );
+		if( j < EQI_MAX_BONUS )
 			script_run_autobonus(autobonus->other_script,sd->bl.id,sd->equip_index[j]);
 	}
 
Index: src/map/pc.h
===================================================================
--- src/map/pc.h	(revision 801)
+++ src/map/pc.h	(working copy)
@@ -563,6 +563,8 @@
 	EQI_ARMOR,
 	EQI_HAND_L,
 	EQI_HAND_R,
+	EQI_MAX_BONUS = 10,
 	EQI_COSTUME_HEAD_LOW,
 	EQI_COSTUME_HEAD_MID,
 	EQI_COSTUME_HEAD_TOP,
@@ -574,7 +576,6 @@
 	EQI_SHADOW_SHOES,
 	EQI_SHADOW_ACC_R,
 	EQI_SHADOW_ACC_L,
 	EQI_AMMO,
 	EQI_MAX
 };
 
Index: src/map/script.c
===================================================================
--- src/map/script.c	(revision 801)
+++ src/map/script.c	(working copy)
@@ -208,6 +208,12 @@
 DBMap* script_get_label_db(){ return scriptlabel_db; }
 DBMap* script_get_userfunc_db(){ return userfunc_db; }
 
+// important buildin function references for usage in scripts
+static int buildin_set_ref = 0;
+static int buildin_callsub_ref = 0;
+static int buildin_callfunc_ref = 0;
+static int buildin_getelementofarray_ref = 0;
+
 // Caches compiled autoscript item code. 
 // Note: This is not cleared when reloading itemdb.
 static DBMap* autobonus_db=NULL; // char* script -> char* bytecode
@@ -903,7 +909,7 @@
 /// The argument list can have parenthesis or not.
 /// The number of arguments is checked.
 static
-const char* parse_callfunc(const char* p, int require_paren)
+const char* parse_callfunc(const char* p, int require_paren, int is_custom)
 {
 	const char* p2;
 	const char* arg=NULL;
@@ -917,17 +923,32 @@
 		arg = buildin_func[str_data[func].val].arg;
 	} else if( str_data[func].type == C_USERFUNC || str_data[func].type == C_USERFUNC_POS ){
 		// script defined function
-		int callsub = search_str("callsub");
-		add_scriptl(callsub);
+		add_scriptl(buildin_callsub_ref);
 		add_scriptc(C_ARG);
 		add_scriptl(func);
-		arg = buildin_func[str_data[callsub].val].arg;
+		arg = buildin_func[str_data[buildin_callsub_ref].val].arg;
 		if( *arg == 0 )
 			disp_error_message("parse_callfunc: callsub has no arguments, please review it's definition",p);
 		if( *arg != '*' )
 			++arg; // count func as argument
-	} else
-		disp_error_message("parse_line: expect command, missing function name or calling undeclared function",p);
+	} else {
+#ifdef SCRIPT_CALLFUNC_CHECK
+		const char* name = get_str(func);
+		if( !is_custom && strdb_get(userfunc_db, name) == NULL ) {
+#endif
+			disp_error_message("parse_line: expect command, missing function name or calling undeclared function",p);
+#ifdef SCRIPT_CALLFUNC_CHECK
+		} else {;
+			add_scriptl(buildin_callfunc_ref);
+			add_scriptc(C_ARG);
+			add_scriptc(C_STR);
+			while( *name ) add_scriptb(*name ++);
+			add_scriptb(0);
+			arg = buildin_func[str_data[buildin_callfunc_ref].val].arg;
+			if( *arg != '*' ) ++ arg;
+		}
+#endif
+	}
 
 	p = skip_word(p);
 	p = skip_space(p);
@@ -1002,6 +1023,157 @@
 	str_data[LABEL_NEXTLINE].label     = -1;
 }
 
+/// Parse a variable assignment using the direct equals operator
+/// @param p script position where the function should run from
+/// @return NULL if not a variable assignment, the new position otherwise
+const char* parse_variable(const char* p)
+{
+	int i, j, word;
+	c_op type = C_NOP;
+	const char *p2 = NULL;
+	const char *var = p;
+			
+	// skip the variable where applicable
+	p = skip_word(p);
+	p = skip_space(p);
+
+	if( p == NULL )
+	{// end of the line or invalid buffer
+		return NULL;
+	}
+
+	if( *p == '[' )
+	{// array variable so process the array as appropriate
+		for( p2 = p, i = 0, j = 1; p; ++ i )
+		{
+			if( *p ++ == ']' && --(j) == 0 ) break;
+			if( *p == '[' ) ++ j;
+		}
+
+		if( !(p = skip_space(p)) )
+		{// end of line or invalid characters remaining
+			disp_error_message("Missing right expression or closing bracket for variable.", p);
+		}
+	}
+
+	if( type == C_NOP &&
+	!( ( p[0] == '=' && p[1] != '=' && (type = C_EQ) ) // =
+	|| ( p[0] == '+' && p[1] == '=' && (type = C_ADD) ) // +=
+	|| ( p[0] == '-' && p[1] == '=' && (type = C_SUB) ) // -=
+	|| ( p[0] == '^' && p[1] == '=' && (type = C_XOR) ) // ^=
+	|| ( p[0] == '|' && p[1] == '=' && (type = C_OR ) ) // |=
+	|| ( p[0] == '&' && p[1] == '=' && (type = C_AND) ) // &=
+	|| ( p[0] == '*' && p[1] == '=' && (type = C_MUL) ) // *=
+	|| ( p[0] == '/' && p[1] == '=' && (type = C_DIV) ) // /=
+	|| ( p[0] == '%' && p[1] == '=' && (type = C_MOD) ) // %=
+	|| ( p[0] == '~' && p[1] == '=' && (type = C_NOT) ) // ~=
+	|| ( p[0] == '+' && p[1] == '+' && (type = C_ADD_PP) ) // ++
+	|| ( p[0] == '-' && p[1] == '-' && (type = C_SUB_PP) ) // --
+	|| ( p[0] == '<' && p[1] == '<' && p[2] == '=' && (type = C_L_SHIFT) ) // <<=
+	|| ( p[0] == '>' && p[1] == '>' && p[2] == '=' && (type = C_R_SHIFT) ) // >>=
+	) )
+	{// failed to find a matching operator combination so invalid
+		return NULL;
+	}
+
+	switch( type )
+	{
+		case C_EQ:
+		{// incremental modifier
+			p = skip_space( &p[1] );
+		}
+		break;
+
+		case C_L_SHIFT:
+		case C_R_SHIFT:
+		{// left or right shift modifier
+			p = skip_space( &p[3] );
+		}
+		break;
+
+		default:
+		{// normal incremental command
+			p = skip_space( &p[2] );
+		}
+	}
+
+	if( p == NULL )
+	{// end of line or invalid buffer
+		return NULL;
+	}
+	
+	// push the set function onto the stack
+	add_scriptl(buildin_set_ref);
+	add_scriptc(C_ARG);
+
+	// always append parenthesis to avoid errors
+	syntax.curly[syntax.curly_count].type = TYPE_ARGLIST;
+	syntax.curly[syntax.curly_count].count = 0;
+	syntax.curly[syntax.curly_count].flag = ARGLIST_PAREN;
+
+	// increment the total curly count for the position in the script
+	++ syntax.curly_count;
+	
+	// parse the variable currently being modified
+	word = add_word(var);
+
+	if( str_data[word].type == C_FUNC || str_data[word].type == C_USERFUNC || str_data[word].type == C_USERFUNC_POS )
+	{// cannot assign a variable which exists as a function or label
+		disp_error_message("Cannot modify a variable which has the same name as a function or label.", p);
+	}
+
+	if( p2 )
+	{// process the variable index
+		const char* p3 = NULL;
+
+		// push the getelementofarray method into the stack
+		add_scriptl(buildin_getelementofarray_ref);
+		add_scriptc(C_ARG);
+		add_scriptl(word);
+			
+		// process the sub-expression for this assignment
+		p3 = parse_subexpr(p2 + 1, 1);
+		p3 = skip_space(p3);
+
+		if( *p3 != ']' )
+		{// closing parenthesis is required for this script
+			disp_error_message("Missing closing ']' parenthesis for the variable assignment.", p3);
+		}
+
+		// push the closing function stack operator onto the stack
+		add_scriptc(C_FUNC);
+		p3 ++;
+	}
+	else
+	{// simply push the variable or value onto the stack
+		add_scriptl(word);
+	}
+	
+	if( type == C_ADD_PP || type == C_SUB_PP )
+	{// incremental operator for the method
+		add_scripti(1);
+		add_scriptc(type == C_ADD_PP ? C_ADD : C_SUB);
+	}
+	else
+	{// process the value as an expression
+		p = parse_subexpr(p, -1);
+
+		if( type != C_EQ )
+		{// push the type of modifier onto the stack
+			add_scriptc(type);
+		}
+	}
+
+	// decrement the curly count for the position within the script
+	-- syntax.curly_count;
+	
+	// close the script by appending the function operator
+	add_scriptc(C_FUNC);
+		
+	// push the buffer from the method
+	return p;
+}
+
 /*==========================================
  * €‚̉ðÍ
  *------------------------------------------*/
@@ -1059,6 +1231,8 @@
 		p++;	//'"'
 	} else {
 		int l;
+		const char* pv;
+
 		// label , register , function etc
 		if(skip_word(p)==p)
 			disp_error_message("parse_simpleexpr: unexpected character",p);
@@ -1065,12 +1239,25 @@
 
 		l=add_word(p);
 		if( str_data[l].type == C_FUNC || str_data[l].type == C_USERFUNC || str_data[l].type == C_USERFUNC_POS)
-			return parse_callfunc(p,1);
+			return parse_callfunc(p,1,0);
+#ifdef SCRIPT_CALLFUNC_CHECK
+		else {
+			const char* name = get_str(l);
+			if( strdb_get(userfunc_db,name) != NULL ) {
+				return parse_callfunc(p,1,1);
+			}
+		}
+#endif
 
+		if( (pv = parse_variable(p)) )
+		{// successfully processed a variable assignment
+			return pv;
+		}
+
 		p=skip_word(p);
 		if( *p == '[' ){
 			// array(name[i] => getelementofarray(name,i) )
-			add_scriptl(search_str("getelementofarray"));
+			add_scriptl(buildin_getelementofarray_ref);
 			add_scriptc(C_ARG);
 			add_scriptl(l);
 			
@@ -1196,7 +1383,15 @@
 	if(p2 != NULL)
 		return p2;
 
-	p = parse_callfunc(p,0);
+	// attempt to process a variable assignment
+	p2 = parse_variable(p);
+
+	if( p2 != NULL )
+	{// variable assignment processed so leave the method
+		return parse_syntax_close(p2 + 1);
+	}
+
+	p = parse_callfunc(p,0,0);
 	p = skip_space(p);
 
 	if(parse_syntax_for_flag) {
@@ -1919,6 +2114,11 @@
 			str_data[n].type = C_FUNC;
 			str_data[n].val = i;
 			str_data[n].func = buildin_func[i].func;
+
+			if( !strcmp(buildin_func[i].name, "set") ) buildin_set_ref = n; else
+			if( !strcmp(buildin_func[i].name, "callsub") ) buildin_callsub_ref = n; else
+			if( !strcmp(buildin_func[i].name, "callfunc") ) buildin_callfunc_ref = n; else
+			if( !strcmp(buildin_func[i].name, "getelementofarray") ) buildin_getelementofarray_ref = n;
 		}
 	}
 }
@@ -3442,7 +3642,7 @@
 			run_func(st);
 			if(st->state==GOTO){
 				st->state = RUN;
-				if( gotocount>0 && (--gotocount)<=0 ){
+				if( !st->freeloop && gotocount>0 && (--gotocount)<=0 ){
 					ShowError("run_script: infinity loop !\n");
 					script_reportsrc(st);
 					st->state=END;
@@ -3490,7 +3690,7 @@
 			st->state=END;
 			break;
 		}
-		if( cmdcount>0 && (--cmdcount)<=0 ){
+		if( !st->freeloop && cmdcount>0 && (--cmdcount)<=0 ){
 			ShowError("run_script: infinity loop !\n");
 			script_reportsrc(st);
 			st->state=END;
@@ -15073,6 +15273,134 @@
 	return 0;
 }
 
+/**
+ * Retrieves quantity of arguments provided to callfunc/callsub.
+ * getargcount() -> amount of arguments received in a function
+ **/
+BUILDIN_FUNC(getargcount) {
+	struct script_retinfo* ri;
+
+	if( st->stack->defsp < 1 || st->stack->stack_data[st->stack->defsp - 1].type != C_RETINFO ) {
+		ShowError("script:getargcount: used out of function or callsub label!\n");
+		st->state = END;
+		return 1;
+	}
+	ri = st->stack->stack_data[st->stack->defsp - 1].u.ri;
+
+	script_pushint(st, ri->nargs);
+
+	return 0;
+}
+
+/**
+ * is_function(<function name>) -> 1 if function exists, 0 otherwise
+ **/
+BUILDIN_FUNC(is_function) {
+	const char* str = script_getstr(st,2);
+
+	if( ((struct script_code*)strdb_get(userfunc_db, str)) != NULL )
+		script_pushint(st,1);
+	else
+		script_pushint(st,0);
+
+	return 0;
+}
+
+/**
+ * freeloop(<toggle>) -> toggles this script instance's looping-check ability
+ **/
+BUILDIN_FUNC(freeloop) {
+
+	if( script_getnum(st,2) )
+		st->freeloop = 1;
+	else
+		st->freeloop = 0;
+
+	script_pushint(st, st->freeloop);
+
+	return 0;
+}
+
+BUILDIN_FUNC(consumeitem)
+{
+	TBL_PC *sd;
+	struct script_data *data;
+	struct item_data *item_data;
+
+	sd = script_rid2sd(st);
+	if( sd == NULL )
+		return 0;
+
+	data = script_getdata( st, 2 );
+	get_val( st, data );
+
+	if( data_isstring( data ) ){
+		const char *name = conv_str( st, data );
+
+		if( ( item_data = itemdb_searchname( name ) ) == NULL ){
+			ShowError( "buildin_consumeitem: Nonexistant item %s requested.\n", name );
+			return 1;
+		}
+	}else if( data_isint( data ) ){
+		unsigned short nameid = conv_num( st, data );
+
+		if( ( item_data = itemdb_exists( nameid ) ) == NULL ){
+			ShowError("buildin_consumeitem: Nonexistant item %hu requested.\n", nameid );
+			return 1;
+		}
+	}else{
+		ShowError("buildin_consumeitem: invalid data type for argument #1 (%d).\n", data->type );
+		return 1;
+	}
+
+	run_script( item_data->script, 0, sd->bl.id, 0 );
+	return 0;
+}
+
+/*==========================================
+ * Costume Items
+ *------------------------------------------*/
+BUILDIN_FUNC(costume)
+{
+	int i = -1, num, ep;
+	TBL_PC *sd;
+
+	num = script_getnum(st,2); // Equip Slot
+	sd = script_rid2sd(st);
+
+	if( sd == NULL )
+		return 0;
+	if( num > 0 && num <= ARRAYLENGTH(equip) )
+		i = pc_checkequip(sd, equip[num - 1]);
+	if( i < 0 )
+		return 0;
+
+	ep = sd->status.inventory[i].equip;
+	if( !(ep&EQP_HEAD_LOW) && !(ep&EQP_HEAD_MID) && !(ep&EQP_HEAD_TOP) )
+		return 0;
+
+	pc_unequipitem(sd,i,2);
+	clif_delitem(sd,i,1,3);
+	// --------------------------------------------------------------------
+	sd->status.inventory[i].refine = 0;
+	sd->status.inventory[i].attribute = 0;
+	sd->status.inventory[i].card[0] = CARD0_CREATE;
+	sd->status.inventory[i].card[1] = 0;
+	sd->status.inventory[i].card[2] = GetWord(battle_config.reserved_costume_id, 0);
+	sd->status.inventory[i].card[3] = GetWord(battle_config.reserved_costume_id, 1);
+
+	if( ep&EQP_HEAD_TOP ) { ep &= ~EQP_HEAD_TOP; ep |= EQP_COSTUME_HEAD_TOP; }
+	if( ep&EQP_HEAD_LOW ) { ep &= ~EQP_HEAD_LOW; ep |= EQP_COSTUME_HEAD_LOW; }
+	if( ep&EQP_HEAD_MID ) { ep &= ~EQP_HEAD_MID; ep |= EQP_COSTUME_HEAD_MID; }
+	// --------------------------------------------------------------------
+
+	clif_additem(sd,i,1,0);
+	pc_equipitem(sd,i,ep);
+	clif_misceffect(&sd->bl,3);
+
+	return 0;
+}
+
 // declarations that were supposed to be exported from npc_chat.c
 #ifdef PCRE_SUPPORT
 BUILDIN_FUNC(defpattern);
@@ -15464,6 +15792,15 @@
 	BUILDIN_DEF(bg_getareausers,"isiiii"),
 	BUILDIN_DEF(bg_updatescore,"sii"),
 
+		/**
+	 * rAthena and beyond!
+	 **/
+	BUILDIN_DEF(getargcount,""),
+	BUILDIN_DEF(is_function,"s"),
+	BUILDIN_DEF(freeloop,"i"),
+	BUILDIN_DEF(consumeitem,"v?"),
+	BUILDIN_DEF(costume,"i"),
+
 	// Instancing
 	BUILDIN_DEF(instance_create,"si"),
 	BUILDIN_DEF(instance_destroy,"?"),
Index: src/map/script.h
===================================================================
--- src/map/script.h	(revision 801)
+++ src/map/script.h	(working copy)
@@ -68,7 +68,9 @@
 	C_LNOT, // ! a
 	C_NOT, // ~ a
 	C_R_SHIFT, // a >> b
-	C_L_SHIFT // a << b
+	C_L_SHIFT, // a << b
+	C_ADD_PP, // ++a
+	C_SUB_PP, // --a
 } c_op;
 
 struct script_retinfo {
@@ -125,6 +127,7 @@
 	//For backing up purposes
 	struct script_state *bk_st;
 	int bk_npcid;
+	unsigned freeloop : 1;// used by buildin_freeloop
 };
 
 struct script_reg {
Index: src/map/status.c
===================================================================
--- src/map/status.c	(revision 801)
+++ src/map/status.c	(working copy)
@@ -2471,7 +2471,7 @@
 	pc_delautobonus(sd,sd->autobonus3,ARRAYLENGTH(sd->autobonus3),true);
 
 	// Parse equipment.
-	for( i = 0; i < EQI_MAX - 1; i++ )
+	for( i = 0; i < EQI_MAX_BONUS; i++ )
 	{
 		current_equip_item_index = index = sd->equip_index[i]; //We pass INDEX to current_equip_item_index - for EQUIP_SCRIPT (new cards solution) [Lupus]
 		if( index < 0 )

 

Kindly report for any missing dependencies.
i will fix it
 
:D

3CEAM_COSTUME_CONVERTER.patch

3CEAM_COSTUME_CONVERTER_V2.patch

costume_v2.txt

Edited by keitenai

Share this post


Link to post
Share on other sites

ty bro perfect!!!!!!



sir can you convert the costume script need 100tcg per convert?? 


here sir thanks 



error on line 130 here's the screen shot thanks for reply



up up up



bro another error script.c

Costume-IT.txt

post-12558-0-05799100-1458052021_thumb.jpg

post-12558-0-79387500-1458059252_thumb.jpg

Share this post


Link to post
Share on other sites

Revert the changes from the first patch before applying the V2 patch. else you will have double function patches like you have now

Share this post


Link to post
Share on other sites

Did anyone figure out how to remove the weight from costumed items (or anything worn in the costume tab)?

Try editing the item db and edit the weight of the costume item.? 

Share this post


Link to post
Share on other sites

@pc.h:

you've destroyed the ammo-fix, rytech did some time ago. EQI_AMMO ALLWAYS needs to be the last on this enum. ^^

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

×
×
  • Create New...

Important Information

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