Jump to content

Ramikad

Members
  • Posts

    1,316
  • Joined

  • Last visited

Everything posted by Ramikad

  1. Yes, the name of the script and the path after scripts/. For example, if you have it in scripts/mymap/endlevel.IBI: Key: deathscript Value: mymap/endlevel Obviously, your scripts will need to play the cutscene, and subsequently use a target_level_change set to your next map, or alternatively the script could play the cutscene and fade to credits. Play around with script commands, to get the hang of it.
  2. In this specific case (and in most others as far as SP missions are concerned) you'll need .IBI scripts, yes. You'll want to set up a deathscript key on your NPC, and the path to the .IBI script file after scripts/ as value. Feel free to take a look at the Tutorial Section, as well as Redsaurus' excellent SP mapping / mission making Tutorial.
  3. How about Blender? It has a [nomaterial] shader key under the GLM options of a mesh.
  4. 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.)
  5. You can check this list for servers to join: http://my.jacklul.com/jkhubservers/
  6. That was a tricky part for me too at the beginning. To animate a character, I generally put a small plane at -2.5 units under the player model - apparently that's where the ground is in Jedi Outcast and Jedi Academy. Then you must select its skeleton and enter Pose Mode. Generally, to align the character with the ground I move its model_root down to -2.5, and the rest of the bones down of another -0.25. That seems to align pretty good with the ground, in case of a walking character. The next step is to define a frame range (notice the Start and End numbers): it is used to define how many frames that animation will have. Then, start posing the model. Whenever the model is in the pose you want, you'll have to insert a keyframe, so that the character will remain in that pose at that specific frame: press I, then select Whole Character. Then, move to another frame, so that you can pose the character again and keyframe it. Keep in mind the speed of the animation: many animations in Jedi Academy are played at 15-20 FPS, so you can keep it as a measure to know how many frames you might want to skip. The character will automatically blend the two poses in the frames between them. You can also preview the animation pressing Alt + A, or clicking on the Play animation button, and change the speed at which it is played, in Render menu -> Dimension -> Frame Rate - default is 24 FPS. You can also add a specific pose to a Pose Library, so that you can re-use it again later on (Pose -> Pose Library -> Add Pose). Rinse and repeat until you have the animation you want. At this point you should keyframe every single frame of your animation. You can do that pretty efficiently and quickly by baking the animation (Pose -> Animation -> Bake Action). Just select the Start Frame, the End Frame and the Frame Step (you'll want that to be 1, so that every single frame of the animation is keyframed). That way you'll have a whole load of keyframes that make up the animation. Now you can Export a new .gla file which will contain these animation frames. It is important, since you want to create new animations for an existing skeleton, to write up the gla reference, under the Export JA Ghoul 2 Skeleton & Animations options. The path is relative to the base path, so you'll want to write models/players/<model name>/<skeleton>.gla. I generally export the newly created .gla in base/models/players/<random model>, just to be safe. You can also (but this is not a necessary part) Export a new .cfg, but first you'll have to add markers to the frames. Select a frame, then Marker -> Add Marker, or press M. Then you can rename it for better understanding. When exporting the .cfg you can also select an offset - basically, the .cfg will show its frames starting at the offset frames, which you'll want to be the total animation frames of the original animations. For example, the _humanoid.gla skeleton has a total of 21376 frames. Setting that as offset will cause the exported .cfg to start from frame 21377. It is useful when you're dealing with a lot of animations and you don't want any to overlap each other. Now it's time to merge the animations. Grab GLAMerge, then put the .exe in a folder with both the new .gla and the original .gla. I'm not sure if there's already a gla_merge.bat, but anyway you should modify it as follows: @[member='Echo'] OFF "glamerge.exe" "<original animations>.gla" "<new animations>.gla" -o PAUSE EXIT So that the program can merge the two. Enter an output name for the new .gla, which you'll have to modify to what the original animations name was right after the program is done. In case of merging with a _humanoid.gla, you'll want to rename it to _humanoid.gla. Put it in a folder with the same name as the original one. To pick up the example of _humanoid.gla, I'll want to put the new one in models/players/_humanoid/. Then modify the animations.cfg, so that you can replace the original animations with the new ones. Find the animation you want to replace (you can check them out with ModView). Then replace the frames of that animation with the new ones. For example, to change BOTH_STAND1, it'll have to be modified from this: BOTH_RUN1 12305 26 0 40 To this: BOTH_RUN1 21377 45 0 30 In short, you have to replace it with the new frames you merged. Just for completeness, those values mean: BOTH_RUN1 12305 26 0 40 <Name of anim> <St. Frame> <Number of frames> <Loop, 0=Y,-1=N> <Speed (FPS)> Then pack everything up in the correct folder in a new .pk3 file. And voilà! Hope this was clear enough. And sorry for hijacking the thread
  7. I think the only solution would be to fix the muzzle tags where the weapons shoot, rotating them.
  8. You could try the Blender + glamerge combo. You import the droid model, animate it, export the .gla (with the right skeleton setup), merge with the original animations and change its animations.cfg. I've only tested this with _humanoid NPCs, but in theory it should work fine with everything.
  9. Last time I tricked him with a large dose of Saber Throw to demolish his health after the first wave of prisoners, and finished him off during the second wave, securing their run. Rinse and repeat
  10. The entity description doesn't give much to work on, just the line model="models/players/atst/model.glm", a health and target keys. Huh, interestingly enough, the textures for the original AT-ST player model are located in map_objects/imp_detention/.
  11. MB2 has a KotOR 1 Dark Jedi model, as far as I know. Seems to be just a reborn reskin though.
  12. I think they hacked its spinning into the mod, so I doubt it's gonna work properly in SP. If you can pass on the spinning, in theory it should work, though.
  13. You can replace the original objectives with new ones for the mod, and add them in the map with scripts. Refer to this post, in case it might help: https://jkhub.org/topic/5149-lets-map-singleplayer/page-2?do=findComment&comment=76721
  14. I could swear it's 4096, or even more. I think Pande also mentioned that once. And in theory a test shader I did a long time ago was working fine with a 4096 texture.
  15. Looks very good from the screenshots, downloading now. The installation path (unless it's meant for Steam/OpenJK/anyhing) could use a small fix though, it's supposed to be Star Wars Jedi Knight Jedi Academy/GameData/Base, not Star Wars Jedi Knight Jedi Academy/Base. Though probably everyone and their mother know how to install mods and maps by now.
  16. It's not a matter of NPC files. It's a problem with the different _humanoid skeletons used in Jedi Outcast and Jedi Academy. The Jedi Outcast _humanoid skeleton has more bones, so the only way to fix that problem is to rig the specific JA player model to the Jedi Outcast skeleton.
  17. Add a bladeEffect path_after_effects/effect.efx in the .sab file. There are other effects, but I can't remember them right now. Edit: Found them: blockEffect, hitOtherEffect, hitPersonEffect.
  18. I tried this in the past, but it didn't seem to turn out that well. In my case it seemed like the effect was somehow "delayed" or not updated as frequently as the saber blade, thus looking a bit off.
  19. Luke mentions in Jedi Outcast he sealed the Valley. Luke: Not anymore. I managed to scatter Desann and his Reborn troops, and Rogue Squadron chased away their ships. For now the Valley's effectively sealed off, but we have no idea how many troops Desann managed to empower before we got there. It is possible that Tavion might have returned to the Valley after she found the Scepter, Luke mentions that he needs Kyle to check the Valley.
  20. There's a continuity error of sorts between Taspir and Korriban: if Jaden came with the Raven's Claw, how is it that he lands on Korriban with his Z-95?
  21. He didn't try. He did sell the mod, and I'm not sure if it's actually 50$, because I read 100$ somewhere. And he asked for donations, multiple times, which were actually fulfilled.
×
×
  • Create New...