Hola comunidad, estoy trabajando en una adaptación visual para mi servidor Season 3 (Main 1.04x).
Estoy portando el código de **RenderLinkObject** (original de fuentes S6) para que las **Armaduras +15** tengan los efectos visuales correctos (Magic + Shiny) alineados a los huesos del personaje.
Ya adapté toda la lógica matemática del archivo original. Tengo las **Matrices de Transformación** y los ángulos para cada parte del set (Casco, Botas, Guantes, etc.), de modo que el brillo no salga "chueco" o en el piso.
// ... resto de los casos (Head, Boots, etc) ...
El código original de S6 usa una función `RenderLinkObject` con **12 argumentos**.
En mi Main Season 3, la función equivalente (`RenderPartObjectBody` o similar) usa **9 argumentos** y no pasa el puntero `CHARACTER*` explícitamente.
Necesito ayuda para ubicar el **Offset correcto** de la función que renderiza las partes del cuerpo en un Main Season 3 (Protocolo KOR/JPN 1.04x).
* Dato: Mi `GetItemColor` está en `0x0052870B`.
* Sé que la función que busco llama a `GetItemColor` internamente.
Si alguien tiene el offset o sabe cómo adaptar el Hook para que tome estas matrices en S3, agradecería mucho la ayuda. Estoy dispuesto a liberar el código completo de la clase `ArmorEffect` con las matemáticas corregidas una vez funcione.
LoadItemModel(MODEL_15GRADE_ARMOR_OBJ_ARMLEFT, "Item\\", "class15_armleft");
LoadItemModel(MODEL_15GRADE_ARMOR_OBJ_ARMRIGHT, "Item\\", "class15_armright");
LoadItemModel(MODEL_15GRADE_ARMOR_OBJ_BODYLEFT, "Item\\", "class15_bodyleft");
LoadItemModel(MODEL_15GRADE_ARMOR_OBJ_BODYRIGHT, "Item\\", "class15_bodyright");
LoadItemModel(MODEL_15GRADE_ARMOR_OBJ_BOOTLEFT, "Item\\", "class15_bootleft");
LoadItemModel(MODEL_15GRADE_ARMOR_OBJ_BOOTRIGHT, "Item\\", "class15_bootright");
LoadItemModel(MODEL_15GRADE_ARMOR_OBJ_HEAD, "Item\\", "class15_head");
LoadItemModel(MODEL_15GRADE_ARMOR_OBJ_PANTLEFT, "Item\\", "class15_pantleft");
LoadItemModel(MODEL_15GRADE_ARMOR_OBJ_PANTRIGHT, "\\Item\\", "class15_pantright");
LoadItemTexture(MODEL_15GRADE_ARMOR_OBJ_ARMLEFT, "Item\\");
LoadItemTexture(MODEL_15GRADE_ARMOR_OBJ_ARMRIGHT, "Item\\");
LoadItemTexture(MODEL_15GRADE_ARMOR_OBJ_BODYLEFT, "Item\\");
LoadItemTexture(MODEL_15GRADE_ARMOR_OBJ_BODYRIGHT, "Item\\");
LoadItemTexture(MODEL_15GRADE_ARMOR_OBJ_BOOTLEFT, "Item\\");
LoadItemTexture(MODEL_15GRADE_ARMOR_OBJ_BOOTRIGHT, "Item\\");
LoadItemTexture(MODEL_15GRADE_ARMOR_OBJ_HEAD, "Item\\");
LoadItemTexture(MODEL_15GRADE_ARMOR_OBJ_PANTLEFT, "Item\\");
LoadItemTexture(MODEL_15GRADE_ARMOR_OBJ_PANTRIGHT, "Item\\");
// ============================================================
// SECCIÓN 1: Verificación de tipo de armadura en RenderLinkObject
// ============================================================
void RenderLinkObject(float x, float y, float z, CHARACTER* c, PART_t* f, int Type, int Level, int Option1, bool Link, bool Translate, int RenderType, bool bRightHandItem)
{
// ... código anterior omitido ...
// Configuración de matriz de transformación para piezas de armadura grado 15
if (Type == MODEL_15GRADE_ARMOR_OBJ_ARMLEFT || Type == MODEL_15GRADE_ARMOR_OBJ_ARMRIGHT ||
Type == MODEL_15GRADE_ARMOR_OBJ_BODYLEFT || Type == MODEL_15GRADE_ARMOR_OBJ_BODYRIGHT ||
Type == MODEL_15GRADE_ARMOR_OBJ_BOOTLEFT || Type == MODEL_15GRADE_ARMOR_OBJ_BOOTRIGHT ||
Type == MODEL_15GRADE_ARMOR_OBJ_HEAD || Type == MODEL_15GRADE_ARMOR_OBJ_PANTLEFT ||
Type == MODEL_15GRADE_ARMOR_OBJ_PANTRIGHT)
{
switch (Type)
{
case MODEL_15GRADE_ARMOR_OBJ_ARMLEFT:
{
Vector(0.f, -90.f, 0.f, Angle);
AngleMatrix(Angle, Matrix);
Matrix[0][3] = 30.f;
Matrix[1][3] = 0.f;
Matrix[2][3] = 20.f;
}break;
case MODEL_15GRADE_ARMOR_OBJ_ARMRIGHT:
{
Vector(0.f, -90.f, 0.f, Angle);
AngleMatrix(Angle, Matrix);
Matrix[0][3] = 30.f;
Matrix[1][3] = 0.f;
Matrix[2][3] = -20.f;
}break;
case MODEL_15GRADE_ARMOR_OBJ_BODYLEFT:
{
Vector(0.f, -90.f, 0.f, Angle);
AngleMatrix(Angle, Matrix);
Matrix[0][3] = 5.f;
Matrix[1][3] = -20.f;
Matrix[2][3] = 0.f;
}break;
case MODEL_15GRADE_ARMOR_OBJ_BODYRIGHT:
{
Vector(0.f, -90.f, 0.f, Angle);
AngleMatrix(Angle, Matrix);
Matrix[0][3] = 5.f;
Matrix[1][3] = -20.f;
Matrix[2][3] = 0.f;
}break;
case MODEL_15GRADE_ARMOR_OBJ_BOOTLEFT:
{
Vector(0.f, 90.f, 180.f, Angle);
AngleMatrix(Angle, Matrix);
Matrix[0][3] = 20.f;
Matrix[1][3] = 15.f;
Matrix[2][3] = -10.f;
}break;
case MODEL_15GRADE_ARMOR_OBJ_BOOTRIGHT:
{
Vector(0.f, 90.f, 180.f, Angle);
AngleMatrix(Angle, Matrix);
Matrix[0][3] = 20.f;
Matrix[1][3] = 15.f;
Matrix[2][3] = 10.f;
}break;
case MODEL_15GRADE_ARMOR_OBJ_HEAD:
{
Vector(180.f, -90.f, 0.f, Angle); // y, x, z
AngleMatrix(Angle, Matrix);
Matrix[0][3] = 28.f; // y
Matrix[1][3] = 20.f; // x
Matrix[2][3] = 0.f;
}break;
case MODEL_15GRADE_ARMOR_OBJ_PANTLEFT:
{
Vector(0.f, 90.f, 180.f, Angle);
AngleMatrix(Angle, Matrix);
Matrix[0][3] = 25.f;
Matrix[1][3] = 5.f;
Matrix[2][3] = -5.f;
}break;
case MODEL_15GRADE_ARMOR_OBJ_PANTRIGHT:
{
Vector(0.f, 90.f, 180.f, Angle);
AngleMatrix(Angle, Matrix);
Matrix[0][3] = 25.f;
Matrix[1][3] = 5.f;
Matrix[2][3] = 5.f;
}break;
}
}
// ... resto del código omitido ...
}
// ============================================================
// SECCIÓN 2: Renderizado del cuerpo en RenderPartObjectBody
// ============================================================
void RenderPartObjectBody(BMD* b, OBJECT* o, int Type, float Alpha, int RenderType)
{
// ... código anterior omitido ...
if (o->Type == MODEL_15GRADE_ARMOR_OBJ_ARMLEFT ||
o->Type == MODEL_15GRADE_ARMOR_OBJ_ARMRIGHT ||
o->Type == MODEL_15GRADE_ARMOR_OBJ_BODYLEFT ||
o->Type == MODEL_15GRADE_ARMOR_OBJ_BODYRIGHT ||
o->Type == MODEL_15GRADE_ARMOR_OBJ_BOOTLEFT ||
o->Type == MODEL_15GRADE_ARMOR_OBJ_BOOTRIGHT ||
o->Type == MODEL_15GRADE_ARMOR_OBJ_HEAD ||
o->Type == MODEL_15GRADE_ARMOR_OBJ_PANTLEFT ||
o->Type == MODEL_15GRADE_ARMOR_OBJ_PANTRIGHT)
{
float fLight, texCoordU;
// Primer pase: Renderizado con brillo variable
fLight = 0.8f - absf(sinf(WorldTime * 0.0018f) * 0.5f);
b->RenderMesh(0, RENDER_TEXTURE | RENDER_BRIGHT, o->Alpha, 0, fLight - 0.1f, o->BlendMeshTexCoordU, o->BlendMeshTexCoordV);
// Segundo pase: Efecto de textura animada
texCoordU = absf(sinf(WorldTime * 0.0005f));
b->RenderMesh(0, RENDER_TEXTURE | RENDER_BRIGHT, o->Alpha, 0, fLight - 0.3f, texCoordU, o->BlendMeshTexCoordV, BITMAP_RGB_MIX);
// Tercer pase: Efecto cromado
b->RenderMesh(0, RENDER_TEXTURE | RENDER_CHROME4, o->Alpha, 0, o->BlendMeshLight, o->BlendMeshTexCoordU, o->BlendMeshTexCoordV);
}
}
// ============================================================
// SECCIÓN 3: Renderizado de efectos de armadura en NextGradeObjectRender
// ============================================================
void NextGradeObjectRender(CHARACTER* c)
{
// ... código anterior omitido ...
int bornIndex[2]{}; // left, right
int gradeType[2]{}; // left, right
BMD* b = &Models[c->Object.Type];
PART_t* w;
vec3_t vPos, vLight;
float fLight2;
int Level;
// Iterar sobre todas las partes del cuerpo
for (int k = 0; k < MAX_BODYPART; k++)
{
w = &c->BodyPart[k];
Level = w->Level;
if (k == 0) continue; // Saltar primera parte
if (Level < 15 || w->Type == -1) continue; // Solo grado 15+
// Asignar índices de huesos y tipos según la parte del cuerpo
switch (k)
{
case 1: // Cabeza
{
bornIndex[0] = 20;
bornIndex[1] = -1;
gradeType[0] = MODEL_15GRADE_ARMOR_OBJ_HEAD;
gradeType[1] = -1;
}break;
case 2: // Cuerpo
{
bornIndex[0] = 35;
bornIndex[1] = 26;
gradeType[0] = MODEL_15GRADE_ARMOR_OBJ_BODYLEFT;
gradeType[1] = MODEL_15GRADE_ARMOR_OBJ_BODYRIGHT;
}break;
case 3: // Pantalones
{
bornIndex[0] = 3;
bornIndex[1] = 10;
gradeType[0] = MODEL_15GRADE_ARMOR_OBJ_PANTLEFT;
gradeType[1] = MODEL_15GRADE_ARMOR_OBJ_PANTRIGHT;
}break;
case 4: // Brazos
{
bornIndex[0] = 36;
bornIndex[1] = 27;
gradeType[0] = MODEL_15GRADE_ARMOR_OBJ_ARMLEFT;
gradeType[1] = MODEL_15GRADE_ARMOR_OBJ_ARMRIGHT;
}break;
case 5: // Botas
{
bornIndex[0] = 4;
bornIndex[1] = 11;
gradeType[0] = MODEL_15GRADE_ARMOR_OBJ_BOOTLEFT;
gradeType[1] = MODEL_15GRADE_ARMOR_OBJ_BOOTRIGHT;
}break;
default:
bornIndex[0] = -1;
bornIndex[1] = -1;
gradeType[0] = -1;
gradeType[1] = -1;
break;
}
OBJECT* o = &c->Object;
// Renderizar efectos para cada lado (izquierdo/derecho)
for (int m = 0; m < 2; m++)
{
if (gradeType[m] == -1) continue;
switch (Level)
{
case 15: // Efectos para armadura +15
{
// Vincular al hueso correspondiente
w->LinkBone = bornIndex[m];
// Renderizar objeto vinculado
RenderLinkObject(0.f, 0.f, 0.f, c, w, gradeType[m], 0, 0, true, true);
// Obtener posición transformada
b->TransformByBoneMatrix(vPos, BoneTransform[0], o->Position);
// Efecto mágico pulsante azul
fLight2 = absf(sinf(WorldTime * 0.01f));
Vector(0.2f * fLight2, 0.4f * fLight2, 1.0f * fLight2, vLight);
CreateSprite(BITMAP_MAGIC, vPos, 0.12f, vLight, o);
// Efecto brillante azul
Vector(0.4f, 0.7f, 1.0f, vLight);
CreateSprite(BITMAP_SHINY + 5, vPos, 0.4f, vLight, o);
// Efecto de luz pin azul rotado
Vector(0.1f, 0.3f, 1.0f, vLight);
CreateSprite(BITMAP_PIN_LIGHT, vPos, 0.6f, vLight, o, 90.0f);
}break;
}
}
}
}