Jump to content

CUSTOM SKEL NPC: AT-ST


Recommended Posts

Yes the misc_atst_driveable is completely separate from NPC vehicle code.

 

I have searched high and low for the files that control this vehicle, any idea where they are so that I can make the textures work? I feel like it's some sort of cfg file or something that is pointing to the base textures that are being over written so the misc_atst_driveable loads as my model but with missing shaders.

Link to comment

Dunno. It really is a weird thing:

/*QUAKED misc_atst_drivable (1 0 0.25) (-40 -40 -24) (40 40 248)
model="models/players/atst/model.glm"

Drivable ATST, when used by player, they become the ATST.  When the player hits use again, they get out.

"health" - how much health the atst has - default 800

"target" - what to use when it dies
*/
void misc_atst_setanim( gentity_t *self, int bone, int anim )
{
    if ( bone < 0 || anim < 0 )
    {
        return;
    }
    int    firstFrame = -1;
    int    lastFrame = -1;
    float animSpeed = 0;
    //try to get anim ranges from the animation.cfg for an AT-ST
    for ( int i = 0; i < level.numKnownAnimFileSets; i++ )
    {
        if ( !Q_stricmp( "atst", level.knownAnimFileSets[i].filename ) )
        {
            firstFrame = level.knownAnimFileSets[i].animations[anim].firstFrame;
            lastFrame = firstFrame+level.knownAnimFileSets[i].animations[anim].numFrames;
            animSpeed = 50.0f / level.knownAnimFileSets[i].animations[anim].frameLerp;
            break;
        }
    }
    if ( firstFrame != -1 && lastFrame != -1 && animSpeed != 0 )
    {
        if (!gi.G2API_SetBoneAnimIndex( &self->ghoul2[self->playerModel], bone, firstFrame,
                                lastFrame, BONE_ANIM_OVERRIDE_FREEZE|BONE_ANIM_BLEND, animSpeed,
                                (cg.time?cg.time:level.time), -1, 150 ))
        {
            gi.G2API_SetBoneAnimIndex( &self->ghoul2[self->playerModel], bone, firstFrame,
                                lastFrame, BONE_ANIM_OVERRIDE_FREEZE, animSpeed,
                                (cg.time?cg.time:level.time), -1, 150 );
        }
    }
}
void misc_atst_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int mod,int dFlags,int hitLoc )
{//ATST was destroyed while you weren't in it
    //can't be used anymore
    self->e_UseFunc = useF_NULL;
    //sigh... remove contents so we don't block the player's path...
    self->contents = CONTENTS_CORPSE;
    self->takedamage = qfalse;
    self->maxs[2] = 48;

    //FIXME: match to slope
    vec3_t effectPos;
    VectorCopy( self->currentOrigin, effectPos );
    effectPos[2] -= 15;
    G_PlayEffect( "explosions/droidexplosion1", effectPos );
//    G_PlayEffect( "small_chunks", effectPos );
    //set these to defaults that work in a worst-case scenario (according to current animation.cfg)
    gi.G2API_StopBoneAnimIndex( &self->ghoul2[self->playerModel], self->craniumBone );
    misc_atst_setanim( self, self->rootBone, BOTH_DEATH1 );
}

