[SHARE] Fix for client disconnection while buying item from npc

Newbie Spellweaver
Joined
Jun 9, 2005
Messages
31
Reaction score
3
1st of all u need to know the map id. For now we going to fix the cause of dc in while buying EOD pt 2 from Sally the grocery shop in FR

FR world id = 5

Next, go to etc/caba/data/Data_World/
look for world5-npc.scp <-- this file will handle all the npc attributes such as position/trainer/item price for npc in Fort Ruina.

Under the shoplist, [ShopLst], look for shop list number 78

[ShopLst] NpcsIdx NSetIdx ItemKind ItemOpt ReputationClass DurationIdx Price

78 7 42 945 1288 -19 0 5000000

Thats the item(EOD pt 2).
Ok, now to identify the problem, u must download the file decrypted by SAURON, open the decrypted cabal.enc and try to look for the shoplist.

And we found it here:
<item slot_id="41" item_id="945" option="1288" reputation_class="-19" duration_id="0" price="5000000" />

U may found that NpcIdx in server file not same with item slot id in cabal.enc, so just change it to

78 7 41 945 1288 -19 0 5000000

and its work. the same goes with MF :)
 
I tried to add items to npc in MF (the store is empty) I added it like what was written in cabal.enc but the game got crushed when someone tried to buy.
 
in world 9, there are 2 shop ids which are 7 & 50. 7 for the secret merchant. u need to start from 0 not 27.. and after u finished the list of item for npc 7, continue with npc 50.
example, lets see if there is 30 items in npc 7, then for npc 50.. u must start the with 49.

ex:

0 7 0 1178 4053 -19 2 1000000 <-- npc no 7 because its come 1st in cabal.enc

then followed with :
1 50 0 3 1 -19 0 60 <-- for npc no 50.
 
in world 9, there are 2 shop ids which are 7 & 50. 7 for the secret merchant. u need to start from 0 not 27.. and after u finished the list of item for npc 7, continue with npc 50.
example, lets see if there is 30 items in npc 7, then for npc 50.. u must start the with 49.

ex:

0 7 0 1178 4053 -19 2 1000000 <-- npc no 7 because its come 1st in cabal.enc

then followed with :
1 50 0 3 1 -19 0 60 <-- for npc no 50.


Working now, Thanks =P.
 
Acid can you post all the fixes please? i mean all the items that have to be change.. coz i dont know how to find my self and i think (not sure) there is more items that make ppls DC. i fixed the B2F, now there is more things to fix? if yes, give me list please if you can =P

Thanks. =]
 
but how to make sell price work? i buy potion lvl 2 800, and when i sell that write 200 but my money increae 800 too.
 
this recreate all the worldxx-npc.scp files
cabal.enc as xml (same dir as php) and original worldxx-npc.scp (/world folder) are required..

PHP:
<?php

