Jedi Outcast MP Patch v1.04

This commit is contained in:
James Monroe 2013-04-04 17:24:29 -05:00
parent 6af9b594e1
commit c8563e028a
100 changed files with 3123 additions and 1723 deletions

Binary file not shown.

Binary file not shown.

BIN
CODE-mp/Debug/botlib.lib Normal file

Binary file not shown.

Binary file not shown.

BIN
CODE-mp/Debug/cgamex86.dll Normal file

Binary file not shown.

BIN
CODE-mp/Debug/cgamex86.lib Normal file

Binary file not shown.

BIN
CODE-mp/Debug/jk2/vc60.idb Normal file

Binary file not shown.

BIN
CODE-mp/Debug/jk2mp.exe Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
CODE-mp/Debug/ui/vc60.idb Normal file

Binary file not shown.

BIN
CODE-mp/Debug/uix86.dll Normal file

Binary file not shown.

BIN
CODE-mp/Debug/uix86.lib Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
CODE-mp/Final/OpenAL32.dll Normal file

Binary file not shown.

BIN
CODE-mp/Final/botlib.lib Normal file

Binary file not shown.

Binary file not shown.

BIN
CODE-mp/Final/cgamex86.dll Normal file

Binary file not shown.

BIN
CODE-mp/Final/cgamex86.lib Normal file

Binary file not shown.

BIN
CODE-mp/Final/jk2/vc60.idb Normal file

Binary file not shown.

Binary file not shown.

BIN
CODE-mp/Final/jk2mp.exe Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
CODE-mp/Final/ui/vc60.idb Normal file

Binary file not shown.

BIN
CODE-mp/Final/uix86.dll Normal file

Binary file not shown.

BIN
CODE-mp/Final/uix86.lib Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
CODE-mp/Release/botlib.lib Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
CODE-mp/Release/jk2Ded.exe Normal file

Binary file not shown.

BIN
CODE-mp/Release/jk2mp.exe Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
CODE-mp/Release/ui/vc60.idb Normal file

Binary file not shown.

BIN
CODE-mp/Release/uix86.dll Normal file

Binary file not shown.

BIN
CODE-mp/Release/uix86.lib Normal file

Binary file not shown.

