Hyvraine Posted February 26, 2013 Group: Members Topic Count: 17 Topics Per Day: 0.00 Content Count: 133 Reputation: 15 Joined: 12/23/11 Last Seen: December 20, 2023 Share Posted February 26, 2013 obtain the information inside a file? just like actOR how does it read the act files /fsh is it possible doing so by hexing the client? if you know how or knows someone how to hex, can you teach me pl0x? I have this php code that reads act files, I managed to make it extract the external offsets but it doesn't work with Kagerou and Lord Knight Female acts I thought that maybe it's broken but actOR2 extracts the details fine. can anyone help me? Quote Link to comment
KeyWorld Posted February 26, 2013 Group: Members Topic Count: 9 Topics Per Day: 0.00 Content Count: 379 Reputation: 304 Joined: 11/10/11 Last Seen: December 2, 2014 Share Posted February 26, 2013 Can you paste here your PHP code, I will check if there is an error with (maybe an unsupported version). Quote Link to comment
Hyvraine Posted February 26, 2013 Group: Members Topic Count: 17 Topics Per Day: 0.00 Content Count: 133 Reputation: 15 Joined: 12/23/11 Last Seen: December 20, 2023 Author Share Posted February 26, 2013 (edited) I removed the comments: public function readAct($act,$save,$output,$code) { $this->act = fopen($act, "rb"); $this->aHeader = unpack('H4ident/Sversion/SnumFrames', fread($this->act, 0x06)); $this->aSize = filesize($act); $this->aAnimations = $this->aHeader['numFrames']; $this->aActions = ($this->aAnimations / 8); $this->aVersion = dechex($this->aHeader['version']); $this->aVersion = (double)preg_replace('{([0-9])(.*?)([0-9])}', '$1.$2', $this->aVersion); fseek($this->act, 0xA, SEEK_CUR); $currentAction = 0; $anim = 0; $pointerMemoryANIM = array(); $pointerMemoryNF = array(); $pointerMemoryPAT = array(); while($anim < $this->aAnimations) { $this->aAnimData[$anim] = unpack('lnumFrames', fread($this->act, 0x04)); for($nf = 0; $nf < $this->aAnimData[$anim]['numFrames']; $nf++) { fseek($this->act, 0x20, SEEK_CUR); $this->aAnimData[$anim][$nf] = unpack('lnumSubFrames', fread($this->act, 0x04)); for($patNo = 0; $patNo < $this->aAnimData[$anim][$nf]['numSubFrames']; $patNo++) { $this->aAnimData[$anim][$nf][$patNo] = unpack('lxOffset/lyOffset/lsprNo/lmirrored/Cred/Cgreen/Cblue/Calpha', fread($this->act, 0x14)); if($this->aVersion >= 2.0 && $this->aVersion <= 2.3) $this->aAnimData[$anim][$nf][$patNo] += unpack('fxyScale', fread($this->act, 0x04)); if($this->aVersion >= 2.4) $this->aAnimData[$anim][$nf][$patNo] += unpack('fxScale/fyScale', fread($this->act, 0x08)); $this->aAnimData[$anim][$nf][$patNo] += unpack('lrotation/lsprType', fread($this->act, 0x08)); if($this->aVersion >= 2.5) $this->aAnimData[$anim][$nf][$patNo] += unpack('lsprWidth/lsprHeight', fread($this->act, 0x08)); } $this->aAnimData[$anim][$nf] += unpack('lExtYOffset/lExtYOffset/lExtXOffset/lExtYOffset/lExtXOffset', fread($this->act, 0x14)); $extrainfo = unpack('lbool', fread($this->act, 0x04)); if($extrainfo['bool'] == 1) fseek($this->act, 0x10, SEEK_CUR); } $anim++; } $this->aSoundData = unpack('lnumSounds', fread($this->act, 0x04)); if($this->aSoundData['numSounds'] > 0) { for($nSnd = 0; $nSnd < $this->aSoundData['numSounds']; $nSnd++) { $this->aSoundData[$nSnd] = unpack('H80file', fread($this->act, 0x28)); } } for($intv = 0; $intv < $this->aAnimations; $intv++) { $this->aAnimData[$intv] += unpack('fanimSpeed', fread($this->act, 0x04)); } foreach($this->aSoundData as $id=>$string) { if((string)$id != 'numSounds') $this->aSoundData[$id] = str_replace(pack('H2','00'),"",(pack('H*', $string['file']))); } echo '<pre>'; echo print_r($this->aAnimData, true); echo print_r($this->aSoundData, true); echo '</pre>'; fclose($this->act); } I'm sorry I really have no knowledge of this. I got a lucky guess that's all -SoundNo got removed tho lol- Edited February 26, 2013 by kenshn111 Quote Link to comment
KeyWorld Posted February 26, 2013 Group: Members Topic Count: 9 Topics Per Day: 0.00 Content Count: 379 Reputation: 304 Joined: 11/10/11 Last Seen: December 2, 2014 Share Posted February 26, 2013 Replace this part: for($patNo = 0; $patNo < $this->aAnimData[$anim][$nf]['numSubFrames']; $patNo++) { $this->aAnimData[$anim][$nf][$patNo] = unpack('lxOffset/lyOffset/lsprNo/lmirrored/Cred/Cgreen/Cblue/Calpha', fread($this->act, 0x14)); if($this->aVersion >= 2.0 && $this->aVersion <= 2.3) $this->aAnimData[$anim][$nf][$patNo] += unpack('fxyScale', fread($this->act, 0x04)); if($this->aVersion >= 2.4) $this->aAnimData[$anim][$nf][$patNo] += unpack('fxScale/fyScale', fread($this->act, 0x08)); $this->aAnimData[$anim][$nf][$patNo] += unpack('lrotation/lsprType', fread($this->act, 0x08)); if($this->aVersion >= 2.5) $this->aAnimData[$anim][$nf][$patNo] += unpack('lsprWidth/lsprHeight', fread($this->act, 0x08)); } With: for($patNo = 0; $patNo < $this->aAnimData[$anim][$nf]['numSubFrames']; $patNo++) { $this->aAnimData[$anim][$nf][$patNo] = unpack('lxOffset/lyOffset/lsprNo/lmirrored/Cred/Cgreen/Cblue/Calpha', fread($this->act, 0x14)); if($this->aVersion < 2.0 ); else if($this->aVersion < 2.4 ) $this->aAnimData[$anim][$nf][$patNo] += unpack('fxyScale/lrotation/lsprType', fread($this->act, 12)); else if($this->aVersion == 2.4 ) $this->aAnimData[$anim][$nf][$patNo] += unpack('fxScale/fyScale/lrotation/lspr_type', fread($this->act, 16)); else $this->aAnimData[$anim][$nf][$patNo] += unpack('fxScale/fyScale/lrotation/lsprType/lsprWidth/lsprHeight', fread($this->act, 24)); }There is also another problem after if you are reading a version < 2.3Well your function is very ugly, hard to debug. If there is still a problem, can you report your act version ? Edit: Sorry for the quote, the code bbcode was buggy... Quote Link to comment
Hyvraine Posted February 26, 2013 Group: Members Topic Count: 17 Topics Per Day: 0.00 Content Count: 133 Reputation: 15 Joined: 12/23/11 Last Seen: December 20, 2023 Author Share Posted February 26, 2013 (edited) It still doesn't work: Kagerou (version is 0 when I changed it to your code, 2.5 on the original code; weird lol) --- Original Code: Errors on: $this->aAnimData[$anim][$nf][$patNo] += unpack('lrotation/lsprType', fread($this->act, 0x08)); ------------------------------------ else $this->aAnimData[$anim][$nf][$patNo] += unpack('fxScale/fyScale/lrotation/lsprType/lsprWidth/lsprHeight', fread($this->act, 24)); With my edit + yours: It just times out. ---- With Original Code + my edit: else $this->aAnimData[$anim][$nf][$patNo] += unpack('fxScale/fyScale/lrotation/lsprType/lsprWidth/lsprHeight', fread($this->act, 24)); ---- I've added this line after my edit (after the ExtOffsets) : ---- $this->aAnimData[$anim][$nf] += unpack('lsoundNo', fread($this->act, 0x04)); ---- Lord Knight Female (version is 2.5) - Doesn't error on original code. May I ask how you know what length to put in fread() ? Edited February 26, 2013 by kenshn111 Quote Link to comment
KeyWorld Posted February 26, 2013 Group: Members Topic Count: 9 Topics Per Day: 0.00 Content Count: 379 Reputation: 304 Joined: 11/10/11 Last Seen: December 2, 2014 Share Posted February 26, 2013 May I ask how you know what length to put in fread() ?You just need to put enough length for the unpack(). Example: unpack('fxScale/fyScale/lrotation/lsprType/lsprWidth/lsprHeight', fread($this->act, 24));For each name in the unpack(), take the first letter: f = float = 4 bytes l = long = 4 bytes 4 (xScale) + 4 (yScale) + 4 (rotation) + 4 (sprType) + 4 (sprWidth) + 4 (sprHeight) = 24. Can you upload a act you have problem with ? Quote Link to comment
Hyvraine Posted February 26, 2013 Group: Members Topic Count: 17 Topics Per Day: 0.00 Content Count: 133 Reputation: 15 Joined: 12/23/11 Last Seen: December 20, 2023 Author Share Posted February 26, 2013 (edited) May I ask how you know what length to put in fread() ?You just need to put enough length for the unpack().Example: unpack('fxScale/fyScale/lrotation/lsprType/lsprWidth/lsprHeight', fread($this->act, 24));For each name in the unpack(), take the first letter:f = float = 4 bytes l = long = 4 bytes 4 (xScale) + 4 (yScale) + 4 (rotation) + 4 (sprType) + 4 (sprWidth) + 4 (sprHeight) = 24. Can you upload a act you have problem with ? And why isn't that in the PHP Manual.. or maybe I just missed it: Here are the files: 4008_4211.rar Edit: Why does this work tho: $this->aAnimData[$anim][$nf] += unpack('lExtYOffset/lExtYOffset/lExtXOffset/lExtYOffset/lExtXOffset', fread($this->act, 0x14)); except f_4008 and 4211 of course Edited February 26, 2013 by kenshn111 Quote Link to comment
KeyWorld Posted February 26, 2013 Group: Members Topic Count: 9 Topics Per Day: 0.00 Content Count: 379 Reputation: 304 Joined: 11/10/11 Last Seen: December 2, 2014 Share Posted February 26, 2013 Ok I see the problem. // Change this: $this->aAnimData[$anim][$nf] += unpack('lExtYOffset/lExtYOffset/lExtXOffset/lExtYOffset/lExtXOffset', fread($this->act, 0x14)); $extrainfo = unpack('lbool', fread($this->act, 0x04)); if($extrainfo['bool'] == 1) fseek($this->act, 0x10, SEEK_CUR); // To: fseek( $this->act, 4, SEEK_CUR ); // sound id, store it in a variable if you want $extrainfo = unpack('lbool', fread($this->act, 0x04)); // Extras infos (if you need) fseek($this->act, 0x10 * $extrainfo['bool'], SEEK_CUR); 1 Quote Link to comment
Hyvraine Posted February 26, 2013 Group: Members Topic Count: 17 Topics Per Day: 0.00 Content Count: 133 Reputation: 15 Joined: 12/23/11 Last Seen: December 20, 2023 Author Share Posted February 26, 2013 Hey ;o It still doesn't work However this is the code with the comments and I added my edit to view the external offsets: again it doesn't work with Kagerou and F_Lord Knight public function readAct($act,$save,$output,$code) { // Open the act file. $this->act = fopen($act, "rb"); // Just like on the sprites we read some infos: ident=ACT, version, number of frames $this->aHeader = unpack('H4ident/Sversion/SnumFrames', fread($this->act, 0x06)); // Get the filesize (used this for sql database etc.) $this->aSize = filesize($act); // The total amount of animations used $this->aAnimations = $this->aHeader['numFrames']; // The number of actions is the num of animations divided by 8. // So what are the "actions"? I just named them like this. They're basicly the directions you can look at. Just like in actOR. // \ | / } // -- o -- }-> 8 in total // / | \ } $this->aActions = ($this->aAnimations / 8); // The version $this->aVersion = dechex($this->aHeader['version']); // Format the version nicely $this->aVersion = (double)preg_replace('{([0-9])(.*?)([0-9])}', '$1.$2', $this->aVersion); // Skip some useless data on one needs fseek($this->act, 0xA, SEEK_CUR); // We're currently at action 0 $currentAction = 0; // Our index for the while loop $anim = 0; // Arrays we save our informations in $pointerMemoryANIM = array(); $pointerMemoryNF = array(); $pointerMemoryPAT = array(); // Lets go through the animations, shall we? while($anim < $this->aAnimations) { // First how many Frames does the action have? // On a normal headgear this would be 3. Because when you are sitting downwards you can look down with your head, left and right. So 3 in total. // Ff you have an animated sprite its more obviously $this->aAnimData[$anim] = unpack('lnumFrames', fread($this->act, 0x04)); // So lets loop through those Frames, cuz they all got individual informations for us for($nf = 0; $nf < $this->aAnimData[$anim]['numFrames']; $nf++) { // Skip useless data fseek($this->act, 0x20, SEEK_CUR); // And now we check how many subFrames this frame got. Or better said Patterns (like in actOR) // For example, if you have a monster sprite and some special effects as seperates sprite frames in the .spr file. // You'll have to paste them onto the stage right? Thats where the patters are being created. Like layers in photoshop. $this->aAnimData[$anim][$nf] = unpack('lnumSubFrames', fread($this->act, 0x04)); // Loop through the patterns or layers for more info about them for($patNo = 0; $patNo < $this->aAnimData[$anim][$nf]['numSubFrames']; $patNo++) { // Grab OffsetX, OffsetY (I didnt go to the point where i would need to figure out the (0,0) coordinates to which this relates to) // Spr number (the sprite frame from the .spr file) // mirrored? red,green,blue,alpha $this->aAnimData[$anim][$nf][$patNo] = unpack('lxOffset/lyOffset/lsprNo/lmirrored/Cred/Cgreen/Cblue/Calpha', fread($this->act, 0x14)); // Now there are different informations stored depending on the act version. // from 2.0 till 2.3 we grab XYScale if($this->aVersion >= 2.0 && $this->aVersion <= 2.3) $this->aAnimData[$anim][$nf][$patNo] += unpack('fxyScale', fread($this->act, 0x04)); // If its 2.4 or higher we get XScale and YScale if($this->aVersion >= 2.4) $this->aAnimData[$anim][$nf][$patNo] += unpack('fxScale/fyScale', fread($this->act, 0x08)); // Now the rotation and the sprType (32 bit or not) $this->aAnimData[$anim][$nf][$patNo] += unpack('lrotation/lsprType', fread($this->act, 0x08)); // If its 2.5 or higher we also got the sprites Width and Height (we should have this info from the sprite itself already though, dont ask me why they put this there) if($this->aVersion >= 2.5) $this->aAnimData[$anim][$nf][$patNo] += unpack('lsprWidth/lsprHeight', fread($this->act, 0x08)); } // The end of the Patterns/Layers on the Frame. // So lets see if it has some kind of sound attached to it? (To the frame) $this->aAnimData[$anim][$nf] += unpack('lsoundNo/fExtXOffset/lExtXOffset/lExtXOffset/sExtYOffset', fread($this->act, 0x14)); // See if there are some extra info, if yes: Skip it, we dont need that crap $extrainfo = unpack('lbool', fread($this->act, 0x04)); if($extrainfo['bool'] == 1) fseek($this->act, 0x10, SEEK_CUR); } // Increase our Action and loop through the next frames and patterns^^ $anim++; } // After reading all infos we are at the end of the act file where the sound informations are stored. $this->aSoundData = unpack('lnumSounds', fread($this->act, 0x04)); // It has some sounds? if($this->aSoundData['numSounds'] > 0) { // We loop through number of sounds to grab it. for($nSnd = 0; $nSnd < $this->aSoundData['numSounds']; $nSnd++) { // Now because the sound file is a string (directs to some .wav file in the grf), saved in hex and for our advantage always exactly 40 bytes long // we read the string as hex values and save it like that $this->aSoundData[$nSnd] = unpack('H80file', fread($this->act, 0x28)); } } // Oh we also got the interval a frame is played at? That info is ours! > for($intv = 0; $intv < $this->aAnimations; $intv++) { $this->aAnimData[$intv] += unpack('fanimSpeed', fread($this->act, 0x04)); } // Lets format our earlier saved hex string to a actual string with letters and not just numbers ^^ // Some note: If there are sounds in the act (mostly monsters) there always appears to be a sound called "atk", just like that. // It doesnt exist in the grf and I have no idea how it is being handled. Maybe some description of the sounds? foreach($this->aSoundData as $id=>$string) { if((string)$id != 'numSounds') $this->aSoundData[$id] = str_replace(pack('H2','00'),"",(pack('H*', $string['file']))); } // Lets display our results of the act file. $act = '$jact'; if (strpos($output, "head")) { $act = '$hact'; } if ($save==1) { file_put_contents($output."$code.php", "<?php $act = ".var_export($this->aAnimData,true).";?>"); } else { echo '<pre>'; echo print_r($this->aAnimData, true); echo print_r($this->aSoundData, true); echo '</pre>'; } // Close the file, its no longer needed. =( fclose($this->act); } Quote Link to comment
KeyWorld Posted February 26, 2013 Group: Members Topic Count: 9 Topics Per Day: 0.00 Content Count: 379 Reputation: 304 Joined: 11/10/11 Last Seen: December 2, 2014 Share Posted February 26, 2013 Did you even read what I wrote ? fseek( $this->act, 4, SEEK_CUR ); // sound id, store it in a variable if you want $extrainfo = unpack('lbool', fread($this->act, 0x04));// Extras infos (if you need) fseek($this->act, 0x10 * $extrainfo['bool'], SEEK_CUR); If you want to store extrainfo, you have to do this:fseek( $this->act, 4, SEEK_CUR ); // sound id, store it in a variable if you want extract( unpack("lnumExtraInfo", fread($this->fp,0x04) ) ); $extraInfos = array(); for ( $i=0; $i<$numExtraInfo; ++$i ) { $extraInfos[$i] = unpack( "x4/VExtXOffsetX/VExtXOffsetY/x4", fread($this->act,16) ); }Edit: Why the bbcode is buggy ? Quote Link to comment
Hyvraine Posted February 26, 2013 Group: Members Topic Count: 17 Topics Per Day: 0.00 Content Count: 133 Reputation: 15 Joined: 12/23/11 Last Seen: December 20, 2023 Author Share Posted February 26, 2013 (edited) Yeah I have read your note and tried to extract it, it still didn't work (now it doesn't read all of them): Sorry if I'm wasting your time >_> This is now the code with your fix: public function readAct($act,$save,$output,$code) { // Open the act file. $this->act = fopen($act, "rb"); // Just like on the sprites we read some infos: ident=ACT, version, number of frames $this->aHeader = unpack('H4ident/Sversion/SnumFrames', fread($this->act, 0x06)); // Get the filesize (used this for sql database etc.) $this->aSize = filesize($act); // The total amount of animations used $this->aAnimations = $this->aHeader['numFrames']; // The number of actions is the num of animations divided by 8. // So what are the "actions"? I just named them like this. They're basicly the directions you can look at. Just like in actOR. // \ | / } // -- o -- }-> 8 in total // / | \ } $this->aActions = ($this->aAnimations / 8); // The version $this->aVersion = dechex($this->aHeader['version']); // Format the version nicely $this->aVersion = (double)preg_replace('{([0-9])(.*?)([0-9])}', '$1.$2', $this->aVersion); // Skip some useless data on one needs fseek($this->act, 0xA, SEEK_CUR); // We're currently at action 0 $currentAction = 0; // Our index for the while loop $anim = 0; // Arrays we save our informations in $pointerMemoryANIM = array(); $pointerMemoryNF = array(); $pointerMemoryPAT = array(); // Lets go through the animations, shall we? while($anim < $this->aAnimations) { // First how many Frames does the action have? // On a normal headgear this would be 3. Because when you are sitting downwards you can look down with your head, left and right. So 3 in total. // Ff you have an animated sprite its more obviously $this->aAnimData[$anim] = unpack('lnumFrames', fread($this->act, 0x04)); // So lets loop through those Frames, cuz they all got individual informations for us for($nf = 0; $nf < $this->aAnimData[$anim]['numFrames']; $nf++) { // Skip useless data fseek($this->act, 0x20, SEEK_CUR); // And now we check how many subFrames this frame got. Or better said Patterns (like in actOR) // For example, if you have a monster sprite and some special effects as seperates sprite frames in the .spr file. // You'll have to paste them onto the stage right? Thats where the patters are being created. Like layers in photoshop. $this->aAnimData[$anim][$nf] = unpack('lnumSubFrames', fread($this->act, 0x04)); // Loop through the patterns or layers for more info about them for($patNo = 0; $patNo < $this->aAnimData[$anim][$nf]['numSubFrames']; $patNo++) { $this->aAnimData[$anim][$nf][$patNo] = unpack('lxOffset/lyOffset/lsprNo/lmirrored/Cred/Cgreen/Cblue/Calpha', fread($this->act, 0x14)); if($this->aVersion < 2.0 ); else if($this->aVersion < 2.4 ) $this->aAnimData[$anim][$nf][$patNo] += unpack('fxyScale/lrotation/lsprType', fread($this->act, 12)); else if($this->aVersion == 2.4 ) $this->aAnimData[$anim][$nf][$patNo] += unpack('fxScale/fyScale/lrotation/lspr_type', fread($this->act, 16)); else $this->aAnimData[$anim][$nf][$patNo] += unpack('fxScale/fyScale/lrotation/lsprType/lsprWidth/lsprHeight', fread($this->act, 24)); } // The end of the Patterns/Layers on the Frame. // So lets see if it has some kind of sound attached to it? (To the frame) fseek( $this->act, 4, SEEK_CUR ); // sound id, store it in a variable if you want extract( unpack("lnumExtraInfo", fread($this->fp,0x04) ) ); $extraInfos = array(); for ( $i=0; $i<$numExtraInfo; ++$i ) { $extraInfos[$i] = unpack( "x4/VExtXOffsetX/VExtXOffsetY/x4", fread($this->act,16) ); } } // Increase our Action and loop through the next frames and patterns^^ $anim++; } // After reading all infos we are at the end of the act file where the sound informations are stored. $this->aSoundData = unpack('lnumSounds', fread($this->act, 0x04)); // It has some sounds? if($this->aSoundData['numSounds'] > 0) { // We loop through number of sounds to grab it. for($nSnd = 0; $nSnd < $this->aSoundData['numSounds']; $nSnd++) { // Now because the sound file is a string (directs to some .wav file in the grf), saved in hex and for our advantage always exactly 40 bytes long // we read the string as hex values and save it like that $this->aSoundData[$nSnd] = unpack('H80file', fread($this->act, 0x28)); } } // Oh we also got the interval a frame is played at? That info is ours! > for($intv = 0; $intv < $this->aAnimations; $intv++) { $this->aAnimData[$intv] += unpack('fanimSpeed', fread($this->act, 0x04)); } // Lets format our earlier saved hex string to a actual string with letters and not just numbers ^^ // Some note: If there are sounds in the act (mostly monsters) there always appears to be a sound called "atk", just like that. // It doesnt exist in the grf and I have no idea how it is being handled. Maybe some description of the sounds? foreach($this->aSoundData as $id=>$string) { if((string)$id != 'numSounds') $this->aSoundData[$id] = str_replace(pack('H2','00'),"",(pack('H*', $string['file']))); } // Lets display our results of the act file. $act = '$jact'; if (strpos($output, "head")) { $act = '$hact'; } if ($save==1) { file_put_contents($output."$code.php", "<?php $act = ".var_export($this->aAnimData,true).";?>"); } else { echo '<pre>'; echo print_r($this->aAnimData, true); echo print_r($this->aSoundData, true); echo '</pre>'; } // Close the file, its no longer needed. =( fclose($this->act); } Edited February 26, 2013 by kenshn111 Quote Link to comment
KeyWorld Posted February 26, 2013 Group: Members Topic Count: 9 Topics Per Day: 0.00 Content Count: 379 Reputation: 304 Joined: 11/10/11 Last Seen: December 2, 2014 Share Posted February 26, 2013 Oups the latest thing I wrote was wrong: fseek( $this->act, 4, SEEK_CUR ); // sound id, store it in a variable if you want extract( unpack("lnumExtraInfo", fread($this->act,0x04) ) ); $extraInfos = array(); for ( $i=0; $i<$numExtraInfo; ++$i ) { $extraInfos[$i] = unpack( "x2/VExtXOffsetX/VExtXOffsetY/x2", fread($this->act,10) ); }Now working. Quote Link to comment
Hyvraine Posted February 26, 2013 Group: Members Topic Count: 17 Topics Per Day: 0.00 Content Count: 133 Reputation: 15 Joined: 12/23/11 Last Seen: December 20, 2023 Author Share Posted February 26, 2013 Lol Unsupported Operand Types: else $this->aAnimData[$anim][$nf][$patNo] += unpack('fxScale/fyScale/lrotation/lsprType/lsprWidth/lsprHeight', fread($this->act, 24)); Quote Link to comment
KeyWorld Posted February 26, 2013 Group: Members Topic Count: 9 Topics Per Day: 0.00 Content Count: 379 Reputation: 304 Joined: 11/10/11 Last Seen: December 2, 2014 Share Posted February 26, 2013 Well test this: public function readAct($act,$save,$output,$code) { // Open the act file. $this->act = fopen($act, "rb"); // Just like on the sprites we read some infos: ident=ACT, version, number of frames $this->aHeader = unpack('H4ident/Sversion/SnumFrames', fread($this->act, 0x06)); // Get the filesize (used this for sql database etc.) $this->aSize = filesize($act); // The total amount of animations used $this->aAnimations = $this->aHeader['numFrames']; // The number of actions is the num of animations divided by 8. // So what are the "actions"? I just named them like this. They're basicly the directions you can look at. Just like in actOR. // \ | / } // -- o -- }-> 8 in total // / | \ } $this->aActions = ($this->aAnimations / 8); // The version $this->aVersion = dechex($this->aHeader['version']); // Format the version nicely $this->aVersion = (double)preg_replace('{([0-9])(.*?)([0-9])}', '$1.$2', $this->aVersion); // Skip some useless data on one needs fseek($this->act, 0xA, SEEK_CUR); // We're currently at action 0 $currentAction = 0; // Our index for the while loop $anim = 0; // Arrays we save our informations in $pointerMemoryANIM = array(); $pointerMemoryNF = array(); $pointerMemoryPAT = array(); // Lets go through the animations, shall we? while($anim < $this->aAnimations) { // First how many Frames does the action have? // On a normal headgear this would be 3. Because when you are sitting downwards you can look down with your head, left and right. So 3 in total. // Ff you have an animated sprite its more obviously $this->aAnimData[$anim] = unpack('lnumFrames', fread($this->act, 0x04)); // So lets loop through those Frames, cuz they all got individual informations for us for($nf = 0; $nf < $this->aAnimData[$anim]['numFrames']; $nf++) { // Skip useless data fseek($this->act, 0x20, SEEK_CUR); // And now we check how many subFrames this frame got. Or better said Patterns (like in actOR) // For example, if you have a monster sprite and some special effects as seperates sprite frames in the .spr file. // You'll have to paste them onto the stage right? Thats where the patters are being created. Like layers in photoshop. $this->aAnimData[$anim][$nf] = unpack('lnumSubFrames', fread($this->act, 0x04)); // Loop through the patterns or layers for more info about them for($patNo = 0; $patNo < $this->aAnimData[$anim][$nf]['numSubFrames']; $patNo++) { $this->aAnimData[$anim][$nf][$patNo] = unpack('lxOffset/lyOffset/lsprNo/lmirrored/Cred/Cgreen/Cblue/Calpha', fread($this->act, 0x14)); if($this->aVersion < 2.0 ); else if($this->aVersion < 2.4 ) $this->aAnimData[$anim][$nf][$patNo] += unpack('fxyScale/lrotation/lsprType', fread($this->act, 12)); else if($this->aVersion == 2.4 ) $this->aAnimData[$anim][$nf][$patNo] += unpack('fxScale/fyScale/lrotation/lspr_type', fread($this->act, 16)); else $this->aAnimData[$anim][$nf][$patNo] += unpack('fxScale/fyScale/lrotation/lsprType/lsprWidth/lsprHeight', fread($this->act, 24)); } // The end of the Patterns/Layers on the Frame. // So lets see if it has some kind of sound attached to it? (To the frame) fseek( $this->act, 4, SEEK_CUR ); // sound id, store it in a variable if you want extract( unpack("lnumExtraInfo", fread($this->act,0x04) ) ); $extraInfos = array(); for ( $i=0; $i<$numExtraInfo; ++$i ) { $extraInfos[$i] = unpack( "x4/VExtXOffsetX/VExtXOffsetY/x4", fread($this->act,16) ); } } // Increase our Action and loop through the next frames and patterns^^ $anim++; } // After reading all infos we are at the end of the act file where the sound informations are stored. $this->aSoundData = unpack('lnumSounds', fread($this->act, 0x04)); // It has some sounds? if($this->aSoundData['numSounds'] > 0) { // We loop through number of sounds to grab it. for($nSnd = 0; $nSnd < $this->aSoundData['numSounds']; $nSnd++) { // Now because the sound file is a string (directs to some .wav file in the grf), saved in hex and for our advantage always exactly 40 bytes long // we read the string as hex values and save it like that $this->aSoundData[$nSnd] = unpack('H80file', fread($this->act, 0x28)); } } // Oh we also got the interval a frame is played at? That info is ours! > for($intv = 0; $intv < $this->aAnimations; $intv++) { $this->aAnimData[$intv] += unpack('fanimSpeed', fread($this->act, 0x04)); } // Lets format our earlier saved hex string to a actual string with letters and not just numbers ^^ // Some note: If there are sounds in the act (mostly monsters) there always appears to be a sound called "atk", just like that. // It doesnt exist in the grf and I have no idea how it is being handled. Maybe some description of the sounds? foreach($this->aSoundData as $id=>$string) { if((string)$id != 'numSounds') $this->aSoundData[$id] = str_replace(pack('H2','00'),"",(pack('H*', $string['file']))); } // Lets display our results of the act file. $act = '$jact'; if (strpos($output, "head")) { $act = '$hact'; } else { echo '<pre>'; echo print_r($this->aAnimData, true); echo print_r($this->aSoundData, true); echo '</pre>'; } // Close the file, its no longer needed. =( fclose($this->act); } 1 Quote Link to comment
Hyvraine Posted February 26, 2013 Group: Members Topic Count: 17 Topics Per Day: 0.00 Content Count: 133 Reputation: 15 Joined: 12/23/11 Last Seen: December 20, 2023 Author Share Posted February 26, 2013 OMG! It's finally working! Thank you so much! Just one more question: where did you study this stuff? how did you know that they'll be available in: extract( unpack("lnumExtraInfo", fread($this->act,0x04) ) ); ?? I just want to learn more 8D Quote Link to comment
KeyWorld Posted February 26, 2013 Group: Members Topic Count: 9 Topics Per Day: 0.00 Content Count: 379 Reputation: 304 Joined: 11/10/11 Last Seen: December 2, 2014 Share Posted February 26, 2013 You can find it by reversing the client, or by searching in some source tools as Actor. But in the past we just have reverse engineering and trying to search by finding redundant informations in the hex. But your current function is not really good, some bugs on some versions, not really good name convention... If you want mine: <?php /** * @fileoverview Action - Loader for the Gravity .act file * @author Vincent Thibault (alias KeyWorld - Twitter: @robrowser) * @version 2.3.0 */ class Action { private $fp, $version; public $actions = array(), $sounds = array(); /// Loader on construct public function __construct($filename=false) { if ( $filename ) $this->open($filename); } /// Open a Action file /// Do some check before. public function open($filename) { if ( substr( $filename, 0, 7 ) !== "data://" ) { if ( ! file_exists($filename) ) throw new Exception("ACT::open() - Can't find file '{$filename}'."); if ( ! is_readable($filename) ) throw new Exception("ACT::open() - Can't read file '{$filename}'."); $this->size = filesize($filename); if ( $this->size < 0x08 ) throw new Exception("ACT::open() - Incorrect file size, shoulnot be a ACT file"); } $this->fp = fopen($filename,'r'); $this->load(); } /// Load an Action file private function load() { extract( unpack( "a2head/C2ver", fread($this->fp, 0x4 ) ) ); if ( $head !== 'AC' ) throw new Exception("ACT::load() - Incorrect act header, is '{$head}' - should be 'AC'"); $this->version = $ver1/10 + $ver2; $this->readActions(); if ( $this->version >= 2.1 ) { // Sound extract( unpack("Vcount", fread( $this->fp, 0x04 ) ) ); for ( $i=0; $i<$count; ++$i ) $this->sounds[$i] = current( unpack('a40', fread( $this->fp, 40 ) ) ); // Delay if ( $this->version >= 2.2 ) foreach( $this->actions as &$action ) $action->delay = current( unpack("f", fread($this->fp, 0x04) ) ) * 25; } } /// Load ACT actions private function readActions() { extract( unpack("vcount/x10", fread( $this->fp, 12 ) ) ); for ( $i=0; $i<$count; ++$i ) { $this->actions[$i] = (object) array( "animations" => $this->readAnimations(), "delay" => 150 ); } } /// Load ACT animations private function readAnimations() { extract( unpack("Vcount", fread( $this->fp, 0x04 ) ) ); $animations = array(); for ( $i=0; $i<$count; ++$i ) { fseek( $this->fp, 32, SEEK_CUR ); $animations[$i] = $this->readLayers(); } return $animations; } /// Load ACT layers private function readLayers() { extract( unpack("Vcount", fread( $this->fp, 0x04 ) ) ); $layers = array(); if ( $this->version < 2.0 ) { $size = 0; $struct = ""; } else if ( $this->version < 2.4 ) { $size = 16; $struct = "C4color/f1scale/Vangle/Vspr_type"; } else if ( $this->version === 2.4 ) { $size = 20; $struct = "C4color/f2scale/Vangle/Vspr_type"; } else { $size = 28; $struct = "C4color/f2scale/Vangle/Vspr_type/Vwidth/Vheight"; } for ( $i=0; $i<$count; ++$i ) { $param = unpack( "Vx/Vy/Vindex/Vis_mirror/" . $struct, fread($this->fp, $size + 16) ); $layers[$i] = (object) array( "pos" => array( $param['x'], $param['y'] ), "index" => $param['index'], "is_mirror" => $param['is_mirror'], "scale" => array( 1.0, 1.0 ), "color" => array( 255, 255, 255, 255 ), "angle" => 0, "spr_type" => 0, "width" => 0, "height" => 0 ); $layer = &$layers[$i]; $layer->color[0] = $param['color1']/255; $layer->color[1] = $param['color2']/255; $layer->color[2] = $param['color3']/255; $layer->color[3] = $param['color4']/255; $layer->scale[0] = isset($param['scale1']) ? $param['scale1'] : 1.0; $layer->scale[1] = isset($param['scale2']) ? $param['scale2'] : $layer->scale[0]; if ( isset($param['angle']) ) $layer->angle = $param['angle']; if ( isset($param['spr_type']) ) $layer->spr_type = $param['spr_type']; if ( isset($param['width']) ) $layer->width = $param['width']; if ( isset($param['height']) ) $layer->height = $param['height']; } $sound = -1; if ( $this->version >= 2.0 ) extract( unpack("Vsound", fread($this->fp,0x04) ) ); $pos= array(); if ( $this->version >= 2.3 ) { extract( unpack("Vcount", fread($this->fp,0x04) ) ); for ( $i=0; $i<$count; ++$i ) { $pos[$i] = (object) unpack( "Vunk/Vx/Vy/Vattr", fread($this->fp,16) ); } } return (object) array( "layers" => $layers, "sound" => $sound, "pos" => $pos ); } /// Compile a ACT file public function compile() { // Header $result = pack('a2C2', 'AC', $this->version * 10 % 10, floor($this->version * 10)/10 ); // Action count $result .= pack( 'vx10', count($this->actions) ); // Compile each actions foreach( $this->actions as $action ) { // Number of animations $result .= pack( 'V', count($action->animations) ); // Compile animations foreach( $action->animations as $animation ) { // 32 uknown offset + layers count $result .= pack( 'x32V', count($animation->layers) ); // Compile layers foreach( $animation->layers as $layer ) { $result .= pack('V4', $layer->pos[0], $layer->pos[1], $layer->index, $layer->is_mirror); if ( $this->version < 2.0 ) continue; else if ( $this->version < 2.4 ) $result .= pack( 'C4fV2', $layer->color[0]*255, $layer->color[1]*255, $layer->color[2]*255, $layer->color[3]*255, $layer->scale[0], $layer->angle, $layer->spr_type ); else if ( $this->version === 2.4 ) $result .= pack( 'C4f2V2', $layer->color[0]*255, $layer->color[1]*255, $layer->color[2]*255, $layer->color[3]*255, $layer->scale[0], $layer->scale[1], $layer->angle, $layer->spr_type ); else $result .= pack( 'C4f2V4', $layer->color[0]*255, $layer->color[1]*255, $layer->color[2]*255, $layer->color[3]*255, $layer->scale[0], $layer->scale[1], $layer->angle, $layer->spr_type, $layer->width, $layer->height ); } // Animation sound if ( $this->version >= 2.0 ) { $result .= pack('V', $animation->sound ); } // Animation imf (head pos) if ( $this->version >= 2.3 ) { $result .= pack('V', count($animation->pos) ); foreach( $animation->pos as $pos ) { $result .= pack( 'V4', $pos->unk, $pos->x, $pos->y, $pos->attr ); } } } } if ( $this->version >= 2.1 ) { // Comple sounds $result .= pack( 'V', count($this->sounds) ); foreach( $this->sounds as $sound ) { $result .= pack( 'a40', $sound ); } // Comple delay if ( $this->version >= 2.2 ) { foreach( $this->actions as $action ) { $result .= pack( 'f', $action->delay / 25 ); } } } return $result; } } ?>Maybe should I release my character-viewer...Have fun~ Quote Link to comment
Hyvraine Posted February 26, 2013 Group: Members Topic Count: 17 Topics Per Day: 0.00 Content Count: 133 Reputation: 15 Joined: 12/23/11 Last Seen: December 20, 2023 Author Share Posted February 26, 2013 You can find it by reversing the client, or by searching in some source tools as Actor. But in the past we just have reverse engineering and trying to search by finding redundant informations in the hex. But your current function is not really good, some bugs on some versions, not really good name convention... If you want mine: <?php /** * @fileoverview Action - Loader for the Gravity .act file * @author Vincent Thibault (alias KeyWorld - Twitter: @robrowser) * @version 2.3.0 */ class Action { private $fp, $version; public $actions = array(), $sounds = array(); /// Loader on construct public function __construct($filename=false) { if ( $filename ) $this->open($filename); } /// Open a Action file /// Do some check before. public function open($filename) { if ( substr( $filename, 0, 7 ) !== "data://" ) { if ( ! file_exists($filename) ) throw new Exception("ACT::open() - Can't find file '{$filename}'."); if ( ! is_readable($filename) ) throw new Exception("ACT::open() - Can't read file '{$filename}'."); $this->size = filesize($filename); if ( $this->size < 0x08 ) throw new Exception("ACT::open() - Incorrect file size, shoulnot be a ACT file"); } $this->fp = fopen($filename,'r'); $this->load(); } /// Load an Action file private function load() { extract( unpack( "a2head/C2ver", fread($this->fp, 0x4 ) ) ); if ( $head !== 'AC' ) throw new Exception("ACT::load() - Incorrect act header, is '{$head}' - should be 'AC'"); $this->version = $ver1/10 + $ver2; $this->readActions(); if ( $this->version >= 2.1 ) { // Sound extract( unpack("Vcount", fread( $this->fp, 0x04 ) ) ); for ( $i=0; $i<$count; ++$i ) $this->sounds[$i] = current( unpack('a40', fread( $this->fp, 40 ) ) ); // Delay if ( $this->version >= 2.2 ) foreach( $this->actions as &$action ) $action->delay = current( unpack("f", fread($this->fp, 0x04) ) ) * 25; } } /// Load ACT actions private function readActions() { extract( unpack("vcount/x10", fread( $this->fp, 12 ) ) ); for ( $i=0; $i<$count; ++$i ) { $this->actions[$i] = (object) array( "animations" => $this->readAnimations(), "delay" => 150 ); } } /// Load ACT animations private function readAnimations() { extract( unpack("Vcount", fread( $this->fp, 0x04 ) ) ); $animations = array(); for ( $i=0; $i<$count; ++$i ) { fseek( $this->fp, 32, SEEK_CUR ); $animations[$i] = $this->readLayers(); } return $animations; } /// Load ACT layers private function readLayers() { extract( unpack("Vcount", fread( $this->fp, 0x04 ) ) ); $layers = array(); if ( $this->version < 2.0 ) { $size = 0; $struct = ""; } else if ( $this->version < 2.4 ) { $size = 16; $struct = "C4color/f1scale/Vangle/Vspr_type"; } else if ( $this->version === 2.4 ) { $size = 20; $struct = "C4color/f2scale/Vangle/Vspr_type"; } else { $size = 28; $struct = "C4color/f2scale/Vangle/Vspr_type/Vwidth/Vheight"; } for ( $i=0; $i<$count; ++$i ) { $param = unpack( "Vx/Vy/Vindex/Vis_mirror/" . $struct, fread($this->fp, $size + 16) ); $layers[$i] = (object) array( "pos" => array( $param['x'], $param['y'] ), "index" => $param['index'], "is_mirror" => $param['is_mirror'], "scale" => array( 1.0, 1.0 ), "color" => array( 255, 255, 255, 255 ), "angle" => 0, "spr_type" => 0, "width" => 0, "height" => 0 ); $layer = &$layers[$i]; $layer->color[0] = $param['color1']/255; $layer->color[1] = $param['color2']/255; $layer->color[2] = $param['color3']/255; $layer->color[3] = $param['color4']/255; $layer->scale[0] = isset($param['scale1']) ? $param['scale1'] : 1.0; $layer->scale[1] = isset($param['scale2']) ? $param['scale2'] : $layer->scale[0]; if ( isset($param['angle']) ) $layer->angle = $param['angle']; if ( isset($param['spr_type']) ) $layer->spr_type = $param['spr_type']; if ( isset($param['width']) ) $layer->width = $param['width']; if ( isset($param['height']) ) $layer->height = $param['height']; } $sound = -1; if ( $this->version >= 2.0 ) extract( unpack("Vsound", fread($this->fp,0x04) ) ); $pos= array(); if ( $this->version >= 2.3 ) { extract( unpack("Vcount", fread($this->fp,0x04) ) ); for ( $i=0; $i<$count; ++$i ) { $pos[$i] = (object) unpack( "Vunk/Vx/Vy/Vattr", fread($this->fp,16) ); } } return (object) array( "layers" => $layers, "sound" => $sound, "pos" => $pos ); } /// Compile a ACT file public function compile() { // Header $result = pack('a2C2', 'AC', $this->version * 10 % 10, floor($this->version * 10)/10 ); // Action count $result .= pack( 'vx10', count($this->actions) ); // Compile each actions foreach( $this->actions as $action ) { // Number of animations $result .= pack( 'V', count($action->animations) ); // Compile animations foreach( $action->animations as $animation ) { // 32 uknown offset + layers count $result .= pack( 'x32V', count($animation->layers) ); // Compile layers foreach( $animation->layers as $layer ) { $result .= pack('V4', $layer->pos[0], $layer->pos[1], $layer->index, $layer->is_mirror); if ( $this->version < 2.0 ) continue; else if ( $this->version < 2.4 ) $result .= pack( 'C4fV2', $layer->color[0]*255, $layer->color[1]*255, $layer->color[2]*255, $layer->color[3]*255, $layer->scale[0], $layer->angle, $layer->spr_type ); else if ( $this->version === 2.4 ) $result .= pack( 'C4f2V2', $layer->color[0]*255, $layer->color[1]*255, $layer->color[2]*255, $layer->color[3]*255, $layer->scale[0], $layer->scale[1], $layer->angle, $layer->spr_type ); else $result .= pack( 'C4f2V4', $layer->color[0]*255, $layer->color[1]*255, $layer->color[2]*255, $layer->color[3]*255, $layer->scale[0], $layer->scale[1], $layer->angle, $layer->spr_type, $layer->width, $layer->height ); } // Animation sound if ( $this->version >= 2.0 ) { $result .= pack('V', $animation->sound ); } // Animation imf (head pos) if ( $this->version >= 2.3 ) { $result .= pack('V', count($animation->pos) ); foreach( $animation->pos as $pos ) { $result .= pack( 'V4', $pos->unk, $pos->x, $pos->y, $pos->attr ); } } } } if ( $this->version >= 2.1 ) { // Comple sounds $result .= pack( 'V', count($this->sounds) ); foreach( $this->sounds as $sound ) { $result .= pack( 'a40', $sound ); } // Comple delay if ( $this->version >= 2.2 ) { foreach( $this->actions as $action ) { $result .= pack( 'f', $action->delay / 25 ); } } } return $result; } } ?>Maybe should I release my character-viewer...Have fun~ My god! Thank you for this! Well, I was just trying out if I could make my own charsim, it's just in the... garbage state lol. Thank you very much!! again! How can I repay you )) Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.