function xml2array($contents, $get_attributes=1) {
    if(!$contents) return array();

    if(!function_exists('xml_parser_create')) {
        //print "'xml_parser_create()' function not found!";
        return array();
    }
    //Get the XML parser of PHP - PHP must have this module for the parser to work
    $parser = xml_parser_create();
    xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, 0 );
    xml_parser_set_option( $parser, XML_OPTION_SKIP_WHITE, 1 );
    xml_parse_into_struct( $parser, $contents, $xml_values );
    xml_parser_free( $parser );

    if(!$xml_values) return;//Hmm...

    //Initializations
    $xml_array = array();
    $parents = array();
    $opened_tags = array();
    $arr = array();

    $current = &$xml_array;

    //Go through the tags.
    foreach($xml_values as $data) {
        unset($attributes,$value);//Remove existing values, or there will be trouble

        //This command will extract these variables into the foreach scope
        // tag(string), type(string), level(int), attributes(array).
        extract($data);//We could use the array by itself, but this cooler.

        $result = '';
        if($get_attributes) {//The second argument of the function decides this.
            $result = array();
            if(isset($value)) $result['value'] = $value;

            //Set the attributes too.
            if(isset($attributes)) {
                foreach($attributes as $attr => $val) {
                    if($get_attributes == 1) $result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr'
                    /**  :TODO: should we change the key name to '_attr'? Someone may use the tagname 'attr'. Same goes for 'value' too */
                }
            }
        } elseif(isset($value)) {
            $result = $value;
        }

        //See tag status and do the needed.
        if($type == "open") {//The starting of the tag '<tag>'
            $parent[$level-1] = &$current;

            if(!is_array($current) or (!in_array($tag, array_keys($current)))) { //Insert New tag
                $current[$tag] = $result;
                $current = &$current[$tag];

            } else { //There was another element with the same tag name
                if(isset($current[$tag][0])) {
                    array_push($current[$tag], $result);
                } else {
                    $current[$tag] = array($current[$tag],$result);
                }
                $last = count($current[$tag]) - 1;
                $current = &$current[$tag][$last];
            }

        } elseif($type == "complete") { //Tags that ends in 1 line '<tag />'
            //See if the key is already taken.
            if(!isset($current[$tag])) { //New Key
                $current[$tag] = $result;

            } else { //If taken, put all things inside a list(array)
                if((is_array($current[$tag]) and $get_attributes == 0)//If it is already an array...
                        or (isset($current[$tag][0]) and is_array($current[$tag][0]) and $get_attributes == 1)) {
                    array_push($current[$tag],$result); // ...push the new element into that array.
                } else { //If it is not an array...
                    $current[$tag] = array($current[$tag],$result); //...Make it an array using using the existing value and the new value
                }
            }

        } elseif($type == 'close') { //End of tag '</tag>'
            $current = &$parent[$level-1];
        }
    }

    return($xml_array);
}


function shoplist( $r )
{
	$t = "	";
	$d = 0;
	$c = count($r);
	$s = "";
	
	if($c < 1) return $s;
	if(!is_array($r[0]))
	{
		$id = $r["attr"]["id"];
		echo $id."\n";
		foreach($r["item"] as $k => $v)
		{
			$s .= $d.$t.$id.$t.$v["attr"]["slot_id"].$t.$v["attr"]["item_id"].$t.$v["attr"]["option"].$t.$v["attr"]["reputation_class"].$t.$v["attr"]["duration_id"].$t.$v["attr"]["price"]."\n";	
			$d++;
		}
		return $s;
	}
	
	for($i = 0; $i < $c; $i++)
	{
		$id = $r[$i]["attr"]["id"];
		if(count($r[$i]["item"]) == 1 )
		{
			$v = $r[$i]["item"];
			$s .= $d.$t.$id.$t.$v["attr"]["slot_id"].$t.$v["attr"]["item_id"].$t.$v["attr"]["option"].$t.$v["attr"]["reputation_class"].$t.$v["attr"]["duration_id"].$t.$v["attr"]["price"]."\n";	
			$d++;
			continue;
		}
		foreach($r[$i]["item"] as $k => $v)
		{
			$s .= $d.$t.$id.$t.$v["attr"]["slot_id"].$t.$v["attr"]["item_id"].$t.$v["attr"]["option"].$t.$v["attr"]["reputation_class"].$t.$v["attr"]["duration_id"].$t.$v["attr"]["price"]."\n";	
			$d++;
		}
	}
	return $s;
}

