Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drake has wrong body skin color #129

Merged
merged 1 commit into from May 9, 2021
Merged

Drake has wrong body skin color #129

merged 1 commit into from May 9, 2021

Conversation

AmProsius
Copy link
Owner

@AmProsius AmProsius commented May 9, 2021

Describe the bug
Drake's body skin color does not match his head.

Expected behavior
Drake's body skin color now matches his head.

Additional context
Instance Grd_260_Drake.

@AmProsius AmProsius changed the title Grd_260_Drake uses the wrong body texture Drake has wrong body texture Feb 16, 2021
@szapp szapp added compatibility: difficult type: revert on save compatibility: easy and removed compatibility: difficult labels Feb 16, 2021
@szapp
Copy link
Collaborator

@szapp szapp commented Feb 17, 2021

Similar to #124. No, see below.

@AmProsius AmProsius added the validation: validated label Feb 18, 2021
@szapp szapp added this to NPC property in Fix templates Apr 5, 2021
@szapp szapp added compatibility: difficult impl: modify/analyze script func and removed compatibility: easy labels Apr 5, 2021
@szapp
Copy link
Collaborator

@szapp szapp commented Apr 5, 2021

//-------- visuals --------
// animations
Mdl_SetVisual (self,"HUMANS.MDS");
Mdl_ApplyOverlayMds (self,"Humans_Militia.mds");
// body mesh ,bdytex,skin,head mesh ,1headtex,teethtex,ruestung
Mdl_SetVisualBody (self,"hum_body_Naked0", 0, 3,"Hum_Head_Fighter",110 , 1, GRD_ARMOR_M);
B_Scale (self);
Mdl_SetModelFatness(self,0);

The forth argument passed to the function Mdl_SetVisualBody has to be adjusted. I don't know by heart to what number. To replace it the function call and its arguments need to be identified within the instance function.

@AmProsius
Copy link
Owner

@AmProsius AmProsius commented Apr 6, 2021

The forth argument passed to the function Mdl_SetVisualBody has to be adjusted.

We want to change the body texture, so it's actually the second argument.

@szapp
Copy link
Collaborator

@szapp szapp commented Apr 6, 2021

No, the second argument is the body mesh.

Gothic refers to a 3D model as mesh and a surface color/pattern/image as texture.

Parameters of Mdl_SetVisualBody:

  1. NPC instance
  2. Body mesh (= 3D model of the body, for humans either "hum_body_Naked0" or "Bab_body_Naked0")
  3. Body texture (= Image placed on the mesh)
  4. Body skin color (= Texture variation)
  5. Head mesh
  6. Head texture
  7. Teeth texture
  8. Armor

Here, Drake's body skin has a darker shade than his head does. (I will update the title and description of this issue.)

image

changed to

image

Provided Fix

//-------- visuals --------
// animations
Mdl_SetVisual (self,"HUMANS.MDS");
Mdl_ApplyOverlayMds (self,"Humans_Militia.mds");
// body mesh ,bdytex,skin,head mesh ,1headtex,teethtex,ruestung
Mdl_SetVisualBody (self,"hum_body_Naked0", 0, 3,"Hum_Head_Fighter",110 , 1, GRD_ARMOR_M);
B_Scale (self);
Mdl_SetModelFatness(self,0);

changed to

    //-------- visuals --------
    //          animations
    Mdl_SetVisual       (self,"HUMANS.MDS");
    Mdl_ApplyOverlayMds (self,"Humans_Militia.mds");
    //          body mesh     ,bdytex,skin,head mesh     ,1headtex,teethtex,ruestung
    Mdl_SetVisualBody (self,"hum_body_Naked0", 0, 1,"Hum_Head_Fighter",110 ,  1, GRD_ARMOR_M);

    B_Scale (self);
        Mdl_SetModelFatness(self,0);

Since the NPC appearance is not loaded from the savegame but set by the NPC's instance function, this fix does not have to be reverted. Instead, the instance function will be modified to replace the forth argument to the function call. The way I would implement it is by finding the last call to Mdl_SetVisualBody in the function (zPAR_TOK_CALLEXTERN MEM_GetFuncID(Mdl_SetVisualBody)). From the address of the call, go 25 bytes back (5 bytes for each of the last 5 pushed arguments). Then, check against zPAR_TOK_PUSHINT 3 or zPAR_TOK_PUSHVAR some variable with content 3. If so, replace it by zPAR_TOK_PUSHINT 1 and mark the fix as applied.



