Ramikad
Members-
Posts
1,316 -
Joined
-
Last visited
Content Type
Profiles
News Articles
Tutorials
Forums
Downloads
Everything posted by Ramikad
-
How to get started with playing online?
Ramikad replied to BruceJohnJenner's topic in Jedi Knight General Discussions
It would need an official map too then -
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.
-
A relatively simple request, if I may...
Ramikad replied to the_raven's topic in Mod Requests & Suggestions
I know, BUT fun -
A relatively simple request, if I may...
Ramikad replied to the_raven's topic in Mod Requests & Suggestions
Eh, you gotta follow your heart -
How about Blender? It has a [nomaterial] shader key under the GLM options of a mesh.
-
I can try. Send it.
-
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.)
-
How to get started with playing online?
Ramikad replied to BruceJohnJenner's topic in Jedi Knight General Discussions
You can check this list for servers to join: http://my.jacklul.com/jkhubservers/ -
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
-
A couple of weird bugs with some vehicles
Ramikad replied to GLTh3Pr0's topic in Jedi Knight Tech Support
I think the only solution would be to fix the muzzle tags where the weapons shoot, rotating them. -
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.
-
Which boss battle from the Jedi Knight series was your favorite?
Ramikad replied to eezstreet's topic in Latest Poll
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 -
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/.
-
MB2 has a KotOR 1 Dark Jedi model, as far as I know. Seems to be just a reborn reskin though.
-
Bespin Cloud City Vader SP Mission - WIP
Ramikad replied to Langerd's topic in WIPs, Teasers & Releases
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 -
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.
-
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.
-
Is it possible to make JKA NPCs compatible with JO?
Ramikad replied to ClassicRockJedi's topic in Modding Assistance
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. -
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.
-
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?
-
The above are very good picks. My suggestion before you map, though, is to pick pencil and paper and start drawing concept arts. Being a mapper myself, I find that drawing a good concept art before starting the brush and patchwork in Radiant really helps me better visualize the area I want to create, and have a general idea that can be reworked before the map gets too "compact".