function skilllist( $r )
{
	$t = "	";
	$d = 0;
	$c = count($r);
	$s = "";
	
	if($c < 1) return $s;
	if(!is_array($r[0]))
	{
		$id = $r["attr"]["id"];
		foreach($r["skill"] as $k => $v)
		{
			//fwrite($o, $d.$t.$id.$t.$v["attr"]["id"].$t.$v["attr"]["day"].$t.$v["attr"]["hour"]."\n");
			$s .= $d.$t.$v["attr"]["slot_id"].$t.$id.$t.$v["attr"]["id"].$t.$v["attr"]["level"]."\n";	
			$d++;
		}
		return $s;
	}
	for($i = 0; $i < $c; $i++)
	{
		$id = $r["attr"]["id"];
		if(count($r[$i]["skill"]) == 1 )
		{
			$v = $r[$i]["skill"];
			$s .= $d.$t.$v["attr"]["slot_id"].$t.$id.$t.$v["attr"]["id"].$t.$v["attr"]["level"]."\n";	
			$d++;
			continue;
		}
		foreach($r[$i]["skill"] as $k => $v)
		{
			//fwrite($o, $d.$t.$id.$t.$v["attr"]["id"].$t.$v["attr"]["day"].$t.$v["attr"]["hour"]."\n");
			$s .= $d.$t.$v["attr"]["slot_id"].$t.$id.$t.$v["attr"]["id"].$t.$v["attr"]["level"]."\n";	
			$d++;
		}
	}
	return $s;
}

function warplist( $r )
{
	//print_r($r);
	
	$t = "	";
	$d = 0;
	$c = count($r);
	$s = "";
	
	if($c < 1) return $s;
	if(!is_array($r[0]))
	{
		$id = $r["attr"]["id"];
		if(count($r["warp_list"]) == 1 )
		{
			$v = $r["warp_list"];
			$s .= $d.$t.$id.$t.intval($v["attr"]["order"]).$t.intval($v["attr"]["target_id"]).$t.intval($v["attr"]["level"]).$t.intval($v["attr"]["Fee"]).$t.intval($v["attr"]["type"])."\n";
			return $s;
		}
		foreach($r["warp_list"] as $k => $v)
		{
			$s .= $d.$t.$id.$t.intval($v["attr"]["order"]).$t.intval($v["attr"]["target_id"]).$t.intval($v["attr"]["level"]).$t.intval($v["attr"]["Fee"]).$t.intval($v["attr"]["type"])."\n";	
			$d++;
		}
		return $s;
	}
	
	for($i = 0; $i < $c; $i++)
	{
		$id = $r[$i]["attr"]["id"];
	//	echo $id."\n";
		
		if(count($r[$i]["warp_list"]) == 1 )
		{
		//	echo "LALAL";
			$v = $r[$i]["warp_list"];// print_r($v);
			$s .= $d.$t.$id.$t.intval($v["attr"]["order"]).$t.intval($v["attr"]["target_id"]).$t.intval($v["attr"]["level"]).$t.intval($v["attr"]["Fee"]).$t.intval($v["attr"]["type"])."\n";	
		//	echo $s."\n";
			$d++;
			continue;
		}
		foreach($r[$i]["warp_list"] as $k => $v)
		{
			$s .= $d.$t.$id.$t.intval($v["attr"]["order"]).$t.intval($v["attr"]["target_id"]).$t.intval($v["attr"]["level"]).$t.intval($v["attr"]["Fee"]).$t.intval($v["attr"]["type"])."\n";	
			$d++;
		}
	}
	//echo $s;
	return $s;
}


$contents = file_get_contents('cabal.xml');
$r = xml2array($contents);


foreach($r["cabal"]["warp_npc"]["world"] as $k => $v)
	echo $k."   ".$v["attr"]["id"]."\n";
	


$c = count($r["cabal"]["cabal_world"]["world"]);
$c = 2;
	
for($i = 0; $i < 30; $i++)
{
	$shop[$r["cabal"]["cabal_world"]["world"][$i]["attr"]["id"]] = shoplist($r["cabal"]["cabal_world"]["world"][$i]["shop"]);
	$skill[$r["cabal"]["cabal_world"]["world"][$i]["attr"]["id"]] = skilllist($r["cabal"]["cabal_world"]["world"][$i]["trainer"]);
	$warp[$r["cabal"]["warp_npc"]["world"][$i]["attr"]["id"]] = warplist($r["cabal"]["warp_npc"]["world"][$i]["npc"]);
	
}

//	echo $r["cabal"]["warp_npc"]["world"][10]["attr"]["id"];