This is a draft for the implementation:

/*
 * #129 Drake has wrong body skin color
 */
func int G1CP_149_DrakeBodySkin() {
    var int applied; applied = FALSE;

    // Get necessary symbol indices
    var int symbId; symbId = G1CP_GetNpcInstID("Grd_260_Drake");
    if (symbId == -1) {
        return FALSE;
    };

    // Find call to "Mdl_SetVisualBody"
    const int bytes[2] = {zPAR_TOK_CALLEXTERNAL<<24, -1};
    bytes[1] = MEM_GetFuncID(Mdl_SetVisualBody);
    var int matches; matches = G1CP_FindInFunc(symbId, _@(bytes)+3, 5);

    // Check for last occurrence
    if (MEM_ArraySize(matches) > 0) {
        var int pos; pos = MEM_ArrayLast(matches);

        // Get the necessary pushed arguments
        var int arg6; arg6 = MEM_ReadInt(pos-14);
        var int arg4; arg4 = MEM_ReadInt(pos-24);
        if (MEM_ReadByte(pos-15) == zPAR_TOK_PUSHVAR) {
            arg6 = G1CP_GetIntI(arg6, 0, arg6);
        };
        if (MEM_ReadByte(pos-25) == zPAR_TOK_PUSHVAR) {
            arg4 = G1CP_GetIntI(arg4, 0, arg4);
        };

        // Confirm head texture and body skin color
        if (arg6 == 110) && (arg4 == 3) {
            // Write the correct byte code for the forth argument
            MEMINT_OverrideFunc_Ptr = pos-25;
            MEMINT_OFTokPar(zPAR_TOK_PUSHINT, 1);
            applied = TRUE;
        };
    };

    // Free the array
    MEM_ArrayFree(matches);

    return applied;
};

As for a test, create a manual one, that teleports the player to the waypoint in front of Drake. There is example code on how to auto-trigger changing the world. See the test regarding the Free Mine.

@szapp szapp added provided fix type: session fix and removed type: revert on save labels Apr 6, 2021
@szapp szapp changed the title Drake has wrong body texture Drake has wrong body skin color Apr 6, 2021
@szapp szapp added provided implementation compatibility: easy and removed provided fix compatibility: difficult labels Apr 12, 2021
@AmProsius AmProsius added this to To Do in v1.2.0 Apr 17, 2021
@AmProsius AmProsius self-assigned this Apr 17, 2021
@AmProsius AmProsius added this to the v1.2.0 milestone Apr 18, 2021
@AmProsius AmProsius merged commit 999b8f7 into master May 9, 2021
v1.2.0 automation moved this from To Do to Done May 9, 2021
@AmProsius AmProsius deleted the bug129 branch May 9, 2021
@AmProsius AmProsius removed their assignment May 12, 2021
Copy link
Collaborator

@szapp szapp left a comment

@AmProsius I noted a slight improvement. Otherwise all good.

// Find call to "Mdl_SetVisualBody"
const int bytes[2] = {zPAR_TOK_CALLEXTERN<<24, -1};
bytes[1] = MEM_GetFuncID(Mdl_SetVisualBody);
var int matches; matches = G1CP_FindInFunc(symbId, _@(bytes)+3, 5);
Copy link
Collaborator

@szapp szapp May 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks to more recent changes we can replace these three lines by just one:

// Find call to "Mdl_SetVisualBody"
var int matches; matches = G1CP_FindCall(symbId, 0, MEM_GetFuncID(Mdl_SetVisualBody));

It may be even possible to omit the call to MEM_GetFuncID - that should be tested.

AmProsius added a commit that referenced this issue May 14, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compatibility: easy impl: modify/analyze script func provided implementation type: session fix validation: validated
Projects
Fix templates
Change NPC instance variable (int)
v1.2.0
  
Done
Development

Successfully merging this pull request may close these issues.

None yet

2 participants