Jump to content

Jedi Fighter beta 2 released


Recommended Posts

Posted

Hi everybody,

 

I've been working on a 2D fighting game mod for Jedi Academy called Jedi Fighter (something I started while in university and decided to finish near the release of TFA).

 

21_9.PNG

 

shot2016-01-18_23-56-37.png

 

 
8189.png

 

Beta 2 was just released on Jan. 21, 2016 on moddb.  I'd love to get the JKHub community to download it, try it out, and give me feedback.

 

It's incredible that Jedi Academy still has such a vibrant modding scene and that you all are still putting out such high quality content, which is what spurred me to continue with the release. Some of the player models and lightsbaer models I'm using came from the downloads section on this site, and only in the case that the download states that permission is given to freely redistribute if credit is provided. I've cited you guys in the credits by name in game, in a CREDITS.txt, and in the README.txt. If anyone has any issue with their content being included, please let me know and I can remove it.

 

Teaser video

 

Note that I didn't touch the AI and didn't include botroutes (because apparently I was doing something wrong... bots would run up and not attack at all) so you'll want to play multiplayer for now.

 

---- BEGIN MARKETING ----

 

Features in beta 2

  • Fight as 10 characters from the Star Wars movies and expanded universe, each armed with unique force powers and devastating special moves
  • Fight in 5 arenas, from a Tie hangar bay, to turbolifts in the Deathstar, to the aftermath on Hoth
  • Full widescreen support for 16:9 (1080p and 720p), 16:10, 4K and 21:9 resolutions! Or any custom resolution!
  • A dynamic camera that gives a cinematic view of the action
  • Awesome title music
  • and much, much more!

Feedback

Your honest feedback is incredibly important and very much appreciated! Please post comments to the forums. I'll be checking them regularly so your comments will help shape the direction of the mod!

If you would like to contribute by making maps, please reach out to me via email or messages, or post to the forums. I'd appreciate the help!

 

Requirements:

You'll need to install Jedi Academy, the OpenJK engine, and Jedi Fighter beta 2 to play.

 

OpenJK download link (proper licenses included):

96783.png

JEDI FIGHTER beta 2 download link:

96827.png

 

Installation:

 

Check out these installation instructions to get started.

 

  1. Unzip both Jedi Fighter beta 2 and the OpenJK engine to your Jedi Academy\gamedata directory.
  2. Right click on SETUP.BAT in the Jedi Academy\gamedata\jedifighter directory and choose "Run as Administrator".

Run JF_CLIENT_OJK.BAT in your Jedi Academy\gamedata\jedifighter directory to get started. Configure your controls, max out your video settings and resolution, and have fun!

 

If you have any issues, check out the detailed instructions in jedifighter\_README_.txt. If you still have problems, feel free to post in the forums or here.

 

Future plans:


I'll try to get some dedicated servers running in the next few weeks, and will be setting up some play sessions on my own machine. Stay tuned to moddb for details!

 

JEDI FIGHTER will continue to be improved until the v1.0 release near June, 2016, with a beta 3 in the next two months.

 

Beta 3 will focus on a few key areas:

  • improved AI based on neural networks
  • balancing and adding fighters (including from Star Wars: The Force Awakens)
  • improved user experience with the server browser and match making

---- END MARKETING ----

 

Feature details

 

Since this is JKHUB, I can go into technical details on of the features. Yay!

 

I'm planning on making sure all of my own asset sources and the full source code are eventually made available. Right now I've got a local SVN repo that is 12 years old so want to make sure I don't lose history converting it to git and putting it up.

 

Customizable fighter sets:

 

