/** * updateShardOpenFromFile() * Update ShardOpen from a file. * Read a line of text in the file, converts it to int (atoi), then casts into bool for ShardOpen. */ void updateShardOpenFromFile(const std::string& filename) { CIFile f; if (!f.open(filename)) { nlwarning("Failed to update ShardOpen from file '%s', couldn't open file", filename.c_str()); return; } try { char readBuffer[256]; f.getline(readBuffer, 256); sint state; NLMISC::fromString(std::string(readBuffer), state); setShardOpenState((TShardOpenState)state); nlinfo("Updated ShardOpen state to '%u' from file '%s'", ShardOpen.get(), filename.c_str()); } catch (const Exception& e) { nlwarning("Failed to update ShardOpen from file '%s', exception raised while getline() '%s'", filename.c_str(), e.what()); } }
// *************************************************************************** void makeAnimMeleeImpact(const std::string &animSetFile, const set<CAnimCombatSet> &combatAnimSets) { // look if this animSetFile is in the combat list to patch string shortName= CFile::getFilenameWithoutExtension(animSetFile); strlwr(shortName); CAnimCombatSet key; key.Name= shortName; set<CAnimCombatSet>::const_iterator it= combatAnimSets.find(key); if(it == combatAnimSets.end()) return; const CAnimCombatSet ¤tCombatAnimSet= *it; InfoLog->displayRawNL("patching %s", animSetFile.c_str()); // *** Read the animset file. CIFile iFile; iFile.open(animSetFile, true); // Read all text static vector<string> animSetText; animSetText.clear(); while(!iFile.eof()) { char tmp[50000]; iFile.getline(tmp, 50000); animSetText.push_back(tmp); } iFile.close(); bool someChangeDone= false; // *** Parse the animSet { // For each line of the animSet sint structLevel= 0; sint meleeImpactDelayLine= -1; string currentStateName; for(uint j=0;j<animSetText.size();j++) { string line= animSetText[j]; string lineLwr= toLower(line); // Find <LOG> TAg? => stop if(line.find("<LOG>")!=string::npos) break; // Find a STRUCT start? if(line.find("<STRUCT")!=string::npos) { // inc struct structLevel++; // if start a new State block if(structLevel==2) { // reset info for this state currentStateName.clear(); meleeImpactDelayLine= -1; // try to get the name const string tagStart= "name=\""; std::string::size_type start= lineLwr.find(tagStart); if(start!=string::npos) { start+= tagStart.size(); std::string::size_type end= lineLwr.find("\"", start); if(end!=string::npos) currentStateName= lineLwr.substr(start, end-start); } } } // Find a STRUCT end? if(line.find("</STRUCT>")!=string::npos) { // if end a state block, may add or replace MeleeDelayImpact if(structLevel==2 && !currentStateName.empty()) { // If the state is not in the combat state, no need to patch anything static CAnimCombatState key; // must translate for instance "attack1" to "A1" key.StateCode= StateNameToStateCode[currentStateName]; set<CAnimCombatState>::const_iterator it= currentCombatAnimSet.States.find(key); if(it!=currentCombatAnimSet.States.end()) { // else take the mean anim time string format= " <ATOM Name=\"MeleeImpactDelay\" Value=\"%.3f\"/>"; string newLine= toString(format.c_str(), it->MeanAnimTime * MeleeImpactTimeFactor); // melee impact delay doesn't exist? if(meleeImpactDelayLine==-1) { // add just before this line the Melee Impact Atom animSetText.insert(animSetText.begin()+j, newLine); j++; someChangeDone= true; } // else exist and want to replace? else if(ReplaceExistingMeleeImpactDelay) { animSetText[meleeImpactDelayLine]= newLine; someChangeDone= true; } } } // dec struct level structLevel--; } // if we are in level 2 structure, try to get the line to modify (if exist) if(structLevel==2) { if( line.find("Name=\"MeleeImpactDelay\"")!=string::npos ) meleeImpactDelayLine= j; } } } // *** Write the animset file. if(someChangeDone) { COFile oFile; oFile.open(animSetFile, false, true); // Write all text for(uint i=0;i<animSetText.size();i++) { string str= animSetText[i]; str+= "\n"; oFile.serialBuffer((uint8*)str.c_str(), (uint)str.size()); } } }
// *************************************************************************** int main(int argc, char *argv[]) { NLMISC::createDebug(); // make_anim_melee_impact animset_dir if(argc!=2) return usage(); string animSetDir= argv[1]; // *** parse the anim.txt file set<CAnimCombatSet> combatAnimSets; CIFile animFile; if(!animFile.open("anim.txt", true)) { nlwarning("Can't open anim.txt file. abort"); return 0; } else { char tmp[5000]; CAnimCombatSet lastAnimSet; // parse all lines while(!animFile.eof()) { animFile.getline(tmp, 5000); string line= tmp; if(line.empty()) continue; // new anim set? if(line[0]!=' ') { // insert the last anim state if(!lastAnimSet.States.empty()) combatAnimSets.insert(lastAnimSet); lastAnimSet.States.clear(); lastAnimSet.Name= line; } // new anim state? else if(!lastAnimSet.Name.empty()) { CAnimCombatState state; state.build(line); lastAnimSet.States.insert(state); } } // append the last anim set if needed if(!lastAnimSet.States.empty()) combatAnimSets.insert(lastAnimSet); animFile.close(); } // *** Get the list of .animset to make by race vector<string> files; files.clear(); CPath::getPathContent(animSetDir, true, false, true, files); vector<string> animSetList; InfoLog->displayRawNL(""); InfoLog->displayRawNL("*****************************"); InfoLog->displayRawNL("**** .animation_set list ****"); InfoLog->displayRawNL("*****************************"); for(uint i=0;i<files.size();i++) { if(testWildCard(files[i], "*.animation_set")) { animSetList.push_back(files[i]); InfoLog->displayRawNL(animSetList.back().c_str()); } } // *** Init StateNameToStateCode StateNameToStateCode["attack1"]= "A1"; StateNameToStateCode["attack2"]= "A2"; StateNameToStateCode["walk atk"]= "Wa"; StateNameToStateCode["run atk"]= "Ra"; StateNameToStateCode["backward atk"]= "Ba"; StateNameToStateCode["default atk low"]= "Dl"; StateNameToStateCode["default atk middle"]= "Dm"; StateNameToStateCode["default atk high"]= "Dh"; StateNameToStateCode["powerful atk low"]= "Pl"; StateNameToStateCode["powerful atk middle"]= "Pm"; StateNameToStateCode["powerful atk high"]= "Ph"; StateNameToStateCode["area atk low"]= "Al"; StateNameToStateCode["area atk middle"]= "Am"; StateNameToStateCode["area atk high"]= "Ah"; // *** For each animset, test if can replace some anim InfoLog->displayRawNL(""); InfoLog->displayRawNL("**************************"); InfoLog->displayRawNL("**** Starting Process ****"); InfoLog->displayRawNL("**************************"); for(uint i=0;i<animSetList.size();i++) { makeAnimMeleeImpact(animSetList[i], combatAnimSets); } return 0; }
// *************************************************************************** void makeAnimByRace(const std::string &animSetFile, const std::vector<string> &animList) { // *** Read the animset file. CIFile iFile; iFile.open(animSetFile, true); // Read all text static vector<string> animSetText; animSetText.clear(); while(!iFile.eof()) { char tmp[50000]; iFile.getline(tmp, 50000); animSetText.push_back(tmp); } iFile.close(); bool someChangeDone= false; // *** For each possible anim for(uint i=0;i<animList.size();i++) { // get the possible anim file name (lowered) static vector<string> raceAnimNames; raceAnimNames.clear(); buildRaceAnimNames(raceAnimNames, toLower(CFile::getFilename(animList[i]))); // For each line of the animSet uint lastStructLine= 0; bool raceRestrictionFound= false; for(uint j=0;j<animSetText.size();) { string line= animSetText[j]; string lineLwr= toLower(line); // Find <LOG> TAg? => stop if(line.find("<LOG>")!=string::npos) break; // Find a STRUCT start? if(line.find("<STRUCT>")!=string::npos) { lastStructLine= j; raceRestrictionFound= false; } // Find a RaceRestriction? if( line.find("Name=\"Race Restriction\"")!=string::npos ) raceRestrictionFound= true; // Find the anim name? uint nameIndexInLine= findAnimName(lineLwr, raceAnimNames); if(nameIndexInLine!=-1) { // Find the enclosing struct nlassert(lastStructLine!=0); uint startBlock= lastStructLine; uint nameLineInBlock= j-startBlock; uint endBlock= 0; for(uint k=j+1;k<animSetText.size();k++) { string line= animSetText[k]; // Find a RaceRestriction? if( line.find("Name=\"Race Restriction\"")!=string::npos ) raceRestrictionFound= true; // end of block? if(line.find("</STRUCT>")!=string::npos) { // endBlock is exclusive endBlock= k+1; break; } } // if not found, abort if(endBlock==0) break; // if a raceRestriction has been found, no op (already done) if(raceRestrictionFound) { j= endBlock; } else { // LOG InfoLog->displayRawNL("%s: Specifying %s by race", CFile::getFilename(animSetFile).c_str(), CFile::getFilename(animList[i]).c_str()); // *** Start a copy paste ^^ // Copy static vector<string> copyText; copyText.clear(); for(uint k=startBlock;k<endBlock;k++) { // add an empty line before </STRUCT>, for race selection node (filled later) if(k==endBlock-1) copyText.push_back(string()); copyText.push_back(animSetText[k]); } // erase this part animSetText.erase(animSetText.begin()+startBlock, animSetText.begin()+endBlock); uint nextBlock= startBlock; // Append for each race for(uint k=0;k<raceAnimNames.size();k++) { appendRaceAnim(animSetText, nextBlock, copyText, nameLineInBlock, nameIndexInLine, raceAnimNames[k]); // nextBlock is then shifted nextBlock+= copyText.size(); } someChangeDone= true; // *** then let j point to next block j= nextBlock; } } else { j++; } } } // *** Write the animset file. if(someChangeDone) { COFile oFile; oFile.open(animSetFile, false, true); // Write all text for(uint i=0;i<animSetText.size();i++) { string str= animSetText[i]; str+= "\n"; oFile.serialBuffer((uint8*)str.c_str(), str.size()); } } }