extern void G_DriveATST( gentity_t *ent, gentity_t *atst );
extern void SetClientViewAngle( gentity_t *ent, vec3_t angle );
extern qboolean PM_InSlopeAnim( int anim );
void misc_atst_use( gentity_t *self, gentity_t *other, gentity_t *activator )
{
    if ( !activator || activator->s.number )
    {//only player can do this
        return;
    }

    int    tempLocDmg[HL_MAX];
    int    hl, tempHealth;

    if ( activator->client->NPC_class != CLASS_ATST )
    {//get in the ATST
        if ( activator->client->ps.groundEntityNum != self->s.number )
        {//can only get in if on top of me...
            //we *could* even check for the hatch surf...?
            return;
        }
        //copy origin
        G_SetOrigin( activator, self->currentOrigin );

        //copy angles
        VectorCopy( self->s.angles2, self->currentAngles );
        G_SetAngles( activator, self->currentAngles );
        SetClientViewAngle( activator, self->currentAngles );

        //set player to my g2 instance
        gi.G2API_StopBoneAnimIndex( &self->ghoul2[self->playerModel], self->craniumBone );
        G_DriveATST( activator, self );
        activator->activator = self;
        self->s.eFlags |= EF_NODRAW;
        self->svFlags |= SVF_NOCLIENT;
        self->contents = 0;
        self->takedamage = qfalse;
        //transfer armor
        tempHealth = self->health;
        self->health = activator->client->ps.stats[STAT_ARMOR];
        activator->client->ps.stats[STAT_ARMOR] = tempHealth;
        //transfer locationDamage
        for ( hl = HL_NONE; hl < HL_MAX; hl++ )
        {
            tempLocDmg[hl] = activator->locationDamage[hl];
            activator->locationDamage[hl] = self->locationDamage[hl];
            self->locationDamage[hl] = tempLocDmg[hl];
        }
        if ( !self->s.number )
        {
            CG_CenterPrint( "@SP_INGAME_EXIT_VIEW", SCREEN_HEIGHT * 0.95 );
        }
    }
    else
    {//get out of ATST
        int legsAnim = activator->client->ps.legsAnim;
        if ( legsAnim != BOTH_STAND1
            && !PM_InSlopeAnim( legsAnim )
            && legsAnim != BOTH_TURN_RIGHT1 && legsAnim != BOTH_TURN_LEFT1 )
        {//can't get out of it while it's still moving
            return;
        }
        //FIXME: after a load/save, this crashes, BAD... somewhere in G2
        G_SetOrigin( self, activator->currentOrigin );
        VectorSet( self->currentAngles, 0, activator->client->ps.legsYaw, 0 );
        //self->currentAngles[PITCH] = activator->currentAngles[ROLL] = 0;
        G_SetAngles( self, self->currentAngles );
        VectorCopy( activator->currentAngles, self->s.angles2 );
        //remove my G2
        if ( self->playerModel >= 0 )
        {
            gi.G2API_RemoveGhoul2Model( self->ghoul2, self->playerModel );
            self->playerModel = -1;
        }
        //copy player's
        gi.G2API_CopyGhoul2Instance( activator->ghoul2, self->ghoul2 );
        self->playerModel = 0;//assumption
        //reset player to kyle
        G_DriveATST( activator, NULL );
        activator->activator = NULL;
        self->s.eFlags &= ~EF_NODRAW;
        self->svFlags &= ~SVF_NOCLIENT;
        self->contents = CONTENTS_SOLID|CONTENTS_BODY|CONTENTS_MONSTERCLIP|CONTENTS_BOTCLIP;
        self->takedamage = qtrue;
        //transfer armor
        tempHealth = self->health;
        self->health = activator->client->ps.stats[STAT_ARMOR];
        activator->client->ps.stats[STAT_ARMOR] = tempHealth;
        //transfer locationDamage
        for ( hl = HL_NONE; hl < HL_MAX; hl++ )
        {
            tempLocDmg[hl] = self->locationDamage[hl];
            self->locationDamage[hl] = activator->locationDamage[hl];
            activator->locationDamage[hl] = tempLocDmg[hl];
        }
        //link me back in
        gi.linkentity ( self );
        //put activator on top of me?
        vec3_t    newOrg = {activator->currentOrigin[0], activator->currentOrigin[1], activator->currentOrigin[2] + (self->maxs[2]-self->mins[2]) + 1 };
        G_SetOrigin( activator, newOrg );
        //open the hatch
        misc_atst_setanim( self, self->craniumBone, BOTH_STAND2 );
        gi.G2API_SetSurfaceOnOff( &self->ghoul2[self->playerModel], "head_hatchcover", 0 );
        G_Sound( self, G_SoundIndex( "sound/chars/atst/atst_hatch_open" ));
    }
}