The fighters are defined in jedifighter/fighters/%FIGHTER_SET_NAME%/*.fighters text files. The %FIGHTER_SET_NAME% is stored in a server CVAR and sent over to the clients for loading files. However, I hardcoded the value of that CVAR to "default" in beta 2 but it will be hopefully unlocked in beta 3.

 

The intention of this is to allow server operators to make their own fighters altogether.  An example of a .fighter file is shown below.  The format sucks since I was naive about 10 years ago when I came up with it. but it "works" for now.

 

The format shows that each fighter has a fighterinfo block that define models, skins, sabers, and the saberstyle enforced on the client, and then a moves section. Each move has an attack or a "program" that is triggered when the combo is matched (more on "programs" below).  Combos are defined as a string of buttons that must be pressed in sequence, with the min and max time from the previous button being defined.

 

I am going consider coming up with a way to customize fighters in game while on a server with some kind of constraints (e.g. powerful moves require a certain combo complexity, and measure the complexity of the combo based on adjacency of buttons, time between presses, length of combo, etc).

fighter Carnor_Jax {
  fighterinfo {
    description 'Blah blah'
    alignment dark
    model_path carnor_jax
    skin_path default
	saberstyle staff
	saber1 jf_carnorjax
	saber2 none
  }
  moves 12 {
    inherits none
    move Kanos'_Revenge {
      attack LS_A_JUMP_T__B_
      combo {
        comboinfo {
          clearable yes
          min_input_time 20
          max_input_time -1
        }
        buttons 4 {
          button BUTTON_RIGHT -1 -1
          button BUTTON_DOWN 10 2000
          button BUTTON_RIGHT 10 600
          button BUTTON_VERTICAL_ATTACK -1 -1
        }
      }
    }
    move Lunge {
      attack LS_A_LUNGE
      combo {
        comboinfo {
          clearable yes
          min_input_time 20
          max_input_time -1
        }
        buttons 3 {
          button BUTTON_DOWN -1 -1
          button BUTTON_RIGHT 10 600
          button BUTTON_HORIZONTAL_ATTACK -1 -1
        }
      }
    }
    move Back_Stab {
      attack LS_A_BACKSTAB
      combo {
        comboinfo {
          clearable yes
          min_input_time -1
          max_input_time -1
        }
        buttons 3 {
          button BUTTON_DOWN -1 -1
          button BUTTON_LEFT 10 600
          button BUTTON_HORIZONTAL_ATTACK -1 -1
        }
      }
    }
    move Backward_Kick {
      attack LS_KICK_B
      combo {
        comboinfo {
          clearable no
          min_input_time -1
          max_input_time -1
        }
        buttons 2 {
          button BUTTON_LEFT -1 -1
          button BUTTON_ALT_ATTACK 10 600
        }
      }
    }
    move Spin_Kick {
      attack LS_KICK_S
      combo {
        comboinfo {
          clearable yes
          min_input_time -1
          max_input_time -1
        }
        buttons 3 {
          button BUTTON_DOWN -1 -1
          button BUTTON_LEFT 10 600
          button BUTTON_ALT_ATTACK -1 -1
        }
      }
    }
    move Forward_Kick {
      attack LS_KICK_F
      combo {
        comboinfo {
          clearable no
          min_input_time -1
          max_input_time -1
        }
        buttons 1 {
          button BUTTON_ALT_ATTACK -1 -1
        }
      }
    }
    move Horizontal_Slash {
      attack LS_A_L2R
      combo {
        comboinfo {
          clearable no
          min_input_time -1
          max_input_time -1
        }
        buttons 1 {
          button BUTTON_HORIZONTAL_ATTACK -1 -1
        }
      }
    }
    move Vertical_Slash {
      attack LS_A_T2B
      combo {
        comboinfo {
          clearable no
          min_input_time -1
          max_input_time -1
        }
        buttons 1 {
          button BUTTON_VERTICAL_ATTACK -1 -1
        }
      }
    }
    move Schmetterling {
      program LS_BUTTERFLY_LEFT
      permissives 3
      combo {
        comboinfo {
	  clearable yes
          min_input_time -1
          max_input_time -1
        }
        buttons 3 {
          button BUTTON_DOWN -1 -1
          button BUTTON_LEFT 10 600
          button BUTTON_VERTICAL_ATTACK -1 -1
        }
      }
    }
    move Hammer_Blow {
      program LS_A3_SPECIAL
      permissives 3
      combo {
        comboinfo {
	  clearable yes
          min_input_time -1
          max_input_time -1
        }
        buttons 3 {
          button BUTTON_RIGHT -1 -1
          button BUTTON_RIGHT 10 600
          button BUTTON_VERTICAL_ATTACK -1 -1
        }
      }
    }
    move Kanos_Killer {
      program LS_STAFF_SOULCAL
      permissives 3
      combo {
        comboinfo {
	  clearable yes
          min_input_time -1
          max_input_time -1
        }
        buttons 3 {
          button BUTTON_DOWN -1 -1
          button BUTTON_RIGHT 10 600
          button BUTTON_VERTICAL_ATTACK -1 -1
        }
      }
    }
    move Force_Saber_Throw {
      program FORCE_SABER_THROW
      permissives 1
      combo {
        comboinfo {
          clearable yes
          min_input_time -1
          max_input_time -1
        }
        buttons 3 {
          button BUTTON_DOWN -1 -1
          button BUTTON_RIGHT 10 600
          button BUTTON_ALT_ATTACK -1 -1
        }
      }
    }
  }
}

Fighter "programs" and an interpreter to perform the special moves

 

Fighter programs are text files found in jedifighter/fighters/%FIGHTER_SET_NAME%/programs/*.program that the character designer can use to create special moves. The files contain a set of instructions that are run in a fighter program interpreter on the server to enforce player movement, jumping, force power selections and activation, saber move execution, etc. when the special move is triggered. 

 

With this, I had a lot of flexibility to do timing correction to get rid of sliding feet, fire of particular moves, combine saber moves and force powers, etc. Not to mention it let me finish up defining all of the force power and other special moves in about 5 minutes apiece. Well worth the time to implement the interpreter 3 days before release so I could get it done in time!

 

Each program can have up to 32 commands, and there can be a total of 256 programs on a server at any point in time. Any client can only execute one program at a time right now, but that's all I needed for now.

 

The execution of a program is a bit strange. When a fighter executes a move with an associated program, a pointer to that program is added to the client and an instruction pointer is created which iterates through the instructions. Instructions will all be run at the same moment in time by  wall clock unless a WAIT or WAITUNTIL command is encountered, in which case it will wait to resume execution. This was needed to simultaneously activate force powers, start saber moves, enforce movement speeds, and then wait for a particular animation keyframe to change speeds, terminate the move, etc.

 

All of the supported opcodes are listed below.  Ones other than this will be ignored, and comments can be included in the files.

typedef enum {
	JFOP_NOP, // nothing
	JFOP_WAIT, // time period (ms)
	JFOP_WAITUNTIL, // absolute time since start (ms)
	JFOP_SETMOVE, // up, right, forward vector for pmove
	JFOP_CLEARMOVE, // nothing, unsets the JF_PROGRAMSTATE_MOVING bit from the fighter program state
	JFOP_JUMP, // velocity
	JFOP_PLAYSOUND, // sound
	JFOP_PLAYANIM, // target (legs, torso, or both), anim, start frame, end frame, speed scale
	JFOP_SETSABERMOVE, // move number
	JFOP_SETFORCEPOWER, // force power index to become active, the force level, and start using it by setting JF_PROGRAMSTATE_FORCEON
	JFOP_CLEARFORCEPOWER, // stop using the active force power
	JFOP_MAX
} fighterOpCodes_e;

An example fighter program is listed below.

program PAPILLON {
	JFOP_SETSABERMOVE 24
	JFOP_SETMOVE 0 0 127
	JFOP_WAITUNTIL 550
	JFOP_SETMOVE 0 0 60
	JFOP_WAITUNTIL 900
	JFOP_SETMOVE 0 0 127
	JFOP_WAITUNTIL 1500
	JFOP_SETMOVE 0 0 80
	JFOP_WAITUNTIL 2350
	JFOP_SETMOVE 0 0 60
	JFOP_WAITUNTIL 2700
	JFOP_SETMOVE 0 0 0
	JFOP_WAITUNTIL 2800
	JFOP_SETSABERMOVE 0
	JFOP_CLEARSABERMOVE
} 

Cinematic camera

 

There is a third person camera which has a ton of CVARs to control the FOV, origin offsets from the target, absolute viewangle offsets, settling times (using an ideal low pass filter on the position and viewangles setpoints to create the current position and viewangles -- smoothing), and others. All of the relevant CVARs are shown below, but use them with caution because fighting is constrained to a particular fighting plane orientation and you could end up with the camera pointing off to nowhere!

vmCvar_t cg_jediFighterCam;
vmCvar_t cg_jediFighterCamInterpolate;
vmCvar_t cg_jediFighterCamSettlingTime;
vmCvar_t cg_jediFighterCamFollowEnemyZ;
vmCvar_t cg_jediFighterCamAutoYaw;
vmCvar_t cg_jediFighterCamYaw;
vmCvar_t cg_jediFighterCamPitch;
vmCvar_t cg_jediFighterCamRoll;
vmCvar_t cg_jediFighterCamOffsetX;
vmCvar_t cg_jediFighterCamOffsetY;
vmCvar_t cg_jediFighterCamOffsetZ;
vmCvar_t cg_jediFighterCamRangeX;
vmCvar_t cg_jediFighterCamRangeY;
vmCvar_t cg_jediFighterCamRangeZ;
vmCvar_t cg_jediFighterCamFovX;
vmCvar_t cg_jediFighterCamFovY;

Map entities and fighter plane

 

The maps all have their .map source included in jedifighter\maps\mp\*.map.  

 

A special spawn point entity was added for jedifighter to define where the spawn will happen, and if the spawn is the left side or the right side.  If these don't exist, your map will cause a client to exit the server with an error.

 

Examples of the info_jedifighter_start entities from jf_test.map are shown below, where side 0 corresponds to the left, and side 1 corresponds to the right.

// entity 15
{
"classname" "info_jedifighter_start"
"origin" "-56 0 -16"
"side" "0"
}
// entity 16
{
"classname" "info_jedifighter_start"
"origin" "64 0 -16"
"side" "1"
}

Right now, the fighters are constrained to 2D motion in one particular plane orientation. The plane normal is along the Y axis.  This means you need the Y and Z components of the origin key for the info_jedifighter_start entities to be the same.  In the future, I'll consider allowing them to fight along a dynamic fighter plane (and possibly add sidestepping), enabled by a CVAR for a map, but for now this is a hard rule or things won't work right...

 

 

 

Map autorun scripts:

 

When a map is loaded, a corresponding .jedifighter script (console commands) from the same directory is executed on the server and on each client.

 

For example, if maps/mp/jf_test.bsp was loaded, then maps/mp/jf_test.jedifighter would get executed. In this script you can set any CVARs. The intention of this was to customize the number of rounds, camera settings, fighter sets, or anything else particular to that map.

 

An example of a .jedifighter file for jedifighter/maps/mp/jf2_fire.jedifighter is shown below:

seta cg_thirdperson "1"
seta cg_jediFighterCam "1"
seta cg_jediFighterCamYaw "0"
seta cg_jediFighterCamPitch "0"
seta cg_jediFighterCamRoll "0"
seta cg_jediFighterCamOffsetX "0"
seta cg_jediFighterCamOffsetY "100"
seta cg_jediFighterCamOffsetZ "4"
seta cg_jediFighterCamRangeX "0"
seta cg_jediFighterCamRangeY "0"
seta cg_jediFighterCamRangeZ "0"
seta cg_jediFighterCamFovX "0"
seta cg_jediFighterCamFovY "0"
seta cg_jediFighterCamInterpolate "1"
seta cg_jediFighterCamFollowEnemyZ "0"
seta cg_jediFighterCamAutoYaw "1"

g_jf_timelimit 60
g_jf_rounds 3

r_drawfog 1
r_we gustingwind
r_we gustingwind

There are more novelties which I'll post about later. 

 

As always, thank you for taking the time to read this, playing, and for your feedback!

 

--

Adnan

Posted

Oh wow. Didn't even know this existed. That looks awesome so far. I'll have to try it!

 

One note, the bots are jumping around the whole time. Pretty sure that means the maps don't have bot routes. :P

skew and Bek like this
Posted

 

One note, the bots are jumping around the whole time. Pretty sure that means the maps don't have bot routes.  :P

 

You're totally right, no botroutes included.  I tried to include some by following a super old tutorial on laying them out and got the bots to move naturally throughout the maps, but it wasn't working correctly.  They would run right up to your face and would only attack when outside of arms reach but closer than some distance. Ultimately I figured their random flailing was better than impaling themselves on your saber :\

 

I'll look around for a better tutorial on how to do that. If anyone has any links handy I'd appreciate it.

Posted

@@skew did you make those breathing animations?

Yes, but they're all done via code. I didn't make any animations in the traditional sense.

 

In game I'm accomplishing the breathing by manipulating the viewangles, because those cause the skeleton to look as if it were breathing.  The code was really credue and needs my more refined method from the UI.

 

Game code here:

// adnan - make them seem as if theyre breathing
	// add some randomness to this!
	if(pm->ps->stats[STAT_HEALTH] <= 0) {
		breatheScale = 0;
	} else if(pm->ps->stats[STAT_HEALTH] < 25) {
		breatheScale = 2;
	} else if(pm->ps->stats[STAT_HEALTH] < 50) {
		breatheScale = 1.5;
	} else if(pm->ps->stats[STAT_HEALTH] < 75) {
		breatheScale = 1.25;
	} else {
		breatheScale = 1;
	}

	pm->ps->viewangles[PITCH] = breatheScale * 10 * sin(breatheScale * (pm->cmd.serverTime)/600.0f);

In the main menu (and the fighter selection screen), I'm doing it via bones directly. I also did blinking, neck tilting, saber re-gripping, etc via the code here. It's not super efficient, but generally works too.

viewAngles[YAW] = 0;
		viewAngles[PITCH] = 2.0f * sin(time / 700.0f + ui_jf_seed.integer) + 1.0f;
		viewAngles[ROLL] = 0;

		//distribute the angles differently up the spine
		//NOTE: each of these distributions must add up to 1.0f
		thoracicAngles[PITCH] = viewAngles[PITCH] * 0.20f;
		llAngles[PITCH] = viewAngles[PITCH] * 0.40f;
		ulAngles[PITCH] = viewAngles[PITCH] * 0.40f;
		craniumAngles[PITCH] = viewAngles[PITCH] * -0.8f;
		pelvisAngles[PITCH] = viewAngles[PITCH] * -0.2f;
		eyeAngles[PITCH] = -craniumAngles[PITCH] + 20.0f;

		thoracicAngles[YAW] = viewAngles[YAW] * 0.20f;
		ulAngles[YAW] = viewAngles[YAW] * 0.35f;
		llAngles[YAW] = viewAngles[YAW] * 0.45f;
		craniumAngles[YAW] = viewAngles[YAW] * -0.8f;
		pelvisAngles[YAW] = viewAngles[YAW] * 0.1f;
		eyeAngles[YAW] = -craniumAngles[YAW];

		thoracicAngles[ROLL] = viewAngles[ROLL] * 0.20f;
		ulAngles[ROLL] = viewAngles[ROLL] * 0.35f;
		llAngles[ROLL] = viewAngles[ROLL] * 0.45f;
		craniumAngles[ROLL] = viewAngles[ROLL] * -0.8f;
		pelvisAngles[ROLL] = viewAngles[ROLL] * -0.1f;
		eyeAngles[ROLL] = -craniumAngles[ROLL];

		// blink in 150 ms every 5 seconds
		if (time % 5000 < 150)
			eyeAngles[PITCH] -= 40.0f * fabs(sin(2*M_PI * 1000/300.0f * (time % 5000) / 1000.0f));
		
		// regrip pinky for half a second every 7 seconds
		if (time % 7000 < 500)
			pinkyFingerAngle[PITCH] = -40.0f * fabs(sin(2 * M_PI * 1000 / 1000.0f * (time % 7000) / 1000.0f));
		else
			pinkyFingerAngle[PITCH] = 0.0f;
		pinkyFingerAngle[ROLL] = 0;
		pinkyFingerAngle[YAW] = 0;

		// regrip thumb and forefingers for half a second every 7 seconds, 250 ms after with the forefingers
		if ((time % 7000 < 750) && (time % 7000 > 250))
			pointerFingerAngle[PITCH] = -40.0f * fabs(sin(2 * M_PI * 1000 / 1000.0f * ((time % 7000) - 250) / 1000.0f));
		else
			pointerFingerAngle[PITCH] = 0.0f;
		pointerFingerAngle[ROLL] = 0;
		pointerFingerAngle[YAW] = 0;

		thumbAngle[YAW] = pointerFingerAngle[YAW];
		thumbAngle[PITCH] = pointerFingerAngle[PITCH];
		thumbAngle[ROLL] = pointerFingerAngle[ROLL];

		// tilt the head every 40 seconds for 2 seconds
		if (time % 40000 < 2000)
			craniumAngles[ROLL] += -25.0f * sin(2 * M_PI * 1000 / 2000.0f * (time % 40000) / 1000.0f);
		//else
		//	craniumAngles[ROLL] = 0.0f;

		trap_G2API_SetBoneAngles(item->ghoul2, 0, "lower_lumbar", &llAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, uiInfo.uiDC.realTime);
		trap_G2API_SetBoneAngles(item->ghoul2, 0, "upper_lumbar", &ulAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, uiInfo.uiDC.realTime);
		trap_G2API_SetBoneAngles(item->ghoul2, 0, "cranium", &craniumAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, uiInfo.uiDC.realTime);
		trap_G2API_SetBoneAngles(item->ghoul2, 0, "thoracic", &thoracicAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, uiInfo.uiDC.realTime);
		trap_G2API_SetBoneAngles(item->ghoul2, 0, "pelvis", &pelvisAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, uiInfo.uiDC.realTime);

		trap_G2API_SetBoneAngles(item->ghoul2, 0, "r_d1_j2", &thumbAngle, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, uiInfo.uiDC.realTime);
		trap_G2API_SetBoneAngles(item->ghoul2, 0, "r_d2_j2", &pointerFingerAngle, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, uiInfo.uiDC.realTime);
		trap_G2API_SetBoneAngles(item->ghoul2, 0, "r_d4_j2", &pinkyFingerAngle, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, uiInfo.uiDC.realTime);

		eyeAngles[YAW] = -5.0f;
		trap_G2API_SetBoneAngles(item->ghoul2, 0, "leye", &eyeAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, uiInfo.uiDC.realTime);
		eyeAngles[YAW] = 5.0f;
		trap_G2API_SetBoneAngles(item->ghoul2, 0, "reye", &eyeAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, uiInfo.uiDC.realTime);

Futuza likes this
Posted

That looks awesome, great work. I love the breathing animations and how they adjust their grip on their lightsaber in the player configuration menu. Those would be cool to add into JA:E, @@Circa. ;)

Circa, skew and Bek like this
Posted

It would be cool to see fatalities or something here haha.

Haha, awesome idea!

 

I was planning on adding something that would make it work. Right now the fighter programs control your own client on the server but I was going to add an operation to fire off a program on your opponent. That way I could do proper grabs and stuff. Fatalities would be icing on the cake.

Posted

Haha, awesome idea!

 

I was planning on adding something that would make it work. Right now the fighter programs control your own client on the server but I was going to add an operation to fire off a program on your opponent. That way I could do proper grabs and stuff. Fatalities would be icing on the cake.

 

I'd rather have a blocking system! That would be awesome. 

skew likes this
Posted

I'd rather have a blocking system! That would be awesome. 

It has a pseudo functional blocking system... While you have the block button held down, then it'll clash sabers, do knock-aways and parries depending on saber skill level.  It kinda of works but is pretty terrible.

 

I'll make that a higher priority for the next release.

 

Got any thoughts on what you'd want to see in a blocking system? A blocking stance that gets held where you can adjust blocking direction or something? I really want to incorporate parries to do counter attacks (like in the Last Blade games) in the next version so it would need to be conducive to that.

I really like this, congratulations on bringing something fresh to the modding scene.

Thanks, appreciate it!

Jolly likes this
Posted

 

Yes, but they're all done via code. I didn't make any animations in the traditional sense.

 

In game I'm accomplishing the breathing by manipulating the viewangles, because those cause the skeleton to look as if it were breathing. The code was really credue and needs my more refined method from the UI.

 

Game code here:

// adnan - make them seem as if theyre breathing
	// add some randomness to this!
	if(pm->ps->stats[STAT_HEALTH] <= 0) {
		breatheScale = 0;
	} else if(pm->ps->stats[STAT_HEALTH] < 25) {
		breatheScale = 2;
	} else if(pm->ps->stats[STAT_HEALTH] < 50) {
		breatheScale = 1.5;
	} else if(pm->ps->stats[STAT_HEALTH] < 75) {
		breatheScale = 1.25;
	} else {
		breatheScale = 1;
	}

	pm->ps->viewangles[PITCH] = breatheScale * 10 * sin(breatheScale * (pm->cmd.serverTime)/600.0f);
In the main menu (and the fighter selection screen), I'm doing it via bones directly. I also did blinking, neck tilting, saber re-gripping, etc via the code here. It's not super efficient, but generally works too.
viewAngles[YAW] = 0;
		viewAngles[PITCH] = 2.0f * sin(time / 700.0f + ui_jf_seed.integer) + 1.0f;
		viewAngles[ROLL] = 0;

		//distribute the angles differently up the spine
		//NOTE: each of these distributions must add up to 1.0f
		thoracicAngles[PITCH] = viewAngles[PITCH] * 0.20f;
		llAngles[PITCH] = viewAngles[PITCH] * 0.40f;
		ulAngles[PITCH] = viewAngles[PITCH] * 0.40f;
		craniumAngles[PITCH] = viewAngles[PITCH] * -0.8f;
		pelvisAngles[PITCH] = viewAngles[PITCH] * -0.2f;
		eyeAngles[PITCH] = -craniumAngles[PITCH] + 20.0f;

		thoracicAngles[YAW] = viewAngles[YAW] * 0.20f;
		ulAngles[YAW] = viewAngles[YAW] * 0.35f;
		llAngles[YAW] = viewAngles[YAW] * 0.45f;
		craniumAngles[YAW] = viewAngles[YAW] * -0.8f;
		pelvisAngles[YAW] = viewAngles[YAW] * 0.1f;
		eyeAngles[YAW] = -craniumAngles[YAW];

		thoracicAngles[ROLL] = viewAngles[ROLL] * 0.20f;
		ulAngles[ROLL] = viewAngles[ROLL] * 0.35f;
		llAngles[ROLL] = viewAngles[ROLL] * 0.45f;
		craniumAngles[ROLL] = viewAngles[ROLL] * -0.8f;
		pelvisAngles[ROLL] = viewAngles[ROLL] * -0.1f;
		eyeAngles[ROLL] = -craniumAngles[ROLL];

		// blink in 150 ms every 5 seconds
		if (time % 5000 < 150)
			eyeAngles[PITCH] -= 40.0f * fabs(sin(2*M_PI * 1000/300.0f * (time % 5000) / 1000.0f));
		
		// regrip pinky for half a second every 7 seconds
		if (time % 7000 < 500)
			pinkyFingerAngle[PITCH] = -40.0f * fabs(sin(2 * M_PI * 1000 / 1000.0f * (time % 7000) / 1000.0f));
		else
			pinkyFingerAngle[PITCH] = 0.0f;
		pinkyFingerAngle[ROLL] = 0;
		pinkyFingerAngle[YAW] = 0;

		// regrip thumb and forefingers for half a second every 7 seconds, 250 ms after with the forefingers
		if ((time % 7000 < 750) && (time % 7000 > 250))
			pointerFingerAngle[PITCH] = -40.0f * fabs(sin(2 * M_PI * 1000 / 1000.0f * ((time % 7000) - 250) / 1000.0f));
		else
			pointerFingerAngle[PITCH] = 0.0f;
		pointerFingerAngle[ROLL] = 0;
		pointerFingerAngle[YAW] = 0;

		thumbAngle[YAW] = pointerFingerAngle[YAW];
		thumbAngle[PITCH] = pointerFingerAngle[PITCH];
		thumbAngle[ROLL] = pointerFingerAngle[ROLL];

		// tilt the head every 40 seconds for 2 seconds
		if (time % 40000 < 2000)
			craniumAngles[ROLL] += -25.0f * sin(2 * M_PI * 1000 / 2000.0f * (time % 40000) / 1000.0f);
		//else
		//	craniumAngles[ROLL] = 0.0f;

		trap_G2API_SetBoneAngles(item->ghoul2, 0, "lower_lumbar", &llAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, uiInfo.uiDC.realTime);
		trap_G2API_SetBoneAngles(item->ghoul2, 0, "upper_lumbar", &ulAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, uiInfo.uiDC.realTime);
		trap_G2API_SetBoneAngles(item->ghoul2, 0, "cranium", &craniumAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, uiInfo.uiDC.realTime);
		trap_G2API_SetBoneAngles(item->ghoul2, 0, "thoracic", &thoracicAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, uiInfo.uiDC.realTime);
		trap_G2API_SetBoneAngles(item->ghoul2, 0, "pelvis", &pelvisAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, uiInfo.uiDC.realTime);

		trap_G2API_SetBoneAngles(item->ghoul2, 0, "r_d1_j2", &thumbAngle, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, uiInfo.uiDC.realTime);
		trap_G2API_SetBoneAngles(item->ghoul2, 0, "r_d2_j2", &pointerFingerAngle, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, uiInfo.uiDC.realTime);
		trap_G2API_SetBoneAngles(item->ghoul2, 0, "r_d4_j2", &pinkyFingerAngle, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, uiInfo.uiDC.realTime);

		eyeAngles[YAW] = -5.0f;
		trap_G2API_SetBoneAngles(item->ghoul2, 0, "leye", &eyeAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, uiInfo.uiDC.realTime);
		eyeAngles[YAW] = 5.0f;
		trap_G2API_SetBoneAngles(item->ghoul2, 0, "reye", &eyeAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, 0, 0, uiInfo.uiDC.realTime);

Wow. Nice work. That's genius. :P if I understand correctly, that wouldn't work in vanilla JKA then, otherwise the camera would move, correct?

Posted

Wow. Nice work. That's genius. :P if I understand correctly, that wouldn't work in vanilla JKA then, otherwise the camera would move, correct?

 

Right. The in-game solutions works well when the camera is separated from the viewangles of the actual player because all it does is move the viewangles that translate into client model deformation. If you turn off the jedifighter camera, you'd see the player bobbing his head up and down proportional to his health.

 

You could do it in-game if you used the method I did in the UI, though. I wanted to keep the fighters actually facing each other, so I applied the viewangles grossly as the base of the neck and then applied the inverse of those angles when you go up the spine to the cranium. This way they're technically keeping their faces parallel. That would stop weirdness from happening with the normal third person view.

Circa likes this
Posted

It has a pseudo functional blocking system... While you have the block button held down, then it'll clash sabers, do knock-aways and parries depending on saber skill level.  It kinda of works but is pretty terrible.

 

I'll make that a higher priority for the next release.

 

Got any thoughts on what you'd want to see in a blocking system? A blocking stance that gets held where you can adjust blocking direction or something? I really want to incorporate parries to do counter attacks (like in the Last Blade games) in the next version so it would need to be conducive to that.

Thanks, appreciate it!

 

Your work is genious and you should do what you think is better!

 

A blocking system I've seen that works well on JA is the MBII blocking. It's basically a block button that protects the player from most harm, but it's linked to the equivalent of a stamina bar, so you can't keep blocking forever. 

 

I remember counter attacks on Soul Calibur, when you blocked an attack on the moment of impact, the enemy would stagger.

 

Whatever you do, I'm sure it will work fine. This is the most original mod I've ever seen in Jedi Academy.

skew likes this
Posted

Probably just holding a button to enter a blocking mode would be best. Think of it like Assassin's Creed. Left stick moves the character, and he has 4 actions to choose from on the buttons. But, if you hold right trigger, you can still move with the left stick but your 4 buttons now do different actions. This would be a great way to implement a blocking system without forcing you to stay in one spot, or to make things too complex. Depends on how you want to implement things, and maintain a good balance, really.

skew likes this
Posted

@@skew If I were you I'd be pist about the that quote.

I tried to contact them to correct it (and posted comments to that effect) but didn't get a response.

 

I'm not pissed but thankful because this made Jedi Fighter jump to #4 on moddb momentarily. People playing it is all I wanted :).

 

There are a lot of follow-on articles on other sites where they get the facts right so I'm not too concerned.

Jolly and eezstreet like this
Posted

@@skew

I hope they correct that ASAP. It's good that you didn't get pissed because of that, but it might have a different effect to those who aren't aware of

that the mod is not as the authors described it. I mean, they were talking about an advanced AI that is not yet in the mod. Because of that, some people might think "Yeah! Mortal Kombat for Jedi Academy!" without

even knowing that Jedi Fighter doesn't have that yet. It would be terrible if people would complain about missing features that will be included in the next versions.

 

And talking about Mortal Kombat: It's just an idea and I don't know if it's possible, but some sort of finishing moves would be pretty cool.

Posted

I tried to make a list of the different sites that linked to it over the last few days. It's awesome to see that people are still interested in mods like this.

 

http://www.kotaku.com.au/2016/01/theres-a-mod-that-sort-of-turns-jedi-academy-into-street-fighter/

 

http://www.kotaku.com.au/2016/01/mod-turns-star-wars-shooter-into-2d-fighter/

 

http://kotaku.com/mod-turns-star-wars-shooter-into-2d-fighter-1754846197

 

http://www.gameblog.fr/news/56334-un-mod-transforme-star-wars-jedi-knight-en-jeu-de-combat

 

http://www.playground.ru/blogs/star_wars_jedi_knight_jedi_academy/shuter_po_motivam_star_wars_prevratili_v_fajting-178928/

 

http://www.melty.fr/un-star-wars-a-la-street-fighter-a494062.html

 

http://www.tweaktown.com/news/49942/cool-mod-turns-classic-jedi-academy-fighting-game/index.html

 

http://www.meristation.com/pc/noticias/jedi-knight-se-convierte-en-un-juego-de-lucha-con-un-mod/58/2106009?id_externo_promo=meri-ob&prm=meri-ob&ncid=meri-ob

 

http://www.hobbyconsolas.com/noticias/star-wars-jedi-knight-convertido-juego-lucha-gracias-mod-135806

 

http://www.pcgamer.com/mod-turns-jedi-academy-into-a-fighting-game/

 

https://www.reddit.com/r/Fighters/comments/42mbuq/jedi_fighter_jedi_academy_2d_fighting_game_mod/

 

http://www.gamestar.hu/star-wars-jedi-knight-jedi-academy-jedi-fighter-2d-verekedos-jatek-mod.html

 

http://blogjob.com/oneangrygamer/2016/01/jedi-academy-mod-jedi-fighter-turns-battles-into-a-street-fighter-like-game/

 

http://www.slashgear.com/mod-turns-jedi-academy-into-a-1v1-star-wars-fighting-game-25424231/

 

http://gamerant.com/star-wars-jedi-knight-fighting-game-mod/

 

http://news.douxie.com/zx/40808.html

therfiles, Noodle, Futuza and 3 others like this

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...