for($i = 1; $i < 31; $i++)
{
	$file = file_get_contents("world/world".$i."-npc.scp");
	$npcpos = substr($file, 0, strpos($file, "[WarpLst]"));
	
	$out = fopen("fixed/world".$i."-npc.scp", "w");
	fwrite($out, $npcpos."\n\n[WarpLst]	NpcsIdx	NSetIdx	TargetIdx	LV	Fee	Type\n".$warp[$i]."\n\n[SkillLst]	NSetIdx	NpcsIdx	SkillIdx	SkillLv\n".$skill[$i]."\n\n[ShopLst]	NpcsIdx	NSetIdx	ItemKind	ItemOpt	ReputationClass	DurationIdx	Price\n".$shop[$i]);
	fclose($out);

}

die();


?>
 
wow, sound good, but how to use it, maybe i must experiment firrst, cause not detail guide from you sauron, what file name must write in that sript? but you are the best too...
 
Do u have correct .scp (s) for all maps to suit english (GP) client. Seem like i cant use your tools, take forever to recreate new .scp
 
this recreate all the worldxx-npc.scp files
cabal.enc as xml (same dir as php) and original worldxx-npc.scp (/world folder) are required..

PHP:
<?php

function xml2array($contents, $get_attributes=1) {
    if(!$contents) return array();

    if(!function_exists('xml_parser_create')) {
        //print "'xml_parser_create()' function not found!";
        return array();
    }
    //Get the XML parser of PHP - PHP must have this module for the parser to work
    $parser = xml_parser_create();
    xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, 0 );
    xml_parser_set_option( $parser, XML_OPTION_SKIP_WHITE, 1 );
    xml_parse_into_struct( $parser, $contents, $xml_values );
    xml_parser_free( $parser );

    if(!$xml_values) return;//Hmm...

    //Initializations
    $xml_array = array();
    $parents = array();
    $opened_tags = array();
    $arr = array();

    $current = &$xml_array;

    //Go through the tags.
    foreach($xml_values as $data) {
        unset($attributes,$value);//Remove existing values, or there will be trouble

        //This command will extract these variables into the foreach scope
        // tag(string), type(string), level(int), attributes(array).
        extract($data);//We could use the array by itself, but this cooler.

        $result = '';
        if($get_attributes) {//The second argument of the function decides this.
            $result = array();
            if(isset($value)) $result['value'] = $value;

            //Set the attributes too.
            if(isset($attributes)) {
                foreach($attributes as $attr => $val) {
                    if($get_attributes == 1) $result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr'
                    /**  :TODO: should we change the key name to '_attr'? Someone may use the tagname 'attr'. Same goes for 'value' too */
                }
            }
        } elseif(isset($value)) {
            $result = $value;
        }

        //See tag status and do the needed.
        if($type == "open") {//The starting of the tag '<tag>'
            $parent[$level-1] = &$current;

            if(!is_array($current) or (!in_array($tag, array_keys($current)))) { //Insert New tag
                $current[$tag] = $result;
                $current = &$current[$tag];

            } else { //There was another element with the same tag name
                if(isset($current[$tag][0])) {
                    array_push($current[$tag], $result);
                } else {
                    $current[$tag] = array($current[$tag],$result);
                }
                $last = count($current[$tag]) - 1;
                $current = &$current[$tag][$last];
            }

        } elseif($type == "complete") { //Tags that ends in 1 line '<tag />'
            //See if the key is already taken.
            if(!isset($current[$tag])) { //New Key
                $current[$tag] = $result;

            } else { //If taken, put all things inside a list(array)
                if((is_array($current[$tag]) and $get_attributes == 0)//If it is already an array...
                        or (isset($current[$tag][0]) and is_array($current[$tag][0]) and $get_attributes == 1)) {
                    array_push($current[$tag],$result); // ...push the new element into that array.
                } else { //If it is not an array...
                    $current[$tag] = array($current[$tag],$result); //...Make it an array using using the existing value and the new value
                }
            }

        } elseif($type == 'close') { //End of tag '</tag>'
            $current = &$parent[$level-1];
        }
    }

    return($xml_array);
}


