mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-27 14:57:44 +00:00
quest parser improvements
- add actor and item names as comments - add actor positions as comments (bnpc/eobj teris may be inaccurate) - sort script entities properly with shameless natural sort steal
This commit is contained in:
parent
cb5f8067d6
commit
446228cc0d
1 changed files with 171 additions and 18 deletions
|
@ -5,6 +5,7 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
|
@ -24,8 +25,8 @@ Sapphire::Data::ExdData g_exdDataGen;
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
using namespace Sapphire;
|
using namespace Sapphire;
|
||||||
|
|
||||||
std::string javaPath( "\"C:\\Program Files (x86)\\Java\\jre1.8.0_301\\bin\\java.exe\"" );
|
std::string javaPath("java " );
|
||||||
std::string gamePath( "F:\\client3.0\\game\\sqpack" );
|
std::string gamePath( "H:\\Games\\ffxiv3.05\\game\\sqpack" );
|
||||||
|
|
||||||
const std::string onWithinRangeStr(
|
const std::string onWithinRangeStr(
|
||||||
" void onWithinRange( World::Quest& quest, Entity::Player& player, uint64_t eRangeId, float x, float y, float z ) override\n"
|
" void onWithinRange( World::Quest& quest, Entity::Player& player, uint64_t eRangeId, float x, float y, float z ) override\n"
|
||||||
|
@ -39,6 +40,38 @@ const std::string onEmoteStr(
|
||||||
" }\n\n"
|
" }\n\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// https://stackoverflow.com/a/9745132
|
||||||
|
bool compareNat(const std::string& a, const std::string& b)
|
||||||
|
{
|
||||||
|
if (a.empty())
|
||||||
|
return true;
|
||||||
|
if (b.empty())
|
||||||
|
return false;
|
||||||
|
if (std::isdigit(a[0]) && !std::isdigit(b[0]))
|
||||||
|
return true;
|
||||||
|
if (!std::isdigit(a[0]) && std::isdigit(b[0]))
|
||||||
|
return false;
|
||||||
|
if (!std::isdigit(a[0]) && !std::isdigit(b[0]))
|
||||||
|
{
|
||||||
|
if (std::toupper(a[0]) == std::toupper(b[0]))
|
||||||
|
return compareNat(a.substr(1), b.substr(1));
|
||||||
|
return (std::toupper(a[0]) < std::toupper(b[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::istringstream issa(a);
|
||||||
|
std::istringstream issb(b);
|
||||||
|
int ia, ib;
|
||||||
|
issa >> ia;
|
||||||
|
issb >> ib;
|
||||||
|
if (ia != ib)
|
||||||
|
return ia < ib;
|
||||||
|
|
||||||
|
std::string anew, bnew;
|
||||||
|
std::getline(issa, anew);
|
||||||
|
std::getline(issb, bnew);
|
||||||
|
return (compareNat(anew, bnew));
|
||||||
|
}
|
||||||
|
|
||||||
std::string titleCase( const std::string& str )
|
std::string titleCase( const std::string& str )
|
||||||
{
|
{
|
||||||
if( str.empty() )
|
if( str.empty() )
|
||||||
|
@ -99,6 +132,117 @@ Container& split(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const std::string& getItemNameFromExd( uint32_t id )
|
||||||
|
{
|
||||||
|
static std::unordered_map< uint32_t, std::string > itemNames;
|
||||||
|
static std::string invalid;
|
||||||
|
|
||||||
|
if( itemNames.empty() )
|
||||||
|
{
|
||||||
|
auto nameIdList = g_exdDataGen.getIdList< Excel::Item >();
|
||||||
|
for( auto id : nameIdList )
|
||||||
|
{
|
||||||
|
auto itemName = g_exdDataGen.getRow< Excel::Item >( id );
|
||||||
|
if( itemName && !itemName->getString( itemName->data().Text.SGL ).empty() )
|
||||||
|
itemNames[id] = itemName->getString( itemName->data().Text.SGL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( auto name = itemNames.find( id ); name != itemNames.end() )
|
||||||
|
return name->second;
|
||||||
|
|
||||||
|
return invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& getActorPosFromLevelExd( uint32_t id )
|
||||||
|
{
|
||||||
|
static std::unordered_map< uint32_t, std::string > levelPositions;
|
||||||
|
static std::string invalid;
|
||||||
|
|
||||||
|
if( levelPositions.empty() )
|
||||||
|
{
|
||||||
|
auto levelIdList = g_exdDataGen.getIdList< Excel::Level >();
|
||||||
|
for( auto id : levelIdList )
|
||||||
|
{
|
||||||
|
auto levelRow = g_exdDataGen.getRow< Excel::Level >( id );
|
||||||
|
if( levelRow )
|
||||||
|
{
|
||||||
|
auto assetType = levelRow->data().eAssetType;
|
||||||
|
// enpc, bnpc, eobj
|
||||||
|
if( assetType != 8 && assetType != 9 && assetType != 45 )
|
||||||
|
continue;
|
||||||
|
std::string pos(" ( Pos: ");
|
||||||
|
pos +=
|
||||||
|
std::to_string( levelRow->data().TransX ) + " " +
|
||||||
|
std::to_string( levelRow->data().TransY ) + " " +
|
||||||
|
std::to_string( levelRow->data().TransZ ) + " " +
|
||||||
|
"Teri: " + std::to_string( levelRow->data().TerritoryType ) + " )";
|
||||||
|
levelPositions.emplace( levelRow->data().BaseId, pos );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( auto pos = levelPositions.find( id ); pos != levelPositions.end() )
|
||||||
|
return pos->second;
|
||||||
|
return invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& getActorNameFromExd( uint32_t id )
|
||||||
|
{
|
||||||
|
static std::unordered_map< uint32_t, std::string > bnpcNames, enpcNames, eobjNames;
|
||||||
|
static std::string invalid;
|
||||||
|
|
||||||
|
// bnpc
|
||||||
|
if( id < 1000000 )
|
||||||
|
{
|
||||||
|
if( bnpcNames.empty() )
|
||||||
|
{
|
||||||
|
auto nameIdList = g_exdDataGen.getIdList< Excel::BNpcName >();
|
||||||
|
for( auto id : nameIdList )
|
||||||
|
{
|
||||||
|
auto BNpcName = g_exdDataGen.getRow< Excel::BNpcName >( id );
|
||||||
|
if( BNpcName && !BNpcName->getString( BNpcName->data().Text.SGL ).empty() )
|
||||||
|
bnpcNames[id] = BNpcName->getString( BNpcName->data().Text.SGL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( auto name = bnpcNames.find( id ); name != bnpcNames.end() )
|
||||||
|
return name->second;
|
||||||
|
}
|
||||||
|
// enpcresident
|
||||||
|
else if( id < 2000000 )
|
||||||
|
{
|
||||||
|
if( enpcNames.empty() )
|
||||||
|
{
|
||||||
|
auto nameIdList = g_exdDataGen.getIdList< Excel::ENpcResident >();
|
||||||
|
for( auto id : nameIdList )
|
||||||
|
{
|
||||||
|
auto eNpcName = g_exdDataGen.getRow< Excel::ENpcResident >( id );
|
||||||
|
if( eNpcName && !eNpcName->getString( eNpcName->data().Text.SGL ).empty() )
|
||||||
|
enpcNames[id] = eNpcName->getString( eNpcName->data().Text.SGL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( auto name = enpcNames.find( id ); name != enpcNames.end() )
|
||||||
|
return name->second;
|
||||||
|
}
|
||||||
|
// eobj
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( eobjNames.empty() )
|
||||||
|
{
|
||||||
|
auto nameIdList = g_exdDataGen.getIdList< Excel::EObj >();
|
||||||
|
for( auto id : nameIdList )
|
||||||
|
{
|
||||||
|
auto eObjName = g_exdDataGen.getRow< Excel::EObj >( id );
|
||||||
|
if( eObjName && !eObjName->getString( eObjName->data().Text.SGL ).empty() )
|
||||||
|
eobjNames[id] = eObjName->getString( eObjName->data().Text.SGL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( auto name = eobjNames.find( id ); name != eobjNames.end() )
|
||||||
|
return name->second;
|
||||||
|
}
|
||||||
|
return invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
createScript( std::shared_ptr< Excel::ExcelStruct< Excel::Quest > >& pQuestData, std::set< std::string >& additionalList, int questId, std::vector< std::string >& functions )
|
createScript( std::shared_ptr< Excel::ExcelStruct< Excel::Quest > >& pQuestData, std::set< std::string >& additionalList, int questId, std::vector< std::string >& functions )
|
||||||
{
|
{
|
||||||
|
@ -152,11 +296,6 @@ createScript( std::shared_ptr< Excel::ExcelStruct< Excel::Quest > >& pQuestData,
|
||||||
std::size_t splitPos( pQuestData->getString( pQuestData->data().Script ).find( '_' ) );
|
std::size_t splitPos( pQuestData->getString( pQuestData->data().Script ).find( '_' ) );
|
||||||
std::string className( pQuestData->getString( pQuestData->data().Script ).substr( 0, splitPos ) );
|
std::string className( pQuestData->getString( pQuestData->data().Script ).substr( 0, splitPos ) );
|
||||||
|
|
||||||
if( className == "SubFst033" )
|
|
||||||
{
|
|
||||||
className = className;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string todoInfo;
|
std::string todoInfo;
|
||||||
for( int i = 0; i < 23; ++i )
|
for( int i = 0; i < 23; ++i )
|
||||||
{
|
{
|
||||||
|
@ -181,8 +320,8 @@ createScript( std::shared_ptr< Excel::ExcelStruct< Excel::Quest > >& pQuestData,
|
||||||
std::string rewardString(
|
std::string rewardString(
|
||||||
" if( result.getResult( 0 ) == 1 )\n"
|
" if( result.getResult( 0 ) == 1 )\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" if( player.giveQuestRewards( getId(), 0 ) )\n"
|
" if( player.giveQuestRewards( getId(), 0, result.getResult( 1 ) )\n"
|
||||||
" player.finishQuest( getId() );\n"
|
" player.finishQuest( getId(), result.getResult( 1 ) );\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -319,29 +458,43 @@ createScript( std::shared_ptr< Excel::ExcelStruct< Excel::Quest > >& pQuestData,
|
||||||
|
|
||||||
if( !name.empty() )
|
if( !name.empty() )
|
||||||
{
|
{
|
||||||
if( titleCaseNoUnderscores(name).substr( 0, 5 ) == "Actor" )
|
auto nameStripped = titleCaseNoUnderscores( name );
|
||||||
{
|
if( nameStripped.substr( 0, 5 ) == "Actor" )
|
||||||
actorList.push_back( titleCaseNoUnderscores( name ) );
|
actorList.push_back( titleCaseNoUnderscores( name ) );
|
||||||
|
|
||||||
|
std::transform( nameStripped.begin(), nameStripped.end(), nameStripped.begin(), ::tolower);
|
||||||
|
// comment actor names and positions if possible
|
||||||
|
if( nameStripped.find( "acto" ) != std::string::npos || nameStripped.find( "enemy" ) != std::string::npos
|
||||||
|
|| nameStripped.find( "eobj" ) != std::string::npos || nameStripped.find( "npc" ) != std::string::npos )
|
||||||
|
{
|
||||||
|
script_entities.push_back( name + " = " + std::to_string( pQuestData->data().Define[ ca ].Value ) + "; // " +
|
||||||
|
getActorNameFromExd( pQuestData->data().Define[ca].Value ) + getActorPosFromLevelExd( pQuestData->data().Define[ca].Value ) );
|
||||||
}
|
}
|
||||||
script_entities.push_back(
|
// comment item names
|
||||||
name + " = " + std::to_string( pQuestData->data().Define[ ca ].Value ) );
|
else if( nameStripped.find( "ritem" ) != std::string::npos )
|
||||||
|
{
|
||||||
|
script_entities.push_back( name + " = " + std::to_string( pQuestData->data().Define[ ca ].Value ) + "; // " + getItemNameFromExd( pQuestData->data().Define[ca].Value ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
script_entities.push_back(
|
||||||
|
name + " = " + std::to_string( pQuestData->data().Define[ ca ].Value ) + ";");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::sort( script_entities.begin(), script_entities.end() );
|
std::sort( script_entities.begin(), script_entities.end(), compareNat );
|
||||||
for( auto& entity : script_entities )
|
for( auto& entity : script_entities )
|
||||||
{
|
{
|
||||||
auto name = titleCaseNoUnderscores( entity );
|
auto name = titleCaseNoUnderscores( entity );
|
||||||
sentities += " static constexpr auto " + name + ";\n";
|
sentities += " static constexpr auto " + name + "\n";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string additional = "// Quest Script: " + pQuestData->getString( pQuestData->data().Script ) + "\n";
|
std::string additional = "// Quest Script: " + pQuestData->getString( pQuestData->data().Script ) + "\n";
|
||||||
additional += "// Quest Name: " + pQuestData->getString( pQuestData->data().Text.Name ) + "\n";
|
additional += "// Quest Name: " + pQuestData->getString( pQuestData->data().Text.Name ) + "\n";
|
||||||
additional += "// Quest ID: " + std::to_string( questId ) + "\n";
|
additional += "// Quest ID: " + std::to_string( questId ) + "\n";
|
||||||
additional += "// Start NPC: " + std::to_string( pQuestData->data().Client ) + "\n";
|
additional += "// Start NPC: " + std::to_string( pQuestData->data().Client ) + " (" + getActorNameFromExd( pQuestData->data().Client ) + ")\n";
|
||||||
additional += "// End NPC: " + std::to_string( pQuestData->data().Finish ) + "\n\n";
|
additional += "// End NPC: " + std::to_string( pQuestData->data().Finish ) + " (" + getActorNameFromExd( pQuestData->data().Finish ) + ")\n\n";
|
||||||
|
|
||||||
additional += "using namespace Sapphire;\n\n";
|
additional += "using namespace Sapphire;\n\n";
|
||||||
|
|
||||||
|
@ -598,7 +751,7 @@ int main( int argc, char** argv )
|
||||||
offset += static_cast< uint32_t >( entry.size() + 1 );
|
offset += static_cast< uint32_t >( entry.size() + 1 );
|
||||||
|
|
||||||
if( entry.size() > 3
|
if( entry.size() > 3
|
||||||
&& entry.find_first_not_of( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_-" ) ==
|
&& entry.find_first_not_of( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-" ) ==
|
||||||
std::string::npos )
|
std::string::npos )
|
||||||
{
|
{
|
||||||
if( entry.find( "SEQ" ) != std::string::npos
|
if( entry.find( "SEQ" ) != std::string::npos
|
||||||
|
|
Loading…
Add table
Reference in a new issue