BIN
CODE-mp/base/vm/cgame.qvm Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -208,50 +208,69 @@ to a fixed color.
Coordinates are at 640 by 480 virtual resolution
==================
*/
#include "../../ui/menudef.h" // for "ITEM_TEXTSTYLE_SHADOWED"
void CG_DrawStringExt( int x, int y, const char *string, const float *setColor,
qboolean forceColor, qboolean shadow, int charWidth, int charHeight, int maxChars )
{
vec4_t color;
const char *s;
int xx;
if (trap_Language_IsAsian())
{
// hack-a-doodle-do (post-release quick fix code)...
//
vec4_t color;
memcpy(color,setColor, sizeof(color)); // de-const it
CG_Text_Paint(x, y, 1.0f, // float scale,
color, // vec4_t color,
string, // const char *text,
0.0f, // float adjust,
0, // int limit,
shadow ? ITEM_TEXTSTYLE_SHADOWED : 0, // int style,
FONT_MEDIUM // iMenuFont
) ;
}
else
{
vec4_t color;
const char *s;
int xx;
// draw the drop shadow
if (shadow) {
color[0] = color[1] = color[2] = 0;
color[3] = setColor[3];
trap_R_SetColor( color );
// draw the drop shadow
if (shadow) {
color[0] = color[1] = color[2] = 0;
color[3] = setColor[3];
trap_R_SetColor( color );
s = string;
xx = x;
while ( *s ) {
if ( Q_IsColorString( s ) ) {
s += 2;
continue;
}
CG_DrawChar( xx + 2, y + 2, charWidth, charHeight, *s );
xx += charWidth;
s++;
}
}
// draw the colored text
s = string;
xx = x;
trap_R_SetColor( setColor );
while ( *s ) {
if ( Q_IsColorString( s ) ) {
if ( !forceColor ) {
memcpy( color, g_color_table[ColorIndex(*(s+1))], sizeof( color ) );
color[3] = setColor[3];
trap_R_SetColor( color );
}
s += 2;
continue;
}
CG_DrawChar( xx + 2, y + 2, charWidth, charHeight, *s );
CG_DrawChar( xx, y, charWidth, charHeight, *s );
xx += charWidth;
s++;
}
trap_R_SetColor( NULL );
}
// draw the colored text
s = string;
xx = x;
trap_R_SetColor( setColor );
while ( *s ) {
if ( Q_IsColorString( s ) ) {
if ( !forceColor ) {
memcpy( color, g_color_table[ColorIndex(*(s+1))], sizeof( color ) );
color[3] = setColor[3];
trap_R_SetColor( color );
}
s += 2;
continue;
}
CG_DrawChar( xx, y, charWidth, charHeight, *s );
xx += charWidth;
s++;
}
trap_R_SetColor( NULL );
}
void CG_DrawBigString( int x, int y, const char *s, float alpha ) {

View file

@ -524,7 +524,7 @@ static void CG_General( centity_t *cent ) {
}
else
{
clEnt = &cg_entities[cent->currentState.modelindex2];
clEnt = &cg_entities[cent->currentState.otherEntityNum2];
}
if (!dismember_settings)
@ -793,6 +793,10 @@ static void CG_General( centity_t *cent ) {
trap_G2API_GiveMeVectorFromMatrix(&matrix, ORIGIN, boltOrg);
trap_G2API_GiveMeVectorFromMatrix(&matrix, NEGATIVE_Y, boltAng);
if (!boltAng[0] && !boltAng[1] && !boltAng[2])
{
boltAng[1] = 1;
}
trap_FX_PlayEffectID(trap_FX_RegisterEffect("blaster/smoke_bolton"), boltOrg, boltAng);
cent->trailTime = cg.time + 400;

View file

@ -2236,7 +2236,9 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) {
// local player sounds are triggered in CG_CheckLocalSounds,
// so ignore events on the player
DEBUGNAME("EV_PAIN");
if ( cent->currentState.number != cg.snap->ps.clientNum ) {
if ( !cg_oldPainSounds.integer || (cent->currentState.number != cg.snap->ps.clientNum) )
{
CG_PainEvent( cent, es->eventParm );
}
break;

View file

@ -167,6 +167,17 @@ void CG_DrawInformation( void ) {
y += iPropHeight;
}
{ // display global MOTD at bottom (mirrors ui_main UI_DrawConnectScreen
char motdString[1024];
trap_Cvar_VariableStringBuffer( "cl_motdString", motdString, sizeof( motdString ) );
if (motdString[0])
{
UI_DrawProportionalString( 320, 425, motdString,
UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
}
}
// some extra space after hostname and motd
y += 10;
}

View file

@ -1313,6 +1313,11 @@ typedef struct {
int capturelimit;
int timelimit;
int maxclients;
qboolean needpass;
qboolean jediVmerc;
int wDisable;
int fDisable;
char mapname[MAX_QPATH];
char redTeam[MAX_QPATH];
char blueTeam[MAX_QPATH];
@ -1456,10 +1461,17 @@ extern vmCvar_t cg_zoomFov;
extern vmCvar_t cg_swingAngles;
extern vmCvar_t cg_oldPainSounds;
#ifdef G2_COLLISION_ENABLED
extern vmCvar_t cg_saberModelTraceEffect;
#endif
extern vmCvar_t cg_fpls;
extern vmCvar_t cg_saberDynamicMarks;
extern vmCvar_t cg_saberDynamicMarkTime;
extern vmCvar_t cg_saberContact;
extern vmCvar_t cg_saberTrail;

View file

@ -410,10 +410,17 @@ vmCvar_t cg_zoomFov;
vmCvar_t cg_swingAngles;
vmCvar_t cg_oldPainSounds;
#ifdef G2_COLLISION_ENABLED
vmCvar_t cg_saberModelTraceEffect;
#endif
vmCvar_t cg_fpls;
vmCvar_t cg_saberDynamicMarks;
vmCvar_t cg_saberDynamicMarkTime;
vmCvar_t cg_saberContact;
vmCvar_t cg_saberTrail;
@ -557,10 +564,17 @@ static cvarTable_t cvarTable[] = { // bk001129
{ &cg_swingAngles, "cg_swingAngles", "1", 0 },
{ &cg_oldPainSounds, "cg_oldPainSounds", "0", 0 },
#ifdef G2_COLLISION_ENABLED
{ &cg_saberModelTraceEffect, "cg_saberModelTraceEffect", "0", 0 },
#endif
{ &cg_fpls, "cg_fpls", "0", 0 },
{ &cg_saberDynamicMarks, "cg_saberDynamicMarks", "0", 0 },
{ &cg_saberDynamicMarkTime, "cg_saberDynamicMarkTime", "60000", 0 },
{ &cg_saberContact, "cg_saberContact", "1", 0 },
{ &cg_saberTrail, "cg_saberTrail", "1", 0 },

View file

@ -265,7 +265,7 @@ retryModel:
trap_G2API_CleanGhoul2Models(&(ci->ghoul2Model));
}
if (cgs.gametype >= GT_TEAM)
if ( cgs.gametype >= GT_TEAM && !cgs.jediVmerc )
{
if (ci->team == TEAM_RED)
{
@ -662,7 +662,22 @@ void CG_LoadClientInfo( clientInfo_t *ci ) {
dir = ci->modelName;
fallback = DEFAULT_MALE_SOUNDPATH; //(cgs.gametype >= GT_TEAM) ? DEFAULT_TEAM_MODEL : DEFAULT_MODEL;
fLen = trap_FS_FOpenFile(va("models/players/%s/sounds.cfg", dir), &f, FS_READ);
if ( !ci->skinName || !Q_stricmp( "default", ci->skinName ) )
{//try default sounds.cfg first
fLen = trap_FS_FOpenFile(va("models/players/%s/sounds.cfg", dir), &f, FS_READ);
if ( !f )
{//no? Look for _default sounds.cfg
fLen = trap_FS_FOpenFile(va("models/players/%s/sounds_default.cfg", dir), &f, FS_READ);
}
}
else
{//use the .skin associated with this skin
fLen = trap_FS_FOpenFile(va("models/players/%s/sounds_%s.cfg", dir, ci->skinName), &f, FS_READ);
if ( !f )
{//fall back to default sounds
fLen = trap_FS_FOpenFile(va("models/players/%s/sounds.cfg", dir), &f, FS_READ);
}
}
soundpath[0] = 0;
@ -1129,7 +1144,7 @@ void CG_NewClientInfo( int clientNum, qboolean entitiesInitialized ) {
newInfo.ATST = wasATST;
if (cgs.gametype >= GT_TEAM)
if (cgs.gametype >= GT_TEAM && !cgs.jediVmerc )
{
if (newInfo.team == TEAM_RED)
{
@ -1190,23 +1205,29 @@ void CG_NewClientInfo( int clientNum, qboolean entitiesInitialized ) {
if (entitiesInitialized && ci->ghoul2Model && (oldGhoul2 != ci->ghoul2Model))
{ // Copy the new ghoul2 model to the centity.
animation_t *anim;
// First check if we have a ghoul2 model on the client entity.
centity_t *cent = &cg_entities[clientNum];
anim = &bgGlobalAnimations[ (cg_entities[clientNum].currentState.legsAnim & ~ANIM_TOGGLEBIT) ];
if (anim)
{
int flags = BONE_ANIM_OVERRIDE_FREEZE;
int firstFrame = anim->firstFrame + anim->numFrames-1;
int firstFrame = anim->firstFrame;
int setFrame = -1;
float animSpeed = 50.0f / anim->frameLerp;
if (anim->loopFrames != -1)
{
flags = BONE_ANIM_OVERRIDE_LOOP;
firstFrame = anim->firstFrame;
flags |= BONE_ANIM_OVERRIDE_LOOP;
}
if (cent->pe.legs.frame >= anim->firstFrame && cent->pe.legs.frame <= (anim->firstFrame + anim->numFrames))
{
setFrame = cent->pe.legs.frame;
}
//rww - Set the animation again because it just got reset due to the model change
trap_G2API_SetBoneAnim(ci->ghoul2Model, 0, "model_root", firstFrame, anim->firstFrame + anim->numFrames, flags, 1.0f, cg.time, -1, 150);
trap_G2API_SetBoneAnim(ci->ghoul2Model, 0, "model_root", firstFrame, anim->firstFrame + anim->numFrames, flags, animSpeed, cg.time, setFrame, 150);
cg_entities[clientNum].currentState.legsAnim = 0;
}
@ -1216,16 +1237,22 @@ void CG_NewClientInfo( int clientNum, qboolean entitiesInitialized ) {
if (anim)
{
int flags = BONE_ANIM_OVERRIDE_FREEZE;
int firstFrame = anim->firstFrame + anim->numFrames-1;
int firstFrame = anim->firstFrame;
int setFrame = -1;
float animSpeed = 50.0f / anim->frameLerp;
if (anim->loopFrames != -1)
{
flags = BONE_ANIM_OVERRIDE_LOOP;
firstFrame = anim->firstFrame;
flags |= BONE_ANIM_OVERRIDE_LOOP;
}
if (cent->pe.torso.frame >= anim->firstFrame && cent->pe.torso.frame <= (anim->firstFrame + anim->numFrames))
{
setFrame = cent->pe.torso.frame;
}
//rww - Set the animation again because it just got reset due to the model change
trap_G2API_SetBoneAnim(ci->ghoul2Model, 0, "lower_lumbar", anim->firstFrame + anim->numFrames-1, anim->firstFrame + anim->numFrames, flags, 1.0f, cg.time, -1, 150);
trap_G2API_SetBoneAnim(ci->ghoul2Model, 0, "lower_lumbar", firstFrame, anim->firstFrame + anim->numFrames, flags, animSpeed, cg.time, setFrame, 150);
cg_entities[clientNum].currentState.torsoAnim = 0;
}
@ -1235,26 +1262,7 @@ void CG_NewClientInfo( int clientNum, qboolean entitiesInitialized ) {
trap_G2API_CleanGhoul2Models(&cg_entities[clientNum].ghoul2);
}
trap_G2API_DuplicateGhoul2Instance(ci->ghoul2Model, &cg_entities[clientNum].ghoul2);
/*
if (cg_entities[clientNum].currentState.weapon > WP_NONE)
{
CG_CopyG2WeaponInstance(cg_entities[clientNum].currentState.weapon, cg_entities[clientNum].ghoul2);
}
*/
//It should catch this next update anyway. We just set all ghoul2weapon's to NULL above.
}
/*
else if (ci->team == TEAM_SPECTATOR && cg_entities[clientNum].ghoul2 && trap_G2_HaveWeGhoul2Models(cg_entities[clientNum].ghoul2))
{ //this shouldn't actually happen now because we are not trying to register models for spectators. But just in case.
trap_G2API_CleanGhoul2Models(&cg_entities[clientNum].ghoul2);
if (ci->ghoul2Model && trap_G2_HaveWeGhoul2Models(ci->ghoul2Model))
{
trap_G2API_DuplicateGhoul2Instance(ci->ghoul2Model, &cg_entities[clientNum].ghoul2);
}
}
*/
}
@ -2295,6 +2303,35 @@ void CG_G2SetBoneAngles(void *ghoul2, int modelIndex, const char *boneName, cons
blendTime, currentTime);
}
qboolean CG_InKnockDown( int anim )
{
switch ( (anim&~ANIM_TOGGLEBIT) )
{
case BOTH_KNOCKDOWN1:
case BOTH_KNOCKDOWN2:
case BOTH_KNOCKDOWN3:
case BOTH_KNOCKDOWN4:
case BOTH_KNOCKDOWN5:
return qtrue;
break;
case BOTH_GETUP1:
case BOTH_GETUP2:
case BOTH_GETUP3:
case BOTH_GETUP4:
case BOTH_GETUP5:
case BOTH_FORCE_GETUP_F1:
case BOTH_FORCE_GETUP_F2:
case BOTH_FORCE_GETUP_B1:
case BOTH_FORCE_GETUP_B2:
case BOTH_FORCE_GETUP_B3:
case BOTH_FORCE_GETUP_B4:
case BOTH_FORCE_GETUP_B5:
return qtrue;
break;
}
return qfalse;
}
void CG_G2ClientSpineAngles( centity_t *cent, vec3_t viewAngles, const vec3_t angles, vec3_t thoracicAngles, vec3_t ulAngles, vec3_t llAngles )
{
float legDif = 0;
@ -2323,6 +2360,11 @@ void CG_G2ClientSpineAngles( centity_t *cent, vec3_t viewAngles, const vec3_t an
!BG_SaberInSpecialAttack(cent->currentState.torsoAnim&~ANIM_TOGGLEBIT) &&
!BG_SaberInSpecialAttack(cent->currentState.legsAnim&~ANIM_TOGGLEBIT) &&
!CG_InKnockDown(cent->currentState.torsoAnim) &&
!CG_InKnockDown(cent->currentState.legsAnim) &&
!CG_InKnockDown(cgs.clientinfo[cent->currentState.number].torsoAnim) &&
!CG_InKnockDown(cgs.clientinfo[cent->currentState.number].legsAnim) &&
!BG_FlippingAnim( cgs.clientinfo[cent->currentState.number].legsAnim&~ANIM_TOGGLEBIT ) &&
!BG_SpinningSaberAnim( cgs.clientinfo[cent->currentState.number].legsAnim&~ANIM_TOGGLEBIT ) &&
!BG_SpinningSaberAnim( cgs.clientinfo[cent->currentState.number].torsoAnim&~ANIM_TOGGLEBIT ) &&
@ -3801,7 +3843,6 @@ void CG_CreateSaberMarks( vec3_t start, vec3_t end, vec3_t normal )
numFragments = trap_CM_MarkFragments( 4, (const float (*)[3])originalPoints,
projection, MAX_MARK_POINTS, markPoints[0], MAX_MARK_FRAGMENTS, markFragments );
for ( i = 0, mf = markFragments ; i < numFragments ; i++, mf++ )
{
// we have an upper limit on the complexity of polygons that we store persistantly
@ -3824,26 +3865,111 @@ void CG_CreateSaberMarks( vec3_t start, vec3_t end, vec3_t normal )
v->st[1] = 0.5 + DotProduct( delta, axis[2] ) * (0.15f + random() * 0.05f);
}
// save it persistantly, do burn first
mark = CG_AllocMark();
mark->time = cg.time;
mark->alphaFade = qtrue;
mark->markShader = cgs.media.rivetMarkShader;
mark->poly.numVerts = mf->numPoints;
mark->color[0] = mark->color[1] = mark->color[2] = mark->color[3] = 255;
memcpy( mark->verts, verts, mf->numPoints * sizeof( verts[0] ) );
if (cg_saberDynamicMarks.integer)
{
int i = 0;
int i_2 = 0;
addpolyArgStruct_t apArgs;
vec3_t x;
// And now do a glow pass
// by moving the start time back, we can hack it to fade out way before the burn does
mark = CG_AllocMark();
mark->time = cg.time - 8500;
mark->alphaFade = qfalse;
mark->markShader = trap_R_RegisterShader("gfx/effects/saberDamageGlow" );
mark->poly.numVerts = mf->numPoints;
mark->color[0] = 215 + random() * 40.0f;
mark->color[1] = 96 + random() * 32.0f;
mark->color[2] = mark->color[3] = random()*15.0f;
memcpy( mark->verts, verts, mf->numPoints * sizeof( verts[0] ) );
memset (&apArgs, 0, sizeof(apArgs));
while (i < 4)
{
while (i_2 < 3)
{
apArgs.p[i][i_2] = verts[i].xyz[i_2];
i_2++;
}
i_2 = 0;
i++;
}
i = 0;
i_2 = 0;
while (i < 4)
{
while (i_2 < 2)
{
apArgs.ev[i][i_2] = verts[i].st[i_2];
i_2++;
}
i_2 = 0;
i++;
}
//When using addpoly, having a situation like this tends to cause bad results.
//(I assume it doesn't like trying to draw a polygon over two planes and extends
//the vertex out to some odd value)
VectorSubtract(apArgs.p[0], apArgs.p[3], x);
if (VectorLength(x) > 3.0f)
{
return;
}
apArgs.numVerts = mf->numPoints;
VectorCopy(vec3_origin, apArgs.vel);
VectorCopy(vec3_origin, apArgs.accel);
apArgs.alpha1 = 1.0f;
apArgs.alpha2 = 0.0f;
apArgs.alphaParm = 255.0f;
VectorSet(apArgs.rgb1, 0.0f, 0.0f, 0.0f);
VectorSet(apArgs.rgb2, 0.0f, 0.0f, 0.0f);
apArgs.rgbParm = 0.0f;
apArgs.bounce = 0;
apArgs.motionDelay = 0;
apArgs.killTime = cg_saberDynamicMarkTime.integer;
apArgs.shader = cgs.media.rivetMarkShader;
apArgs.flags = 0x08000000|0x00000004;
trap_FX_AddPoly(&apArgs);
apArgs.shader = trap_R_RegisterShader("gfx/effects/saberDamageGlow");
apArgs.rgb1[0] = 215 + random() * 40.0f;
apArgs.rgb1[1] = 96 + random() * 32.0f;
apArgs.rgb1[2] = apArgs.alphaParm = random()*15.0f;
apArgs.rgb1[0] /= 255;
apArgs.rgb1[1] /= 255;
apArgs.rgb1[2] /= 255;
VectorCopy(apArgs.rgb1, apArgs.rgb2);
apArgs.killTime = 100;
trap_FX_AddPoly(&apArgs);
}
else
{
// save it persistantly, do burn first
mark = CG_AllocMark();
mark->time = cg.time;
mark->alphaFade = qtrue;
mark->markShader = cgs.media.rivetMarkShader;
mark->poly.numVerts = mf->numPoints;
mark->color[0] = mark->color[1] = mark->color[2] = mark->color[3] = 255;
memcpy( mark->verts, verts, mf->numPoints * sizeof( verts[0] ) );
// And now do a glow pass
// by moving the start time back, we can hack it to fade out way before the burn does
mark = CG_AllocMark();
mark->time = cg.time - 8500;
mark->alphaFade = qfalse;
mark->markShader = trap_R_RegisterShader("gfx/effects/saberDamageGlow");
mark->poly.numVerts = mf->numPoints;
mark->color[0] = 215 + random() * 40.0f;
mark->color[1] = 96 + random() * 32.0f;
mark->color[2] = mark->color[3] = random()*15.0f;
memcpy( mark->verts, verts, mf->numPoints * sizeof( verts[0] ) );
}
}
}
@ -4060,7 +4186,7 @@ Ghoul2 Insert Start
scolor = cgs.clientinfo[cent->currentState.number].icolor1;
if (cgs.gametype >= GT_TEAM)
if (cgs.gametype >= GT_TEAM && !cgs.jediVmerc )
{
if (cgs.clientinfo[cent->currentState.number].team == TEAM_RED)
{
@ -5521,6 +5647,95 @@ void CG_G2Animated( centity_t *cent )
}
//rww - here ends the majority of my g2animent stuff.
int cgFPLSState = 0;
void CG_ForceFPLSPlayerModel(centity_t *cent, clientInfo_t *ci)
{
int clientNum = cent->currentState.number;
animation_t *anim;
if (cg_fpls.integer && !cg.renderingThirdPerson)
{
int skinHandle;
skinHandle = trap_R_RegisterSkin("models/players/kyle/model_fpls2.skin");
trap_G2API_CleanGhoul2Models(&(ci->ghoul2Model));
ci->torsoSkin = skinHandle;
trap_G2API_InitGhoul2Model(&ci->ghoul2Model, "models/players/kyle/model.glm", 0, ci->torsoSkin, 0, 0, 0);
ci->bolt_rhand = trap_G2API_AddBolt(ci->ghoul2Model, 0, "*r_hand");
trap_G2API_SetBoneAnim(ci->ghoul2Model, 0, "model_root", 0, 12, BONE_ANIM_OVERRIDE_LOOP, 1.0f, cg.time, -1, -1);
trap_G2API_SetBoneAngles(ci->ghoul2Model, 0, "upper_lumbar", vec3_origin, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, NULL, 0, cg.time);
trap_G2API_SetBoneAngles(ci->ghoul2Model, 0, "cranium", vec3_origin, BONE_ANGLES_POSTMULT, POSITIVE_Z, NEGATIVE_Y, POSITIVE_X, NULL, 0, cg.time);
ci->bolt_lhand = trap_G2API_AddBolt(ci->ghoul2Model, 0, "*l_hand");
ci->bolt_head = trap_G2API_AddBolt(ci->ghoul2Model, 0, "*head_top");
ci->bolt_motion = trap_G2API_AddBolt(ci->ghoul2Model, 0, "Motion");
//We need a lower lumbar bolt for footsteps
ci->bolt_llumbar = trap_G2API_AddBolt(ci->ghoul2Model, 0, "lower_lumbar");
}
else
{
CG_RegisterClientModelname(ci, ci->modelName, ci->skinName, ci->teamName, cent->currentState.number);
}
anim = &bgGlobalAnimations[ (cg_entities[clientNum].currentState.legsAnim & ~ANIM_TOGGLEBIT) ];
if (anim)
{
int flags = BONE_ANIM_OVERRIDE_FREEZE;
int firstFrame = anim->firstFrame;
int setFrame = -1;
float animSpeed = 50.0f / anim->frameLerp;
if (anim->loopFrames != -1)
{
flags |= BONE_ANIM_OVERRIDE_LOOP;
}
if (cent->pe.legs.frame >= anim->firstFrame && cent->pe.legs.frame <= (anim->firstFrame + anim->numFrames))
{
setFrame = cent->pe.legs.frame;
}
trap_G2API_SetBoneAnim(ci->ghoul2Model, 0, "model_root", firstFrame, anim->firstFrame + anim->numFrames, flags, animSpeed, cg.time, setFrame, 150);
cg_entities[clientNum].currentState.legsAnim = 0;
}
anim = &bgGlobalAnimations[ (cg_entities[clientNum].currentState.torsoAnim & ~ANIM_TOGGLEBIT) ];
if (anim)
{
int flags = BONE_ANIM_OVERRIDE_FREEZE;
int firstFrame = anim->firstFrame;
int setFrame = -1;
float animSpeed = 50.0f / anim->frameLerp;
if (anim->loopFrames != -1)
{
flags |= BONE_ANIM_OVERRIDE_LOOP;
}
if (cent->pe.torso.frame >= anim->firstFrame && cent->pe.torso.frame <= (anim->firstFrame + anim->numFrames))
{
setFrame = cent->pe.torso.frame;
}
trap_G2API_SetBoneAnim(ci->ghoul2Model, 0, "lower_lumbar", firstFrame, anim->firstFrame + anim->numFrames, flags, animSpeed, cg.time, setFrame, 150);
cg_entities[clientNum].currentState.torsoAnim = 0;
}
trap_G2API_CleanGhoul2Models(&(cent->ghoul2));
trap_G2API_DuplicateGhoul2Instance(ci->ghoul2Model, &cent->ghoul2);
cg_entities[clientNum].ghoul2 = cent->ghoul2;
}
/*
===============
@ -5709,7 +5924,10 @@ void CG_Player( centity_t *cent ) {
renderfx = 0;
if ( cent->currentState.number == cg.snap->ps.clientNum) {
if (!cg.renderingThirdPerson) {
renderfx = RF_THIRD_PERSON; // only draw in mirrors
if (!cg_fpls.integer || cent->currentState.weapon != WP_SABER)
{
renderfx = RF_THIRD_PERSON; // only draw in mirrors
}
} else {
if (cg_cameraMode.integer) {
iwantout = 1;
@ -5922,6 +6140,61 @@ doEssentialOne:
trap_G2API_GetBoltMatrix(cent->ghoul2, 0, cgs.clientinfo[cent->currentState.number].bolt_lhand, &lHandMatrix, cent->turAngles, cent->lerpOrigin, cg.time, cgs.gameModels, cent->modelScale);
gotLHandMatrix = qtrue;
if (cg.renderingThirdPerson)
{
if (cgFPLSState != 0)
{
CG_ForceFPLSPlayerModel(cent, ci);
cgFPLSState = 0;
return;
}
}
else if (ci->team == TEAM_SPECTATOR || (cg.snap && (cg.snap->ps.pm_flags & PMF_FOLLOW)))
{ //don't allow this when spectating
if (cgFPLSState != 0)
{
trap_Cvar_Set("cg_fpls", "0");
cg_fpls.integer = 0;
CG_ForceFPLSPlayerModel(cent, ci);
cgFPLSState = 0;
return;
}
if (cg_fpls.integer)
{
trap_Cvar_Set("cg_fpls", "0");
}
}
else
{
if (cg_fpls.integer && cent->currentState.weapon == WP_SABER && cg.snap && cent->currentState.number == cg.snap->ps.clientNum)
{
if (cgFPLSState != cg_fpls.integer)
{
CG_ForceFPLSPlayerModel(cent, ci);
cgFPLSState = cg_fpls.integer;
return;
}
/*
mdxaBone_t headMatrix;
trap_G2API_GetBoltMatrix(cent->ghoul2, 0, cgs.clientinfo[cent->currentState.number].bolt_head, &headMatrix, cent->turAngles, cent->lerpOrigin, cg.time, cgs.gameModels, cent->modelScale);
trap_G2API_GiveMeVectorFromMatrix(&headMatrix, ORIGIN, cg.refdef.vieworg);
*/
}
else if (!cg_fpls.integer && cgFPLSState)
{
if (cgFPLSState != cg_fpls.integer)
{
CG_ForceFPLSPlayerModel(cent, ci);
cgFPLSState = cg_fpls.integer;
return;
}
}
}
if (cent->currentState.eFlags & EF_DEAD)
{
dead = qtrue;
@ -6002,6 +6275,10 @@ doEssentialTwo:
CG_PlayerAnimation( cent, &legs.oldframe, &legs.frame, &legs.backlerp,
&torso.oldframe, &torso.frame, &torso.backlerp );
//Need these set because we use them in other functions (cent pointer differs from cg_entities values)
cg_entities[cent->currentState.number].pe.torso.frame = cent->pe.torso.frame;
cg_entities[cent->currentState.number].pe.legs.frame = cent->pe.legs.frame;
// add the talk baloon or disconnect icon
CG_PlayerSprites( cent );
@ -6010,13 +6287,6 @@ doEssentialTwo:
cgs.clientinfo[cent->currentState.number].frame = cent->pe.torso.frame;
}
/* if ( cent->gent->s.number == 0 && cg_thirdPersonAlpha.value < 1.0f )
{
ent.renderfx |= RF_ALPHA_FADE;
ent.shaderRGBA[3] = (unsigned char)(cg_thirdPersonAlpha.value * 255.0f);
}
*/
if (cent->isATST)
{
goto doEssentialThree;

View file

@ -332,9 +332,14 @@ void CG_CheckLocalSounds( playerState_t *ps, playerState_t *ops ) {
}
// health changes of more than -3 should make pain sounds
if ( ps->stats[STAT_HEALTH] < (ops->stats[STAT_HEALTH] - 3)) {
if ( ps->stats[STAT_HEALTH] > 0 ) {
CG_PainEvent( &cg.predictedPlayerEntity, ps->stats[STAT_HEALTH] );
if (cg_oldPainSounds.integer)
{
if ( ps->stats[STAT_HEALTH] < (ops->stats[STAT_HEALTH] - 3))
{
if ( ps->stats[STAT_HEALTH] > 0 )
{
CG_PainEvent( &cg.predictedPlayerEntity, ps->stats[STAT_HEALTH] );
}
}
}

View file

@ -363,7 +363,12 @@ qboolean CG_DrawOldScoreboard( void ) {
CG_DrawPic ( SB_SCORELINE_X - 40, y - 5, SB_SCORELINE_WIDTH + 80, 40, trap_R_RegisterShaderNoMip ( "gfx/menus/menu_buttonback.tga" ) );
CG_Text_Paint ( SB_NAME_X, y, 1.0f, colorWhite, "Name", 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM );
// "NAME", "SCORE", "PING", "TIME" weren't localised, GODDAMMIT!!!!!!!!
//
// Unfortunately, since it's so sodding late now and post release I can't enable the localisation code (REM'd) since some of
// the localised strings don't fit - since no-one's ever seen them to notice this. Smegging brilliant. Thanks people.
//
CG_Text_Paint ( SB_NAME_X, y, 1.0f, colorWhite, /*CG_GetStripEdString("MENUS3", "NAME")*/"Name",0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM );
if (cgs.gametype == GT_TOURNAMENT)
{
char sWL[100];
@ -373,10 +378,10 @@ qboolean CG_DrawOldScoreboard( void ) {
}
else
{
CG_Text_Paint ( SB_SCORE_X, y, 1.0f, colorWhite, "Score", 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM );
CG_Text_Paint ( SB_SCORE_X, y, 1.0f, colorWhite, /*CG_GetStripEdString("MENUS3", "SCORE")*/"Score", 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM );
}
CG_Text_Paint ( SB_PING_X, y, 1.0f, colorWhite, "Ping", 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM );
CG_Text_Paint ( SB_TIME_X, y, 1.0f, colorWhite, "Time", 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM );
CG_Text_Paint ( SB_PING_X, y, 1.0f, colorWhite, /*CG_GetStripEdString("MENUS0", "PING")*/"Ping", 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM );
CG_Text_Paint ( SB_TIME_X, y, 1.0f, colorWhite, /*CG_GetStripEdString("MENUS3", "TIME")*/"Time", 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM );
y = SB_TOP;

View file

@ -136,6 +136,10 @@ void CG_ParseServerinfo( void ) {
info = CG_ConfigString( CS_SERVERINFO );
cgs.gametype = atoi( Info_ValueForKey( info, "g_gametype" ) );
trap_Cvar_Set("g_gametype", va("%i", cgs.gametype));
cgs.needpass = atoi( Info_ValueForKey( info, "needpass" ) );
cgs.jediVmerc = atoi( Info_ValueForKey( info, "g_jediVmerc" ) );
cgs.wDisable = atoi( Info_ValueForKey( info, "wdisable" ) );
cgs.fDisable = atoi( Info_ValueForKey( info, "fdisable" ) );
cgs.dmflags = atoi( Info_ValueForKey( info, "dmflags" ) );
cgs.teamflags = atoi( Info_ValueForKey( info, "teamflags" ) );
cgs.fraglimit = atoi( Info_ValueForKey( info, "fraglimit" ) );
@ -145,6 +149,7 @@ void CG_ParseServerinfo( void ) {
cgs.maxclients = atoi( Info_ValueForKey( info, "sv_maxclients" ) );
mapname = Info_ValueForKey( info, "mapname" );
//rww - You must do this one here, Info_ValueForKey always uses the same memory pointer.
trap_Cvar_Set ( "ui_about_mapname", mapname );

View file

@ -1559,7 +1559,14 @@ void CG_DrawActiveFrame( int serverTime, stereoFrame_t stereoView, qboolean demo
if (cg.snap->ps.stats[STAT_HEALTH] > 0 && (cg.predictedPlayerState.weapon == WP_SABER || cg.predictedPlayerState.usingATST ||
cg.predictedPlayerState.forceHandExtend == HANDEXTEND_KNOCKDOWN || cg.predictedPlayerState.fallingToDeath))
{
cg.renderingThirdPerson = 1;
if (cg_fpls.integer && cg.predictedPlayerState.weapon == WP_SABER)
{ //force to first person for fpls
cg.renderingThirdPerson = 0;
}
else
{
cg.renderingThirdPerson = 1;
}
}
else if (cg.snap->ps.zoomMode)
{ //always force first person when zoomed

View file

@ -349,8 +349,8 @@ void CL_ConsolePrint( char *txt ) {
color = ColorIndex(COLOR_WHITE);
while ( (c = *txt) != 0 ) {
if ( Q_IsColorString( txt ) ) {
while ( (c = (unsigned char) *txt) != 0 ) {
if ( Q_IsColorString( (unsigned char*) txt ) ) {
color = ColorIndex( *(txt+1) );
txt += 2;
continue;

View file

@ -477,7 +477,7 @@ void CL_ParseDownload ( msg_t *msg ) {
int block;
// read the data
block = MSG_ReadShort ( msg );
block = (unsigned short)MSG_ReadShort ( msg );
if ( !block )
{
@ -493,7 +493,7 @@ void CL_ParseDownload ( msg_t *msg ) {
}
}
size = MSG_ReadShort ( msg );
size = (unsigned short)MSG_ReadShort ( msg );
if (size > 0)
MSG_ReadData( msg, data, size );

View file

@ -2198,6 +2198,11 @@ int BotIsAChickenWuss(bot_state_t *bs)
return 0;
}
if (g_gametype.integer == GT_SINGLE_PLAYER)
{
return 0;
}
if (g_gametype.integer == GT_JEDIMASTER && !bs->cur_ps.isJediMaster)
{ //Then you may know no fear.
//Well, unless he's strong.
@ -3724,7 +3729,15 @@ void GetIdealDestination(bot_state_t *bs)
if (tempInt != -1 && TotalTrailDistance(bs->wpCurrent->index, tempInt, bs) != -1)
{
bs->wpDestination = gWPArray[tempInt];
bs->wpDestSwitchTime = level.time + Q_irand(1000, 5000);
if (g_gametype.integer == GT_SINGLE_PLAYER)
{ //be more aggressive
bs->wpDestSwitchTime = level.time + Q_irand(300, 1000);
}
else
{
bs->wpDestSwitchTime = level.time + Q_irand(1000, 5000);
}
}
}
}
@ -6439,6 +6452,8 @@ void StandardBotAI(bot_state_t *bs, float thinktime)
{
if (BotGetWeaponRange(bs) == BWEAPONRANGE_SABER)
{
int saberRange = SABER_ATTACK_RANGE;
VectorSubtract(bs->currentEnemy->client->ps.origin, bs->eye, a_fo);
vectoangles(a_fo, a_fo);
@ -6478,7 +6493,12 @@ void StandardBotAI(bot_state_t *bs, float thinktime)
}
}
if (bs->frame_Enemy_Len <= SABER_ATTACK_RANGE)
if (g_gametype.integer == GT_SINGLE_PLAYER)
{
saberRange *= 3;
}
if (bs->frame_Enemy_Len <= saberRange)
{
SaberCombatHandling(bs);

View file

@ -101,3 +101,4 @@ void PM_SetAnim(int setAnimParts,int anim,int setAnimFlags, int blendTime);
void PM_WeaponLightsaber(void);
void PM_SetSaberMove(short newMove);
void PM_SetForceJumpZStart(float value);

View file

@ -161,12 +161,18 @@ int WeaponAttackAnim[WP_NUM_WEAPONS] =
};
//The magical function to end all functions.
//This will take the force power string in powerOut and parse through it, then legalize
//it based on the supposed rank and spit it into powerOut, returning true if it was legal
//to begin with and false if not.
//fpDisabled is actually only expected (needed) from the server, because the ui disables
//force power selection anyway when force powers are disabled on the server.
/*
================
BG_LegalizedForcePowers
The magical function to end all functions.
This will take the force power string in powerOut and parse through it, then legalize
it based on the supposed rank and spit it into powerOut, returning true if it was legal
to begin with and false if not.
fpDisabled is actually only expected (needed) from the server, because the ui disables
force power selection anyway when force powers are disabled on the server.
================
*/
qboolean BG_LegalizedForcePowers(char *powerOut, int maxRank, qboolean freeSaber, int teamForce, int gametype, int fpDisabled)
{
char powerBuf[128];
@ -254,7 +260,6 @@ qboolean BG_LegalizedForcePowers(char *powerOut, int maxRank, qboolean freeSaber
{
final_Powers[i] = 0;
//This is only likely to happen with g_forceBasedTeams. Let it slide.
//maintainsValidity = 0;
}
if ( final_Powers[i] &&
@ -410,16 +415,16 @@ qboolean BG_LegalizedForcePowers(char *powerOut, int maxRank, qboolean freeSaber
final_Powers[FP_LEVITATION] = 1;
}
/*
if (fpDisabled)
i = 0;
while (i < NUM_FORCE_POWERS)
{
final_Powers[FP_LEVITATION] = 1;
final_Powers[FP_SABERATTACK] = 3;
final_Powers[FP_SABERDEFEND] = 3;
final_Powers[FP_SABERTHROW] = 0;
if (final_Powers[i] > FORCE_LEVEL_3)
{
final_Powers[i] = FORCE_LEVEL_3;
}
i++;
}
*/
//Ahh. I have no idea why I did this, but I would say that it makes me a very bad man.
if (fpDisabled)
{ //If we specifically have attack or def disabled, force them up to level 3. It's the way
//things work for the case of all powers disabled.
@ -1303,7 +1308,7 @@ qboolean BG_CanUseFPNow(int gametype, playerState_t *ps, int time, forcePowers_t
if (ps->duelInProgress)
{
if (power != FP_SABERATTACK && power != FP_SABERDEFEND && power != FP_SABERTHROW &&
if (power != FP_SABERATTACK && power != FP_SABERDEFEND && /*power != FP_SABERTHROW &&*/
power != FP_LEVITATION)
{
if (!ps->saberLockFrame || power != FP_PUSH)
@ -1466,68 +1471,68 @@ void BG_CycleForce(playerState_t *ps, int direction)
presel = x;
if (direction == 1)
{
{ //get the next power
x++;
}
else
{
{ //get the previous power
x--;
}
if (x >= NUM_FORCE_POWERS)
{
{ //cycled off the end.. cycle around to the first
x = 0;
}
if (x < 0)
{
{ //cycled off the beginning.. cycle around to the last
x = NUM_FORCE_POWERS-1;
}
i = forcePowerSorted[x];
i = forcePowerSorted[x]; //the "sorted" value of this power
while (x != presel)
{
{ //loop around to the current force power
if (ps->fd.forcePowersKnown & (1 << i) && i != ps->fd.forcePowerSelected)
{
{ //we have the force power
if (i != FP_LEVITATION &&
i != FP_SABERATTACK &&
i != FP_SABERDEFEND &&
i != FP_SABERTHROW)
{
{ //it's selectable
foundnext = i;
break;
}
}
if (direction == 1)
{
{ //next
x++;
}
else
{
{ //previous
x--;
}
if (x >= NUM_FORCE_POWERS)
{
{ //loop around
x = 0;
}
if (x < 0)
{
{ //loop around
x = NUM_FORCE_POWERS-1;
}
i = forcePowerSorted[x];
i = forcePowerSorted[x]; //set to the sorted value again
}
if (foundnext != -1)
{
{ //found one, select it
ps->fd.forcePowerSelected = foundnext;
}
}
int BG_GetItemIndexByTag(int tag, int type)
{
{ //Get the itemlist index from the tag and type
int i = 0;
while (i < bg_numItems)
@ -1553,37 +1558,37 @@ void BG_CycleInven(playerState_t *ps, int direction)
original = i;
if (direction == 1)
{
{ //next
i++;
}
else
{
{ //previous
i--;
}
while (i != original)
{ //go in a full loop until hitting something, if hit nothing then select nothing
if (ps->stats[STAT_HOLDABLE_ITEMS] & (1 << i))
{
{ //we have it, select it.
ps->stats[STAT_HOLDABLE_ITEM] = BG_GetItemIndexByTag(i, IT_HOLDABLE);
break;
}
if (direction == 1)
{
{ //next
i++;
}
else
{
{ //previous
i--;
}
if (i < 0)
{
{ //wrap around to the last
i = HI_NUM_HOLDABLE;
}
else if (i >= HI_NUM_HOLDABLE)
{
{ //wrap around to the first
i = 0;
}
}
@ -2039,7 +2044,6 @@ void BG_TouchJumpPad( playerState_t *ps, entityState_t *jumppad ) {
} else {
effectNum = 1;
}
//BG_AddPredictableEventToPlayerstate( EV_JUMP_PAD, effectNum, ps );
}
// remember hitting this jumppad this frame
ps->jumppad_ent = jumppad->number;
@ -2333,179 +2337,6 @@ PLAYER ANGLES
=============================================================================
*/
/*
==================
BG_SwingAngles
==================
*/
static void BG_SwingAngles( float destination, float swingTolerance, float clampTolerance,
float speed, float *angle, qboolean *swinging, int frameTime ) {
float swing;
float move;
float scale;
if ( !*swinging ) {
// see if a swing should be started
swing = AngleSubtract( *angle, destination );
if ( swing > swingTolerance || swing < -swingTolerance ) {
*swinging = qtrue;
}
}
if ( !*swinging ) {
return;
}
// modify the speed depending on the delta
// so it doesn't seem so linear
swing = AngleSubtract( destination, *angle );
scale = fabs( swing );
if ( scale < swingTolerance * 0.5 ) {
scale = 0.5;
} else if ( scale < swingTolerance ) {
scale = 1.0;
} else {
scale = 2.0;
}
// swing towards the destination angle
if ( swing >= 0 ) {
move = frameTime * scale * speed;
if ( move >= swing ) {
move = swing;
*swinging = qfalse;
}
*angle = AngleMod( *angle + move );
} else if ( swing < 0 ) {
move = frameTime * scale * -speed;
if ( move <= swing ) {
move = swing;
*swinging = qfalse;
}
*angle = AngleMod( *angle + move );
}
// clamp to no more than tolerance
swing = AngleSubtract( destination, *angle );
if ( swing > clampTolerance ) {
*angle = AngleMod( destination - (clampTolerance - 1) );
} else if ( swing < -clampTolerance ) {
*angle = AngleMod( destination + (clampTolerance - 1) );
}
}
/*
=================
CG_AddPainTwitch
=================
*/
#define PAIN_TWITCH_TIME 200
static void BG_AddPainTwitch( int painTime, int painDirection, int currentTime, vec3_t torsoAngles ) {
int t;
float f;
t = currentTime - painTime;
if ( t >= PAIN_TWITCH_TIME ) {
return;
}
f = 1.0 - (float)t / PAIN_TWITCH_TIME;
if ( painDirection ) {
torsoAngles[ROLL] += 20 * f;
} else {
torsoAngles[ROLL] -= 20 * f;
}
}
void BG_G2PlayerAngles( vec3_t startAngles, vec3_t legs[3], vec3_t legsAngles, int painTime, int painDirection, int currentTime,
qboolean *torso_yawing, float *torso_yawAngle, qboolean *torso_pitching, float *torso_pitchAngle, qboolean *legs_yawing, float *legs_yawAngle,
int frameTime, vec3_t velocity, int legsAnim, int torsoAnim, qboolean dead, float movementDir, void *ghoul2, qhandle_t *modelList, int weapon){
vec3_t torsoAngles, headAngles;
float dest;
static int movementOffsets[8] = { 0, 22, 45, -22, 0, 22, -45, -22 };
float speed;
int dir;
VectorCopy( startAngles, headAngles );
headAngles[YAW] = AngleMod( headAngles[YAW] );
VectorClear( legsAngles );
VectorClear( torsoAngles );
// --------- yaw -------------
// allow yaw to drift a bit
if ( ( legsAnim & ~ANIM_TOGGLEBIT ) != WeaponReadyAnim[weapon]
|| ( torsoAnim & ~ANIM_TOGGLEBIT ) != WeaponReadyAnim[weapon] ) {
// if not standing still, always point all in the same direction
*torso_yawing = qtrue; // always center
*torso_pitching = qtrue; // always center
*legs_yawing = qtrue; // always center
}
// adjust legs for movement dir
if (dead ) {
// don't let dead bodies twitch
dir = 0;
} else {
dir = movementDir;
// if ( dir < 0 || dir > 7 ) {
// CG_Error( "Bad player movement angle" );
// }
}
legsAngles[YAW] = headAngles[YAW] + movementOffsets[ dir ];
torsoAngles[YAW] = headAngles[YAW] + 0.25 * movementOffsets[ dir ];
// torso
BG_SwingAngles( torsoAngles[YAW], 25, 90, /*cg_swingSpeed.value*/ 0.3, torso_yawAngle, torso_yawing, frameTime );
BG_SwingAngles( legsAngles[YAW], 40, 90, /*cg_swingSpeed.value*/ 0.3, legs_yawAngle, legs_yawing, frameTime );
torsoAngles[YAW] = *torso_yawAngle;
legsAngles[YAW] = *legs_yawAngle;
// --------- pitch -------------
// only show a fraction of the pitch angle in the torso
if ( headAngles[PITCH] > 180 ) {
dest = (-360 + headAngles[PITCH]) * 0.75;
} else {
dest = headAngles[PITCH] * 0.75;
}
BG_SwingAngles( dest, 15, 30, 0.1, torso_pitchAngle, torso_pitching, frameTime );
torsoAngles[PITCH] = *torso_pitchAngle;
// --------- roll -------------
// lean towards the direction of travel
speed = VectorNormalize( velocity );
if ( speed ) {
vec3_t axis[3];
float side;
speed *= 0.05;
AnglesToAxis( legsAngles, axis );
side = speed * DotProduct( velocity, axis[1] );
legsAngles[ROLL] -= side;
side = speed * DotProduct( velocity, axis[0] );
legsAngles[PITCH] += side;
}
// pain twitch
BG_AddPainTwitch( painTime, painDirection, currentTime, torsoAngles );
// pull the angles back out of the hierarchial chain
AnglesSubtract( headAngles, torsoAngles, headAngles );
AnglesSubtract( torsoAngles, legsAngles, torsoAngles );
AnglesToAxis( legsAngles, legs );
// we assume that model 0 is the player model.
//g2r trap_G2API_SetBoneAngles(ghoul2, 0, "upper_lumbar", torsoAngles, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, modelList, 0, currentTime);
//g2r trap_G2API_SetBoneAngles(ghoul2, 0, "cranium", headAngles, BONE_ANGLES_POSTMULT, POSITIVE_Z, NEGATIVE_Y, POSITIVE_X, modelList,0, currentTime);
}
#define MAX_POOL_SIZE 2048000 //1024000
static char bg_pool[MAX_POOL_SIZE];

View file

@ -1077,15 +1077,13 @@ void PM_SetAnimFinal(int setAnimParts,int anim,int setAnimFlags,
PM_StartTorsoAnim( anim );
if (setAnimFlags & SETANIM_FLAG_HOLD)
{//FIXME: allow to set a specific time?
{
if (setAnimFlags & SETANIM_FLAG_HOLDLESS)
{ // Make sure to only wait in full 1/20 sec server frame intervals.
int dur;
int speedDif;
dur = (animations[anim].numFrames-1) * fabs(animations[anim].frameLerp);
//dur = ((int)(dur/50.0)) * 50 / timeScaleMod;
//dur -= blendTime+fabs(animations[anim].frameLerp)*2;
speedDif = dur - (dur * editAnimSpeed);
dur += speedDif;
if (dur > 1)
@ -1127,15 +1125,13 @@ setAnimLegs:
PM_StartLegsAnim(anim);
if (setAnimFlags & SETANIM_FLAG_HOLD)
{//FIXME: allow to set a specific time?
{
if (setAnimFlags & SETANIM_FLAG_HOLDLESS)
{ // Make sure to only wait in full 1/20 sec server frame intervals.
int dur;
int speedDif;
dur = (animations[anim].numFrames-1) * fabs(animations[anim].frameLerp);
//dur = ((int)(dur/50.0)) * 50 / timeScaleMod;
//dur -= blendTime+fabs(animations[anim].frameLerp)*2;
speedDif = dur - (dur * editAnimSpeed);
dur += speedDif;
if (dur > 1)
@ -1152,11 +1148,6 @@ setAnimLegs:
pm->ps->legsTimer = ((animations[anim].numFrames ) * fabs(animations[anim].frameLerp));
}
/*
PM_DebugLegsAnim(anim);
Com_Printf("%i\n", pm->ps->legsTimer);
*/
if (pm->ps->fd.forcePowersActive & (1 << FP_RAGE))
{
pm->ps->legsTimer /= 1.3;
@ -1186,8 +1177,7 @@ void PM_SetAnim(int setAnimParts,int anim,int setAnimFlags, int blendTime)
}
if (BG_InRoll(pm->ps, pm->ps->legsAnim))
{
//setAnimFlags |= SETANIM_FLAG_RESTART;
{ //never interrupt a roll
return;
}

View file

@ -467,7 +467,7 @@ qboolean PM_ForceJumpingUp(void)
}
if ( pm->ps->groundEntityNum == ENTITYNUM_NONE && //in air
(pm->ps->pm_flags & PMF_JUMP_HELD) &&//forceJumpZStart && //jumped
(pm->ps->pm_flags & PMF_JUMP_HELD) && //jumped
pm->ps->fd.forcePowerLevel[FP_LEVITATION] > FORCE_LEVEL_0 && //force-jump capable
pm->ps->velocity[2] > 0 )//going up
{
@ -506,7 +506,7 @@ static void PM_JumpForDir( void )
}
if(!BG_InDeathAnim(pm->ps->legsAnim))
{
PM_SetAnim(SETANIM_LEGS,anim,SETANIM_FLAG_OVERRIDE, 100); // Only blend over 100ms
PM_SetAnim(SETANIM_LEGS,anim,SETANIM_FLAG_OVERRIDE, 100);
}
}
@ -514,14 +514,13 @@ void PM_SetPMViewAngle(playerState_t *ps, vec3_t angle, usercmd_t *ucmd)
{
int i;
// set the delta angle
for (i=0 ; i<3 ; i++) {
for (i=0 ; i<3 ; i++)
{ // set the delta angle
int cmdAngle;
cmdAngle = ANGLE2SHORT(angle[i]);
ps->delta_angles[i] = cmdAngle - ucmd->angles[i];
}
//VectorCopy( angle, ent->s.angles );
VectorCopy (angle, ps->viewangles);
}
@ -555,8 +554,6 @@ qboolean PM_AdjustAngleForWallRun( playerState_t *ps, usercmd_t *ucmd, qboolean
if ( trace.fraction < 1.0f )
{//still a wall there
//FIXME: don't pull around 90 turns
//FIXME: simulate stepping up steps here, somehow?
if ( (ps->legsAnim&~ANIM_TOGGLEBIT) == BOTH_WALL_RUN_RIGHT )
{
ucmd->rightmove = 127;
@ -572,7 +569,6 @@ qboolean PM_AdjustAngleForWallRun( playerState_t *ps, usercmd_t *ucmd, qboolean
//make me face perpendicular to the wall
ps->viewangles[YAW] = vectoyaw( trace.plane.normal )+yawAdjust;
//SetClientViewAngle( ent, ent->client->ps.viewangles );
PM_SetPMViewAngle(ps, ps->viewangles, ucmd);
ucmd->angles[YAW] = ANGLE2SHORT( ps->viewangles[YAW] ) - ps->delta_angles[YAW];
@ -587,7 +583,7 @@ qboolean PM_AdjustAngleForWallRun( playerState_t *ps, usercmd_t *ucmd, qboolean
fwdAngles[YAW] = ps->viewangles[YAW];
AngleVectors( fwdAngles, fwd, NULL, NULL );
//FIXME: or MA?
if ( ucmd->forwardmove < 0 )
{//slower
speed = 100;
@ -621,12 +617,21 @@ qboolean PM_AdjustAngleForWallRun( playerState_t *ps, usercmd_t *ucmd, qboolean
return qfalse;
}
//Set the height for when a force jump was started. If it's 0, nuge it up (slight hack to prevent holding jump over slopes)
void PM_SetForceJumpZStart(float value)
{
pm->ps->fd.forceJumpZStart = value;
if (!pm->ps->fd.forceJumpZStart)
{
pm->ps->fd.forceJumpZStart -= 0.1;
}
}
/*
=============
PM_CheckJump
=============
*/
static qboolean PM_CheckJump( void )
{
if (pm->ps->usingATST)
@ -653,15 +658,9 @@ static qboolean PM_CheckJump( void )
{
pm->ps->fd.forcePowersActive &= ~(1<<FP_LEVITATION);
}
/*
if ( pm->cmd.buttons & BUTTON_FORCEJUMP )
{
pm->ps->pm_flags |= PMF_JUMP_HELD;
}
*/
if (pm->ps->fd.forcePowersActive & (1 << FP_LEVITATION))
{
{ //Force jump is already active.. continue draining power appropriately until we land.
if (pm->ps->fd.forcePowerDebounce[FP_LEVITATION] < pm->cmd.serverTime)
{
BG_ForcePowerDrain( pm->ps, FP_LEVITATION, 5 );
@ -677,7 +676,7 @@ static qboolean PM_CheckJump( void )
}
if (pm->ps->forceJumpFlip)
{
{ //Forced jump anim
int anim = BOTH_FORCEINAIR1;
int parts = SETANIM_BOTH;
@ -711,18 +710,15 @@ static qboolean PM_CheckJump( void )
{
if ( pm->ps->gravity > 0 )
{//can't do this in zero-G
//FIXME: still able to pogo-jump...
if ( PM_ForceJumpingUp() )
{//holding jump in air
float curHeight = pm->ps->origin[2] - pm->ps->fd.forceJumpZStart;
//check for max force jump level and cap off & cut z vel
if ( ( curHeight<=forceJumpHeight[0] ||//still below minimum jump height
(pm->ps->fd.forcePower&&pm->cmd.upmove>=10) ) &&////still have force power available and still trying to jump up
curHeight < forceJumpHeight[pm->ps->fd.forcePowerLevel[FP_LEVITATION]] )//still below maximum jump height
curHeight < forceJumpHeight[pm->ps->fd.forcePowerLevel[FP_LEVITATION]] &&
pm->ps->fd.forceJumpZStart)//still below maximum jump height
{//can still go up
//FIXME: after a certain amount of time of held jump, play force jump sound and flip if a dir is being held
//FIXME: if hit a wall... should we cut velocity or allow them to slide up it?
//FIXME: constantly drain force power at a rate by which the usage for maximum height would use up the full cost of force jump
if ( curHeight > forceJumpHeight[0] )
{//passed normal jump height *2?
if ( !(pm->ps->fd.forcePowersActive&(1<<FP_LEVITATION)) )//haven't started forcejump yet
@ -731,13 +727,12 @@ static qboolean PM_CheckJump( void )
pm->ps->fd.forcePowersActive |= (1<<FP_LEVITATION);
pm->ps->fd.forceJumpSound = 1;
//play flip
//FIXME: do this only when they stop the jump (below) or when they're just about to hit the peak of the jump
if ((pm->cmd.forwardmove || pm->cmd.rightmove) && //pushing in a dir
(pm->ps->legsAnim&~ANIM_TOGGLEBIT) != BOTH_FLIP_F &&//not already flipping
(pm->ps->legsAnim&~ANIM_TOGGLEBIT) != BOTH_FLIP_B &&
(pm->ps->legsAnim&~ANIM_TOGGLEBIT) != BOTH_FLIP_R &&
(pm->ps->legsAnim&~ANIM_TOGGLEBIT) != BOTH_FLIP_L )
{//FIXME: this could end up playing twice if the jump is very long...
{
int anim = BOTH_FORCEINAIR1;
int parts = SETANIM_BOTH;
@ -758,15 +753,15 @@ static qboolean PM_CheckJump( void )
anim = BOTH_FLIP_L;
}
if ( pm->ps->weaponTime )
{//FIXME: really only care if we're in a saber attack anim...
{
parts = SETANIM_LEGS;
}
PM_SetAnim( parts, anim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 150 );
}
else if ( pm->ps->fd.forcePowerLevel[FP_LEVITATION] > FORCE_LEVEL_1 )
{//FIXME: really want to know how far off ground we are, probably...
vec3_t facingFwd, facingRight, facingAngles;// = {0, pm->ps->viewangles[YAW], 0};
{
vec3_t facingFwd, facingRight, facingAngles;
int anim = -1;
float dotR, dotF;
@ -811,7 +806,7 @@ static qboolean PM_CheckJump( void )
}
}
else
{
{ //jump is already active (the anim has started)
if ( pm->ps->legsTimer < 1 )
{//not in the middle of a legsAnim
int anim = (pm->ps->legsAnim&~ANIM_TOGGLEBIT);
@ -835,7 +830,7 @@ static qboolean PM_CheckJump( void )
{
int parts = SETANIM_BOTH;
if ( pm->ps->weaponTime )
{//FIXME: really only care if we're in a saber attack anim...
{
parts = SETANIM_LEGS;
}
@ -871,16 +866,6 @@ static qboolean PM_CheckJump( void )
pm->cmd.upmove = 0;
return qfalse;
}
/*
else if ( pm->ps->groundEntityNum == ENTITYNUM_NONE )
{
int legsAnim = (pm->ps->legsAnim&~ANIM_TOGGLEBIT);
if ( legsAnim != BOTH_WALL_RUN_LEFT && legsAnim != BOTH_WALL_RUN_RIGHT )
{//special case.. these let you jump off a wall
return qfalse;
}
}
*/
}
}
@ -911,19 +896,16 @@ static qboolean PM_CheckJump( void )
if ( trace.fraction <= 1.0f )
{
VectorMA( pm->ps->velocity, JUMP_VELOCITY*2, forward, pm->ps->velocity );
//FIXME: kicking off wall anim? At least check what anim we're in?
PM_SetAnim(SETANIM_LEGS,BOTH_FORCEJUMP1,SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD|SETANIM_FLAG_RESTART, 150);
}//else no surf close enough to push off of
pm->cmd.upmove = 0;
}
else if ( pm->cmd.upmove > 0 && pm->waterlevel < 2 &&
pm->ps->fd.forcePowerLevel[FP_LEVITATION] > FORCE_LEVEL_0 &&
!(pm->ps->pm_flags&PMF_JUMP_HELD) /*&&
WP_ForcePowerAvailable( pm->gent, FP_LEVITATION, 0 ) */ &&
!(pm->ps->pm_flags&PMF_JUMP_HELD) &&
pm->ps->weapon == WP_SABER &&
!BG_HasYsalamiri(pm->gametype, pm->ps) &&
BG_CanUseFPNow(pm->gametype, pm->ps, pm->cmd.serverTime, FP_LEVITATION)
)
BG_CanUseFPNow(pm->gametype, pm->ps, pm->cmd.serverTime, FP_LEVITATION) )
{
if ( pm->ps->groundEntityNum != ENTITYNUM_NONE )
{//on the ground
@ -956,39 +938,21 @@ static qboolean PM_CheckJump( void )
anim = BOTH_WALL_FLIP_LEFT;
}
}
/*
else if ( pm->cmd.forwardmove > 0 && pm->ps->fd.forcePowerLevel[FP_LEVITATION] > FORCE_LEVEL_1 )
{//run up wall, flip backwards
vertPush = forceJumpStrength[FORCE_LEVEL_2]/2.25f;
anim = BOTH_WALL_FLIP_BACK1;
}
*/
else if ( pm->cmd.forwardmove < 0 && !(pm->cmd.buttons&BUTTON_ATTACK) )
{//backflip
vertPush = JUMP_VELOCITY;
anim = BOTH_FLIP_BACK1;//PM_PickAnim( BOTH_FLIP_BACK1, BOTH_FLIP_BACK3 );
}
/*
else if ( VectorLengthSquared( pm->ps->velocity ) < 256 )
{//not moving
if ( pm->ps->weapon == WP_SABER && (pm->cmd.buttons & BUTTON_ATTACK) && pm->ps->fd.saberAnimLevel == FORCE_LEVEL_2 )
{//butterfly... FIXME: does direction matter?
vertPush = JUMP_VELOCITY;
anim = BOTH_BUTTERFLY_LEFT;
}
}
*/
//FIXME: Do we want special moves in MP?
vertPush += 128; //is gravity different in SP or something?
vertPush += 128; //give them an extra shove
if ( anim != -1 /*&& PM_HasAnimation( pm->gent, anim )*/ )
if ( anim != -1 )
{
vec3_t fwd, right, traceto, mins, maxs, fwdAngles;
vec3_t idealNormal;
trace_t trace;
qboolean doTrace = qfalse;
int contents = /*CONTENTS_SOLID*/MASK_PLAYERSOLID;
int contents = MASK_PLAYERSOLID;
VectorSet(mins, pm->mins[0],pm->mins[1],0);
VectorSet(maxs, pm->maxs[0],pm->maxs[1],24);
@ -1002,7 +966,6 @@ static qboolean PM_CheckJump( void )
switch ( anim )
{
case BOTH_WALL_FLIP_LEFT:
//contents |= CONTENTS_BODY;
//NOTE: purposely falls through to next case!
case BOTH_WALL_RUN_LEFT:
doTrace = qtrue;
@ -1010,7 +973,6 @@ static qboolean PM_CheckJump( void )
break;
case BOTH_WALL_FLIP_RIGHT:
//contents |= CONTENTS_BODY;
//NOTE: purposely falls through to next case!
case BOTH_WALL_RUN_RIGHT:
doTrace = qtrue;
@ -1018,7 +980,6 @@ static qboolean PM_CheckJump( void )
break;
case BOTH_WALL_FLIP_BACK1:
//contents |= CONTENTS_BODY;
doTrace = qtrue;
VectorMA( pm->ps->origin, 16, fwd, traceto );
break;
@ -1030,11 +991,9 @@ static qboolean PM_CheckJump( void )
VectorSubtract( pm->ps->origin, traceto, idealNormal );
VectorNormalize( idealNormal );
}
// gentity_t *traceEnt = &g_entities[trace.entityNum];
//if ( !doTrace || (trace.fraction < 1.0f&&((trace.entityNum<ENTITYNUM_WORLD&&traceEnt&&traceEnt->s.solid!=SOLID_BMODEL)||DotProduct(trace.plane.normal,idealNormal)>0.7)) )
if ( !doTrace || (trace.fraction < 1.0f && (trace.entityNum < MAX_CLIENTS || DotProduct(trace.plane.normal,idealNormal) > 0.7)) )
{//there is a wall there
{//there is a wall there.. or hit a client
int parts;
//move me to side
if ( anim == BOTH_WALL_FLIP_LEFT )
@ -1055,26 +1014,7 @@ static qboolean PM_CheckJump( void )
pm->ps->velocity[0] = pm->ps->velocity[1] = 0;
VectorMA( pm->ps->velocity, -150, fwd, pm->ps->velocity );
}
//kick if jumping off an ent
/*
if ( doTrace && anim != BOTH_WALL_RUN_LEFT && anim != BOTH_WALL_RUN_RIGHT )
{
if ( pm->gent && trace.entityNum < ENTITYNUM_WORLD )
{
if ( traceEnt && traceEnt->client && traceEnt->health && traceEnt->takedamage )
{//push them away and do pain
vec3_t oppDir;
float strength = VectorNormalize2( pm->ps->velocity, oppDir );
VectorScale( oppDir, -1, oppDir );
//FIXME: need knockdown anim
G_Damage( traceEnt, pm->gent, pm->gent, oppDir, traceEnt->currentOrigin, 10, DAMAGE_NO_ARMOR|DAMAGE_NO_HIT_LOC|DAMAGE_NO_KNOCKBACK, MOD_MELEE );
NPC_SetAnim( traceEnt, SETANIM_BOTH, BOTH_KNOCKDOWN1, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
G_Throw( traceEnt, oppDir, strength );
G_Sound( traceEnt, G_SoundIndex( va("sound/weapons/melee/punch%d", Q_irand(1, 4)) ) );
}
}
}
*/
if ( doTrace && anim != BOTH_WALL_RUN_LEFT && anim != BOTH_WALL_RUN_RIGHT )
{
if (trace.entityNum < MAX_CLIENTS)
@ -1083,8 +1023,6 @@ static qboolean PM_CheckJump( void )
}
}
//FIXMEFIXME
//up
if ( vertPush )
{
@ -1108,10 +1046,9 @@ static qboolean PM_CheckJump( void )
{
pm->ps->weaponTime = pm->ps->torsoTimer;
}
pm->ps->fd.forceJumpZStart = pm->ps->origin[2];//so we don't take damage if we land at same height
pm->ps->pm_flags |= PMF_JUMP_HELD;//PMF_JUMPING|PMF_SLOW_MO_FALL;
PM_SetForceJumpZStart(pm->ps->origin[2]);//so we don't take damage if we land at same height
pm->ps->pm_flags |= PMF_JUMP_HELD;
pm->cmd.upmove = 0;
//WP_ForcePowerDrain( pm->gent, FP_LEVITATION, 0 );
pm->ps->fd.forceJumpSound = 1;
}
}
@ -1180,8 +1117,6 @@ static qboolean PM_CheckJump( void )
parts = SETANIM_BOTH;
}
PM_SetAnim( parts, anim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0 );
//FIXME: do damage to traceEnt, like above?
//pm->ps->pm_flags |= PMF_JUMPING|PMF_SLOW_MO_FALL;
pm->cmd.upmove = 0;
}
}
@ -1193,10 +1128,9 @@ static qboolean PM_CheckJump( void )
else if ( pm->cmd.forwardmove > 0 //pushing forward
&& pm->ps->fd.forcePowerLevel[FP_LEVITATION] > FORCE_LEVEL_1
&& pm->ps->velocity[2] > 200
&& /*(level.time - pm->ps->lastOnGround) <= 500*/ PM_GroundDistance() <= 80 //unfortunately we do not have a happy ground timer.
&& PM_GroundDistance() <= 80 //unfortunately we do not have a happy ground timer like SP (this would use up more bandwidth if we wanted prediction workign right), so we'll just use the actual ground distance.
&& !BG_InSpecialJump(pm->ps->legsAnim))
{//run up wall, flip backwards
//FIXME: have to be moving... make sure it's opposite the wall... or at least forward?
vec3_t fwd, traceto, mins, maxs, fwdAngles;
trace_t trace;
vec3_t idealNormal;
@ -1229,10 +1163,8 @@ static qboolean PM_CheckJump( void )
pm->ps->legsTimer -= 600; //I force this anim to play to the end to prevent landing on your head and suddenly flipping over.
//It is a bit too long at the end though, so I'll just shorten it.
pm->ps->fd.forceJumpZStart = pm->ps->origin[2];//so we don't take damage if we land at same height
//pm->ps->pm_flags |= PMF_JUMPING|PMF_SLOW_MO_FALL;
PM_SetForceJumpZStart(pm->ps->origin[2]);//so we don't take damage if we land at same height
pm->cmd.upmove = 0;
//G_SoundOnEnt( pm->gent, CHAN_BODY, "sound/weapons/force/jump.wav" );
pm->ps->fd.forceJumpSound = 1;
BG_ForcePowerDrain( pm->ps, FP_LEVITATION, 5 );
@ -1242,10 +1174,6 @@ static qboolean PM_CheckJump( void )
}
}
}
else
{
//FIXME: if in a butterfly, kick people away?
}
}
}
@ -1259,8 +1187,7 @@ static qboolean PM_CheckJump( void )
&& !BG_FlippingAnim( pm->ps->legsAnim )
&& !PM_SpinningAnim( pm->ps->legsAnim )
&& !BG_SaberInSpecialAttack( pm->ps->torsoAnim )
&& ( BG_SaberInAttack( pm->ps->saberMove ) )
/*&& PM_InAnimForSaberMove( pm->ps->torsoAnim, pm->ps->saberMove )*/ )
&& ( BG_SaberInAttack( pm->ps->saberMove ) ) )
{//not in an anim we shouldn't interrupt
//see if it's not too late to start a special jump-attack
float animLength = PM_AnimLength( 0, (animNumber_t)pm->ps->torsoAnim );
@ -1269,8 +1196,7 @@ static qboolean PM_CheckJump( void )
//check for special-case jump attacks
if ( pm->ps->fd.saberAnimLevel == FORCE_LEVEL_2 )
{//using medium attacks
if (/*pm->ps->velocity[2] > 100 &&*/
PM_GroundDistance() < 32 &&
if (PM_GroundDistance() < 32 &&
!BG_InSpecialJump(pm->ps->legsAnim))
{ //FLIP AND DOWNWARD ATTACK
trace_t tr;
@ -1314,17 +1240,9 @@ static qboolean PM_CheckJump( void )
}
if ( pm->cmd.upmove > 0 )
{//no special jumps
/*
gentity_t *groundEnt = &g_entities[pm->ps->groundEntityNum];
if ( groundEnt && groundEnt->NPC )
{//Can't jump off of someone's head
return qfalse;
}
*/
pm->ps->velocity[2] = JUMP_VELOCITY;
pm->ps->fd.forceJumpZStart = pm->ps->origin[2];//so we don't take damage if we land at same height
pm->ps->pm_flags |= PMF_JUMP_HELD;//PMF_JUMPING;
PM_SetForceJumpZStart(pm->ps->origin[2]);//so we don't take damage if we land at same height
pm->ps->pm_flags |= PMF_JUMP_HELD;
}
//Jumping
@ -1332,7 +1250,7 @@ static qboolean PM_CheckJump( void )
pml.walking = qfalse;
pm->ps->pm_flags |= PMF_JUMP_HELD;
pm->ps->groundEntityNum = ENTITYNUM_NONE;
pm->ps->fd.forceJumpZStart = pm->ps->origin[2];
PM_SetForceJumpZStart(pm->ps->origin[2]);
PM_AddEvent( EV_JUMP );
@ -1696,7 +1614,6 @@ static void PM_WalkMove( void ) {
wishvel[i] = pml.forward[i]*fmove + pml.right[i]*smove;
}
// when going up or down slopes the wish velocity should Not be zero
// wishvel[2] = 0;
VectorCopy (wishvel, wishdir);
wishspeed = VectorNormalize(wishdir);
@ -1740,11 +1657,9 @@ static void PM_WalkMove( void ) {
//Com_Printf("velocity = %1.1f %1.1f %1.1f\n", pm->ps->velocity[0], pm->ps->velocity[1], pm->ps->velocity[2]);
//Com_Printf("velocity1 = %1.1f\n", VectorLength(pm->ps->velocity));
if ( ( pml.groundTrace.surfaceFlags & SURF_SLICK ) || pm->ps->pm_flags & PMF_TIME_KNOCKBACK ) {
if ( ( pml.groundTrace.surfaceFlags & SURF_SLICK ) || pm->ps->pm_flags & PMF_TIME_KNOCKBACK )
{
pm->ps->velocity[2] -= pm->ps->gravity * pml.frametime;
} else {
// don't reset the z velocity for slopes
// pm->ps->velocity[2] = 0;
}
vel = VectorLength(pm->ps->velocity);
@ -1766,7 +1681,6 @@ static void PM_WalkMove( void ) {
PM_StepSlideMove( qfalse );
//Com_Printf("velocity2 = %1.1f\n", VectorLength(pm->ps->velocity));
}
@ -1870,11 +1784,14 @@ PM_FootstepForSurface
Returns an event number apropriate for the groundsurface
================
*/
static int PM_FootstepForSurface( void ) {
if ( pml.groundTrace.surfaceFlags & SURF_NOSTEPS ) {
static int PM_FootstepForSurface( void )
{
if ( pml.groundTrace.surfaceFlags & SURF_NOSTEPS )
{
return 0;
}
if ( pml.groundTrace.surfaceFlags & SURF_METALSTEPS ) {
if ( pml.groundTrace.surfaceFlags & SURF_METALSTEPS )
{
return EV_FOOTSTEP_METAL;
}
return EV_FOOTSTEP;
@ -1895,22 +1812,19 @@ static int PM_TryRoll( void )
if (pm->ps->weapon != WP_SABER || BG_HasYsalamiri(pm->gametype, pm->ps) ||
!BG_CanUseFPNow(pm->gametype, pm->ps, pm->cmd.serverTime, FP_LEVITATION))
{
{ //Not using saber, or can't use jump
return 0;
}
//VectorSet(mins, pm->mins[0],pm->mins[1],pm->mins[2]+STEPSIZE);
//VectorSet(maxs, pm->maxs[0],pm->maxs[1],pm->gent->client->crouchheight);
VectorSet(mins, pm->mins[0],pm->mins[1],pm->mins[2]+STEPSIZE);
VectorSet(maxs, pm->maxs[0],pm->maxs[1],CROUCH_MAXS_2);
VectorSet(fwdAngles, 0, pm->ps->viewangles[YAW], 0);
AngleVectors( fwdAngles, fwd, right, NULL );
//FIXME: trace ahead for clearance to roll
if ( pm->cmd.forwardmove )
{
{ //check forward/backward rolls
if ( pm->ps->pm_flags & PMF_BACKWARDS_RUN )
{
anim = BOTH_ROLL_B;
@ -1923,25 +1837,21 @@ static int PM_TryRoll( void )
}
}
else if ( pm->cmd.rightmove > 0 )
{
{ //right
anim = BOTH_ROLL_R;
VectorMA( pm->ps->origin, 64, right, traceto );
}
else if ( pm->cmd.rightmove < 0 )
{
{ //left
anim = BOTH_ROLL_L;
VectorMA( pm->ps->origin, -64, right, traceto );
}
else
{//???
}
if ( anim != -1 )
{
{ //We want to roll. Perform a trace to see if we can, and if so, send us into one.
pm->trace( &trace, pm->ps->origin, mins, maxs, traceto, pm->ps->clientNum, CONTENTS_SOLID );
if ( trace.fraction >= 1.0f )
{
//PM_AddEvent( EV_ROLL );
//Done later..
pm->ps->saberMove = LS_NONE;
return anim;
}
@ -2001,14 +1911,9 @@ static void PM_CrashLand( void ) {
}
}
/*
if (pm->ps->forceHandExtend == HANDEXTEND_NONE)
{
pm->ps->forceHandExtend = HANDEXTEND_WEAPONREADY;
}
*/
if (pm->ps->weapon != WP_SABER)
{ //saber handles its own anims
//This will push us back into our weaponready stance from the land anim.
if (pm->ps->weapon == WP_DISRUPTOR && pm->ps->zoomMode == 1)
{
PM_StartTorsoAnim( TORSO_WEAPONREADY4 );
@ -2025,13 +1930,12 @@ static void PM_CrashLand( void ) {
}
}
}
//just a stupid hack to push us back into our "idle" stance
if (!BG_InSpecialJump(pm->ps->legsAnim) ||
pm->ps->legsTimer < 1 ||
(pm->ps->legsAnim&~ANIM_TOGGLEBIT) == BOTH_WALL_RUN_LEFT ||
(pm->ps->legsAnim&~ANIM_TOGGLEBIT) == BOTH_WALL_RUN_RIGHT)
{
{ //Only set the timer if we're in an anim that can be interrupted (this would not be, say, a flip)
if (!BG_InRoll(pm->ps, pm->ps->legsAnim) && pm->ps->inAirAnim)
{
if (!BG_SaberInSpecial(pm->ps->saberMove) || pm->ps->weapon != WP_SABER)
@ -2062,7 +1966,8 @@ static void PM_CrashLand( void ) {
if ( pm->ps->pm_flags & PMF_DUCKED )
{
if( delta >= 2 && !PM_InOnGroundAnim( pm->ps->legsAnim ) && !PM_InKnockDown( pm->ps ) && !BG_InRoll(pm->ps, pm->ps->legsAnim) )
if( delta >= 2 && !PM_InOnGroundAnim( pm->ps->legsAnim ) && !PM_InKnockDown( pm->ps ) && !BG_InRoll(pm->ps, pm->ps->legsAnim) &&
pm->ps->forceHandExtend == HANDEXTEND_NONE )
{//roll!
int anim = PM_TryRoll();
@ -2078,7 +1983,6 @@ static void PM_CrashLand( void ) {
if ( anim )
{//absorb some impact
pm->ps->legsTimer = 0;
//delta /= 2;
delta /= 3; // /= 2 just cancels out the above delta *= 2 when landing while crouched, the roll itself should absorb a little damage
pm->ps->legsAnim = 0;
PM_SetAnim(SETANIM_BOTH,anim,SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 150);
@ -2087,8 +1991,6 @@ static void PM_CrashLand( void ) {
}
}
// create a local entity event to play the sound
// SURF_NODAMAGE is used for bounce pads where you don't ever
// want to take damage or play a crunch sound
if ( !(pml.groundTrace.surfaceFlags & SURF_NODAMAGE) ) {
@ -2135,7 +2037,7 @@ static void PM_CrashLand( void ) {
}
if (didRoll)
{
{ //Add the appropriate event..
PM_AddEventWithParm( EV_ROLL, delta_send );
}
else
@ -2163,22 +2065,6 @@ static void PM_CrashLand( void ) {
pm->ps->bobCycle = 0;
}
/*
=============
PM_CheckStuck
=============
*/
/*
void PM_CheckStuck(void) {
trace_t trace;
pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, pm->ps->origin, pm->ps->clientNum, pm->tracemask);
if (trace.allsolid) {
//int shit = qtrue;
}
}
*/
/*
=============
PM_CorrectAllSolid
@ -2234,23 +2120,18 @@ static void PM_GroundTraceMissed( void ) {
//rww - don't want to do this when handextend_choke, because you can be standing on the ground
//while still holding your throat.
if ( pm->ps->pm_type == PM_FLOAT ) {
if ( pm->ps->pm_type == PM_FLOAT )
{
//we're assuming this is because you're being choked
int parts = SETANIM_LEGS;
/*
if ( !pm->ps->weaponTime && pm->ps->forceHandExtend >= HANDEXTEND_CHOKE )
{//still on ground, only set anim on torso
parts = SETANIM_BOTH;
}
*/
//rww - also don't use SETANIM_FLAG_HOLD, it will cause the legs to float around a bit before going into
//a proper anim even when on the ground.
PM_SetAnim(parts, BOTH_CHOKE3, SETANIM_FLAG_OVERRIDE, 100);
//pm->ps->torsoTimer = 1;
//pm->ps->legsTimer = 1;
}
//If the anim is choke3, act like we just went into the air because we aren't in a float
else if ( pm->ps->groundEntityNum != ENTITYNUM_NONE || (pm->ps->legsAnim&~ANIM_TOGGLEBIT) == BOTH_CHOKE3 ) {
else if ( pm->ps->groundEntityNum != ENTITYNUM_NONE || (pm->ps->legsAnim&~ANIM_TOGGLEBIT) == BOTH_CHOKE3 )
{
// we just transitioned into freefall
if ( pm->debugLevel ) {
Com_Printf("%i:lift\n", c_pmove);
@ -2264,18 +2145,18 @@ static void PM_GroundTraceMissed( void ) {
pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask);
if ( trace.fraction == 1.0 || pm->ps->pm_type == PM_FLOAT ) {
if ( pm->ps->velocity[2] <= 0 && !(pm->ps->pm_flags&PMF_JUMP_HELD))
{//FIXME: if velocity[2] < 0 and didn't jump, use some falling anim
PM_SetAnim(SETANIM_LEGS,BOTH_INAIR1,SETANIM_FLAG_OVERRIDE, 100); // Only blend over 100ms
{
PM_SetAnim(SETANIM_LEGS,BOTH_INAIR1,SETANIM_FLAG_OVERRIDE, 100);
pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP;
}
else if ( pm->cmd.forwardmove >= 0 )
{
PM_SetAnim(SETANIM_LEGS,BOTH_JUMP1,SETANIM_FLAG_OVERRIDE, 100); // Only blend over 100ms
PM_SetAnim(SETANIM_LEGS,BOTH_JUMP1,SETANIM_FLAG_OVERRIDE, 100);
pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP;
}
else
{
PM_SetAnim(SETANIM_LEGS,BOTH_JUMPBACK1,SETANIM_FLAG_OVERRIDE, 100); // Only blend over 100ms
PM_SetAnim(SETANIM_LEGS,BOTH_JUMPBACK1,SETANIM_FLAG_OVERRIDE, 100);
pm->ps->pm_flags |= PMF_BACKWARDS_JUMP;
}
@ -2297,8 +2178,8 @@ static void PM_GroundTraceMissed( void ) {
}
if (PM_InRollComplete(pm->ps, pm->ps->legsAnim))
{ //HACK -_- (filthy client won't catch an animation restart because it only checks frame against incoming frame, so if you roll when you land after rolling
//off of something it won't replay the roll anim unless we switch it off in the air)
{ //Client won't catch an animation restart because it only checks frame against incoming frame, so if you roll when you land after rolling
//off of something it won't replay the roll anim unless we switch it off in the air. This fixes that.
PM_SetAnim(SETANIM_BOTH,BOTH_INAIR1,SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 150);
pm->ps->inAirAnim = qtrue;
}
@ -2372,8 +2253,6 @@ static void PM_GroundTrace( void ) {
if ( pm->debugLevel ) {
Com_Printf("%i:steep\n", c_pmove);
}
// FIXME: if they can't slide down the slope, let them
// walk (sharp crevices)
pm->ps->groundEntityNum = ENTITYNUM_NONE;
pml.groundPlane = qtrue;
pml.walking = qfalse;
@ -2409,16 +2288,13 @@ static void PM_GroundTrace( void ) {
pm->ps->groundEntityNum = trace.entityNum;
pm->ps->lastOnGround = pm->cmd.serverTime;
// don't reset the z velocity for slopes
// pm->ps->velocity[2] = 0;
PM_AddTouchEnt( trace.entityNum );
}
/*
=============
PM_SetWaterLevel FIXME: avoid this twice? certainly if not moving
PM_SetWaterLevel
=============
*/
static void PM_SetWaterLevel( void ) {
@ -2690,7 +2566,8 @@ static void PM_Footsteps( void ) {
footstep = qfalse;
if ( pm->ps->pm_flags & PMF_DUCKED ) {
if ( pm->ps->pm_flags & PMF_DUCKED )
{
int rolled = 0;
bobmove = 0.5; // ducked characters bob much faster
@ -2700,7 +2577,7 @@ static void PM_Footsteps( void ) {
rolled = PM_TryRoll();
}
if ( !rolled )
{
{ //if the roll failed or didn't attempt, do standard crouching anim stuff.
if ( pm->ps->pm_flags & PMF_BACKWARDS_RUN ) {
if ((pm->ps->legsAnim&~ANIM_TOGGLEBIT) != BOTH_CROUCH1WALKBACK)
{
@ -2723,7 +2600,7 @@ static void PM_Footsteps( void ) {
}
}
else
{
{ //otherwise send us into the roll
pm->ps->legsTimer = 0;
pm->ps->legsAnim = 0;
PM_SetAnim(SETANIM_BOTH,rolled,SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 150);
@ -2733,17 +2610,6 @@ static void PM_Footsteps( void ) {
pm->ps->pm_flags &= ~PMF_DUCKED;
pm->ps->pm_flags |= PMF_ROLLING;
}
// ducked characters never play footsteps
/*
} else if ( pm->ps->pm_flags & PMF_BACKWARDS_RUN ) {
if ( !( pm->cmd.buttons & BUTTON_WALKING ) ) {
bobmove = 0.4; // faster speeds bob faster
footstep = qtrue;
} else {
bobmove = 0.3;
}
PM_ContinueLegsAnim( LEGS_BACK );
*/
}
else if ((pm->ps->pm_flags & PMF_ROLLING) && !BG_InRoll(pm->ps, pm->ps->legsAnim) &&
!PM_InRollComplete(pm->ps, pm->ps->legsAnim))
@ -2830,14 +2696,6 @@ static void PM_Footsteps( void ) {
// if we just crossed a cycle boundary, play an apropriate footstep event
if ( ( ( old + 64 ) ^ ( pm->ps->bobCycle + 64 ) ) & 128 )
{
/*
if ( pm->waterlevel == 0 ) {
// on ground will only play sounds if running
if ( footstep && !pm->noFootsteps ) {
PM_AddEvent( PM_FootstepForSurface() );
}
} else
*/
pm->ps->footstepTime = pm->cmd.serverTime + 300;
if ( pm->waterlevel == 1 ) {
// splashing
@ -3217,6 +3075,11 @@ int PM_ItemUsable(playerState_t *ps, int forcedUse)
return 0;
}
if (ps->duelInProgress)
{ //not allowed to use holdables while in a private duel.
return 0;
}
if (!forcedUse)
{
forcedUse = bg_itemlist[ps->stats[STAT_HOLDABLE_ITEM]].giTag;
@ -3314,7 +3177,8 @@ PM_Weapon
Generates weapon events and modifes the weapon counter
==============
*/
static void PM_Weapon( void ) {
static void PM_Weapon( void )
{
int addTime;
int amount;
int killAfterItem = 0;
@ -3401,6 +3265,8 @@ static void PM_Weapon( void ) {
else if (pm->ps->forceHandExtend != HANDEXTEND_NONE)
{ //nothing else should be allowed to happen during this time, including weapon fire
int desiredAnim = 0;
qboolean seperateOnTorso = qfalse;
int desiredOnTorso = 0;
switch(pm->ps->forceHandExtend)
{
@ -3418,12 +3284,6 @@ static void PM_Weapon( void ) {
break;
case HANDEXTEND_CHOKE:
desiredAnim = BOTH_CHOKE3; //left-handed choke
/*
if ( pm->ps->weapon == WP_NONE || pm->ps->weapon == WP_MELEE )
{
desiredAnim = BOTH_CHOKE1; //two-handed choke
}
*/
break;
case HANDEXTEND_DODGE:
desiredAnim = pm->ps->forceDodgeAnim;
@ -3431,7 +3291,27 @@ static void PM_Weapon( void ) {
case HANDEXTEND_KNOCKDOWN:
if (pm->ps->forceDodgeAnim)
{
if (pm->ps->forceDodgeAnim == 2)
if (pm->ps->forceDodgeAnim > 4)
{ //this means that we want to play a sepereate anim on the torso
int originalDAnim = pm->ps->forceDodgeAnim-8; //-8 is the original legs anim
if (originalDAnim == 2)
{
desiredAnim = BOTH_FORCE_GETUP_B1;
}
else if (originalDAnim == 3)
{
desiredAnim = BOTH_FORCE_GETUP_B3;
}
else
{
desiredAnim = BOTH_GETUP1;
}
//now specify the torso anim
seperateOnTorso = qtrue;
desiredOnTorso = BOTH_FORCEPUSH;
}
else if (pm->ps->forceDodgeAnim == 2)
{
desiredAnim = BOTH_FORCE_GETUP_B1;
}
@ -3471,14 +3351,28 @@ static void PM_Weapon( void ) {
break;
}
PM_SetAnim(SETANIM_TORSO, desiredAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 100);
pm->ps->torsoTimer = 1;
if (!seperateOnTorso)
{ //of seperateOnTorso, handle it after setting the legs
PM_SetAnim(SETANIM_TORSO, desiredAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 100);
pm->ps->torsoTimer = 1;
}
if (pm->ps->forceHandExtend == HANDEXTEND_DODGE || pm->ps->forceHandExtend == HANDEXTEND_KNOCKDOWN ||
(pm->ps->forceHandExtend == HANDEXTEND_CHOKE && pm->ps->groundEntityNum == ENTITYNUM_NONE) )
{ //special case, play dodge anim on whole body, choke anim too if off ground
PM_SetAnim(SETANIM_LEGS, desiredAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 100);
pm->ps->legsTimer = 1;
if (seperateOnTorso)
{
PM_SetAnim(SETANIM_LEGS, desiredAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 100);
pm->ps->legsTimer = 1;
PM_SetAnim(SETANIM_TORSO, desiredOnTorso, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 100);
pm->ps->torsoTimer = 1;
}
else
{
PM_SetAnim(SETANIM_LEGS, desiredAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 100);
pm->ps->legsTimer = 1;
}
}
return;
@ -3876,10 +3770,6 @@ static void PM_Animate( void ) {
if ( pm->cmd.buttons & BUTTON_GESTURE ) {
if ( pm->ps->torsoTimer < 1 && pm->ps->forceHandExtend == HANDEXTEND_NONE &&
pm->ps->legsTimer < 1 && pm->ps->weaponTime < 1 && pm->ps->saberLockTime < pm->cmd.serverTime) {
/*
PM_StartTorsoAnim( BOTH_TALKGESTURE3 );
pm->ps->torsoTimer = TIMER_GESTURE;
*/
pm->ps->forceHandExtend = HANDEXTEND_TAUNT;
@ -4114,34 +4004,6 @@ void PM_AdjustAttackStates( pmove_t *pm )
}
}
/*
// set the firing flag for continuous beam weapons
if ( !(pm->ps->pm_flags & PMF_RESPAWNED) && pm->ps->pm_type != PM_INTERMISSION
&& ( pm->cmd.buttons & (BUTTON_ATTACK|BUTTON_ALT_ATTACK)) && pm->ps->ammo[ weaponData[pm->ps->weapon].ammoIndex ] )
{
// Check more in depth here.
if ((pm->cmd.buttons & BUTTON_ATTACK) &&
pm->ps->ammo[weaponData[pm->ps->weapon].ammoIndex] >= weaponData[pm->ps->weapon].energyPerShot)
{
pm->ps->eFlags |= EF_FIRING;
pm->ps->eFlags &= ~EF_ALT_FIRING;
}
else if ((pm->cmd.buttons & BUTTON_ALT_ATTACK) &&
pm->ps->ammo[weaponData[pm->ps->weapon].ammoIndex] >= weaponData[pm->ps->weapon].altEnergyPerShot)
{
pm->ps->eFlags |= (EF_FIRING|EF_ALT_FIRING); // Both are set in the event of an alt fire
}
else
{
pm->ps->eFlags &= ~(EF_FIRING|EF_ALT_FIRING);
}
}
else
{
pm->ps->eFlags &= ~(EF_FIRING|EF_ALT_FIRING);
}
*/
// set the firing flag for continuous beam weapons, saber will fire even if out of ammo
if ( !(pm->ps->pm_flags & PMF_RESPAWNED) &&
pm->ps->pm_type != PM_INTERMISSION &&
@ -4288,6 +4150,10 @@ void BG_AdjustClientSpeed(playerState_t *ps, usercmd_t *cmd, int svTime)
| BOTH_RUN1;
}
}
else if ( cmd->forwardmove < 0 && !(cmd->buttons&BUTTON_WALKING) && pm->ps->groundEntityNum != ENTITYNUM_NONE )
{//running backwards is slower than running forwards (like SP)
ps->speed *= 0.75;
}
if (ps->fd.forcePowersActive & (1 << FP_GRIP))
{
@ -4369,7 +4235,6 @@ void BG_AdjustClientSpeed(playerState_t *ps, usercmd_t *cmd, int svTime)
ps->speed *= 0.85f;
break;
case FORCE_LEVEL_3:
//ps->speed *= 0.70f;
ps->speed *= 0.55f;
break;
default:
@ -4479,7 +4344,6 @@ void PmoveSingle (pmove_t *pmove) {
if ((pm->ps->legsAnim&~ANIM_TOGGLEBIT) == (BOTH_A2_STABBACK1) ||
(pm->ps->legsAnim&~ANIM_TOGGLEBIT) == (BOTH_ATTACK_BACK) ||
(pm->ps->legsAnim&~ANIM_TOGGLEBIT) == (BOTH_CROUCHATTACKBACK1) ||
//(pm->ps->legsAnim&~ANIM_TOGGLEBIT) == (BOTH_LUNGE2_B__T_) ||
(pm->ps->legsAnim&~ANIM_TOGGLEBIT) == (BOTH_FORCELEAP2_T__B_) ||
(pm->ps->legsAnim&~ANIM_TOGGLEBIT) == (BOTH_JUMPFLIPSTABDOWN) ||
(pm->ps->legsAnim&~ANIM_TOGGLEBIT) == (BOTH_JUMPFLIPSLASHDOWN1))
@ -4489,6 +4353,14 @@ void PmoveSingle (pmove_t *pmove) {
pm->cmd.upmove = 0;
}
if ((pm->ps->legsAnim&~ANIM_TOGGLEBIT) == BOTH_KISSER1LOOP ||
(pm->ps->legsAnim&~ANIM_TOGGLEBIT) == BOTH_KISSEE1LOOP)
{
pm->cmd.forwardmove = 0;
pm->cmd.rightmove = 0;
pm->cmd.upmove = 0;
}
if (pm->ps->emplacedIndex)
{
if (pm->cmd.forwardmove < 0)
@ -4576,25 +4448,17 @@ void PmoveSingle (pmove_t *pmove) {
PM_AdjustAngleForWallRun(pm->ps, &pm->cmd, qtrue);
if (pm->ps->saberMove == LS_A_JUMP_T__B_ || pm->ps->saberMove == LS_A_LUNGE)
if (pm->ps->saberMove == LS_A_JUMP_T__B_ || pm->ps->saberMove == LS_A_LUNGE ||
pm->ps->saberMove == LS_A_BACK_CR || pm->ps->saberMove == LS_A_BACK ||
pm->ps->saberMove == LS_A_BACKSTAB)
{
/*
if (pm->ps->velocity[0] ||
pm->ps->velocity[1] ||
pm->ps->velocity[2])
{ //if we're doing a lunge and we have a velocity, force us to look in the direction we are
//flying with the lunge
vec3_t velAngles;
PM_SetPMViewAngle(pm->ps, pm->ps->viewangles, &pm->cmd);
}
vectoangles(pm->ps->velocity, velAngles);
PM_SetPMViewAngle(pm->ps, velAngles, &pm->cmd);
}
else
{ //otherwise, if there is no valid velocity, just don't let us readjust the angles.
PM_SetPMViewAngle(pm->ps, pm->ps->viewangles, &pm->cmd);
}
*/
//FIXME: Use the above method, and don't let the angles mess up when you hit something.
if ((pm->ps->legsAnim&~ANIM_TOGGLEBIT) == BOTH_KISSER1LOOP ||
(pm->ps->legsAnim&~ANIM_TOGGLEBIT) == BOTH_KISSEE1LOOP)
{
pm->ps->viewangles[PITCH] = 0;
PM_SetPMViewAngle(pm->ps, pm->ps->viewangles, &pm->cmd);
}
@ -4715,11 +4579,6 @@ void PmoveSingle (pmove_t *pmove) {
PM_Use();
if (pm->ps->pm_flags & PMF_UPDATE_ANIM)
{
// PM_UpdateGhoul2AnimFromState();
}
// footstep events / legs animations
PM_Footsteps();
@ -4790,8 +4649,5 @@ void Pmove (pmove_t *pmove) {
pmove->cmd.upmove = 20;
}
}
//PM_CheckStuck();
}

View file

@ -1032,9 +1032,6 @@ void BG_TouchJumpPad( playerState_t *ps, entityState_t *jumppad );
void BG_PlayerStateToEntityState( playerState_t *ps, entityState_t *s, qboolean snap );
void BG_PlayerStateToEntityStateExtraPolate( playerState_t *ps, entityState_t *s, int time, qboolean snap );
void BG_G2PlayerAngles( vec3_t startAngles, vec3_t legs[3], vec3_t legsAngles, int painTime, int painDirection, int currentTime,
qboolean *torso_yawing, float *torso_yawAngle, qboolean *torso_pitching, float *torso_pitchAngle, qboolean *legs_yawing, float *legs_yawAngle,
int frameTime, vec3_t velocity, int legsAnim, int torsoAnim, qboolean dead, float movementDir, void *ghoul2, qhandle_t *modelList, int weapon);
qboolean BG_PlayerTouchesItem( playerState_t *ps, entityState_t *item, int atTime );

View file

@ -30,6 +30,7 @@ void BG_ForcePowerDrain( playerState_t *ps, forcePowers_t forcePower, int overri
return;
}
*/
//No longer grant infinite force with boon.
if ( !drain )
{
@ -353,7 +354,6 @@ qboolean PM_SaberKataDone(int curmove, int newmove);
int PM_SaberAnimTransitionAnim( int curmove, int newmove )
{
//FIXME: take FP_SABER_OFFENSE into account here somehow?
int retmove = newmove;
if ( curmove == LS_READY )
{//just standing there
@ -401,10 +401,8 @@ int PM_SaberAnimTransitionAnim( int curmove, int newmove )
case LS_A_TR2BL:
case LS_A_T2B:
if ( newmove == curmove )
{//FIXME: need a spin or something or go to next level, but for now, just play the return
//going into another attack...
//allow endless chaining in level 1 attacks, several in level 2 and only one or a few in level 3
//FIXME: don't let strong attacks chain to an attack in the opposite direction ( > 45 degrees?)
{
//going into an attack
if ( PM_SaberKataDone( curmove, newmove ) )
{//done with this kata, must return to ready before attack again
retmove = LS_R_TL2BR + (newmove-LS_A_TL2BR);
@ -555,12 +553,11 @@ int PM_SaberMoveQuadrantForMovement( usercmd_t *ucmd )
{//backward= T2B slash //or B2T uppercut?
return Q_T;
}
else //if ( curmove == LS_READY )//???
else
{//Not moving at all
return Q_R;
}
}
//return Q_R;//????
}
//===================================================================
@ -702,7 +699,7 @@ qboolean PM_SaberKataDone(int curmove, int newmove)
}
}
else
{//FIXME: have chainAngle influence fast and medium chains as well?
{//Perhaps have chainAngle influence fast and medium chains as well? For now, just do level 3.
if (newmove == LS_A_TL2BR ||
newmove == LS_A_L2R ||
newmove == LS_A_BL2TR ||
@ -756,7 +753,6 @@ void PM_SaberLockBreak( playerState_t *genemy, qboolean victory )
}
else
{
//loseAnim = BOTH_KNOCKDOWN4;
punishLoser = qtrue;
}
break;
@ -770,7 +766,6 @@ void PM_SaberLockBreak( playerState_t *genemy, qboolean victory )
}
else
{
//loseAnim = BOTH_BF1BREAK;
punishLoser = qtrue;
}
break;
@ -782,9 +777,8 @@ void PM_SaberLockBreak( playerState_t *genemy, qboolean victory )
}
else
{
genemy->saberMove = /*genemy->saberBounceMove =*/ LS_H1_BL;
genemy->saberMove = LS_H1_BL;
genemy->saberBlocked = BLOCKED_PARRY_BROKEN;
//loseAnim = BOTH_H1_S1_BR;
punishLoser = qtrue;
}
break;
@ -796,9 +790,8 @@ void PM_SaberLockBreak( playerState_t *genemy, qboolean victory )
}
else
{
genemy->saberMove = /*genemy->saberBounceMove =*/ LS_H1_BR;
genemy->saberMove = LS_H1_BR;
genemy->saberBlocked = BLOCKED_PARRY_BROKEN;
//loseAnim = BOTH_H1_S1_BL;
punishLoser = qtrue;
}
break;
@ -806,7 +799,7 @@ void PM_SaberLockBreak( playerState_t *genemy, qboolean victory )
PM_SetAnim( SETANIM_BOTH, winAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, -1 );
if (punishLoser)
{
{ //someone lost the lock, so punish them by knocking them down
vec3_t oppDir;
int strength = 8;
@ -829,7 +822,7 @@ void PM_SaberLockBreak( playerState_t *genemy, qboolean victory )
pm->checkDuelLoss = genemy->clientNum+1;
}
else
{
{ //If no one lost, then shove each player away from the other
vec3_t oppDir;
int strength = 4;
@ -849,8 +842,7 @@ void PM_SaberLockBreak( playerState_t *genemy, qboolean victory )
genemy->forceHandExtend = HANDEXTEND_WEAPONREADY;
}
pm->ps->weaponTime = 0;//pm->ps->torsoTimer;
//The enemy unfortunately has no valid torso animation time at this point, so just use ours
pm->ps->weaponTime = 0;
genemy->weaponTime = 0;
pm->ps->saberLockTime = genemy->saberLockTime = 0;
@ -877,12 +869,7 @@ extern qboolean ValidAnimFileIndex ( int index );
void PM_SaberLocked( void )
{
int remaining = 0;
/*
if ( pm->ps->weaponTime )
{//can't attack yet
return;
}
*/
playerState_t *genemy = pm->bgClients[pm->ps->saberLockEnemy];
if ( !genemy )
{
@ -906,13 +893,15 @@ void PM_SaberLocked( void )
genemy->weaponTime = 0;
dist = DistanceSquared(pm->ps->origin,genemy->origin);
if ( dist < 64 || dist > 6400 )//( dist < 128 || dist > 2304 )
{//between 8 and 80 from each other//was 16 and 48
if ( dist < 64 || dist > 6400 )
{//between 8 and 80 from each other
PM_SaberLockBreak( genemy, qfalse );
return;
}
if ( (pm->cmd.buttons & BUTTON_ATTACK) || pm->ps->saberLockAdvance )
{//holding attack
animation_t *anim;
if (pm->ps->saberLockAdvance)
{//tapping
animation_t *anim;
@ -968,24 +957,21 @@ void PM_SaberLocked( void )
{
return;
}
if( 1/*ValidAnimFileIndex( genemy->client->clientInfo.animFileIndex )*/ )
{
animation_t *anim;
anim = &pm->animations[(genemy->torsoAnim&~ANIM_TOGGLEBIT)];
if ( (genemy->torsoAnim&~ANIM_TOGGLEBIT) == BOTH_CWCIRCLELOCK ||
(genemy->torsoAnim&~ANIM_TOGGLEBIT) == BOTH_BF1LOCK )
anim = &pm->animations[(genemy->torsoAnim&~ANIM_TOGGLEBIT)];
if ( (genemy->torsoAnim&~ANIM_TOGGLEBIT) == BOTH_CWCIRCLELOCK ||
(genemy->torsoAnim&~ANIM_TOGGLEBIT) == BOTH_BF1LOCK )
{
if ( !PM_irand_timesync( 0, 2 ) )
{
if ( !PM_irand_timesync( 0, 2 ) )
{
BG_AddPredictableEventToPlayerstate(EV_PAIN, floor((float)80/100*100.0f), genemy);
}
PM_SetAnimFrame( genemy, anim->firstFrame+remaining, qtrue, qtrue );
}
else
{
PM_SetAnimFrame( genemy, anim->firstFrame+anim->numFrames-remaining, qtrue, qtrue );
BG_AddPredictableEventToPlayerstate(EV_PAIN, floor((float)80/100*100.0f), genemy);
}
PM_SetAnimFrame( genemy, anim->firstFrame+remaining, qtrue, qtrue );
}
else
{
PM_SetAnimFrame( genemy, anim->firstFrame+anim->numFrames-remaining, qtrue, qtrue );
}
}
}
@ -1011,8 +997,6 @@ qboolean PM_SaberInBrokenParry( int move )
int PM_BrokenParryForParry( int move )
{
//FIXME: need actual anims for this
//FIXME: need to know which side of the saber was hit! For now, we presume the saber gets knocked away from the center
switch ( move )
{
case LS_PARRY_UP:
@ -1031,13 +1015,13 @@ int PM_BrokenParryForParry( int move )
return LS_H1_BR;
break;
case LS_READY:
return LS_H1_B_;//???
return LS_H1_B_;
break;
}
return LS_NONE;
}
#define BACK_STAB_DISTANCE 128//64
#define BACK_STAB_DISTANCE 128
qboolean PM_CanBackstab(void)
{
@ -1068,7 +1052,6 @@ qboolean PM_CanBackstab(void)
saberMoveName_t PM_SaberFlipOverAttackMove(trace_t *tr)
{
//FIXME: check above for room enough to jump!
vec3_t fwdAngles, jumpFwd;
float zDiff = 0;
playerState_t *psData;
@ -1076,13 +1059,11 @@ saberMoveName_t PM_SaberFlipOverAttackMove(trace_t *tr)
VectorCopy( pm->ps->viewangles, fwdAngles );
fwdAngles[PITCH] = fwdAngles[ROLL] = 0;
AngleVectors( fwdAngles, jumpFwd, NULL, NULL );
VectorScale( jumpFwd, /*100*/50, pm->ps->velocity );
VectorScale( jumpFwd, 50, pm->ps->velocity );
pm->ps->velocity[2] = 400;
psData = pm->bgClients[tr->entityNum];
pm->ps->velocity[2] *= 1;//(pm->gent->enemy->maxs[2]-pm->gent->enemy->mins[2])/64.0f;
//go higher for enemies higher than you, lower for those lower than you
if (psData)
{
@ -1108,7 +1089,7 @@ saberMoveName_t PM_SaberFlipOverAttackMove(trace_t *tr)
pm->ps->velocity[2] = 400;
}
pm->ps->fd.forceJumpZStart = pm->ps->origin[2];//so we don't take damage if we land at same height
PM_SetForceJumpZStart(pm->ps->origin[2]);//so we don't take damage if we land at same height
PM_AddEvent( EV_JUMP );
pm->ps->fd.forceJumpSound = 1;
@ -1161,7 +1142,6 @@ saberMoveName_t PM_SaberLungeAttackMove( void )
//do the lunge
AngleVectors( fwdAngles, jumpFwd, NULL, NULL );
VectorScale( jumpFwd, 150, pm->ps->velocity );
//pm->ps->velocity[2] = 50;
PM_AddEvent( EV_JUMP );
return LS_A_LUNGE;
@ -1174,9 +1154,9 @@ saberMoveName_t PM_SaberJumpAttackMove( void )
VectorCopy( pm->ps->viewangles, fwdAngles );
fwdAngles[PITCH] = fwdAngles[ROLL] = 0;
AngleVectors( fwdAngles, jumpFwd, NULL, NULL );
VectorScale( jumpFwd, /*200*/300, pm->ps->velocity );
pm->ps->velocity[2] = 280;//180;
pm->ps->fd.forceJumpZStart = pm->ps->origin[2];//so we don't take damage if we land at same height
VectorScale( jumpFwd, 300, pm->ps->velocity );
pm->ps->velocity[2] = 280;
PM_SetForceJumpZStart(pm->ps->origin[2]);//so we don't take damage if we land at same height
PM_AddEvent( EV_JUMP );
pm->ps->fd.forceJumpSound = 1;
@ -1240,10 +1220,10 @@ saberMoveName_t PM_SaberAttackForMovement(saberMoveName_t curmove)
if ( pm->cmd.forwardmove > 0 )
{//forward= T2B slash
if (pm->ps->fd.saberAnimLevel == FORCE_LEVEL_2 &&
/*pm->ps->groundEntityNum != ENTITYNUM_NONE &&*/
pm->ps->velocity[2] > 100 &&
PM_GroundDistance() < 32 &&
!BG_InSpecialJump(pm->ps->legsAnim))
!BG_InSpecialJump(pm->ps->legsAnim) &&
!BG_SaberInSpecialAttack(pm->ps->torsoAnim))
{ //FLIP AND DOWNWARD ATTACK
trace_t tr;
@ -1253,8 +1233,10 @@ saberMoveName_t PM_SaberAttackForMovement(saberMoveName_t curmove)
}
}
else if (pm->ps->fd.saberAnimLevel == FORCE_LEVEL_1 &&
pm->ps->groundEntityNum != ENTITYNUM_NONE &&
(pm->ps->pm_flags & PMF_DUCKED) &&
pm->ps->weaponTime <= 0)
pm->ps->weaponTime <= 0 &&
!BG_SaberInSpecialAttack(pm->ps->torsoAnim))
{ //LUNGE (weak)
newmove = PM_SaberLungeAttackMove();
}
@ -1265,7 +1247,7 @@ saberMoveName_t PM_SaberAttackForMovement(saberMoveName_t curmove)
}
else if ( pm->cmd.forwardmove < 0 )
{//backward= T2B slash//B2T uppercut?
if (PM_CanBackstab())
if (PM_CanBackstab() && !BG_SaberInSpecialAttack(pm->ps->torsoAnim))
{ //BACKSTAB (attack varies by level)
if (pm->ps->fd.saberAnimLevel >= FORCE_LEVEL_2)
{//medium and higher attacks
@ -1309,7 +1291,6 @@ saberMoveName_t PM_SaberAttackForMovement(saberMoveName_t curmove)
//prediction values. Under laggy conditions this will cause the appearance of rapid swing
//sequence changes.
//newmove = PM_irand_timesync(LS_A_TL2BR, LS_A_T2B);
newmove = LS_A_T2B; //decided we don't like random attacks when idle, use an overhead instead.
}
}
@ -1532,7 +1513,7 @@ void PM_WeaponLightsaber(void)
case BLOCKED_ATK_BOUNCE:
// If there is absolutely no blocked move in the chart, don't even mess with the animation.
// OR if we are already in a block or parry.
if (pm->ps->saberMove >= LS_T1_BR__R/*LS_BOUNCE_TOP*/ )//|| saberMoveData[pm->ps->saberMove].bounceMove == LS_NONE )
if (pm->ps->saberMove >= LS_T1_BR__R)
{//an actual bounce? Other bounces before this are actually transitions?
pm->ps->saberBlocked = BLOCKED_NONE;
}
@ -1690,8 +1671,6 @@ weapChecks:
// Check for WEAPON ATTACK
// *********************************************************
// NOTENOTE This is simply a client-side struct. Anything that is needed client and server should be moved to bg_weapon.
if(!delayed_fire)
{
// Start with the current move, and cross index it with the current control states.
@ -1704,7 +1683,7 @@ weapChecks:
curmove = LS_READY;
}
// check for fire
if ( !(pm->cmd.buttons & (BUTTON_ATTACK/*|BUTTON_ALT_ATTACK*/)) )
if ( !(pm->cmd.buttons & (BUTTON_ATTACK)) )
{
if (pm->ps->weaponTime != 0)
{//Still firing
@ -1798,12 +1777,6 @@ weapChecks:
}
else//if ( pm->cmd.buttons&BUTTON_ATTACK && !(pm->ps->pm_flags&PMF_ATTACK_HELD) )//only do this if just pressed attack button?
{//get attack move from movement command
/*
if ( PM_SaberKataDone() )
{//we came from a bounce and cannot chain to another attack because our kata is done
newmove = saberMoveData[curmove].chain_idle;
}
else */
saberMoveName_t checkMove = PM_SaberAttackForMovement(curmove);
if (checkMove != -1)
{
@ -1820,39 +1793,17 @@ weapChecks:
{//we came from a bounce and cannot chain to another attack because our kata is done
newmove = saberMoveData[curmove].chain_idle;
}
/*else
{
saberMoveName_t checkMove = PM_SaberAttackForMovement(curmove);
if (checkMove != -1)
{
newmove = checkMove;
}
}
*/
}
/*
if ( newmove == LS_NONE )
{//FIXME: should we allow this? Are there some anims that you should never be able to chain into an attack?
//only curmove that might get in here is LS_NONE, LS_DRAW, LS_PUTAWAY and the LS_R_ returns... all of which are in Q_R
newmove = PM_AttackMoveForQuad( saberMoveData[curmove].endQuad );
}
*/
if ( newmove != LS_NONE )
{
//Now get the proper transition move
newmove = PM_SaberAnimTransitionAnim( curmove, newmove );
// NOTENOTE Had to remove this concept since there is no gent in pmove.
/*
if ( PM_HasAnimation( pm->gent, saberMoveData[newmove].animToUse ) )
*/
assert( bgGlobalAnimations[saberMoveData[newmove].animToUse].firstFrame != 0 ||
bgGlobalAnimations[saberMoveData[newmove].animToUse].numFrames != 0);
if (1)
{
anim = saberMoveData[newmove].animToUse;
}
anim = saberMoveData[newmove].animToUse;
}
}
@ -1890,7 +1841,7 @@ weapChecks:
}
if (anim == BOTH_RUN2 && !pm->cmd.forwardmove && !pm->cmd.rightmove)
{ //semi-hacky
{ //semi-hacky (if not moving on x-y and still playing the running anim, force the player out of it)
anim = PM_GetSaberStance();
}
newmove = LS_READY;
@ -2021,8 +1972,6 @@ void PM_SetSaberMove(short newMove)
!PM_JumpingAnim( pm->ps->legsAnim ) &&
!BG_InSpecialJump( pm->ps->legsAnim ) &&
anim != PM_GetSaberStance() &&
//!PM_CrouchAnim( pm->ps->legsAnim ) &&
//pm->cmd.upmove >= 0 &&
pm->ps->groundEntityNum != ENTITYNUM_NONE &&
!(pm->ps->pm_flags & PMF_DUCKED))
{
@ -2047,7 +1996,7 @@ void PM_SetSaberMove(short newMove)
pm->ps->saberMove = newMove;
pm->ps->saberBlocking = saberMoveData[newMove].blocking;
pm->ps->torsoAnim = anim;//saberMoveData[newMove].animToUse;
pm->ps->torsoAnim = anim;
if (pm->ps->weaponTime <= 0)
{

View file

@ -153,7 +153,7 @@ weaponData_t weaponData[WP_NUM_WEAPONS] =
1, // int energyPerShot; // Amount of energy used per shot
100, // int fireTime; // Amount of time between firings
8192, // int range; // Range of weapon
25, // int altEnergyPerShot; // Amount of energy used for alt-fire
15, // int altEnergyPerShot; // Amount of energy used for alt-fire
800, // int altFireTime; // Amount of time between alt-firings
8192, // int altRange; // Range of alt-fire
0, // int chargeSubTime; // ms interval for subtracting ammo during charge
@ -187,7 +187,7 @@ weaponData_t weaponData[WP_NUM_WEAPONS] =
10, // int energyPerShot; // Amount of energy used per shot
700, // int fireTime; // Amount of time between firings
8192, // int range; // Range of weapon
25, // int altEnergyPerShot; // Amount of energy used for alt-fire
15, // int altEnergyPerShot; // Amount of energy used for alt-fire
800, // int altFireTime; // Amount of time between alt-firings
8192, // int altRange; // Range of alt-fire
0, // int chargeSubTime; // ms interval for subtracting ammo during charge

View file

@ -1295,7 +1295,7 @@ void ClientThink_real( gentity_t *ent ) {
pm.tracemask = MASK_PLAYERSOLID & ~CONTENTS_BODY;
}
else if ( ent->r.svFlags & SVF_BOT ) {
pm.tracemask = MASK_PLAYERSOLID | CONTENTS_BOTCLIP;
pm.tracemask = MASK_PLAYERSOLID | CONTENTS_MONSTERCLIP;
}
else {
pm.tracemask = MASK_PLAYERSOLID;
@ -1643,7 +1643,7 @@ void ClientThink_real( gentity_t *ent ) {
// check for respawning
if ( client->ps.stats[STAT_HEALTH] <= 0 ) {
// wait for the attack button to be pressed
if ( level.time > client->respawnTime ) {
if ( level.time > client->respawnTime && !gDoSlowMoDuel ) {
// forcerespawn is to prevent users from waiting out powerups
if ( g_forcerespawn.integer > 0 &&
( level.time - client->respawnTime ) > g_forcerespawn.integer * 1000 ) {
@ -1656,6 +1656,10 @@ void ClientThink_real( gentity_t *ent ) {
respawn( ent );
}
}
else if (gDoSlowMoDuel)
{
client->respawnTime = level.time + 1000;
}
return;
}

View file

@ -1277,7 +1277,10 @@ void ClientUserinfoChanged( int clientNum ) {
trap_SetConfigstring( CS_PLAYERS+clientNum, s );
//G_LogPrintf( "ClientUserinfoChanged: %i %s\n", clientNum, s );
if (g_logClientInfo.integer)
{
G_LogPrintf( "ClientUserinfoChanged: %i %s\n", clientNum, s );
}
}
@ -1742,6 +1745,46 @@ void ClientSpawn(gentity_t *ent) {
&& !AllForceDisabled( g_forcePowerDisable.integer )
&& g_trueJedi.integer )
{
if ( g_gametype.integer >= GT_TEAM && (client->sess.sessionTeam == TEAM_BLUE || client->sess.sessionTeam == TEAM_RED) )
{//In Team games, force one side to be merc and other to be jedi
if ( level.numPlayingClients > 0 )
{//already someone in the game
int i, forceTeam = TEAM_SPECTATOR;
for ( i = 0 ; i < level.maxclients ; i++ )
{
if ( level.clients[i].pers.connected == CON_DISCONNECTED ) {
continue;
}
if ( level.clients[i].sess.sessionTeam == TEAM_BLUE || level.clients[i].sess.sessionTeam == TEAM_RED )
{//in-game
if ( WP_HasForcePowers( &level.clients[i].ps ) )
{//this side is using force
forceTeam = level.clients[i].sess.sessionTeam;
}
else
{//other team is using force
if ( level.clients[i].sess.sessionTeam == TEAM_BLUE )
{
forceTeam = TEAM_RED;
}
else
{
forceTeam = TEAM_BLUE;
}
}
break;
}
}
if ( WP_HasForcePowers( &client->ps ) && client->sess.sessionTeam != forceTeam )
{//using force but not on right team, switch him over
const char *teamName = TeamName( forceTeam );
//client->sess.sessionTeam = forceTeam;
SetTeam( ent, (char *)teamName );
return;
}
}
}
if ( WP_HasForcePowers( &client->ps ) )
{
client->ps.trueNonJedi = qfalse;
@ -1758,13 +1801,23 @@ void ClientSpawn(gentity_t *ent) {
{
client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_BRYAR_PISTOL );
}
if (!wDisable || !(wDisable & (1 << WP_BLASTER)))
{
client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_BLASTER );
}
if (!wDisable || !(wDisable & (1 << WP_BOWCASTER)))
{
client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_BOWCASTER );
}
client->ps.stats[STAT_WEAPONS] &= ~(1 << WP_SABER);
client->ps.stats[STAT_WEAPONS] |= (1 << WP_STUN_BATON);
client->ps.ammo[AMMO_POWERCELL] = ammoData[AMMO_POWERCELL].max;
client->ps.weapon = WP_BRYAR_PISTOL;
}
}
else
{
{//jediVmerc is incompatible with this gametype, turn it off!
trap_Cvar_Set( "g_jediVmerc", "0" );
if (g_gametype.integer == GT_HOLOCRON)
{
//always get free saber level 1 in holocron

View file

@ -503,8 +503,11 @@ void Cmd_Kill_f( gentity_t *ent ) {
if (g_gametype.integer == GT_TOURNAMENT && level.numPlayingClients > 1 && !level.warmupTime)
{
trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStripEdString("SVINGAME", "ATTEMPTDUELKILL")) );
return;
if (!g_allowDuelSuicide.integer)
{
trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStripEdString("SVINGAME", "ATTEMPTDUELKILL")) );
return;
}
}
ent->flags &= ~FL_GODMODE;
@ -646,7 +649,7 @@ void SetTeam( gentity_t *ent, char *s ) {
//}
}
if ( g_teamForceBalance.integer ) {
if ( g_teamForceBalance.integer && !g_trueJedi.integer ) {
int counts[TEAM_NUM_TEAMS];
counts[TEAM_BLUE] = TeamCount( ent->client->ps.clientNum, TEAM_BLUE );
@ -1407,6 +1410,109 @@ static const char *gameNames[] = {
"Capture the Ysalamiri"
};
/*
==================
G_ClientNumberFromName
Finds the client number of the client with the given name
==================
*/
int G_ClientNumberFromName ( const char* name )
{
char s2[MAX_STRING_CHARS];
char n2[MAX_STRING_CHARS];
int i;
gclient_t* cl;
// check for a name match
SanitizeString( (char*)name, s2 );
for ( i=0, cl=level.clients ; i < level.numConnectedClients ; i++, cl++ )
{
SanitizeString( cl->pers.netname, n2 );
if ( !strcmp( n2, s2 ) )
{
return i;
}
}
return -1;
}
/*
==================
SanitizeString2
Rich's revised version of SanitizeString
==================
*/
void SanitizeString2( char *in, char *out )
{
int i = 0;
int r = 0;
while (in[i])
{
if (i >= MAX_NAME_LENGTH-1)
{ //the ui truncates the name here..
break;
}
if (in[i] == '^')
{
if (in[i+1] >= 48 && //'0'
in[i+1] <= 57) //'9'
{ //only skip it if there's a number after it for the color
i += 2;
continue;
}
else
{ //just skip the ^
i++;
continue;
}
}
if (in[i] < 32)
{
i++;
continue;
}
out[r] = in[i];
r++;
i++;
}
out[r] = 0;
}
/*
==================
G_ClientNumberFromStrippedName
Same as above, but strips special characters out of the names before comparing.
==================
*/
int G_ClientNumberFromStrippedName ( const char* name )
{
char s2[MAX_STRING_CHARS];
char n2[MAX_STRING_CHARS];
int i;
gclient_t* cl;
// check for a name match
SanitizeString2( (char*)name, s2 );
for ( i=0, cl=level.clients ; i < level.numConnectedClients ; i++, cl++ )
{
SanitizeString2( cl->pers.netname, n2 );
if ( !strcmp( n2, s2 ) )
{
return i;
}
}
return -1;
}
/*
==================
Cmd_CallVote_f
@ -1466,7 +1572,8 @@ void Cmd_CallVote_f( gentity_t *ent ) {
}
// special case for g_gametype, check for bad values
if ( !Q_stricmp( arg1, "g_gametype" ) ) {
if ( !Q_stricmp( arg1, "g_gametype" ) )
{
i = atoi( arg2 );
if( i == GT_SINGLE_PLAYER || i < GT_FFA || i >= GT_MAX_GAME_TYPE) {
trap_SendServerCommand( ent-g_entities, "print \"Invalid gametype.\n\"" );
@ -1478,7 +1585,9 @@ void Cmd_CallVote_f( gentity_t *ent ) {
Com_sprintf( level.voteString, sizeof( level.voteString ), "%s %d", arg1, i );
Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "%s %s", arg1, gameNames[i] );
} else if ( !Q_stricmp( arg1, "map" ) ) {
}
else if ( !Q_stricmp( arg1, "map" ) )
{
// special case for map changes, we want to reset the nextmap setting
// this allows a player to change maps, but not upset the map rotation
char s[MAX_STRING_CHARS];
@ -1497,7 +1606,46 @@ void Cmd_CallVote_f( gentity_t *ent ) {
Com_sprintf( level.voteString, sizeof( level.voteString ), "%s %s", arg1, arg2 );
}
Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "%s", level.voteString );
} else if ( !Q_stricmp( arg1, "nextmap" ) ) {
}
else if ( !Q_stricmp ( arg1, "clientkick" ) )
{
int n = atoi ( arg2 );
if ( n < 0 || n >= MAX_CLIENTS )
{
trap_SendServerCommand( ent-g_entities, va("print \"invalid client number %d.\n\"", n ) );
return;
}
if ( g_entities[n].client->pers.connected == CON_DISCONNECTED )
{
trap_SendServerCommand( ent-g_entities, va("print \"there is no client with the client number %d.\n\"", n ) );
return;
}
Com_sprintf ( level.voteString, sizeof(level.voteString ), "%s %s", arg1, arg2 );
Com_sprintf ( level.voteDisplayString, sizeof(level.voteDisplayString), "kick %s", g_entities[n].client->pers.netname );
}
else if ( !Q_stricmp ( arg1, "kick" ) )
{
int clientid = G_ClientNumberFromName ( arg2 );
if ( clientid == -1 )
{
clientid = G_ClientNumberFromStrippedName(arg2);
if (clientid == -1)
{
trap_SendServerCommand( ent-g_entities, va("print \"there is no client named '%s' currently on the server.\n\"", arg2 ) );
return;
}
}
Com_sprintf ( level.voteString, sizeof(level.voteString ), "clientkick %d", clientid );
Com_sprintf ( level.voteDisplayString, sizeof(level.voteDisplayString), "kick %s", g_entities[clientid].client->pers.netname );
}
else if ( !Q_stricmp( arg1, "nextmap" ) )
{
char s[MAX_STRING_CHARS];
trap_Cvar_VariableStringBuffer( "nextmap", s, sizeof(s) );
@ -1507,7 +1655,9 @@ void Cmd_CallVote_f( gentity_t *ent ) {
}
Com_sprintf( level.voteString, sizeof( level.voteString ), "vstr nextmap");
Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "%s", level.voteString );
} else {
}
else
{
Com_sprintf( level.voteString, sizeof( level.voteString ), "%s \"%s\"", arg1, arg2 );
Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "%s", level.voteString );
}
@ -2174,9 +2324,10 @@ void Cmd_EngageDuel_f(gentity_t *ent)
}
}
void PM_SetAnim(int setAnimParts,int anim,int setAnimFlags, int blendTime);
#ifdef _DEBUG
extern stringID_table_t animTable[MAX_ANIMATIONS+1];
void PM_SetAnim(int setAnimParts,int anim,int setAnimFlags, int blendTime);
void Cmd_DebugSetSaberMove_f(gentity_t *self)
{
@ -2206,7 +2357,7 @@ void Cmd_DebugSetSaberMove_f(gentity_t *self)
Com_Printf("Anim for move: %s\n", animTable[saberMoveData[self->client->ps.saberMove].animToUse].name);
}
void Cmd_DebugSetBodyAnim_f(gentity_t *self)
void Cmd_DebugSetBodyAnim_f(gentity_t *self, int flags)
{
int argNum = trap_Argc();
char arg[MAX_STRING_CHARS];
@ -2249,12 +2400,28 @@ void Cmd_DebugSetBodyAnim_f(gentity_t *self)
pmv.gametype = g_gametype.integer;
pm = &pmv;
PM_SetAnim(SETANIM_BOTH, i, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0);
PM_SetAnim(SETANIM_BOTH, i, flags, 0);
Com_Printf("Set body anim to %s\n", arg);
}
#endif
void StandardSetBodyAnim(gentity_t *self, int anim, int flags)
{
pmove_t pmv;
memset (&pmv, 0, sizeof(pmv));
pmv.ps = &self->client->ps;
pmv.animations = bgGlobalAnimations;
pmv.cmd = self->client->pers.cmd;
pmv.trace = trap_Trace;
pmv.pointcontents = trap_PointContents;
pmv.gametype = g_gametype.integer;
pm = &pmv;
PM_SetAnim(SETANIM_BOTH, anim, flags, 0);
}
void DismembermentTest(gentity_t *self);
#ifdef _DEBUG
@ -2478,6 +2645,7 @@ void ClientCommand( int clientNum ) {
*/
//I broke the ATST when I restructured it to use a single global anim set for all client animation.
//You can fix it, but you'll have to implement unique animations (per character) again.
#ifdef _DEBUG //sigh..
else if (Q_stricmp(cmd, "headexplodey") == 0 && CheatsOk( ent ))
{
Cmd_Kill_f (ent);
@ -2493,6 +2661,67 @@ void ClientCommand( int clientNum ) {
{
G_CreateExampleAnimEnt(ent);
}
else if (Q_stricmp(cmd, "loveandpeace") == 0 && CheatsOk( ent ))
{
trace_t tr;
vec3_t fPos;
AngleVectors(ent->client->ps.viewangles, fPos, 0, 0);
fPos[0] = ent->client->ps.origin[0] + fPos[0]*40;
fPos[1] = ent->client->ps.origin[1] + fPos[1]*40;
fPos[2] = ent->client->ps.origin[2] + fPos[2]*40;
trap_Trace(&tr, ent->client->ps.origin, 0, 0, fPos, ent->s.number, ent->clipmask);
if (tr.entityNum < MAX_CLIENTS && tr.entityNum != ent->s.number)
{
gentity_t *other = &g_entities[tr.entityNum];
if (other && other->inuse && other->client)
{
vec3_t entDir;
vec3_t otherDir;
vec3_t entAngles;
vec3_t otherAngles;
if (ent->client->ps.weapon == WP_SABER && !ent->client->ps.saberHolstered)
{
Cmd_ToggleSaber_f(ent);
}
if (other->client->ps.weapon == WP_SABER && !other->client->ps.saberHolstered)
{
Cmd_ToggleSaber_f(other);
}
if ((ent->client->ps.weapon != WP_SABER || ent->client->ps.saberHolstered) &&
(other->client->ps.weapon != WP_SABER || other->client->ps.saberHolstered))
{
VectorSubtract( other->client->ps.origin, ent->client->ps.origin, otherDir );
VectorCopy( ent->client->ps.viewangles, entAngles );
entAngles[YAW] = vectoyaw( otherDir );
SetClientViewAngle( ent, entAngles );
StandardSetBodyAnim(ent, BOTH_KISSER1LOOP, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD|SETANIM_FLAG_HOLDLESS);
ent->client->ps.saberMove = LS_NONE;
ent->client->ps.saberBlocked = 0;
ent->client->ps.saberBlocking = 0;
VectorSubtract( ent->client->ps.origin, other->client->ps.origin, entDir );
VectorCopy( other->client->ps.viewangles, otherAngles );
otherAngles[YAW] = vectoyaw( entDir );
SetClientViewAngle( other, otherAngles );
StandardSetBodyAnim(other, BOTH_KISSEE1LOOP, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD|SETANIM_FLAG_HOLDLESS);
other->client->ps.saberMove = LS_NONE;
other->client->ps.saberBlocked = 0;
other->client->ps.saberBlocking = 0;
}
}
}
}
#endif
else if (Q_stricmp(cmd, "thedestroyer") == 0 && CheatsOk( ent ) && ent && ent->client && ent->client->ps.saberHolstered && ent->client->ps.weapon == WP_SABER)
{
Cmd_ToggleSaber_f(ent);
@ -2521,7 +2750,7 @@ void ClientCommand( int clientNum ) {
}
else if (Q_stricmp(cmd, "debugSetBodyAnim") == 0)
{
Cmd_DebugSetBodyAnim_f(ent);
Cmd_DebugSetBodyAnim_f(ent, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD);
}
else if (Q_stricmp(cmd, "debugDismemberment") == 0)
{
@ -2544,6 +2773,21 @@ void ClientCommand( int clientNum ) {
DismembermentByNum(ent, iArg);
}
}
else if (Q_stricmp(cmd, "debugKnockMeDown") == 0)
{
ent->client->ps.forceHandExtend = HANDEXTEND_KNOCKDOWN;
ent->client->ps.forceDodgeAnim = 0;
if (trap_Argc() > 1)
{
ent->client->ps.forceHandExtendTime = level.time + 1100;
ent->client->ps.quickerGetup = qfalse;
}
else
{
ent->client->ps.forceHandExtendTime = level.time + 700;
ent->client->ps.quickerGetup = qtrue;
}
}
#endif
else

View file

@ -890,6 +890,527 @@ void CheckAlmostCapture( gentity_t *self, gentity_t *attacker ) {
#endif
}
qboolean G_InKnockDown( playerState_t *ps )
{
switch ( (ps->legsAnim&~ANIM_TOGGLEBIT) )
{
case BOTH_KNOCKDOWN1:
case BOTH_KNOCKDOWN2:
case BOTH_KNOCKDOWN3:
case BOTH_KNOCKDOWN4:
case BOTH_KNOCKDOWN5:
return qtrue;
break;
case BOTH_GETUP1:
case BOTH_GETUP2:
case BOTH_GETUP3:
case BOTH_GETUP4:
case BOTH_GETUP5:
case BOTH_FORCE_GETUP_F1:
case BOTH_FORCE_GETUP_F2:
case BOTH_FORCE_GETUP_B1:
case BOTH_FORCE_GETUP_B2:
case BOTH_FORCE_GETUP_B3:
case BOTH_FORCE_GETUP_B4:
case BOTH_FORCE_GETUP_B5:
return qtrue;
break;
}
return qfalse;
}
static int G_CheckSpecialDeathAnim( gentity_t *self, vec3_t point, int damage, int mod, int hitLoc )
{
int deathAnim = -1;
if ( BG_InRoll( &self->client->ps, self->client->ps.legsAnim ) )
{
deathAnim = BOTH_DEATH_ROLL; //# Death anim from a roll
}
else if ( BG_FlippingAnim( self->client->ps.legsAnim ) )
{
deathAnim = BOTH_DEATH_FLIP; //# Death anim from a flip
}
else if ( G_InKnockDown( &self->client->ps ) )
{//since these happen a lot, let's handle them case by case
int animLength = bgGlobalAnimations[self->client->ps.legsAnim&~ANIM_TOGGLEBIT].numFrames * fabs(bgGlobalAnimations[self->client->ps.legsAnim&~ANIM_TOGGLEBIT].frameLerp);
switch ( self->client->ps.legsAnim&~ANIM_TOGGLEBIT )
{
case BOTH_KNOCKDOWN1:
if ( animLength - self->client->ps.legsTimer > 100 )
{//on our way down
if ( self->client->ps.legsTimer > 600 )
{//still partially up
deathAnim = BOTH_DEATH_FALLING_UP;
}
else
{//down
deathAnim = BOTH_DEATH_LYING_UP;
}
}
break;
case BOTH_KNOCKDOWN2:
if ( animLength - self->client->ps.legsTimer > 700 )
{//on our way down
if ( self->client->ps.legsTimer > 600 )
{//still partially up
deathAnim = BOTH_DEATH_FALLING_UP;
}
else
{//down
deathAnim = BOTH_DEATH_LYING_UP;
}
}
break;
case BOTH_KNOCKDOWN3:
if ( animLength - self->client->ps.legsTimer > 100 )
{//on our way down
if ( self->client->ps.legsTimer > 1300 )
{//still partially up
deathAnim = BOTH_DEATH_FALLING_DN;
}
else
{//down
deathAnim = BOTH_DEATH_LYING_DN;
}
}
break;
case BOTH_KNOCKDOWN4:
if ( animLength - self->client->ps.legsTimer > 300 )
{//on our way down
if ( self->client->ps.legsTimer > 350 )
{//still partially up
deathAnim = BOTH_DEATH_FALLING_UP;
}
else
{//down
deathAnim = BOTH_DEATH_LYING_UP;
}
}
else
{//crouch death
vec3_t fwd;
float thrown = 0;
AngleVectors( self->client->ps.viewangles, fwd, NULL, NULL );
thrown = DotProduct( fwd, self->client->ps.velocity );
if ( thrown < -150 )
{
deathAnim = BOTH_DEATHBACKWARD1; //# Death anim when crouched and thrown back
}
else
{
deathAnim = BOTH_DEATH_CROUCHED; //# Death anim when crouched
}
}
break;
case BOTH_KNOCKDOWN5:
if ( self->client->ps.legsTimer < 750 )
{//flat
deathAnim = BOTH_DEATH_LYING_DN;
}
break;
case BOTH_GETUP1:
if ( self->client->ps.legsTimer < 350 )
{//standing up
}
else if ( self->client->ps.legsTimer < 800 )
{//crouching
vec3_t fwd;
float thrown = 0;
AngleVectors( self->client->ps.viewangles, fwd, NULL, NULL );
thrown = DotProduct( fwd, self->client->ps.velocity );
if ( thrown < -150 )
{
deathAnim = BOTH_DEATHBACKWARD1; //# Death anim when crouched and thrown back
}
else
{
deathAnim = BOTH_DEATH_CROUCHED; //# Death anim when crouched
}
}
else
{//lying down
if ( animLength - self->client->ps.legsTimer > 450 )
{//partially up
deathAnim = BOTH_DEATH_FALLING_UP;
}
else
{//down
deathAnim = BOTH_DEATH_LYING_UP;
}
}
break;
case BOTH_GETUP2:
if ( self->client->ps.legsTimer < 150 )
{//standing up
}
else if ( self->client->ps.legsTimer < 850 )
{//crouching
vec3_t fwd;
float thrown = 0;
AngleVectors( self->client->ps.viewangles, fwd, NULL, NULL );
thrown = DotProduct( fwd, self->client->ps.velocity );
if ( thrown < -150 )
{
deathAnim = BOTH_DEATHBACKWARD1; //# Death anim when crouched and thrown back
}
else
{
deathAnim = BOTH_DEATH_CROUCHED; //# Death anim when crouched
}
}
else
{//lying down
if ( animLength - self->client->ps.legsTimer > 500 )
{//partially up
deathAnim = BOTH_DEATH_FALLING_UP;
}
else
{//down
deathAnim = BOTH_DEATH_LYING_UP;
}
}
break;
case BOTH_GETUP3:
if ( self->client->ps.legsTimer < 250 )
{//standing up
}
else if ( self->client->ps.legsTimer < 600 )
{//crouching
vec3_t fwd;
float thrown = 0;
AngleVectors( self->client->ps.viewangles, fwd, NULL, NULL );
thrown = DotProduct( fwd, self->client->ps.velocity );
if ( thrown < -150 )
{
deathAnim = BOTH_DEATHBACKWARD1; //# Death anim when crouched and thrown back
}
else
{
deathAnim = BOTH_DEATH_CROUCHED; //# Death anim when crouched
}
}
else
{//lying down
if ( animLength - self->client->ps.legsTimer > 150 )
{//partially up
deathAnim = BOTH_DEATH_FALLING_DN;
}
else
{//down
deathAnim = BOTH_DEATH_LYING_DN;
}
}
break;
case BOTH_GETUP4:
if ( self->client->ps.legsTimer < 250 )
{//standing up
}
else if ( self->client->ps.legsTimer < 600 )
{//crouching
vec3_t fwd;
float thrown = 0;
AngleVectors( self->client->ps.viewangles, fwd, NULL, NULL );
thrown = DotProduct( fwd, self->client->ps.velocity );
if ( thrown < -150 )
{
deathAnim = BOTH_DEATHBACKWARD1; //# Death anim when crouched and thrown back
}
else
{
deathAnim = BOTH_DEATH_CROUCHED; //# Death anim when crouched
}
}
else
{//lying down
if ( animLength - self->client->ps.legsTimer > 850 )
{//partially up
deathAnim = BOTH_DEATH_FALLING_DN;
}
else
{//down
deathAnim = BOTH_DEATH_LYING_UP;
}
}
break;
case BOTH_GETUP5:
if ( self->client->ps.legsTimer > 850 )
{//lying down
if ( animLength - self->client->ps.legsTimer > 1500 )
{//partially up
deathAnim = BOTH_DEATH_FALLING_DN;
}
else
{//down
deathAnim = BOTH_DEATH_LYING_DN;
}
}
break;
case BOTH_GETUP_CROUCH_B1:
if ( self->client->ps.legsTimer < 800 )
{//crouching
vec3_t fwd;
float thrown = 0;
AngleVectors( self->client->ps.viewangles, fwd, NULL, NULL );
thrown = DotProduct( fwd, self->client->ps.velocity );
if ( thrown < -150 )
{
deathAnim = BOTH_DEATHBACKWARD1; //# Death anim when crouched and thrown back
}
else
{
deathAnim = BOTH_DEATH_CROUCHED; //# Death anim when crouched
}
}
else
{//lying down
if ( animLength - self->client->ps.legsTimer > 400 )
{//partially up
deathAnim = BOTH_DEATH_FALLING_UP;
}
else
{//down
deathAnim = BOTH_DEATH_LYING_UP;
}
}
break;
case BOTH_GETUP_CROUCH_F1:
if ( self->client->ps.legsTimer < 800 )
{//crouching
vec3_t fwd;
float thrown = 0;
AngleVectors( self->client->ps.viewangles, fwd, NULL, NULL );
thrown = DotProduct( fwd, self->client->ps.velocity );
if ( thrown < -150 )
{
deathAnim = BOTH_DEATHBACKWARD1; //# Death anim when crouched and thrown back
}
else
{
deathAnim = BOTH_DEATH_CROUCHED; //# Death anim when crouched
}
}
else
{//lying down
if ( animLength - self->client->ps.legsTimer > 150 )
{//partially up
deathAnim = BOTH_DEATH_FALLING_DN;
}
else
{//down
deathAnim = BOTH_DEATH_LYING_DN;
}
}
break;
case BOTH_FORCE_GETUP_B1:
if ( self->client->ps.legsTimer < 325 )
{//standing up
}
else if ( self->client->ps.legsTimer < 725 )
{//spinning up
deathAnim = BOTH_DEATH_SPIN_180; //# Death anim when facing backwards
}
else if ( self->client->ps.legsTimer < 900 )
{//crouching
vec3_t fwd;
float thrown = 0;
AngleVectors( self->client->ps.viewangles, fwd, NULL, NULL );
thrown = DotProduct( fwd, self->client->ps.velocity );
if ( thrown < -150 )
{
deathAnim = BOTH_DEATHBACKWARD1; //# Death anim when crouched and thrown back
}
else
{
deathAnim = BOTH_DEATH_CROUCHED; //# Death anim when crouched
}
}
else
{//lying down
if ( animLength - self->client->ps.legsTimer > 50 )
{//partially up
deathAnim = BOTH_DEATH_FALLING_UP;
}
else
{//down
deathAnim = BOTH_DEATH_LYING_UP;
}
}
break;
case BOTH_FORCE_GETUP_B2:
if ( self->client->ps.legsTimer < 575 )
{//standing up
}
else if ( self->client->ps.legsTimer < 875 )
{//spinning up
deathAnim = BOTH_DEATH_SPIN_180; //# Death anim when facing backwards
}
else if ( self->client->ps.legsTimer < 900 )
{//crouching
vec3_t fwd;
float thrown = 0;
AngleVectors( self->client->ps.viewangles, fwd, NULL, NULL );
thrown = DotProduct( fwd, self->client->ps.velocity );
if ( thrown < -150 )
{
deathAnim = BOTH_DEATHBACKWARD1; //# Death anim when crouched and thrown back
}
else
{
deathAnim = BOTH_DEATH_CROUCHED; //# Death anim when crouched
}
}
else
{//lying down
//partially up
deathAnim = BOTH_DEATH_FALLING_UP;
}
break;
case BOTH_FORCE_GETUP_B3:
if ( self->client->ps.legsTimer < 150 )
{//standing up
}
else if ( self->client->ps.legsTimer < 775 )
{//flipping
deathAnim = BOTH_DEATHBACKWARD2; //backflip
}
else
{//lying down
//partially up
deathAnim = BOTH_DEATH_FALLING_UP;
}
break;
case BOTH_FORCE_GETUP_B4:
if ( self->client->ps.legsTimer < 325 )
{//standing up
}
else
{//lying down
if ( animLength - self->client->ps.legsTimer > 150 )
{//partially up
deathAnim = BOTH_DEATH_FALLING_UP;
}
else
{//down
deathAnim = BOTH_DEATH_LYING_UP;
}
}
break;
case BOTH_FORCE_GETUP_B5:
if ( self->client->ps.legsTimer < 550 )
{//standing up
}
else if ( self->client->ps.legsTimer < 1025 )
{//kicking up
deathAnim = BOTH_DEATHBACKWARD2; //backflip
}
else
{//lying down
if ( animLength - self->client->ps.legsTimer > 50 )
{//partially up
deathAnim = BOTH_DEATH_FALLING_UP;
}
else
{//down
deathAnim = BOTH_DEATH_LYING_UP;
}
}
break;
case BOTH_FORCE_GETUP_B6:
if ( self->client->ps.legsTimer < 225 )
{//standing up
}
else if ( self->client->ps.legsTimer < 425 )
{//crouching up
vec3_t fwd;
float thrown = 0;
AngleVectors( self->client->ps.viewangles, fwd, NULL, NULL );
thrown = DotProduct( fwd, self->client->ps.velocity );
if ( thrown < -150 )
{
deathAnim = BOTH_DEATHBACKWARD1; //# Death anim when crouched and thrown back
}
else
{
deathAnim = BOTH_DEATH_CROUCHED; //# Death anim when crouched
}
}
else if ( self->client->ps.legsTimer < 825 )
{//flipping up
deathAnim = BOTH_DEATHFORWARD3; //backflip
}
else
{//lying down
if ( animLength - self->client->ps.legsTimer > 225 )
{//partially up
deathAnim = BOTH_DEATH_FALLING_UP;
}
else
{//down
deathAnim = BOTH_DEATH_LYING_UP;
}
}
break;
case BOTH_FORCE_GETUP_F1:
if ( self->client->ps.legsTimer < 275 )
{//standing up
}
else if ( self->client->ps.legsTimer < 750 )
{//flipping
deathAnim = BOTH_DEATH14;
}
else
{//lying down
if ( animLength - self->client->ps.legsTimer > 100 )
{//partially up
deathAnim = BOTH_DEATH_FALLING_DN;
}
else
{//down
deathAnim = BOTH_DEATH_LYING_DN;
}
}
break;
case BOTH_FORCE_GETUP_F2:
if ( self->client->ps.legsTimer < 1200 )
{//standing
}
else
{//lying down
if ( animLength - self->client->ps.legsTimer > 225 )
{//partially up
deathAnim = BOTH_DEATH_FALLING_DN;
}
else
{//down
deathAnim = BOTH_DEATH_LYING_DN;
}
}
break;
}
}
return deathAnim;
}
int G_PickDeathAnim( gentity_t *self, vec3_t point, int damage, int mod, int hitLoc )
{//FIXME: play dead flop anims on body if in an appropriate _DEAD anim when this func is called
int deathAnim = -1;
@ -1036,63 +1557,36 @@ int G_PickDeathAnim( gentity_t *self, vec3_t point, int damage, int mod, int hit
}
if ( deathAnim == -1 )
{
//death anims
switch( hitLoc )
if (self->client)
{
case HL_FOOT_RT:
case HL_FOOT_LT:
if ( mod == MOD_SABER && !Q_irand( 0, 2 ) )
{
return BOTH_DEATH10;//chest: back flip
}
else if ( !Q_irand( 0, 2 ) )
{
deathAnim = BOTH_DEATH4;//back: forward
}
else if ( !Q_irand( 0, 1 ) )
{
deathAnim = BOTH_DEATH5;//same as 4
}
else
{
deathAnim = BOTH_DEATH15;//back: forward
}
break;
case HL_LEG_RT:
if ( !Q_irand( 0, 2 ) )
{
deathAnim = BOTH_DEATH4;//back: forward
}
else if ( !Q_irand( 0, 1 ) )
{
deathAnim = BOTH_DEATH5;//same as 4
}
else
{
deathAnim = BOTH_DEATH15;//back: forward
}
break;
case HL_LEG_LT:
if ( !Q_irand( 0, 2 ) )
{
deathAnim = BOTH_DEATH4;//back: forward
}
else if ( !Q_irand( 0, 1 ) )
{
deathAnim = BOTH_DEATH5;//same as 4
}
else
{
deathAnim = BOTH_DEATH15;//back: forward
}
break;
case HL_BACK:
if ( !VectorLengthSquared( objVelocity ) )
{
deathAnim = BOTH_DEATH17;//head/back: croak
}
else
deathAnim = G_CheckSpecialDeathAnim( self, point, damage, mod, hitLoc );
}
if (deathAnim == -1)
{
//death anims
switch( hitLoc )
{
case HL_FOOT_RT:
case HL_FOOT_LT:
if ( mod == MOD_SABER && !Q_irand( 0, 2 ) )
{
return BOTH_DEATH10;//chest: back flip
}
else if ( !Q_irand( 0, 2 ) )
{
deathAnim = BOTH_DEATH4;//back: forward
}
else if ( !Q_irand( 0, 1 ) )
{
deathAnim = BOTH_DEATH5;//same as 4
}
else
{
deathAnim = BOTH_DEATH15;//back: forward
}
break;
case HL_LEG_RT:
if ( !Q_irand( 0, 2 ) )
{
deathAnim = BOTH_DEATH4;//back: forward
@ -1105,135 +1599,170 @@ int G_PickDeathAnim( gentity_t *self, vec3_t point, int damage, int mod, int hit
{
deathAnim = BOTH_DEATH15;//back: forward
}
}
break;
case HL_CHEST_RT:
case HL_ARM_RT:
case HL_HAND_RT:
case HL_BACK_RT:
if ( damage <= max_health*0.25 )
{
deathAnim = BOTH_DEATH9;//chest right: snap, fall forward
}
else if ( damage <= max_health*0.5 )
{
deathAnim = BOTH_DEATH3;//chest right: back
}
else if ( damage <= max_health*0.75 )
{
deathAnim = BOTH_DEATH6;//chest right: spin
}
else
{
//TEMP HACK: play spinny deaths less often
if ( Q_irand( 0, 1 ) )
break;
case HL_LEG_LT:
if ( !Q_irand( 0, 2 ) )
{
deathAnim = BOTH_DEATH8;//chest right: spin high
deathAnim = BOTH_DEATH4;//back: forward
}
else if ( !Q_irand( 0, 1 ) )
{
deathAnim = BOTH_DEATH5;//same as 4
}
else
{
switch ( Q_irand( 0, 2 ) )
deathAnim = BOTH_DEATH15;//back: forward
}
break;
case HL_BACK:
if ( !VectorLengthSquared( objVelocity ) )
{
deathAnim = BOTH_DEATH17;//head/back: croak
}
else
{
if ( !Q_irand( 0, 2 ) )
{
default:
case 0:
deathAnim = BOTH_DEATH9;//chest right: snap, fall forward
break;
case 1:
deathAnim = BOTH_DEATH3;//chest right: back
break;
case 2:
deathAnim = BOTH_DEATH6;//chest right: spin
break;
deathAnim = BOTH_DEATH4;//back: forward
}
else if ( !Q_irand( 0, 1 ) )
{
deathAnim = BOTH_DEATH5;//same as 4
}
else
{
deathAnim = BOTH_DEATH15;//back: forward
}
}
}
break;
case HL_CHEST_LT:
case HL_ARM_LT:
case HL_HAND_LT:
case HL_BACK_LT:
if ( damage <= max_health*0.25 )
{
deathAnim = BOTH_DEATH11;//chest left: snap, fall forward
}
else if ( damage <= max_health*0.5 )
{
deathAnim = BOTH_DEATH7;//chest left: back
}
else if ( damage <= max_health*0.75 )
{
deathAnim = BOTH_DEATH12;//chest left: spin
}
else
{
//TEMP HACK: play spinny deaths less often
if ( Q_irand( 0, 1 ) )
break;
case HL_CHEST_RT:
case HL_ARM_RT:
case HL_HAND_RT:
case HL_BACK_RT:
if ( damage <= max_health*0.25 )
{
deathAnim = BOTH_DEATH14;//chest left: spin high
deathAnim = BOTH_DEATH9;//chest right: snap, fall forward
}
else if ( damage <= max_health*0.5 )
{
deathAnim = BOTH_DEATH3;//chest right: back
}
else if ( damage <= max_health*0.75 )
{
deathAnim = BOTH_DEATH6;//chest right: spin
}
else
{
switch ( Q_irand( 0, 2 ) )
//TEMP HACK: play spinny deaths less often
if ( Q_irand( 0, 1 ) )
{
default:
case 0:
deathAnim = BOTH_DEATH11;//chest left: snap, fall forward
break;
case 1:
deathAnim = BOTH_DEATH7;//chest left: back
break;
case 2:
deathAnim = BOTH_DEATH12;//chest left: spin
break;
deathAnim = BOTH_DEATH8;//chest right: spin high
}
else
{
switch ( Q_irand( 0, 2 ) )
{
default:
case 0:
deathAnim = BOTH_DEATH9;//chest right: snap, fall forward
break;
case 1:
deathAnim = BOTH_DEATH3;//chest right: back
break;
case 2:
deathAnim = BOTH_DEATH6;//chest right: spin
break;
}
}
}
}
break;
case HL_CHEST:
case HL_WAIST:
if ( damage <= max_health*0.25 || !VectorLengthSquared( objVelocity ) )
{
if ( !Q_irand( 0, 1 ) )
break;
case HL_CHEST_LT:
case HL_ARM_LT:
case HL_HAND_LT:
case HL_BACK_LT:
if ( damage <= max_health*0.25 )
{
deathAnim = BOTH_DEATH18;//gut: fall right
deathAnim = BOTH_DEATH11;//chest left: snap, fall forward
}
else if ( damage <= max_health*0.5 )
{
deathAnim = BOTH_DEATH7;//chest left: back
}
else if ( damage <= max_health*0.75 )
{
deathAnim = BOTH_DEATH12;//chest left: spin
}
else
{
deathAnim = BOTH_DEATH19;//gut: fall left
//TEMP HACK: play spinny deaths less often
if ( Q_irand( 0, 1 ) )
{
deathAnim = BOTH_DEATH14;//chest left: spin high
}
else
{
switch ( Q_irand( 0, 2 ) )
{
default:
case 0:
deathAnim = BOTH_DEATH11;//chest left: snap, fall forward
break;
case 1:
deathAnim = BOTH_DEATH7;//chest left: back
break;
case 2:
deathAnim = BOTH_DEATH12;//chest left: spin
break;
}
}
}
}
else if ( damage <= max_health*0.5 )
{
deathAnim = BOTH_DEATH2;//chest: backward short
}
else if ( damage <= max_health*0.75 )
{
if ( !Q_irand( 0, 1 ) )
break;
case HL_CHEST:
case HL_WAIST:
if ( damage <= max_health*0.25 || !VectorLengthSquared( objVelocity ) )
{
deathAnim = BOTH_DEATH1;//chest: backward med
if ( !Q_irand( 0, 1 ) )
{
deathAnim = BOTH_DEATH18;//gut: fall right
}
else
{
deathAnim = BOTH_DEATH19;//gut: fall left
}
}
else if ( damage <= max_health*0.5 )
{
deathAnim = BOTH_DEATH2;//chest: backward short
}
else if ( damage <= max_health*0.75 )
{
if ( !Q_irand( 0, 1 ) )
{
deathAnim = BOTH_DEATH1;//chest: backward med
}
else
{
deathAnim = BOTH_DEATH16;//same as 1
}
}
else
{
deathAnim = BOTH_DEATH16;//same as 1
deathAnim = BOTH_DEATH10;//chest: back flip
}
break;
case HL_HEAD:
if ( damage <= max_health*0.5 )
{
deathAnim = BOTH_DEATH17;//head/back: croak
}
else
{
deathAnim = BOTH_DEATH13;//head: stumble, fall back
}
break;
default:
break;
}
else
{
deathAnim = BOTH_DEATH10;//chest: back flip
}
break;
case HL_HEAD:
if ( damage <= max_health*0.5 )
{
deathAnim = BOTH_DEATH17;//head/back: croak
}
else
{
deathAnim = BOTH_DEATH13;//head: stumble, fall back
}
break;
default:
break;
}
}
return deathAnim;
@ -1282,6 +1811,15 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int
return;
}
if (g_slowmoDuelEnd.integer && g_gametype.integer == GT_TOURNAMENT && attacker && attacker->inuse && attacker->client)
{
if (!gDoSlowMoDuel)
{
gDoSlowMoDuel = qtrue;
gSlowMoDuelTime = level.time;
}
}
if (inflictor && inflictor->activator && !inflictor->client && !attacker->client &&
inflictor->activator->client && inflictor->activator->inuse &&
inflictor->s.weapon == WP_TURRET)
@ -2180,7 +2718,7 @@ void G_Dismember( gentity_t *ent, vec3_t point, int limbType, float limbRollBase
else
{
limb->s.modelindex = -1;
limb->s.modelindex2 = ent->s.number;
limb->s.otherEntityNum2 = ent->s.number;
}
trap_LinkEntity( limb );
@ -2610,7 +3148,7 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
}
if ( g_trueJedi.integer )
if ( g_trueJedi.integer && client )
{//less explosive damage for jedi, more saber damage for non-jedi
if ( client->ps.trueJedi )
{//if the target is a trueJedi, reduce splash and explosive damage to 1/2
@ -2629,7 +3167,7 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
case MOD_TRIP_MINE_SPLASH:
case MOD_TIMED_MINE_SPLASH:
case MOD_DET_PACK_SPLASH:
damage *= 0.5;
damage *= 0.75;
break;
}
}

View file

@ -792,6 +792,8 @@ void DeathmatchScoreboardMessage (gentity_t *client);
// g_main.c
//
extern vmCvar_t g_ff_objectives;
extern qboolean gDoSlowMoDuel;
extern int gSlowMoDuelTime;
void FindIntermissionPoint( void );
void SetLeader(int team, int client);
@ -964,10 +966,22 @@ extern vmCvar_t g_saberGhoul2Collision;
extern vmCvar_t g_saberAlwaysBoxTrace;
extern vmCvar_t g_saberBoxTraceSize;
extern vmCvar_t g_logClientInfo;
extern vmCvar_t g_slowmoDuelEnd;
extern vmCvar_t g_saberDamageScale;
extern vmCvar_t g_useWhileThrowing;
extern vmCvar_t g_forceRegenTime;
extern vmCvar_t g_spawnInvulnerability;
extern vmCvar_t g_forcePowerDisable;
extern vmCvar_t g_weaponDisable;
extern vmCvar_t g_allowDuelSuicide;
extern vmCvar_t g_fraglimitVoteCorrection;
extern vmCvar_t g_duelWeaponDisable;
extern vmCvar_t g_fraglimit;
extern vmCvar_t g_duel_fraglimit;

View file

@ -40,11 +40,21 @@ vmCvar_t g_saberGhoul2Collision;
vmCvar_t g_saberAlwaysBoxTrace;
vmCvar_t g_saberBoxTraceSize;
vmCvar_t g_logClientInfo;
vmCvar_t g_slowmoDuelEnd;
vmCvar_t g_saberDamageScale;
vmCvar_t g_useWhileThrowing;
vmCvar_t g_forceRegenTime;
vmCvar_t g_spawnInvulnerability;
vmCvar_t g_forcePowerDisable;
vmCvar_t g_weaponDisable;
vmCvar_t g_duelWeaponDisable;
vmCvar_t g_allowDuelSuicide;
vmCvar_t g_fraglimitVoteCorrection;
vmCvar_t g_fraglimit;
vmCvar_t g_duel_fraglimit;
vmCvar_t g_timelimit;
@ -136,7 +146,7 @@ static cvarTable_t gameCvarTable[] = {
// change anytime vars
{ &g_ff_objectives, "g_ff_objectives", "0", /*CVAR_SERVERINFO |*/ CVAR_NORESTART, 0, qtrue },
{ &g_trueJedi, "g_jediVmerc", "0", CVAR_INTERNAL |CVAR_SERVERINFO | CVAR_LATCH, 0, qtrue },
{ &g_trueJedi, "g_jediVmerc", "0", CVAR_SERVERINFO | CVAR_LATCH | CVAR_ARCHIVE, 0, qtrue },
{ &g_autoMapCycle, "g_autoMapCycle", "0", CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue },
{ &g_dmflags, "dmflags", "0", CVAR_SERVERINFO | CVAR_ARCHIVE, 0, qtrue },
@ -154,6 +164,14 @@ static cvarTable_t gameCvarTable[] = {
{ &g_saberAlwaysBoxTrace, "g_saberAlwaysBoxTrace", "0", 0, 0, qtrue },
{ &g_saberBoxTraceSize, "g_saberBoxTraceSize", "2", 0, 0, qtrue },
{ &g_logClientInfo, "g_logClientInfo", "0", CVAR_ARCHIVE, 0, qtrue },
{ &g_slowmoDuelEnd, "g_slowmoDuelEnd", "0", CVAR_ARCHIVE, 0, qtrue },
{ &g_saberDamageScale, "g_saberDamageScale", "1", CVAR_ARCHIVE, 0, qtrue },
{ &g_useWhileThrowing, "g_useWhileThrowing", "1", 0, 0, qtrue },
{ &g_forceRegenTime, "g_forceRegenTime", "200", CVAR_SERVERINFO | CVAR_ARCHIVE, 0, qtrue },
{ &g_spawnInvulnerability, "g_spawnInvulnerability", "3000", CVAR_ARCHIVE, 0, qtrue },
@ -162,6 +180,10 @@ static cvarTable_t gameCvarTable[] = {
{ &g_weaponDisable, "g_weaponDisable", "0", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_LATCH, 0, qtrue },
{ &g_duelWeaponDisable, "g_duelWeaponDisable", "1", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_LATCH, 0, qtrue },
{ &g_allowDuelSuicide, "g_allowDuelSuicide", "0", CVAR_ARCHIVE, 0, qtrue },
{ &g_fraglimitVoteCorrection, "g_fraglimitVoteCorrection", "1", CVAR_ARCHIVE, 0, qtrue },
{ &g_fraglimit, "fraglimit", "20", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue },
{ &g_duel_fraglimit, "duel_fraglimit", "10", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue },
{ &g_timelimit, "timelimit", "0", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue },
@ -1685,6 +1707,11 @@ void CheckExitRules( void ) {
return;
}
if (gDoSlowMoDuel)
{ //don't go to intermission while in slow motion
return;
}
if (gEscaping)
{
int i = 0;
@ -2001,6 +2028,28 @@ void CheckVote( void ) {
{ //otherwise, just leave the map until a restart
G_RefreshNextMap(level.votingGametypeTo, qfalse);
}
if (g_fraglimitVoteCorrection.integer)
{ //This means to auto-correct fraglimit when voting to and from duel.
int currentGT = trap_Cvar_VariableIntegerValue("g_gametype");
int currentFL = trap_Cvar_VariableIntegerValue("fraglimit");
if (level.votingGametypeTo == GT_TOURNAMENT && currentGT != GT_TOURNAMENT)
{
if (currentFL > 3 || !currentFL)
{ //if voting to duel, and fraglimit is more than 3 (or unlimited), then set it down to 3
trap_SendConsoleCommand(EXEC_APPEND, "fraglimit 3\n");
}
}
else if (level.votingGametypeTo != GT_TOURNAMENT && currentGT == GT_TOURNAMENT)
{
if (currentFL && currentFL < 20)
{ //if voting from duel, an fraglimit is less than 20, then set it up to 20
trap_SendConsoleCommand(EXEC_APPEND, "fraglimit 20\n");
}
}
}
level.votingGametype = qfalse;
level.votingGametypeTo = 0;
}
@ -2196,6 +2245,9 @@ void G_RunThink (gentity_t *ent) {
int g_LastFrameTime = 0;
int g_TimeSinceLastFrame = 0;
qboolean gDoSlowMoDuel = qfalse;
int gSlowMoDuelTime = 0;
/*
================
G_RunFrame
@ -2208,7 +2260,64 @@ void G_RunFrame( int levelTime ) {
int i;
gentity_t *ent;
int msec;
int start, end;
int start, end;
if (gDoSlowMoDuel)
{
if (level.restarted)
{
char buf[128];
float tFVal = 0;
trap_Cvar_VariableStringBuffer("timescale", buf, sizeof(buf));
tFVal = atof(buf);
trap_Cvar_Set("timescale", "1");
if (tFVal == 1.0f)
{
gDoSlowMoDuel = qfalse;
}
}
else
{
float timeDif = (level.time - gSlowMoDuelTime); //difference in time between when the slow motion was initiated and now
float useDif = 0; //the difference to use when actually setting the timescale
if (timeDif < 150)
{
trap_Cvar_Set("timescale", "0.1f");
}
else if (timeDif < 1150)
{
useDif = (timeDif/1000); //scale from 0.1 up to 1
if (useDif < 0.1)
{
useDif = 0.1;
}
if (useDif > 1.0)
{
useDif = 1.0;
}
trap_Cvar_Set("timescale", va("%f", useDif));
}
else
{
char buf[128];
float tFVal = 0;
trap_Cvar_VariableStringBuffer("timescale", buf, sizeof(buf));
tFVal = atof(buf);
trap_Cvar_Set("timescale", "1");
if (timeDif > 1500 && tFVal == 1.0f)
{
gDoSlowMoDuel = qfalse;
}
}
}
}
// if we are waiting for the level to restart, do nothing
if ( level.restarted ) {
@ -2295,7 +2404,7 @@ int start, end;
{
G_CheckClientTimeouts ( ent );
if((!level.intermissiontime)&&!(ent->client->ps.pm_flags&PMF_FOLLOW))
if((!level.intermissiontime)&&!(ent->client->ps.pm_flags&PMF_FOLLOW) && ent->client->sess.sessionTeam != TEAM_SPECTATOR)
{
WP_ForcePowersUpdate(ent, &ent->client->pers.cmd );
WP_SaberPositionUpdate(ent, &ent->client->pers.cmd);

View file

@ -1552,6 +1552,9 @@ void SP_fx_runner( gentity_t *ent )
//rww - here starts the main example g2animent stuff
#define ANIMENT_TYPE_STORMTROOPER 0
#define ANIMENT_TYPE_RODIAN 1
#define ANIMENT_TYPE_JAN 2
#define ANIMENT_TYPE_CUSTOM 3
#define MAX_ANIMENTS 4
#define TROOPER_PAIN_SOUNDS 4
#define TROOPER_DEATH_SOUNDS 3
@ -1567,12 +1570,245 @@ int gRodianSound_Pain[RODIAN_PAIN_SOUNDS];
int gRodianSound_Death[RODIAN_DEATH_SOUNDS];
int gRodianSound_Alert[RODIAN_ALERT_SOUNDS];
#define JAN_PAIN_SOUNDS 4
#define JAN_DEATH_SOUNDS 3
#define JAN_ALERT_SOUNDS 5
int gJanSound_Pain[JAN_PAIN_SOUNDS];
int gJanSound_Death[JAN_DEATH_SOUNDS];
int gJanSound_Alert[JAN_ALERT_SOUNDS];
int G_PickDeathAnim( gentity_t *self, vec3_t point, int damage, int mod, int hitLoc );
void AnimEntFireWeapon( gentity_t *ent, qboolean altFire );
int GetNearestVisibleWP(vec3_t org, int ignore);
int InFieldOfVision(vec3_t viewangles, float fov, vec3_t angles);
extern float gBotEdit;
#define ANIMENT_ALIGNED_UNKNOWN 0
#define ANIMENT_ALIGNED_BAD 1
#define ANIMENT_ALIGNED_GOOD 2
#define ANIMENT_CUSTOMSOUND_PAIN 0
#define ANIMENT_CUSTOMSOUND_DEATH 1
#define ANIMENT_CUSTOMSOUND_ALERT 2
int gAnimEntTypes = 0;
typedef struct animentCustomInfo_s
{
int aeAlignment;
int aeIndex;
int aeWeapon;
char *modelPath;
char *soundPath;
void *next;
} animentCustomInfo_t;
animentCustomInfo_t *animEntRoot = NULL;
animentCustomInfo_t *ExampleAnimEntCustomData(gentity_t *self)
{
animentCustomInfo_t *iter = animEntRoot;
int safetyCheck = 0;
while (iter && safetyCheck < 30000)
{
if (iter->aeIndex == self->waterlevel)
{
return iter;
}
iter = iter->next;
safetyCheck++;
}
return NULL;
}
animentCustomInfo_t *ExampleAnimEntCustomDataExists(gentity_t *self, int alignment, int weapon, char *modelname,
char *soundpath)
{
animentCustomInfo_t *iter = animEntRoot;
int safetyCheck = 0;
while (iter && safetyCheck < 30000)
{
if (iter->aeAlignment == alignment &&
iter->aeWeapon == weapon &&
!Q_stricmp(iter->modelPath, modelname) &&
!Q_stricmp(iter->soundPath, soundpath))
{
return iter;
}
iter = iter->next;
safetyCheck++;
}
return NULL;
}
void ExampleAnimEntCustomDataEntry(gentity_t *self, int alignment, int weapon, char *modelname, char *soundpath)
{
animentCustomInfo_t *find = ExampleAnimEntCustomDataExists(self, alignment, weapon, modelname, soundpath);
animentCustomInfo_t *lastValid = NULL;
int safetyCheck = 0;
if (find)
{ //data for this guy already exists. Set our waterlevel (aeIndex) to use this.
self->waterlevel = find->aeIndex;
return;
}
find = animEntRoot;
while (find && safetyCheck < 30000)
{ //find the next null pointer
lastValid = find;
find = find->next;
safetyCheck++;
}
if (!find)
{
find = BG_Alloc(sizeof(animentCustomInfo_t));
if (!find)
{ //careful not to exceed the BG_Alloc limit!
return;
}
find->aeAlignment = alignment;
self->waterlevel = gAnimEntTypes;
find->aeIndex = self->waterlevel;
find->aeWeapon = weapon;
find->next = NULL;
find->modelPath = BG_Alloc(strlen(modelname)+1);
find->soundPath = BG_Alloc(strlen(soundpath)+1);
if (!find->modelPath || !find->soundPath)
{
find->aeIndex = -1;
return;
}
strcpy(find->modelPath, modelname);
strcpy(find->soundPath, soundpath);
find->modelPath[strlen(modelname)] = 0;
find->soundPath[strlen(modelname)] = 0;
if (lastValid)
{
lastValid->next = find;
}
if (!animEntRoot)
{
animEntRoot = find;
}
gAnimEntTypes++;
}
}
void AnimEntCustomSoundPrecache(animentCustomInfo_t *aeInfo)
{
if (!aeInfo)
{
return;
}
G_SoundIndex(va("%s/pain25", aeInfo->soundPath));
G_SoundIndex(va("%s/pain50", aeInfo->soundPath));
G_SoundIndex(va("%s/pain75", aeInfo->soundPath));
G_SoundIndex(va("%s/pain100", aeInfo->soundPath));
G_SoundIndex(va("%s/death1", aeInfo->soundPath));
G_SoundIndex(va("%s/death2", aeInfo->soundPath));
G_SoundIndex(va("%s/death3", aeInfo->soundPath));
G_SoundIndex(va("%s/detected1", aeInfo->soundPath));
G_SoundIndex(va("%s/detected2", aeInfo->soundPath));
G_SoundIndex(va("%s/detected3", aeInfo->soundPath));
G_SoundIndex(va("%s/detected4", aeInfo->soundPath));
G_SoundIndex(va("%s/detected5", aeInfo->soundPath));
}
void ExampleAnimEntCustomSound(gentity_t *self, int soundType)
{
animentCustomInfo_t *aeInfo = ExampleAnimEntCustomData(self);
int customSounds[16];
int numSounds = 0;
if (!aeInfo)
{
return;
}
if (soundType == ANIMENT_CUSTOMSOUND_PAIN)
{
customSounds[0] = G_SoundIndex(va("%s/pain25", aeInfo->soundPath));
customSounds[1] = G_SoundIndex(va("%s/pain50", aeInfo->soundPath));
customSounds[2] = G_SoundIndex(va("%s/pain75", aeInfo->soundPath));
customSounds[3] = G_SoundIndex(va("%s/pain100", aeInfo->soundPath));
numSounds = 4;
}
else if (soundType == ANIMENT_CUSTOMSOUND_DEATH)
{
customSounds[0] = G_SoundIndex(va("%s/death1", aeInfo->soundPath));
customSounds[1] = G_SoundIndex(va("%s/death2", aeInfo->soundPath));
customSounds[2] = G_SoundIndex(va("%s/death3", aeInfo->soundPath));
numSounds = 3;
}
else if (soundType == ANIMENT_CUSTOMSOUND_ALERT)
{
customSounds[0] = G_SoundIndex(va("%s/detected1", aeInfo->soundPath));
customSounds[1] = G_SoundIndex(va("%s/detected2", aeInfo->soundPath));
customSounds[2] = G_SoundIndex(va("%s/detected3", aeInfo->soundPath));
customSounds[3] = G_SoundIndex(va("%s/detected4", aeInfo->soundPath));
customSounds[4] = G_SoundIndex(va("%s/detected5", aeInfo->soundPath));
numSounds = 5;
}
if (!numSounds)
{
return;
}
G_Sound(self, CHAN_AUTO, customSounds[Q_irand(0, numSounds-1)]);
}
int ExampleAnimEntAlignment(gentity_t *self)
{
if (self->watertype == ANIMENT_TYPE_STORMTROOPER)
{
return ANIMENT_ALIGNED_BAD;
}
if (self->watertype == ANIMENT_TYPE_RODIAN)
{
return ANIMENT_ALIGNED_BAD;
}
if (self->watertype == ANIMENT_TYPE_JAN)
{
return ANIMENT_ALIGNED_GOOD;
}
if (self->watertype == ANIMENT_TYPE_CUSTOM)
{
animentCustomInfo_t *aeInfo = ExampleAnimEntCustomData(self);
if (aeInfo)
{
return aeInfo->aeAlignment;
}
}
return ANIMENT_ALIGNED_UNKNOWN;
}
void ExampleAnimEntAlertOthers(gentity_t *self)
{
//alert all the other animents in the area
@ -1584,7 +1820,8 @@ void ExampleAnimEntAlertOthers(gentity_t *self)
g_entities[i].s.eType == ET_GRAPPLE &&
g_entities[i].health > 0)
{
if (g_entities[i].bolt_Motion == ENTITYNUM_NONE && trap_InPVS(self->r.currentOrigin, g_entities[i].r.currentOrigin))
if (g_entities[i].bolt_Motion == ENTITYNUM_NONE && trap_InPVS(self->r.currentOrigin, g_entities[i].r.currentOrigin) &&
ExampleAnimEntAlignment(self) == ExampleAnimEntAlignment(&g_entities[i]))
{
g_entities[i].bolt_Motion = self->bolt_Motion;
g_entities[i].speed = level.time + 4000; //4 seconds til we forget about the enemy
@ -1600,7 +1837,7 @@ void ExampleAnimEnt_Die( gentity_t *self, gentity_t *inflictor, gentity_t *attac
{
self->s.torsoAnim = G_PickDeathAnim(self, self->pos1, damage, mod, HL_NONE);
if (self->s.torsoAnim < 0 || self->s.torsoAnim >= MAX_TOTALANIMATIONS)
if (self->s.torsoAnim <= 0 || self->s.torsoAnim >= MAX_TOTALANIMATIONS)
{ //?! (bad)
self->s.torsoAnim = BOTH_DEATH1;
}
@ -1619,6 +1856,14 @@ void ExampleAnimEnt_Die( gentity_t *self, gentity_t *inflictor, gentity_t *attac
{
G_Sound(self, CHAN_AUTO, gRodianSound_Death[Q_irand(0, RODIAN_DEATH_SOUNDS-1)]);
}
else if (self->watertype == ANIMENT_TYPE_JAN)
{
G_Sound(self, CHAN_AUTO, gJanSound_Death[Q_irand(0, JAN_DEATH_SOUNDS-1)]);
}
else if (self->watertype == ANIMENT_TYPE_CUSTOM)
{
ExampleAnimEntCustomSound(self, ANIMENT_CUSTOMSOUND_DEATH);
}
if (mod == MOD_SABER)
{ //Set the velocity up a bit to make the limb fly up more than it otherwise would.
@ -1647,6 +1892,12 @@ void ExampleAnimEnt_Die( gentity_t *self, gentity_t *inflictor, gentity_t *attac
VectorCopy(preDelta, self->s.pos.trDelta);
}
if (self->bolt_Motion == ENTITYNUM_NONE &&
(attacker->client || attacker->s.eType == ET_GRAPPLE))
{
self->bolt_Motion = attacker->s.number;
}
if (self->bolt_Motion != ENTITYNUM_NONE)
{
ExampleAnimEntAlertOthers(self);
@ -1671,6 +1922,11 @@ void ExampleAnimEnt_Pain(gentity_t *self, gentity_t *attacker, int damage)
self->s.legsAnim = painAnim;
self->bolt_LArm = level.time + animLen;
if (self->s.torsoAnim <= 0 || self->s.torsoAnim >= MAX_TOTALANIMATIONS)
{
self->s.torsoAnim = self->s.legsAnim = BOTH_PAIN1;
}
if (self->watertype == ANIMENT_TYPE_STORMTROOPER)
{
G_Sound(self, CHAN_AUTO, gTrooperSound_Pain[Q_irand(0, TROOPER_PAIN_SOUNDS-1)]);
@ -1679,13 +1935,24 @@ void ExampleAnimEnt_Pain(gentity_t *self, gentity_t *attacker, int damage)
{
G_Sound(self, CHAN_AUTO, gRodianSound_Pain[Q_irand(0, RODIAN_PAIN_SOUNDS-1)]);
}
if (attacker && attacker->client && self->bolt_Motion == ENTITYNUM_NONE)
else if (self->watertype == ANIMENT_TYPE_JAN)
{
self->bolt_Motion = attacker->s.number;
self->speed = level.time + 4000; //4 seconds til we forget about the enemy
ExampleAnimEntAlertOthers(self);
self->bolt_RArm = level.time + Q_irand(500, 1000);
G_Sound(self, CHAN_AUTO, gJanSound_Pain[Q_irand(0, JAN_PAIN_SOUNDS-1)]);
}
else if (self->watertype == ANIMENT_TYPE_CUSTOM)
{
ExampleAnimEntCustomSound(self, ANIMENT_CUSTOMSOUND_PAIN);
}
if (attacker && (attacker->client || attacker->s.eType == ET_GRAPPLE) && self->bolt_Motion == ENTITYNUM_NONE)
{
if (attacker->s.number >= MAX_CLIENTS || (ExampleAnimEntAlignment(self) != ANIMENT_ALIGNED_GOOD && !(attacker->r.svFlags & SVF_BOT)))
{
self->bolt_Motion = attacker->s.number;
self->speed = level.time + 4000; //4 seconds til we forget about the enemy
ExampleAnimEntAlertOthers(self);
self->bolt_RArm = level.time + Q_irand(500, 1000);
}
}
}
@ -1844,10 +2111,27 @@ qboolean ExampleAnimEntClearLOS(gentity_t *self, vec3_t point)
trap_Trace(&tr, self->r.currentOrigin, 0, 0, point, self->s.number, self->clipmask);
if (tr.fraction == 1 ||
tr.entityNum < MAX_CLIENTS)
{ //clear LOS, or would be hitting a client (they're all bad!), so fire.
return qtrue;
if (ExampleAnimEntAlignment(self) == ANIMENT_ALIGNED_GOOD)
{
if (tr.fraction == 1 ||
(g_entities[tr.entityNum].s.eType == ET_GRAPPLE && ExampleAnimEntAlignment(&g_entities[tr.entityNum]) != ANIMENT_ALIGNED_GOOD) ||
(self->bolt_Motion < MAX_CLIENTS && tr.entityNum == self->bolt_Motion))
{ //clear LOS, or would be hitting a bad animent, so fire.
return qtrue;
}
else if (g_entities[tr.entityNum].inuse && g_entities[tr.entityNum].client && (g_entities[tr.entityNum].r.svFlags & SVF_BOT))
{
return qtrue;
}
}
else
{
if (tr.fraction == 1 ||
tr.entityNum < MAX_CLIENTS ||
(g_entities[tr.entityNum].s.eType == ET_GRAPPLE && ExampleAnimEntAlignment(&g_entities[tr.entityNum]) != ANIMENT_ALIGNED_BAD))
{ //clear LOS, or would be hitting a client (they're all bad!), so fire.
return qtrue;
}
}
return qfalse;
@ -1872,7 +2156,19 @@ void ExampleAnimEntWeaponHandling(gentity_t *self)
{
AnimEntFireWeapon(self, qfalse);
G_AddEvent(self, EV_FIRE_WEAPON, 0);
self->bolt_RArm = level.time + Q_irand(700, 1000);
if (self->s.weapon == WP_REPEATER)
{
self->bolt_RArm = level.time + Q_irand(1, 500);
}
else if (ExampleAnimEntAlignment(self) == ANIMENT_ALIGNED_GOOD)
{
self->bolt_RArm = level.time + Q_irand(200, 400);
}
else
{
self->bolt_RArm = level.time + Q_irand(700, 1000);
}
}
}
}
@ -2002,30 +2298,92 @@ void ExampleAnimEntEnemyHandling(gentity_t *self, float enDist)
int bestIndex = -1;
float minDist = enDist;
while (i < MAX_CLIENTS)
if (ExampleAnimEntAlignment(self) == ANIMENT_ALIGNED_GOOD)
{
if (g_entities[i].inuse && g_entities[i].client && g_entities[i].health > 0 && g_entities[i].client->sess.sessionTeam != TEAM_SPECTATOR)
while (i < MAX_GENTITIES)
{
vec3_t checkLen;
float fCheckLen;
VectorSubtract(self->r.currentOrigin, g_entities[i].client->ps.origin, checkLen);
fCheckLen = VectorLength(checkLen);
if (fCheckLen < (minDist - 128))
if (g_entities[i].inuse && (g_entities[i].s.eType == ET_GRAPPLE || (g_entities[i].client && (g_entities[i].r.svFlags & SVF_BOT))) && ExampleAnimEntAlignment(&g_entities[i]) != ANIMENT_ALIGNED_GOOD && g_entities[i].health > 0 && !(g_entities[i].s.eFlags & EF_DEAD))
{
vec3_t enAngles;
VectorSubtract(g_entities[i].client->ps.origin, self->r.currentOrigin, enAngles);
vectoangles(enAngles, enAngles);
if ((InFieldOfVision(self->s.apos.trBase, 120, enAngles) || self->s.genericenemyindex > level.time) && ExampleAnimEntClearLOS(self, g_entities[i].client->ps.origin))
vec3_t checkLen;
float fCheckLen;
VectorSubtract(self->r.currentOrigin, g_entities[i].r.currentOrigin, checkLen);
fCheckLen = VectorLength(checkLen);
if (fCheckLen < (minDist - 128))
{
minDist = fCheckLen;
bestIndex = i;
vec3_t enAngles;
VectorSubtract(g_entities[i].r.currentOrigin, self->r.currentOrigin, enAngles);
vectoangles(enAngles, enAngles);
if ((InFieldOfVision(self->s.apos.trBase, 120, enAngles) || self->s.genericenemyindex > level.time) && ExampleAnimEntClearLOS(self, g_entities[i].r.currentOrigin))
{
minDist = fCheckLen;
bestIndex = i;
}
}
}
i++;
}
}
else
{
while (i < MAX_CLIENTS)
{
if (g_entities[i].inuse && g_entities[i].client && !(g_entities[i].r.svFlags & SVF_BOT) && g_entities[i].health > 0 && !(g_entities[i].s.eFlags & EF_DEAD) && g_entities[i].client->sess.sessionTeam != TEAM_SPECTATOR)
{
vec3_t checkLen;
float fCheckLen;
VectorSubtract(self->r.currentOrigin, g_entities[i].client->ps.origin, checkLen);
fCheckLen = VectorLength(checkLen);
if (fCheckLen < (minDist - 128))
{
vec3_t enAngles;
VectorSubtract(g_entities[i].client->ps.origin, self->r.currentOrigin, enAngles);
vectoangles(enAngles, enAngles);
if ((InFieldOfVision(self->s.apos.trBase, 120, enAngles) || self->s.genericenemyindex > level.time) && ExampleAnimEntClearLOS(self, g_entities[i].client->ps.origin))
{
minDist = fCheckLen;
bestIndex = i;
}
}
}
i++;
}
if (bestIndex == -1)
{
i = 0;
while (i < MAX_GENTITIES)
{
if (g_entities[i].inuse && g_entities[i].s.eType == ET_GRAPPLE && ExampleAnimEntAlignment(&g_entities[i]) != ANIMENT_ALIGNED_BAD && g_entities[i].health > 0 && !(g_entities[i].s.eFlags & EF_DEAD))
{
vec3_t checkLen;
float fCheckLen;
VectorSubtract(self->r.currentOrigin, g_entities[i].r.currentOrigin, checkLen);
fCheckLen = VectorLength(checkLen);
if (fCheckLen < (minDist - 128))
{
vec3_t enAngles;
VectorSubtract(g_entities[i].r.currentOrigin, self->r.currentOrigin, enAngles);
vectoangles(enAngles, enAngles);
if ((InFieldOfVision(self->s.apos.trBase, 120, enAngles) || self->s.genericenemyindex > level.time) && ExampleAnimEntClearLOS(self, g_entities[i].r.currentOrigin))
{
minDist = fCheckLen;
bestIndex = i;
}
}
}
i++;
}
}
i++;
}
if (bestIndex != -1)
@ -2044,6 +2402,14 @@ void ExampleAnimEntEnemyHandling(gentity_t *self, float enDist)
{
G_Sound(self, CHAN_AUTO, gRodianSound_Alert[Q_irand(0, RODIAN_ALERT_SOUNDS-1)]);
}
else if (self->watertype == ANIMENT_TYPE_JAN)
{
G_Sound(self, CHAN_AUTO, gJanSound_Alert[Q_irand(0, JAN_ALERT_SOUNDS-1)]);
}
else if (self->watertype == ANIMENT_TYPE_CUSTOM)
{
ExampleAnimEntCustomSound(self, ANIMENT_CUSTOMSOUND_ALERT);
}
}
}
@ -2099,6 +2465,24 @@ void ExampleAnimEntUpdateSelf(gentity_t *self)
}
}
if (self->bolt_Motion < MAX_CLIENTS &&
(!g_entities[self->bolt_Motion].inuse ||
!g_entities[self->bolt_Motion].client))
{
self->bolt_Motion = ENTITYNUM_NONE;
}
if (self->bolt_Motion != ENTITYNUM_NONE &&
g_entities[self->bolt_Motion].inuse &&
(g_entities[self->bolt_Motion].client || g_entities[self->bolt_Motion].s.eType == ET_GRAPPLE))
{
if (g_entities[self->bolt_Motion].health < 1 ||
(g_entities[self->bolt_Motion].s.eFlags & EF_DEAD))
{
self->bolt_Motion = ENTITYNUM_NONE;
}
}
if (gWPNum > 0)
{
if (self->bolt_Motion != ENTITYNUM_NONE &&
@ -2123,6 +2507,19 @@ void ExampleAnimEntUpdateSelf(gentity_t *self)
hasEnemyLOS = ExampleAnimEntClearLOS(self, enemyOrigin);
}
else if (self->bolt_Motion != ENTITYNUM_NONE &&
g_entities[self->bolt_Motion].inuse &&
g_entities[self->bolt_Motion].s.eType == ET_GRAPPLE)
{
vec3_t enSubVec;
VectorSubtract(self->r.currentOrigin, g_entities[self->bolt_Motion].r.currentOrigin, enSubVec);
enDist = VectorLength(enSubVec);
VectorCopy(g_entities[self->bolt_Motion].r.currentOrigin, enemyOrigin);
hasEnemyLOS = ExampleAnimEntClearLOS(self, enemyOrigin);
}
if (hasEnemyLOS && enDist < 512 && self->splashRadius < level.time)
{
@ -2165,7 +2562,14 @@ void ExampleAnimEntUpdateSelf(gentity_t *self)
if (self->bolt_Motion == ENTITYNUM_NONE)
{
runSpeed = 6;
if (ExampleAnimEntAlignment(self) == ANIMENT_ALIGNED_GOOD)
{
runSpeed = 18;
}
else
{
runSpeed = 6;
}
}
didMove = ExampleAnimEntMove(self, goalPos, runSpeed);
@ -2189,24 +2593,57 @@ void ExampleAnimEntUpdateSelf(gentity_t *self)
}
}
}
else if (self->bolt_Motion != ENTITYNUM_NONE &&
g_entities[self->bolt_Motion].inuse &&
g_entities[self->bolt_Motion].s.eType == ET_GRAPPLE)
{
if (self->speed < level.time || g_entities[self->bolt_Motion].health < 1)
{
self->bolt_Motion = ENTITYNUM_NONE;
}
else
{
if (self->bolt_Motion != originalEnemyIndex)
{
vec3_t enSubVec;
VectorSubtract(self->r.currentOrigin, g_entities[self->bolt_Motion].r.currentOrigin, enSubVec);
enDist = VectorLength(enSubVec);
}
}
}
ExampleAnimEntEnemyHandling(self, enDist);
if (self->bolt_Motion != ENTITYNUM_NONE &&
g_entities[self->bolt_Motion].inuse &&
g_entities[self->bolt_Motion].client)
(g_entities[self->bolt_Motion].client || g_entities[self->bolt_Motion].s.eType == ET_GRAPPLE))
{
vec3_t enOrigin;
if (g_entities[self->bolt_Motion].client)
{
VectorCopy(g_entities[self->bolt_Motion].client->ps.origin, enOrigin);
}
else
{
VectorCopy(g_entities[self->bolt_Motion].r.currentOrigin, enOrigin);
}
if (originalEnemyIndex != self->bolt_Motion)
{
VectorCopy(g_entities[self->bolt_Motion].client->ps.origin, enemyOrigin);
VectorCopy(enOrigin, enemyOrigin);
if (g_entities[self->bolt_Motion].client->pers.cmd.upmove < 0)
if (g_entities[self->bolt_Motion].client)
{
enemyOrigin[2] -= 8;
}
else
{
enemyOrigin[2] += 8;
if (g_entities[self->bolt_Motion].client->pers.cmd.upmove < 0)
{
enemyOrigin[2] -= 8;
}
else
{
enemyOrigin[2] += 8;
}
}
hasEnemyLOS = ExampleAnimEntClearLOS(self, enemyOrigin);
@ -2219,7 +2656,7 @@ void ExampleAnimEntUpdateSelf(gentity_t *self)
vec3_t selfAimOrg;
vec3_t myZeroPitchAngles;
VectorCopy(g_entities[self->bolt_Motion].client->ps.origin, enAimOrg);
VectorCopy(enOrigin, enAimOrg);
VectorCopy(self->r.currentOrigin, selfAimOrg);
enAimOrg[2] = selfAimOrg[2];
@ -2271,8 +2708,8 @@ void ExampleAnimEntUpdateSelf(gentity_t *self)
if (didMove == 1)
{
if (self->bolt_Motion == ENTITYNUM_NONE)
{
if (self->bolt_Motion == ENTITYNUM_NONE && ExampleAnimEntAlignment(self) != ANIMENT_ALIGNED_GOOD)
{ //Good guys are always on "alert"
self->s.torsoAnim = BOTH_WALK1;
self->s.legsAnim = BOTH_WALK1;
}
@ -2306,7 +2743,7 @@ void ExampleAnimEntUpdateSelf(gentity_t *self)
VectorCopy(preserveAngles, self->s.apos.trBase);
}
void G_SpawnExampleAnimEnt(vec3_t pos, int aeType)
void G_SpawnExampleAnimEnt(vec3_t pos, int aeType, animentCustomInfo_t *aeInfo)
{
gentity_t *animEnt;
vec3_t playerMins;
@ -2355,11 +2792,37 @@ void G_SpawnExampleAnimEnt(vec3_t pos, int aeType)
gRodianSound_Alert[4] = G_SoundIndex("sound/chars/rodian1/misc/detected5");
}
}
else if (aeType == ANIMENT_TYPE_JAN)
{
if (!gJanSound_Pain[0])
{
gJanSound_Pain[0] = G_SoundIndex("sound/chars/jan/misc/pain25");
gJanSound_Pain[1] = G_SoundIndex("sound/chars/jan/misc/pain50");
gJanSound_Pain[2] = G_SoundIndex("sound/chars/jan/misc/pain75");
gJanSound_Pain[3] = G_SoundIndex("sound/chars/jan/misc/pain100");
gJanSound_Death[0] = G_SoundIndex("sound/chars/jan/misc/death1");
gJanSound_Death[1] = G_SoundIndex("sound/chars/jan/misc/death2");
gJanSound_Death[2] = G_SoundIndex("sound/chars/jan/misc/death3");
gJanSound_Alert[0] = G_SoundIndex("sound/chars/jan/misc/detected1");
gJanSound_Alert[1] = G_SoundIndex("sound/chars/jan/misc/detected2");
gJanSound_Alert[2] = G_SoundIndex("sound/chars/jan/misc/detected3");
gJanSound_Alert[3] = G_SoundIndex("sound/chars/jan/misc/detected4");
gJanSound_Alert[4] = G_SoundIndex("sound/chars/jan/misc/detected5");
}
}
animEnt = G_Spawn();
animEnt->watertype = aeType; //set the animent type
if (aeType == ANIMENT_TYPE_CUSTOM && aeInfo)
{
ExampleAnimEntCustomDataEntry(animEnt, aeInfo->aeAlignment, aeInfo->aeWeapon, aeInfo->modelPath, aeInfo->soundPath);
AnimEntCustomSoundPrecache(aeInfo);
}
animEnt->s.eType = ET_GRAPPLE; //ET_GRAPPLE is the reserved special type for G2 anim ents.
if (animEnt->watertype == ANIMENT_TYPE_STORMTROOPER)
@ -2370,6 +2833,23 @@ void G_SpawnExampleAnimEnt(vec3_t pos, int aeType)
{
animEnt->s.modelindex = G_ModelIndex( "models/players/rodian/model.glm" );
}
else if (animEnt->watertype == ANIMENT_TYPE_JAN)
{
animEnt->s.modelindex = G_ModelIndex( "models/players/jan/model.glm" );
}
else if (animEnt->watertype == ANIMENT_TYPE_CUSTOM)
{
animentCustomInfo_t *aeInfo = ExampleAnimEntCustomData(animEnt);
if (aeInfo)
{
animEnt->s.modelindex = G_ModelIndex(aeInfo->modelPath);
}
else
{
animEnt->s.modelindex = G_ModelIndex( "models/players/stormtrooper/model.glm" );
}
}
else
{
G_Error("Unknown AnimEnt type!\n");
@ -2385,6 +2865,23 @@ void G_SpawnExampleAnimEnt(vec3_t pos, int aeType)
{
animEnt->s.weapon = WP_DISRUPTOR; //These guys get disruptors instead of blasters.
}
else if (animEnt->watertype == ANIMENT_TYPE_JAN)
{
animEnt->s.weapon = WP_BLASTER;
}
else if (animEnt->watertype == ANIMENT_TYPE_CUSTOM)
{
animentCustomInfo_t *aeInfo = ExampleAnimEntCustomData(animEnt);
if (aeInfo)
{
animEnt->s.weapon = aeInfo->aeWeapon;
}
else
{
animEnt->s.weapon = WP_BLASTER;
}
}
animEnt->s.modelGhoul2 = 1; //Deal with it like any other ghoul2 ent, as far as killing instances.
@ -2433,7 +2930,7 @@ qboolean gEscaping = qfalse;
int gEscapeTime = 0;
#ifdef ANIMENT_SPAWNER
int AESpawner_CountAnimEnts(void)
int AESpawner_CountAnimEnts(gentity_t *spawner, qboolean onlySameType)
{
int i = 0;
int count = 0;
@ -2442,7 +2939,27 @@ int AESpawner_CountAnimEnts(void)
{
if (g_entities[i].inuse && g_entities[i].s.eType == ET_GRAPPLE)
{
count++;
if (!onlySameType)
{
count++;
}
else
{
if (spawner->watertype == g_entities[i].watertype)
{
if (spawner->watertype == ANIMENT_TYPE_CUSTOM)
{
if (spawner->waterlevel == g_entities[i].waterlevel)
{ //only count it if it's the same custom type template, indicated by equal "waterlevel" value.
count++;
}
}
else
{
count++;
}
}
}
}
i++;
}
@ -2500,6 +3017,7 @@ qboolean AESpawner_PassAnimEntPVSCheck(gentity_t *ent)
void AESpawner_Think(gentity_t *ent)
{
int animEntCount;
animentCustomInfo_t *aeInfo = NULL;
if (gBotEdit)
{
@ -2513,7 +3031,13 @@ void AESpawner_Think(gentity_t *ent)
}
else
{
animEntCount = AESpawner_CountAnimEnts();
qboolean onlySameType = qfalse;
if (ent->bolt_RLeg)
{
onlySameType = qtrue;
}
animEntCount = AESpawner_CountAnimEnts(ent, onlySameType);
}
if (animEntCount < ent->bolt_LLeg)
@ -2533,7 +3057,11 @@ void AESpawner_Think(gentity_t *ent)
{
if (AESpawner_PassAnimEntPVSCheck(ent))
{
G_SpawnExampleAnimEnt(ent->s.origin, ent->watertype);
if (ent->watertype == ANIMENT_TYPE_CUSTOM)
{
aeInfo = ExampleAnimEntCustomData(ent); //we can get this info from the spawner, because it has its waterlevel set too.
}
G_SpawnExampleAnimEnt(ent->s.origin, ent->watertype, aeInfo);
}
}
}
@ -2560,6 +3088,9 @@ void SP_misc_animent_spawner(gentity_t *ent)
//0 is unlimited, but that could cause horrible disaster.
G_SpawnInt( "spawntype", "0", &ent->watertype);
//Spawn type. 0 is stormtrooper, 1 is rodian.
G_SpawnInt( "sametype", "1", &ent->bolt_RLeg);
//If 1, only counts other animates of the same type for deciding whether or not to spawn (as opposed to all types).
//Default is 1.
//Just precache the assets now
if (ent->watertype == ANIMENT_TYPE_STORMTROOPER)
@ -2600,6 +3131,52 @@ void SP_misc_animent_spawner(gentity_t *ent)
G_ModelIndex( "models/players/rodian/model.glm" );
}
else if (ent->watertype == ANIMENT_TYPE_JAN)
{
gJanSound_Pain[0] = G_SoundIndex("sound/chars/jan/misc/pain25");
gJanSound_Pain[1] = G_SoundIndex("sound/chars/jan/misc/pain50");
gJanSound_Pain[2] = G_SoundIndex("sound/chars/jan/misc/pain75");
gJanSound_Pain[3] = G_SoundIndex("sound/chars/jan/misc/pain100");
gJanSound_Death[0] = G_SoundIndex("sound/chars/jan/misc/death1");
gJanSound_Death[1] = G_SoundIndex("sound/chars/jan/misc/death2");
gJanSound_Death[2] = G_SoundIndex("sound/chars/jan/misc/death3");
gJanSound_Alert[0] = G_SoundIndex("sound/chars/jan/misc/detected1");
gJanSound_Alert[1] = G_SoundIndex("sound/chars/jan/misc/detected2");
gJanSound_Alert[2] = G_SoundIndex("sound/chars/jan/misc/detected3");
gJanSound_Alert[3] = G_SoundIndex("sound/chars/jan/misc/detected4");
gJanSound_Alert[4] = G_SoundIndex("sound/chars/jan/misc/detected5");
G_ModelIndex( "models/players/jan/model.glm" );
}
else if (ent->watertype == ANIMENT_TYPE_CUSTOM)
{
int alignment = 1;
int weapon = 3;
char *model;
char *soundpath;
animentCustomInfo_t *aeInfo;
G_SpawnInt( "ae_aligned", "1", &alignment );
//Alignedment - 1 is bad, 2 is good.
G_SpawnInt( "ae_weapon", "3", &weapon);
//Weapon - Same values as normal weapons.
G_SpawnString( "ae_model", "models/players/stormtrooper/model.glm", &model);
//Model to use
G_SpawnString( "ae_soundpath", "sound/chars/jan/misc", &soundpath);
//Sound path to use
ExampleAnimEntCustomDataEntry(ent, alignment, weapon, model, soundpath);
aeInfo = ExampleAnimEntCustomData(ent);
if (aeInfo)
{
AnimEntCustomSoundPrecache(aeInfo);
G_ModelIndex( aeInfo->modelPath );
}
}
ent->think = AESpawner_Think;
ent->nextthink = level.time + Q_irand(50, 500);
@ -2689,6 +3266,28 @@ void SP_target_escapetrig(gentity_t *ent)
void G_CreateExampleAnimEnt(gentity_t *ent)
{
vec3_t fwd, fwdPos;
animentCustomInfo_t aeInfo;
char arg[MAX_STRING_CHARS];
int iArg = 0;
int argNum = trap_Argc();
memset(&aeInfo, 0, sizeof(aeInfo));
if (argNum > 1)
{
trap_Argv( 1, arg, sizeof( arg ) );
iArg = atoi(arg);
if (iArg < 0)
{
iArg = 0;
}
if (iArg >= MAX_ANIMENTS)
{
iArg = MAX_ANIMENTS-1;
}
}
AngleVectors(ent->client->ps.viewangles, fwd, 0, 0);
@ -2696,7 +3295,52 @@ void G_CreateExampleAnimEnt(gentity_t *ent)
fwdPos[1] = ent->client->ps.origin[1] + fwd[1]*128;
fwdPos[2] = ent->client->ps.origin[2] + fwd[2]*128;
G_SpawnExampleAnimEnt(fwdPos, 0);
if (iArg == ANIMENT_TYPE_CUSTOM)
{
char arg2[MAX_STRING_CHARS];
if (argNum > 2)
{
trap_Argv( 2, arg, sizeof( arg ) );
aeInfo.aeAlignment = atoi(arg);
}
else
{
aeInfo.aeAlignment = ANIMENT_ALIGNED_BAD;
}
if (argNum > 3)
{
trap_Argv( 3, arg, sizeof( arg ) );
aeInfo.aeWeapon = atoi(arg);
}
else
{
aeInfo.aeWeapon = WP_BRYAR_PISTOL;
}
if (argNum > 4)
{
trap_Argv( 4, arg, sizeof( arg ) );
aeInfo.modelPath = arg;
}
else
{
aeInfo.modelPath = "models/players/stormtrooper/model.glm";
}
if (argNum > 5)
{
trap_Argv( 5, arg2, sizeof( arg2 ) );
aeInfo.soundPath = arg2;
}
else
{
aeInfo.soundPath = "sound/chars/jan/misc";
}
}
G_SpawnExampleAnimEnt(fwdPos, iArg, &aeInfo);
}
//rww - here ends the main example g2animent stuff

View file

@ -190,7 +190,23 @@ qboolean OnSameTeam( gentity_t *ent1, gentity_t *ent2 ) {
if (g_gametype.integer == GT_SINGLE_PLAYER)
{
return qtrue;
qboolean ent1IsBot = qfalse;
qboolean ent2IsBot = qfalse;
if (ent1->r.svFlags & SVF_BOT)
{
ent1IsBot = qtrue;
}
if (ent2->r.svFlags & SVF_BOT)
{
ent2IsBot = qtrue;
}
if ((ent1IsBot && ent2IsBot) || (!ent1IsBot && !ent2IsBot))
{
return qtrue;
}
return qfalse;
}
if ( g_gametype.integer < GT_TEAM ) {

View file

@ -816,7 +816,14 @@ static void WP_BowcasterMainFire( gentity_t *ent )
gentity_t *missile;
int i;
count = ( level.time - ent->client->ps.weaponChargeTime ) / BOWCASTER_CHARGE_UNIT;
if (!ent->client)
{
count = 1;
}
else
{
count = ( level.time - ent->client->ps.weaponChargeTime ) / BOWCASTER_CHARGE_UNIT;
}
if ( count < 1 )
{
@ -2524,8 +2531,16 @@ void WP_FireStunBaton( gentity_t *ent, qboolean alt_fire )
vec3_t mins, maxs, end;
vec3_t muzzleStun;
VectorCopy(ent->client->ps.origin, muzzleStun);
muzzleStun[2] += ent->client->ps.viewheight-6;
if (!ent->client)
{
VectorCopy(ent->r.currentOrigin, muzzleStun);
muzzleStun[2] += 8;
}
else
{
VectorCopy(ent->client->ps.origin, muzzleStun);
muzzleStun[2] += ent->client->ps.viewheight-6;
}
muzzleStun[0] += forward[0]*20;
muzzleStun[1] += forward[1]*20;
@ -2557,7 +2572,8 @@ void WP_FireStunBaton( gentity_t *ent, qboolean alt_fire )
return;
}
if (ent->client->ps.duelInProgress &&
if (ent->client &&
ent->client->ps.duelInProgress &&
ent->client->ps.duelIndex != tr_ent->s.number)
{
return;

View file

@ -672,7 +672,7 @@ extern vec4_t colorDkBlue;
#define Q_COLOR_ESCAPE '^'
// you MUST have the last bit on here about colour strings being less than 7 or taiwanese strings register as colour!!!!
#define Q_IsColorString(p) ( p && *(p) == Q_COLOR_ESCAPE && *((p)+1) && *((p)+1) != Q_COLOR_ESCAPE && *((p)+1) <= '7' )
#define Q_IsColorString(p) ( p && *(p) == Q_COLOR_ESCAPE && *((p)+1) && *((p)+1) != Q_COLOR_ESCAPE && *((p)+1) <= '7' && *((p)+1) >= '0' )
#define COLOR_BLACK '0'

View file

@ -12,8 +12,8 @@
#define CONTENTS_WATER 0x00000004
#define CONTENTS_FOG 0x00000008
#define CONTENTS_PLAYERCLIP 0x00000010
#define CONTENTS_MONSTERCLIP 0x00000020
#define CONTENTS_BOTCLIP 0x00000040
#define CONTENTS_MONSTERCLIP 0x00000020 // Physically block bots
#define CONTENTS_BOTCLIP 0x00000040 // A hint for bots - do not enter this brush by navigation (if possible)
#define CONTENTS_SHOTCLIP 0x00000080
#define CONTENTS_BODY 0x00000100 // should never be on a brush, only in game
#define CONTENTS_CORPSE 0x00000200 // should never be on a brush, only in game

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1089,7 +1089,8 @@ static bool G2_RadiusTracePolys( const mdxmSurface_t *surface, const vec3_t rayS
{
// we hit a triangle, so init a collision record...
//
for (int i=0; i<MAX_G2_COLLISIONS;i++)
int i=0;
for (i=0; i<MAX_G2_COLLISIONS;i++)
{
if (collRecMap[i].mEntityNum == -1)
{

53
CODE-mp/jk2mp-SDK.dsw Normal file
View file

@ -0,0 +1,53 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "JK2cgame"=".\cgame\JK2_cgame.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "JK2game"=".\game\JK2_game.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "ui"=".\ui\ui.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

BIN
CODE-mp/jk2mp-SDK.opt Normal file

Binary file not shown.

Binary file not shown.

View file

@ -3,6 +3,6 @@
// Current version of the multi player game
#define Q3_VERSION "JK2MP: v1.03"
#define Q3_VERSION "JK2MP: v1.04"
//end

View file

@ -321,8 +321,8 @@ qboolean Netchan_Process( netchan_t *chan, msg_t *msg ) {
// read the fragment information
if ( fragmented ) {
fragmentStart = MSG_ReadShort( msg );
fragmentLength = MSG_ReadShort( msg );
fragmentStart = (unsigned short)MSG_ReadShort( msg );
fragmentLength = (unsigned short)MSG_ReadShort( msg );
} else {
fragmentStart = 0; // stop warning message
fragmentLength = 0;
@ -425,10 +425,10 @@ qboolean Netchan_Process( netchan_t *chan, msg_t *msg ) {
return qfalse;
}
if ( chan->fragmentLength > msg->maxsize ) {
if ( chan->fragmentLength+4 > msg->maxsize ) {
Com_Printf( "%s:fragmentLength %i > msg->maxsize\n"
, NET_AdrToString (chan->remoteAddress ),
chan->fragmentLength );
chan->fragmentLength+4 );
return qfalse;
}
@ -437,10 +437,6 @@ qboolean Netchan_Process( netchan_t *chan, msg_t *msg ) {
// make sure the sequence number is still there
*(int *)msg->data = LittleLong( sequence );
if ( chan->fragmentLength + 4 > MAX_MSGLEN )
{
Com_Error( ERR_DROP, "Netchan_Process: length = %i",chan->fragmentLength + 4);
}
Com_Memcpy( msg->data + 4, chan->fragmentBuffer, chan->fragmentLength );
msg->cursize = chan->fragmentLength + 4;
chan->fragmentLength = 0;

View file

@ -196,7 +196,8 @@ PROTOCOL
==============================================================
*/
#define PROTOCOL_VERSION 15
//v1.03 #define PROTOCOL_VERSION 15
#define PROTOCOL_VERSION 16 //v1.04
#define UPDATE_SERVER_NAME "updatejk2.ravensoft.com"
#define MASTER_SERVER_NAME "masterjk2.ravensoft.com"

View file

@ -671,6 +671,7 @@ static void SV_Status_f( void )
const char *s;
int ping;
char state[32];
qboolean avoidTruncation = qfalse;
// make sure server is running
if ( !com_sv_running->integer )
@ -679,6 +680,14 @@ static void SV_Status_f( void )
return;
}
if ( Cmd_Argc() > 1 )
{
if (!Q_stricmp("notrunc", Cmd_Argv(1)))
{
avoidTruncation = qtrue;
}
}
Com_Printf ("map: %s\n", sv_mapname->string );
Com_Printf ("num score ping name lastmsg address qport rate\n");
@ -706,16 +715,33 @@ static void SV_Status_f( void )
ps = SV_GameClientNum( i );
s = NET_AdrToString( cl->netchan.remoteAddress );
Com_Printf ("%3i %5i %s %-15.15s %7i %21s %5i %5i\n",
i,
ps->persistant[PERS_SCORE],
state,
cl->name,
svs.time - cl->lastPacketTime,
s,
cl->netchan.qport,
cl->rate
);
if (!avoidTruncation)
{
Com_Printf ("%3i %5i %s %-15.15s %7i %21s %5i %5i\n",
i,
ps->persistant[PERS_SCORE],
state,
cl->name,
svs.time - cl->lastPacketTime,
s,
cl->netchan.qport,
cl->rate
);
}
else
{
Com_Printf ("%3i %5i %s %s %7i %21s %5i %5i\n",
i,
ps->persistant[PERS_SCORE],
state,
cl->name,
svs.time - cl->lastPacketTime,
s,
cl->netchan.qport,
cl->rate
);
}
}
Com_Printf ("\n");
}

View file

@ -756,7 +756,7 @@ void SV_Frame( int msec ) {
if (!com_dedicated->integer) SV_BotFrame( svs.time + sv.timeResidual );
if ( com_dedicated->integer && sv.timeResidual < frameMsec ) {
if ( com_dedicated->integer && sv.timeResidual < frameMsec && (!com_timescale || com_timescale->value >= 1) ) {
// NET_Sleep will give the OS time slices until either get a packet
// or time enough for a server frame has gone by
NET_Sleep(frameMsec - sv.timeResidual);

View file

@ -20,8 +20,6 @@ set cc=lcc -DQ3_VM -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\
@if errorlevel 1 goto quit
%cc% ../ui_force.c
@if errorlevel 1 goto quit
%cc% ../ui_util.c
@if errorlevel 1 goto quit
%cc% ../ui_shared.c
@if errorlevel 1 goto quit
%cc% ../ui_gameinfo.c

View file

@ -172,10 +172,6 @@ SOURCE=.\ui_shared.c
SOURCE=.\ui_syscalls.c
# End Source File
# Begin Source File
SOURCE=.\ui_util.c
# End Source File
# End Group
# Begin Group "Header Files"

View file

@ -3,7 +3,6 @@ ui_main
..\ui_syscalls
ui_atoms
ui_force
ui_util
ui_shared
ui_gameinfo
bg_misc

View file

@ -777,6 +777,8 @@ typedef struct {
char teamNames[MAX_CLIENTS][MAX_NAME_LENGTH];
int teamClientNums[MAX_CLIENTS];
int playerIndexes[MAX_CLIENTS]; //so we can vote-kick by index
int mapCount;
mapInfo mapList[MAX_MAPS];

View file

@ -1736,20 +1736,22 @@ void UpdateForceStatus()
}
// Take the current team and force a skin color based on it.
switch((int)(trap_Cvar_VariableValue("ui_myteam")))
{
case TEAM_RED:
uiSkinColor = TEAM_RED;
uiInfo.effectsColor = SABER_RED;
break;
case TEAM_BLUE:
uiSkinColor = TEAM_BLUE;
uiInfo.effectsColor = SABER_BLUE;
break;
default:
uiSkinColor = TEAM_FREE;
break;
if ( !UI_TrueJediEnabled() )
{// Take the current team and force a skin color based on it.
switch((int)(trap_Cvar_VariableValue("ui_myteam")))
{
case TEAM_RED:
uiSkinColor = TEAM_RED;
uiInfo.effectsColor = SABER_RED;
break;
case TEAM_BLUE:
uiSkinColor = TEAM_BLUE;
uiInfo.effectsColor = SABER_BLUE;
break;
default:
uiSkinColor = TEAM_FREE;
break;
}
}
}
@ -2373,6 +2375,7 @@ static void UI_BuildPlayerList() {
if (info[0]) {
Q_strncpyz( uiInfo.playerNames[uiInfo.playerCount], Info_ValueForKey( info, "n" ), MAX_NAME_LENGTH );
Q_CleanStr( uiInfo.playerNames[uiInfo.playerCount] );
uiInfo.playerIndexes[uiInfo.playerCount] = n;
uiInfo.playerCount++;
team2 = atoi(Info_ValueForKey(info, "t"));
if (team2 == team && n != uiInfo.playerNumber) {
@ -2989,32 +2992,34 @@ static qboolean UI_Handicap_HandleKey(int flags, float *special, int key) {
}
static qboolean UI_Effects_HandleKey(int flags, float *special, int key) {
if (key == A_MOUSE1 || key == A_MOUSE2 || key == A_ENTER || key == A_KP_ENTER) {
if (key == A_MOUSE1 || key == A_MOUSE2 || key == A_ENTER || key == A_KP_ENTER) {
int team = (int)(trap_Cvar_VariableValue("ui_myteam"));
if (team == TEAM_RED || team==TEAM_BLUE)
{
return qfalse;
}
if ( !UI_TrueJediEnabled() )
{
int team = (int)(trap_Cvar_VariableValue("ui_myteam"));
if (team == TEAM_RED || team==TEAM_BLUE)
{
return qfalse;
}
}
if (key == A_MOUSE2) {
uiInfo.effectsColor--;
uiInfo.effectsColor--;
} else {
uiInfo.effectsColor++;
uiInfo.effectsColor++;
}
if( uiInfo.effectsColor > 5 ) {
uiInfo.effectsColor = 0;
if( uiInfo.effectsColor > 5 ) {
uiInfo.effectsColor = 0;
} else if (uiInfo.effectsColor < 0) {
uiInfo.effectsColor = 5;
uiInfo.effectsColor = 5;
}
trap_Cvar_SetValue( "color1", /*uitogamecode[uiInfo.effectsColor]*/uiInfo.effectsColor );
return qtrue;
}
return qfalse;
trap_Cvar_SetValue( "color1", /*uitogamecode[uiInfo.effectsColor]*/uiInfo.effectsColor );
return qtrue;
}
return qfalse;
}
static qboolean UI_ClanName_HandleKey(int flags, float *special, int key) {
@ -4419,7 +4424,8 @@ static void UI_RunMenuScript(char **args)
}
} else if (Q_stricmp(name, "voteKick") == 0) {
if (uiInfo.playerIndex >= 0 && uiInfo.playerIndex < uiInfo.playerCount) {
trap_Cmd_ExecuteText( EXEC_APPEND, va("callvote kick \"%s\"\n",uiInfo.playerNames[uiInfo.playerIndex]) );
//trap_Cmd_ExecuteText( EXEC_APPEND, va("callvote kick \"%s\"\n",uiInfo.playerNames[uiInfo.playerIndex]) );
trap_Cmd_ExecuteText( EXEC_APPEND, va("callvote clientkick \"%i\"\n",uiInfo.playerIndexes[uiInfo.playerIndex]) );
}
} else if (Q_stricmp(name, "voteGame") == 0) {
if (ui_netGameType.integer >= 0 && ui_netGameType.integer < uiInfo.numGameTypes) {
@ -6922,7 +6928,7 @@ void UI_DrawConnectScreen( qboolean overlay ) {
//UI_DrawProportionalString( 320, 96, "Press Esc to abort", UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, menu_text_color );
// display global MOTD at bottom
Text_PaintCenter(centerPoint, 600, scale, colorWhite, Info_ValueForKey( cstate.updateInfoString, "motd" ), 0, FONT_MEDIUM);
Text_PaintCenter(centerPoint, 425, scale, colorWhite, Info_ValueForKey( cstate.updateInfoString, "motd" ), 0, FONT_MEDIUM);
// print any server info (server full, bad version, etc)
if ( cstate.connState < CA_CONNECTED ) {
Text_PaintCenter(centerPoint, yStart + 176, scale, colorWhite, cstate.messageString, 0, FONT_MEDIUM);
@ -7392,10 +7398,10 @@ static void UI_StartServerRefresh(qboolean full)
ptr = UI_Cvar_VariableString("debug_protocol");
if (strlen(ptr)) {
trap_Cmd_ExecuteText( EXEC_NOW, va( "globalservers %d %s full empty\n", i, ptr));
trap_Cmd_ExecuteText( EXEC_NOW, va( "globalservers %d %s\n", i, ptr));
}
else {
trap_Cmd_ExecuteText( EXEC_NOW, va( "globalservers %d %d full empty\n", i, (int)trap_Cvar_VariableValue( "protocol" ) ) );
trap_Cmd_ExecuteText( EXEC_NOW, va( "globalservers %d %d\n", i, (int)trap_Cvar_VariableValue( "protocol" ) ) );
}
}
}

View file

@ -4087,13 +4087,13 @@ void BindingFromName(const char *cvar) {
break;
}
DC->keynumToStringBuf( b1, g_nameBind1, 32 );
Q_strupr(g_nameBind1);
// do NOT do this or it corrupts asian text!!! Q_strupr(g_nameBind1);
b2 = g_bindings[i].bind2;
if (b2 != -1)
{
DC->keynumToStringBuf( b2, g_nameBind2, 32 );
Q_strupr(g_nameBind2);
// do NOT do this or it corrupts asian text!!! Q_strupr(g_nameBind2);
trap_SP_GetStringTextString("MENUS3_KEYBIND_OR",sOR, sizeof(sOR));
@ -4634,6 +4634,7 @@ void Item_ListBox_Paint(itemDef_t *item) {
{
imageStartX = listPtr->columnInfo[j+1].pos;
}
DC->setColor( NULL );
if (optionalImage3 >= 0) {
DC->drawHandlePic(imageStartX - listPtr->elementHeight*3, y+2, listPtr->elementHeight, listPtr->elementHeight, optionalImage3);
}

View file

@ -5,4 +5,7 @@
//
// memory, string alloc
void RichIsGettingTiredOfEmptyFileVMCompilerWarnings()
{
int andUnderstandablySo = 0;
}

View file

@ -95,12 +95,12 @@ DLL_ONLY=false
# DEBUG_CFLAGS=$(BASE_CFLAGS) -g -Wall -Werror -O
ifeq ($(ARCH),axp)
CC=pgcc
RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O6 -ffast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations
RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O2 -unroll
else
ifeq ($(ARCH),ppc)
NEWPGCC=/loki/global/ppc/bin/gcc
CC=$(NEWPGCC)
RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O6 -fomit-frame-pointer -pipe -ffast-math -malign-loops=2 -malign-jumps=2 -malign-functions=2 -fno-strict-aliasing -fstrength-reduce
RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O2 -pipe -unroll
else
#NEWPGCC=/usr/local/gcc-2.95.2/bin/gcc # bk001205
#NEWPGCC=/loki/global/x86/bin/gcc
@ -112,7 +112,7 @@ DLL_ONLY=false
# TTimo: legacy RELEASE_CFLAGS
# NOTE: the -fomit-frame-pointer option leads to an unstable binary on my test box if it was built on the main box
# but building on the Mdk 7.2 baseline seems to work
RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O6 -mcpu=pentiumpro -march=pentium -fomit-frame-pointer -pipe -ffast-math -malign-loops=2 -malign-jumps=2 -malign-functions=2 -fno-strict-aliasing -fstrength-reduce
RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O2 -unroll -tpp6
# TTimo: use this for building on P3 gcc 2.95.3 libc2.2 for all targets (experimental! -fomit-fram-pointer removed)
# RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O6 -mcpu=pentiumpro -march=pentium -pipe -ffast-math -malign-loops=2 -malign-jumps=2 -malign-functions=2 -fno-strict-aliasing -fstrength-reduce
endif
@ -129,7 +129,7 @@ DLL_ONLY=false
THREAD_LDFLAGS=-lpthread
#LDFLAGS=/opt/sxl/lib/sxlgcc3.a -lpthread -ldl -lm -lstdc++ -static -Wl --gc-sections
LDFLAGS=-ldl -lm -lstdc++ -static
LDFLAGS=-ldl -lm -static
GLLDFLAGS=-L/usr/X11R6/lib -L$(MESADIR)/lib -lX11 -lXext -lXxf86dga -lXxf86vm
TARGETS=\
@ -213,7 +213,6 @@ Q3DOBJ = \
$(B)/ded/cm_polylib.o \
$(B)/ded/cm_test.o \
$(B)/ded/cm_trace.o \
$(B)/ded/cm_shader.o \
$(B)/ded/cmd.o \
$(B)/ded/common.o \
$(B)/ded/cvar.o \

View file

@ -254,7 +254,7 @@ qboolean Sys_IsLANAddress (netadr_t adr) {
// choose which comparison to use based on the class of the address being tested
// any local adresses of a different class than the address being tested will fail based on the first byte
/*
// Class A
if( (adr.ip[0] & 0x80) == 0x00 ) {
for ( i = 0 ; i < numIP ; i++ ) {
@ -279,7 +279,8 @@ qboolean Sys_IsLANAddress (netadr_t adr) {
}
return qfalse;
}
*/
//we only look at class C since ISPs and Universities are using class A but we don't want to consider them on the same LAN.
// Class C
for ( i = 0 ; i < numIP ; i++ ) {
if( adr.ip[0] == localIP[i][0] && adr.ip[1] == localIP[i][1] && adr.ip[2] == localIP[i][2] ) {
@ -412,6 +413,9 @@ void NET_GetLocalAddress( void ) {
int ip;
int n;
// Set this early so we can just return if there is an error
numIP = 0;
if ( gethostname( hostname, 256 ) == -1 ) {
return;
}
@ -431,14 +435,14 @@ void NET_GetLocalAddress( void ) {
return;
}
numIP = 0;
while( ( p = hostInfo->h_addr_list[numIP++] ) != NULL && numIP < MAX_IPS ) {
while( ( p = hostInfo->h_addr_list[numIP] ) != NULL && numIP < MAX_IPS ) {
ip = ntohl( *(int *)p );
localIP[ numIP ][0] = p[0];
localIP[ numIP ][1] = p[1];
localIP[ numIP ][2] = p[2];
localIP[ numIP ][3] = p[3];
Com_Printf( "IP: %i.%i.%i.%i\n", ( ip >> 24 ) & 0xff, ( ip >> 16 ) & 0xff, ( ip >> 8 ) & 0xff, ip & 0xff );
numIP++;
}
}
#endif

View file

@ -397,6 +397,7 @@ qboolean Sys_IsLANAddress( netadr_t adr ) {
return qtrue;
}
/*
// Class A
if( (adr.ip[0] & 0x80) == 0x00 ) {
for ( i = 0 ; i < numIP ; i++ ) {
@ -421,6 +422,8 @@ qboolean Sys_IsLANAddress( netadr_t adr ) {
}
return qfalse;
}
*/
//we only look at class C since ISPs and Universities are using class A but we don't want to consider them on the same LAN.
// Class C
for ( i = 0 ; i < numIP ; i++ ) {
@ -707,6 +710,9 @@ void NET_GetLocalAddress( void ) {
int ip;
int n;
// Set this early so we can just return if there is an error
numIP = 0;
if( gethostname( hostname, 256 ) == SOCKET_ERROR ) {
error = WSAGetLastError();
return;
@ -728,7 +734,6 @@ void NET_GetLocalAddress( void ) {
return;
}
numIP = 0;
while( ( p = hostInfo->h_addr_list[numIP] ) != NULL && numIP < MAX_IPS ) {
ip = ntohl( *(int *)p );
localIP[ numIP ][0] = p[0];