function shoplist( $r )
{
    $t = "    ";
    $d = 0;
    $c = count($r);
    $s = "";
    
    if($c < 1) return $s;
    if(!is_array($r[0]))
    {
        $id = $r["attr"]["id"];
        echo $id."\n";
        foreach($r["item"] as $k => $v)
        {
            $s .= $d.$t.$id.$t.$v["attr"]["slot_id"].$t.$v["attr"]["item_id"].$t.$v["attr"]["option"].$t.$v["attr"]["reputation_class"].$t.$v["attr"]["duration_id"].$t.$v["attr"]["price"]."\n";    
            $d++;
        }
        return $s;
    }
    
    for($i = 0; $i < $c; $i++)
    {
        $id = $r[$i]["attr"]["id"];
        if(count($r[$i]["item"]) == 1 )
        {
            $v = $r[$i]["item"];
            $s .= $d.$t.$id.$t.$v["attr"]["slot_id"].$t.$v["attr"]["item_id"].$t.$v["attr"]["option"].$t.$v["attr"]["reputation_class"].$t.$v["attr"]["duration_id"].$t.$v["attr"]["price"]."\n";    
            $d++;
            continue;
        }
        foreach($r[$i]["item"] as $k => $v)
        {
            $s .= $d.$t.$id.$t.$v["attr"]["slot_id"].$t.$v["attr"]["item_id"].$t.$v["attr"]["option"].$t.$v["attr"]["reputation_class"].$t.$v["attr"]["duration_id"].$t.$v["attr"]["price"]."\n";    
            $d++;
        }
    }
    return $s;
}

function skilllist( $r )
{
    $t = "    ";
    $d = 0;
    $c = count($r);
    $s = "";
    
    if($c < 1) return $s;
    if(!is_array($r[0]))
    {
        $id = $r["attr"]["id"];
        foreach($r["skill"] as $k => $v)
        {
            //fwrite($o, $d.$t.$id.$t.$v["attr"]["id"].$t.$v["attr"]["day"].$t.$v["attr"]["hour"]."\n");
            $s .= $d.$t.$v["attr"]["slot_id"].$t.$id.$t.$v["attr"]["id"].$t.$v["attr"]["level"]."\n";    
            $d++;
        }
        return $s;
    }
    for($i = 0; $i < $c; $i++)
    {
        $id = $r["attr"]["id"];
        if(count($r[$i]["skill"]) == 1 )
        {
            $v = $r[$i]["skill"];
            $s .= $d.$t.$v["attr"]["slot_id"].$t.$id.$t.$v["attr"]["id"].$t.$v["attr"]["level"]."\n";    
            $d++;
            continue;
        }
        foreach($r[$i]["skill"] as $k => $v)
        {
            //fwrite($o, $d.$t.$id.$t.$v["attr"]["id"].$t.$v["attr"]["day"].$t.$v["attr"]["hour"]."\n");
            $s .= $d.$t.$v["attr"]["slot_id"].$t.$id.$t.$v["attr"]["id"].$t.$v["attr"]["level"]."\n";    
            $d++;
        }
    }
    return $s;
}

