static void parseKeyFramer( MeshModel *root ){ _log( "KeyFramer" ); enterChunk(); string file_3ds; unsigned short rev,curr_time=0; while( int id=nextChunk() ){ switch( id ){ case 0xb009: //CURR_TIME in.sgetn( (char*)&curr_time,2 ); _log( "CURR_TIME: "+itoa(curr_time) ); break; case 0xb00a: //KFHDR in.sgetn( (char*)&rev,2 ); file_3ds=parseString(); in.sgetn( (char*)&anim_len,2 ); _log( "KFHDR: revision="+itoa(rev)+" 3dsfile="+file_3ds+" anim_len="+itoa(anim_len) ); break; case 0xb002: //object keyframer data... parseMeshInfo( root,curr_time ); break; } } if( !collapse ){ root->setAnimator( d_new Animator( root,anim_len ) ); } leaveChunk(); }
bool GraphicManager::loadSpriteMetadata(const FileName& datafile, wxString& error, wxArrayString& warnings) { // items.otb has most of the info we need. This only loads the GameSprite metadata FileReadHandle file(nstr(datafile.GetFullPath())); if(!file.isOk()) { error += "Failed to open " + datafile.GetFullPath() + " for reading\nThe error reported was:" + wxstr(file.getErrorMessage()); return false; } uint16_t effect_count, distance_count; uint32_t datSignature; file.getU32(datSignature); //get max id file.getU16(item_count); file.getU16(creature_count); file.getU16(effect_count); file.getU16(distance_count); uint32_t minclientID = 100; // tibia.dat start with id 100 // We don't load distance/effects, if we would, just add effect_count & distance_count here uint32_t maxclientID = item_count + creature_count; dat_format = client_version->getDatFormatForSignature(datSignature); if(!otfi_found) { is_extended = dat_format >= DAT_FORMAT_96; has_frame_durations = dat_format >= DAT_FORMAT_1050; has_frame_groups = dat_format >= DAT_FORMAT_1057; } uint16_t id = minclientID; // loop through all ItemDatabase until we reach the end of file while(id <= maxclientID) { GameSprite* sType = newd GameSprite(); sprite_space[id] = sType; sType->id = id; // Load the sprite flags if(!loadSpriteMetadataFlags(file, sType, error, warnings)) { wxString msg; msg << "Failed to load flags for sprite " << sType->id; warnings.push_back(msg); } // Reads the group count uint8_t group_count = 1; if(has_frame_groups && id > item_count) { file.getU8(group_count); } for(uint32_t k = 0; k < group_count; ++k) { // Skipping the group type if(has_frame_groups && id > item_count) { file.skip(1); } // Size and GameSprite data file.getByte(sType->width); file.getByte(sType->height); // Skipping the exact size if((sType->width > 1) || (sType->height > 1)){ file.skip(1); } file.getU8(sType->layers); // Number of blendframes (some sprites consist of several merged sprites) file.getU8(sType->pattern_x); file.getU8(sType->pattern_y); if(dat_format <= DAT_FORMAT_74) sType->pattern_z = 1; else file.getU8(sType->pattern_z); file.getU8(sType->frames); // Length of animation if(sType->frames > 1) { uint8_t async = 0; int loop_count = 0; int8_t start_frame = 0; if(has_frame_durations) { file.getByte(async); file.get32(loop_count); file.getSByte(start_frame); } sType->animator = newd Animator(sType->frames, start_frame, loop_count, async == 1); if(has_frame_durations) { for(int i = 0; i < sType->frames; i++) { uint32_t min; uint32_t max; file.getU32(min); file.getU32(max); FrameDuration* frame_duration = sType->animator->getFrameDuration(i); frame_duration->setValues(int(min), int(max)); } sType->animator->reset(); } } sType->numsprites = (int)sType->width * (int)sType->height * (int)sType->layers * (int)sType->pattern_x * (int)sType->pattern_y * sType->pattern_z * (int)sType->frames; // Read the sprite ids for(uint32_t i = 0; i < sType->numsprites; ++i) { uint32_t sprite_id; if(is_extended) { file.getU32(sprite_id); } else { uint16_t u16 = 0; file.getU16(u16); sprite_id = u16; } if(image_space[sprite_id] == nullptr) { GameSprite::NormalImage* img = newd GameSprite::NormalImage(); img->id = sprite_id; image_space[sprite_id] = img; } sType->spriteList.push_back(static_cast<GameSprite::NormalImage*>(image_space[sprite_id])); } } ++id; } return true; }