void SP_misc_atst_drivable( gentity_t *ent )
{
    extern void NPC_ATST_Precache(void);
    extern void NPC_PrecacheAnimationCFG( const char *NPC_type );

    ent->s.modelindex = G_ModelIndex( "models/players/atst/model.glm" );
    ent->playerModel = gi.G2API_InitGhoul2Model( ent->ghoul2, "models/players/atst/model.glm", ent->s.modelindex );
    ent->rootBone = gi.G2API_GetBoneIndex( &ent->ghoul2[ent->playerModel], "model_root", qtrue );
    ent->craniumBone = gi.G2API_GetBoneIndex( &ent->ghoul2[ent->playerModel], "cranium", qtrue );    //FIXME: need to somehow set the anim/frame to the equivalent of BOTH_STAND1...  use to be that BOTH_STAND1 was the first frame of the glm, but not anymore
    ent->s.radius = 320;
    VectorSet( ent->s.modelScale, 1.0f, 1.0f, 1.0f );

    //register my weapons, sounds and model
    RegisterItem( FindItemForWeapon( WP_ATST_MAIN ));    //precache the weapon
    RegisterItem( FindItemForWeapon( WP_ATST_SIDE ));    //precache the weapon
    //HACKHACKHACKTEMP - until ATST gets real weapons of it's own?
    RegisterItem( FindItemForWeapon( WP_EMPLACED_GUN ));    //precache the weapon
//    RegisterItem( FindItemForWeapon( WP_ROCKET_LAUNCHER ));    //precache the weapon
//    RegisterItem( FindItemForWeapon( WP_BOWCASTER ));    //precache the weapon
    //HACKHACKHACKTEMP - until ATST gets real weapons of it's own?

    G_SoundIndex( "sound/chars/atst/atst_hatch_open" );
    G_SoundIndex( "sound/chars/atst/atst_hatch_close" );

    NPC_ATST_Precache();
    ent->NPC_type = "atst";
    NPC_PrecacheAnimationCFG( ent->NPC_type );
    //open the hatch
    misc_atst_setanim( ent, ent->rootBone, BOTH_STAND2 );
    gi.G2API_SetSurfaceOnOff( &ent->ghoul2[ent->playerModel], "head_hatchcover", 0 );

    VectorSet( ent->mins, ATST_MINS0, ATST_MINS1, ATST_MINS2 );
    VectorSet( ent->maxs, ATST_MAXS0, ATST_MAXS1, ATST_MAXS2 );

    ent->contents = CONTENTS_SOLID|CONTENTS_BODY|CONTENTS_MONSTERCLIP|CONTENTS_BOTCLIP;
    ent->flags |= FL_SHIELDED;
    ent->takedamage = qtrue;
    if ( !ent->health )
    {
        ent->health = 800;
    }
    ent->s.radius = 320;

    ent->max_health = ent->health; // cg_draw needs this

    G_SetOrigin( ent, ent->s.origin );
    G_SetAngles( ent, ent->s.angles );
    VectorCopy( ent->currentAngles, ent->s.angles2 );

    gi.linkentity ( ent );

    //FIXME: test the origin to make sure I'm clear?

    ent->e_UseFunc = useF_misc_atst_use;
    ent->svFlags |= SVF_PLAYER_USABLE;

    //make it able to take damage and die when you're not in it...
    //do an explosion and play the death anim, remove use func.
    ent->e_DieFunc = dieF_misc_atst_die;
}

extern int    G_FindConfigstringIndex( const char *name, int start, int max, qboolean create );

That should be all the code related to the misc_atst_drivable in g_misc.cpp. It seems to refer to the model itself, its animations, and the NPC as well. Weird.

 

(Not sure if it's allowed to post snippets of source code, since it was taken down, but given that it's basically game logic I don't think it contains much proprietary info or something.)

Link to comment

I'm pretty much out of ideas, I recently just tried deleting all my shaders, skin files and renaming my textures the same as the base ones to try and trick the game but it didn't work.

 

It must be the level itself, is this entity compiled with the level? Is it going to look for the default textures and model regardless?

 

@@Ramikad can I send you the file and maybe on whatever map you may have just add the entity to it but compile the map referencing my model to see if it shows up right?

Link to comment

I'm pretty much out of ideas, I recently just tried deleting all my shaders, skin files and renaming my textures the same as the base ones to try and trick the game but it didn't work.

 

It must be the level itself, is this entity compiled with the level? Is it going to look for the default textures and model regardless?

 

@@Ramikad can I send you the file and maybe on whatever map you may have just add the entity to it but compile the map referencing my model to see if it shows up right?

If you prefer, you can spawn the entity in another map with the console too, just use "spawn misc_atst_drivable" (NOT npc spawn)

Link to comment

I'm pretty much out of ideas, I recently just tried deleting all my shaders, skin files and renaming my textures the same as the base ones to try and trick the game but it didn't work.

 

It must be the level itself, is this entity compiled with the level? Is it going to look for the default textures and model regardless?

 

@@Ramikad can I send you the file and maybe on whatever map you may have just add the entity to it but compile the map referencing my model to see if it shows up right?

 

I can try. Send it.

Link to comment

Well I need to do some testing but Ashura may have found the problem.

 

Even though it has a .skin file if you look at the AT-ST in notepad++ the base glm has texture paths for all it's parts where mine just says [nomaterial] so I'm going to try to fix it with a hex editor like @@Psyk0Sith suggested, should have listened to him earlier lol.

Link to comment

Did you apply your textures in XSI from the correct base folder (same as the one you're trying to replace)? I would try that and compile a new .glm with the correct paths written by XSI itself first. That would rule out potential corruption from hex editing. The original max plugin did it correctly but all the updates broke that feature afaik.

Link to comment

Did you apply your textures in XSI from the correct base folder (same as the one you're trying to replace)? ...The original max plugin did it correctly but all the updates broke that feature afaik.

Heresy! ;) The new 3ds Max dotXSI exporters correctly generate the XSICustomPSet template data used to create the G2 Skin file by Carcass-- as long as you name the materials (in 3dsMax) the "relative path" name.

Link to comment

Did you apply your textures in XSI from the correct base folder (same as the one you're trying to replace)? I would try that and compile a new .glm with the correct paths written by XSI itself first. That would rule out potential corruption from hex editing. The original max plugin did it correctly but all the updates broke that feature afaik.

 

Yeah, tried that, still shows [nomaterial] in a hex editor. Tried editing the file using a hex editor but it just crashes both modview and the game.

Link to comment

Yeah, tried that, still shows [nomaterial] in a hex editor. Tried editing the file using a hex editor but it just crashes both modview and the game.

 

How about Blender? It has a [nomaterial] shader key under the GLM options of a mesh.

Link to comment

Yeah, tried that, still shows [nomaterial] in a hex editor. Tried editing the file using a hex editor but it just crashes both modview and the game.

what does the original Raven asset say for a material texture & path in hex editor?

 

what does your model say in the exported dotXSI XSICustomPSet template (which holds relative texture path for Carcass to make G2 Skin file)?

Link to comment

Heresy! ;) The new 3ds Max dotXSI exporters correctly generate the XSICustomPSet template data used to create the G2 Skin file by Carcass-- as long as you name the materials (in 3dsMax) the "relative path" name.

 

"material #" is what i get when i don't change names, they don't get applied automatically, that's still broken! lol yeah i'm lazy.

Link to comment

"material #" is what i get when i don't change names, they don't get applied automatically, that's still broken! lol yeah i'm lazy.

To do it automatically as you suggest makes me have to assume that people are assigning textures from the proper Game folder path-- and that may not be correct (to just grab the texture path); and it forces people to change to that Workflow. Having the user put in the relative path as the material name leaves no questions or bad assumptions.

 

Sorry. I can can write you a simple maxscript to assign relative texture paths to material names. That would be a simpler thing than modifying the exporter C++ code. But you'll still have to push a button or two... :winkthumb:

Link to comment

Ok..just..WOW

Not only the model looks EXACTLY like the blueprints, but the animations are extremely good. I really love the variants, the textures are very well done!

 

I just found two MINOR bugs:

1) when you get inside the SP entity, the hatch doesn't close but disappears:

http://imgur.com/516bA3s

2) in the map t2_trip, both the NPC and the entity move in a pretty weird way. This doesn't affect Gameplay at all as there shouldn't be AT-STs on t2_trip, but as this doesn't seem to happen with the base AT-ST, I just hope it happens in this map only:

http://imgur.com/BBuF1W3

http://imgur.com/cclNL89 (note: the AT-ST is not dead in this image lol)

But, as I said, they are minor bugs that don't affect gameplay.

 

EDIT: the t2_trip bug seems to happen ONLY if you load a savegame where there was the old AT-ST spawned (not if you begin a mission because they aren't spawned at the beginning) so there's no problem at all.

Link to comment

I've noticed the hatch issue in SP but it only happened for me when I spawned the npc_vehicle which isn't SP compatible. Never happened with the misc_atst_driveable but they weren't spawned, they were ones that were on the map already like t2_dpred and Gavin_canyon. I could never get the misc_atst_driveable to spawn. I don't see the problem in the first trip picture, just looks like the animation BOTH_TURNLEFT1 is playing.

 

Thanks for the comments, I spent a lot of time building the custom rig in softimage to make the animations. Ashura did an amazing job on the textures.

Link to comment

I've noticed the hatch issue in SP but it only happened for me when I spawned the npc_vehicle which isn't SP compatible. Never happened with the misc_atst_driveable but they weren't spawned, they were ones that were on the map already like t2_dpred and Gavin_canyon. I could never get the misc_atst_driveable to spawn. I don't see the problem in the first trip picture, just looks like the animation BOTH_TURNLEFT1 is playing.

 

Thanks for the comments, I spent a lot of time building the custom rig in softimage to make the animations. Ashura did an amazing job on the textures.

No problem, you and Ashura did an amazing job!

The point is that that it moved by only using turning and dying animations, but it looks like this happened ONLY if it was a map when the AT-STs were spawned before the mod was installed.

Link to comment

Spawned before the mod was installed? Are you playing like lugormod or makermod? It properly overwrites all AT-ST's in both SP games. The animation thing is because my frame numbers don't match the original because the animations are new. You didn't rename the pk3 did you? The zzz_ prefix is there for a reason.

Link to comment

Spawned before the mod was installed? Are you playing like lugormod or makermod? It properly overwrites all AT-ST's in both SP games. The animation thing is because my frame numbers don't match the original because the animations are new. You didn't rename the pk3 did you? The zzz_ prefix is there for a reason.

Didn't renamed the file and I'm not using any of these mods. Try to "npc spawn atst", save and then put the model in the Base folder.

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...