function warplist( $r )
{
    //print_r($r);
    
    $t = "    ";
    $d = 0;
    $c = count($r);
    $s = "";
    
    if($c < 1) return $s;
    if(!is_array($r[0]))
    {
        $id = $r["attr"]["id"];
        if(count($r["warp_list"]) == 1 )
        {
            $v = $r["warp_list"];
            $s .= $d.$t.$id.$t.intval($v["attr"]["order"]).$t.intval($v["attr"]["target_id"]).$t.intval($v["attr"]["level"]).$t.intval($v["attr"]["Fee"]).$t.intval($v["attr"]["type"])."\n";
            return $s;
        }
        foreach($r["warp_list"] as $k => $v)
        {
            $s .= $d.$t.$id.$t.intval($v["attr"]["order"]).$t.intval($v["attr"]["target_id"]).$t.intval($v["attr"]["level"]).$t.intval($v["attr"]["Fee"]).$t.intval($v["attr"]["type"])."\n";    
            $d++;
        }
        return $s;
    }
    
    for($i = 0; $i < $c; $i++)
    {
        $id = $r[$i]["attr"]["id"];
    //    echo $id."\n";
        
        if(count($r[$i]["warp_list"]) == 1 )
        {
        //    echo "LALAL";
            $v = $r[$i]["warp_list"];// print_r($v);
            $s .= $d.$t.$id.$t.intval($v["attr"]["order"]).$t.intval($v["attr"]["target_id"]).$t.intval($v["attr"]["level"]).$t.intval($v["attr"]["Fee"]).$t.intval($v["attr"]["type"])."\n";    
        //    echo $s."\n";
            $d++;
            continue;
        }
        foreach($r[$i]["warp_list"] as $k => $v)
        {
            $s .= $d.$t.$id.$t.intval($v["attr"]["order"]).$t.intval($v["attr"]["target_id"]).$t.intval($v["attr"]["level"]).$t.intval($v["attr"]["Fee"]).$t.intval($v["attr"]["type"])."\n";    
            $d++;
        }
    }
    //echo $s;
    return $s;
}


$contents = file_get_contents('cabal.xml');
$r = xml2array($contents);


foreach($r["cabal"]["warp_npc"]["world"] as $k => $v)
    echo $k."   ".$v["attr"]["id"]."\n";
    


$c = count($r["cabal"]["cabal_world"]["world"]);
$c = 2;
    
for($i = 0; $i < 30; $i++)
{
    $shop[$r["cabal"]["cabal_world"]["world"][$i]["attr"]["id"]] = shoplist($r["cabal"]["cabal_world"]["world"][$i]["shop"]);
    $skill[$r["cabal"]["cabal_world"]["world"][$i]["attr"]["id"]] = skilllist($r["cabal"]["cabal_world"]["world"][$i]["trainer"]);
    $warp[$r["cabal"]["warp_npc"]["world"][$i]["attr"]["id"]] = warplist($r["cabal"]["warp_npc"]["world"][$i]["npc"]);
    
}

//    echo $r["cabal"]["warp_npc"]["world"][10]["attr"]["id"];

for($i = 1; $i < 31; $i++)
{
    $file = file_get_contents("world/world".$i."-npc.scp");
    $npcpos = substr($file, 0, strpos($file, "[WarpLst]"));
    
    $out = fopen("fixed/world".$i."-npc.scp", "w");
    fwrite($out, $npcpos."\n\n[WarpLst]    NpcsIdx    NSetIdx    TargetIdx    LV    Fee    Type\n".$warp[$i]."\n\n[SkillLst]    NSetIdx    NpcsIdx    SkillIdx    SkillLv\n".$skill[$i]."\n\n[ShopLst]    NpcsIdx    NSetIdx    ItemKind    ItemOpt    ReputationClass    DurationIdx    Price\n".$shop[$i]);
    fclose($out);

}

die();


?>


I couldn't get it to work, I had /world/world**-npc.scp, .php file, cabal.dec.txt which I changed to cabal.xml, and added this at the beginning of the file:
<cabal>
<version index="1" />
<cabal_server>
<server_line line_id="1" >
Then it said something about /fixed folder, so added it with all the world**-npc.scp files.

Is that right?
 
Last edited:
First i have this error
PHP Error

Warning: Invalid argument supplied for foreach() in D:\wamp\www\index.php on line 226

after add
<cabal>
<version index="1" />
<cabal_server>
<server_line line_id="1" >
stiil error
Fatal error: Allowed memory size of 8388608 bytes exhausted (tried to allocate 35 bytes) in D:\wamp\www\index.php on line 14

xml_parse_into_struct( $parser, $contents, $xml_values );
 
Back