Contém um arquivo de cabeçalho e um banco de dados para facilitar a instalação de plugins DLL do SKSE independentes da versão.
Importante! Agora, isso é dividido em duas versões: Edição Especial (1.5.x) e Edição Aniversária (1.6.x). Os id que apontam para endereços não correspondem entre as duas versões (os arquivos executáveis do jogo são muito diferentes para corresponder e, mesmo que sejam correspondentes, o código nessas funções será diferente).ExplicaçãoPara usuários comuns de mod: Baixe e instale o pacote de software "integrado" da seção do arquivo. Você pode usar o mod manager ou executá-lo manualmente. O arquivo .bin deve ser colocado aqui:
Dados/SKSE/plug-in/Você não precisa ler o restante do conteúdo.
Para o autor do plug-in SKSE DLL:Este é um recurso de modder (arquivo de cabeçalho). Você pode carregar um banco de dados que armazena despesas de deslocamento para que seu plug-in DLL possa ser independente da versão sem precisar ser recompilado. O arquivo de cabeçalho pode ser baixado da parte opcional do arquivo. Para a edição de aniversário, o arquivo de cabeçalho é chamado de versionlibdb.h, não versiondb.h! Se você estiver usando CommonLib, tudo isso é integrado e você não precisa de nada aqui.
Como usarA maneira mais rápida:
Spoiler:
Show
#Incluindo "versiondb.h"
void*MyAddress=NULL
long long long MYOFSET sem sinal = 0;
Introdução bool Zoffsetts()
{
//Atribua na pilha para que ela seja desinstalada quando saímos desta função.
//Não há necessidade de carregar o banco de dados inteiro e a memória está esgotada sem motivo.
Banco de dados de versão;
//Carregando o banco de dados usando a versão executável atual.
Se (!db.Load())
{
_Fatalero ("O banco de dados de versão do arquivo executável atual não pode ser carregado!");
}
else
{
//"SkyrimSE.exe", "1.5.97.0"
_MESSAGE ("Banco de dados carregado da versão %s %s", DB.getmolemename ().c_str (), DB.getloadversão ().c_str ());
}
//Este endereço já contém o endereço base do módulo, então podemos usá-lo diretamente.
MyAddress=DB.Findressbyd(123);
if(MyAddress==NULL)
{
_Faterrol ("Endereço não foi encontrado!");
Retorne a false;
}
//Este deslocamento não inclui o local. O endereço real será ModuleBase+MYOFSET.
if(!DB.FinDOFSETBYID (123, MyOffset))
{
_Fatalero ("Não consigo encontrar o deslocamento das minhas coisas!");
}
//Tudo teve sucesso.
Retornar a verdade;
}
Agora você quer saber qual é o valor "123" lá. Este é o ID de um endereço. Diferentes versões de bancos de dados terão o mesmo ID de endereço, mas podem apontar para valores diferentes. Para obter uma lista de todos os ID e pares de valores para uma versão específica, faça o seguinte:
Spoiler:
Show
#Incluindo "versiondb.h"
Boolean Dumping SPECIFESION()
{
Banco de dados de versão;
//Tente carregar a versão 1.5.62.0 do banco de dados, independentemente da versão executável em execução.
Se (!db.Load (1, 5, 62, 0))
{
_Fatalero ("Banco de dados 1.5.62.0 não pode ser carregado!");
Retorne a false;
}
//Escreva um arquivo chamado offfsets-1.5.62.0.txt, onde cada linha contém ID e desplazamento.
db.Dump ("offsets-1.5.62.0.txt");
_MESSAGE ("1.5.62.0 deslocamento de dump");
Retornar a verdade;
}
Em vez de usar 1, 5, 62, 0, use a versão com a qual você está revertido e com a qual está familiarizado. Primeiro, você deve ter o arquivo de banco de dados correspondente no diretório /Data/SKSE/Plugins.
Após a chamada, você deve ter um novo arquivo chamado "offsets-1.5.62.0.txt" no diretório principal do Skyrim, ou qualquer nome de arquivo que você inserir. O formato de cada linha é o seguinte:
ID decimal<tab>Deslocamento hexagonal<newline>
Por exemplo, se você tiver um endereço 142F4Dev8 (ponteiro estático para personagens do jogador) em 1.5.62.0 e quiser torná-lo irrelevante para a versão, você pode fazer o seguinte:
1. Procure 2F4DEF8 no arquivo offsets. Porque esse é um deslocamento sem base de 14.0000.000
2. Vejo o ID 517014 (decimal!)
3. Se você quiser incluir este endereço em um DLL durante o tempo de execução, faça o seguinte:
void*addressof 142 f 4 def8=DB.Findressbyd (517014);
Agora você tem.
A estrutura VersionDb tem as seguintes funções:
Spoiler:
Show
Dumping boolean (padrão constante: strings e caminhos); //Dumpe o banco de dados atualmente carregado em um arquivo
Carregamento booleano (int Maker, int minor, int revision, int build); //Se db-macher-minor-revision-build.bin estiver presente no diretório Data/SKSE/Plugins, uma versão específica será carregada
bool Load (); //Carregar a versão do aplicativo atual
void Clear (); //Limpar o banco de dados atualmente carregado
void Getloadversion (int & major, int & minor, int & revision, int & build); //Obtenha a versão do arquivo de banco de dados que estamos carregando atualmente
Constante de bool GETEXUABLOVEOR (int & MJOR, int & minor, int & MINISOR, int & MINISOR, int & MINISOR, int & MINISOR, //Obtenha a versão do aplicativo atualmente executado
const std:: string&GETMOLENome ()const; //Obtenha o nome do módulo de banco de dados atualmente carregado, que deve exibir "SkyrimSE.exe"
const std:: string & GETLODSTRING ()const; //Obtenha a versão carregada atualmente em uma string, como "1.5.62.0"
const std:: map<unsigned long long, unsigned long long>&GetOffsetMap () constante; //Se for necessária iteração manual, obtenha o mapeamento do ID para o offset
Constante void*Findressbyid (id longo sem símbolo); //Procure o endereço por ID, que já incluirá o endereço base e será o endereço correto. Se não for encontrado, ele retornará a NULL!
BOL FinDOFSETBYID (id longo sem sinal, longo sem sinal & resultado) constante; //Procure deslocamentos por ID, o que será apenas um deslocamento que não inclui o número base.
Constante (vod*ptr, longlong & resolt sem sinal); //Pesquisar ID por endereço, o que tenta pesquisar reversa para converter o endereço em ID
Constantes bool FinDIDBOFSET (deslocamento de comprimento sem sinal, comprimento sem sinal & resultado); //Pesquisar ID por desplazamento, que tentará pesquisar reversa para converter o desplazamento em um ID
Coisas que você deve saber e lembrar:
1. Você pode incluir qualquer (ou todos) arquivos de banco de dados no plug-in, mas isso pode aumentar significativamente o tamanho do arquivo (aproximadamente 2,5 mb). Até agora, esse mod é frequentemente marcado como dependência.
2. Você deve sempre carregar o banco de dados apenas uma vez no início, inicializar/armazenar em cache o endereço necessário e deixá-lo desinstalá-lo. Desinstalar significa simplesmente que a estrutura VersionDb é excluída ou perdida (se você a atribuir na pilha). Isso garantirá que você não use memória desnecessária enquanto o jogo estiver em execução. Não há necessidade de manter o banco de dados carregado durante o jogo. Se você usar o CommonLib, essa é uma questão controversa porque ele é carregado apenas uma vez, não para cada DLL.
3. O banco de dados contém endereços para funções, variáveis globais, RTTI, vtables e qualquer outro conteúdo que possa ser referenciado a eles. Não contém endereços localizados no meio de uma função ou no meio do mundo global. Se precisar de um endereço no meio de uma função, você deve procurar o endereço base da função e adicionar desplazamento adicional. Ele também não contém coisas inúteis, como alinhamento ao redor da função (referência em rdata), descarte da parte pdata e descarte de informações SEH geradas por alguns compiladores a partir da rdata.
4. Você deve sempre verificar os resultados para garantir que o banco de dados seja carregado com sucesso (o bool Load retorna verdade) e que o endereço da consulta realmente retorna um resultado válido (não NULL). SE não puder ser carregado, isso significa que o arquivo provavelmente será perdido ou terá um erro de versão (por exemplo, tentando usar o cabeçalho SE em AE). Se a consulta falhar, significa que o endereço não poderá ser encontrado nesta versão. Isso pode significar que o código do jogo mudou muito o suficiente para que o endereço não seja mais válido para a versão, ou que o próprio banco de dados não consegue detectar o endereço correto. Se qualquer uma dessas duas situações ocorrer, você deve deixar o plug-in falhar na inicialização e deixar a SKSE saber que você não está carregando corretamente. Ou exiba manualmente a mensagem de erro.
5. Também é melhor se você verificar antes de lançar um plug-in DLL para garantir que o endereço esteja em todas as versões do jogo. Para isso, carregue cada versão do arquivo de banco de dados e consulte o mesmo ID de endereço em cada versão para garantir sua existência:
Spoiler:
Show
bool LoadAll (std:: vector<VersionDb*>(&all)
{
Versão estática int []={3, 16, 23, 39, 50, 53, 62, 73, 80, 97, -1};
Para (int i=0; versão [i]>=0;i++)
{
version db*db=Nova version db();
if(!db->Load (1, 5, versão [i], 0))
{
Excluir o banco de dados;
Retorne a false;
}
all.push_back (db);
}
Retornar a verdade;
}
bool ExistSmall (std::: vector<VersionDb*>(&all, sem id longo de símbolo)
{
Resultado longo sem sinal = 0;
{
if(!db-> Findoffsetyid (id, resultado))
}
Retornar a verdade;
}
void FreeAll (std:: vector<VersionDb*>(&all)
{
Para (banco de dados automático: todos)
Excluir o banco de dados;
Todos. clear ();
}
Boolean IsOk ()
{
std:: vector<VersionDb*>Todos;
Se (! LOALL)
{
_Fatalero ("Não pode carregar uma ou mais versões do banco de dados do arquivo executável atual!");
FreeAll (todos);
Retorne a false;
}
if(! ExistsInAll (all, 517014))
{
_Fatalero ("517014 não existe em todas as versões do banco de dados!");
}
FreeAll (todos);
//Ok!
Retornar a verdade;
}
Dessa forma, você pode garantir que seu DLL mod funcione em todas as versões ou, se não funcionar em algumas versões, você pode escrevê-lo em sua página mod.
6. Às vezes você precisa fazer algo diferente dependendo da versão do jogo em que você está em execução. Você pode fazer isso usando os seguintes fragmentos de código:
Spoiler:
Show
int major=0, minor=0, Revisão=0, build=0;
if (! DB.getexuttableversion (major, minor, revision, build))
{
_Fatalero ("Algo errado!");
Retorne a false;
}
//O jogo em execução é 1.5.x e pelo menos 1.5.39.0
Se (principal===1&secundário==5&revisado>=39)
{
//Coisas...?
}
7. Lembre-se: se você compilar seu SKSE DLL no modo de depuração, o banco de dados pode ser carregado em cerca de 14 segundos! No modo de liberação, isso é de cerca de 0,2 segundos. Isso ocorre porque o contêiner da biblioteca padrão é muito lento neste modo (mapa std).
PermissãoFaça o que quiser.