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,8 +208,26 @@ to a fixed color.
Coordinates are at 640 by 480 virtual resolution 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, void CG_DrawStringExt( int x, int y, const char *string, const float *setColor,
qboolean forceColor, qboolean shadow, int charWidth, int charHeight, int maxChars ) qboolean forceColor, qboolean shadow, int charWidth, int charHeight, int maxChars )
{
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; vec4_t color;
const char *s; const char *s;
@ -253,6 +271,7 @@ void CG_DrawStringExt( int x, int y, const char *string, const float *setColor,
} }
trap_R_SetColor( NULL ); trap_R_SetColor( NULL );
} }
}
void CG_DrawBigString( int x, int y, const char *s, float alpha ) { void CG_DrawBigString( int x, int y, const char *s, float alpha ) {
float color[4]; float color[4];

View file

@ -524,7 +524,7 @@ static void CG_General( centity_t *cent ) {
} }
else else
{ {
clEnt = &cg_entities[cent->currentState.modelindex2]; clEnt = &cg_entities[cent->currentState.otherEntityNum2];
} }
if (!dismember_settings) if (!dismember_settings)
@ -793,6 +793,10 @@ static void CG_General( centity_t *cent ) {
trap_G2API_GiveMeVectorFromMatrix(&matrix, ORIGIN, boltOrg); trap_G2API_GiveMeVectorFromMatrix(&matrix, ORIGIN, boltOrg);
trap_G2API_GiveMeVectorFromMatrix(&matrix, NEGATIVE_Y, boltAng); 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); trap_FX_PlayEffectID(trap_FX_RegisterEffect("blaster/smoke_bolton"), boltOrg, boltAng);
cent->trailTime = cg.time + 400; 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, // local player sounds are triggered in CG_CheckLocalSounds,
// so ignore events on the player // so ignore events on the player
DEBUGNAME("EV_PAIN"); 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 ); CG_PainEvent( cent, es->eventParm );
} }
break; break;

View file

@ -167,6 +167,17 @@ void CG_DrawInformation( void ) {
y += iPropHeight; 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 // some extra space after hostname and motd
y += 10; y += 10;
} }

View file

@ -1313,6 +1313,11 @@ typedef struct {
int capturelimit; int capturelimit;
int timelimit; int timelimit;
int maxclients; int maxclients;
qboolean needpass;
qboolean jediVmerc;
int wDisable;
int fDisable;
char mapname[MAX_QPATH]; char mapname[MAX_QPATH];
char redTeam[MAX_QPATH]; char redTeam[MAX_QPATH];
char blueTeam[MAX_QPATH]; char blueTeam[MAX_QPATH];
@ -1456,10 +1461,17 @@ extern vmCvar_t cg_zoomFov;
extern vmCvar_t cg_swingAngles; extern vmCvar_t cg_swingAngles;
extern vmCvar_t cg_oldPainSounds;
#ifdef G2_COLLISION_ENABLED #ifdef G2_COLLISION_ENABLED
extern vmCvar_t cg_saberModelTraceEffect; extern vmCvar_t cg_saberModelTraceEffect;
#endif #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_saberContact;
extern vmCvar_t cg_saberTrail; extern vmCvar_t cg_saberTrail;

View file

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

View file

@ -265,7 +265,7 @@ retryModel:
trap_G2API_CleanGhoul2Models(&(ci->ghoul2Model)); trap_G2API_CleanGhoul2Models(&(ci->ghoul2Model));
} }
if (cgs.gametype >= GT_TEAM) if ( cgs.gametype >= GT_TEAM && !cgs.jediVmerc )
{ {
if (ci->team == TEAM_RED) if (ci->team == TEAM_RED)
{ {
@ -662,7 +662,22 @@ void CG_LoadClientInfo( clientInfo_t *ci ) {
dir = ci->modelName; dir = ci->modelName;
fallback = DEFAULT_MALE_SOUNDPATH; //(cgs.gametype >= GT_TEAM) ? DEFAULT_TEAM_MODEL : DEFAULT_MODEL; fallback = DEFAULT_MALE_SOUNDPATH; //(cgs.gametype >= GT_TEAM) ? DEFAULT_TEAM_MODEL : DEFAULT_MODEL;
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); 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; soundpath[0] = 0;
@ -1129,7 +1144,7 @@ void CG_NewClientInfo( int clientNum, qboolean entitiesInitialized ) {
newInfo.ATST = wasATST; newInfo.ATST = wasATST;
if (cgs.gametype >= GT_TEAM) if (cgs.gametype >= GT_TEAM && !cgs.jediVmerc )
{ {
if (newInfo.team == TEAM_RED) if (newInfo.team == TEAM_RED)
{ {
@ -1190,23 +1205,29 @@ void CG_NewClientInfo( int clientNum, qboolean entitiesInitialized ) {
if (entitiesInitialized && ci->ghoul2Model && (oldGhoul2 != ci->ghoul2Model)) if (entitiesInitialized && ci->ghoul2Model && (oldGhoul2 != ci->ghoul2Model))
{ // Copy the new ghoul2 model to the centity. { // Copy the new ghoul2 model to the centity.
animation_t *anim; 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) ]; anim = &bgGlobalAnimations[ (cg_entities[clientNum].currentState.legsAnim & ~ANIM_TOGGLEBIT) ];
if (anim) if (anim)
{ {
int flags = BONE_ANIM_OVERRIDE_FREEZE; 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) if (anim->loopFrames != -1)
{ {
flags = BONE_ANIM_OVERRIDE_LOOP; flags |= BONE_ANIM_OVERRIDE_LOOP;
firstFrame = anim->firstFrame; }
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 //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; cg_entities[clientNum].currentState.legsAnim = 0;
} }
@ -1216,16 +1237,22 @@ void CG_NewClientInfo( int clientNum, qboolean entitiesInitialized ) {
if (anim) if (anim)
{ {
int flags = BONE_ANIM_OVERRIDE_FREEZE; 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) if (anim->loopFrames != -1)
{ {
flags = BONE_ANIM_OVERRIDE_LOOP; flags |= BONE_ANIM_OVERRIDE_LOOP;
firstFrame = anim->firstFrame; }
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 //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; 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_CleanGhoul2Models(&cg_entities[clientNum].ghoul2);
} }
trap_G2API_DuplicateGhoul2Instance(ci->ghoul2Model, &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); 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 ) 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; 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.torsoAnim&~ANIM_TOGGLEBIT) &&
!BG_SaberInSpecialAttack(cent->currentState.legsAnim&~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_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].legsAnim&~ANIM_TOGGLEBIT ) &&
!BG_SpinningSaberAnim( cgs.clientinfo[cent->currentState.number].torsoAnim&~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, numFragments = trap_CM_MarkFragments( 4, (const float (*)[3])originalPoints,
projection, MAX_MARK_POINTS, markPoints[0], MAX_MARK_FRAGMENTS, markFragments ); projection, MAX_MARK_POINTS, markPoints[0], MAX_MARK_FRAGMENTS, markFragments );
for ( i = 0, mf = markFragments ; i < numFragments ; i++, mf++ ) for ( i = 0, mf = markFragments ; i < numFragments ; i++, mf++ )
{ {
// we have an upper limit on the complexity of polygons that we store persistantly // we have an upper limit on the complexity of polygons that we store persistantly
@ -3824,6 +3865,90 @@ 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); v->st[1] = 0.5 + DotProduct( delta, axis[2] ) * (0.15f + random() * 0.05f);
} }
if (cg_saberDynamicMarks.integer)
{
int i = 0;
int i_2 = 0;
addpolyArgStruct_t apArgs;
vec3_t x;
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 // save it persistantly, do burn first
mark = CG_AllocMark(); mark = CG_AllocMark();
mark->time = cg.time; mark->time = cg.time;
@ -3846,6 +3971,7 @@ void CG_CreateSaberMarks( vec3_t start, vec3_t end, vec3_t normal )
memcpy( mark->verts, verts, mf->numPoints * sizeof( verts[0] ) ); memcpy( mark->verts, verts, mf->numPoints * sizeof( verts[0] ) );
} }
} }
}
#ifdef G2_COLLISION_ENABLED #ifdef G2_COLLISION_ENABLED
qboolean CG_G2TraceCollide(trace_t *tr, vec3_t lastValidStart, vec3_t lastValidEnd) qboolean CG_G2TraceCollide(trace_t *tr, vec3_t lastValidStart, vec3_t lastValidEnd)
@ -4060,7 +4186,7 @@ Ghoul2 Insert Start
scolor = cgs.clientinfo[cent->currentState.number].icolor1; 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) 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. //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; renderfx = 0;
if ( cent->currentState.number == cg.snap->ps.clientNum) { if ( cent->currentState.number == cg.snap->ps.clientNum) {
if (!cg.renderingThirdPerson) { if (!cg.renderingThirdPerson) {
if (!cg_fpls.integer || cent->currentState.weapon != WP_SABER)
{
renderfx = RF_THIRD_PERSON; // only draw in mirrors renderfx = RF_THIRD_PERSON; // only draw in mirrors
}
} else { } else {
if (cg_cameraMode.integer) { if (cg_cameraMode.integer) {
iwantout = 1; 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); 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; 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) if (cent->currentState.eFlags & EF_DEAD)
{ {
dead = qtrue; dead = qtrue;
@ -6002,6 +6275,10 @@ doEssentialTwo:
CG_PlayerAnimation( cent, &legs.oldframe, &legs.frame, &legs.backlerp, CG_PlayerAnimation( cent, &legs.oldframe, &legs.frame, &legs.backlerp,
&torso.oldframe, &torso.frame, &torso.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 // add the talk baloon or disconnect icon
CG_PlayerSprites( cent ); CG_PlayerSprites( cent );
@ -6010,13 +6287,6 @@ doEssentialTwo:
cgs.clientinfo[cent->currentState.number].frame = cent->pe.torso.frame; 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) if (cent->isATST)
{ {
goto doEssentialThree; goto doEssentialThree;

View file

@ -332,11 +332,16 @@ void CG_CheckLocalSounds( playerState_t *ps, playerState_t *ops ) {
} }
// health changes of more than -3 should make pain sounds // health changes of more than -3 should make pain sounds
if ( ps->stats[STAT_HEALTH] < (ops->stats[STAT_HEALTH] - 3)) { if (cg_oldPainSounds.integer)
if ( ps->stats[STAT_HEALTH] > 0 ) { {
if ( ps->stats[STAT_HEALTH] < (ops->stats[STAT_HEALTH] - 3))
{
if ( ps->stats[STAT_HEALTH] > 0 )
{
CG_PainEvent( &cg.predictedPlayerEntity, ps->stats[STAT_HEALTH] ); CG_PainEvent( &cg.predictedPlayerEntity, ps->stats[STAT_HEALTH] );
} }
} }
}
// if we are going into the intermission, don't start any voices // if we are going into the intermission, don't start any voices
if ( cg.intermissionStarted ) { if ( cg.intermissionStarted ) {

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_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) if (cgs.gametype == GT_TOURNAMENT)
{ {
char sWL[100]; char sWL[100];
@ -373,10 +378,10 @@ qboolean CG_DrawOldScoreboard( void ) {
} }
else 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_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, "Time", 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; y = SB_TOP;

View file

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

View file

@ -1558,9 +1558,16 @@ 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 || 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.predictedPlayerState.forceHandExtend == HANDEXTEND_KNOCKDOWN || cg.predictedPlayerState.fallingToDeath))
{
if (cg_fpls.integer && cg.predictedPlayerState.weapon == WP_SABER)
{ //force to first person for fpls
cg.renderingThirdPerson = 0;
}
else
{ {
cg.renderingThirdPerson = 1; cg.renderingThirdPerson = 1;
} }
}
else if (cg.snap->ps.zoomMode) else if (cg.snap->ps.zoomMode)
{ //always force first person when zoomed { //always force first person when zoomed
cg.renderingThirdPerson = 0; cg.renderingThirdPerson = 0;

View file

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

View file

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

View file

@ -2198,6 +2198,11 @@ int BotIsAChickenWuss(bot_state_t *bs)
return 0; return 0;
} }
if (g_gametype.integer == GT_SINGLE_PLAYER)
{
return 0;
}
if (g_gametype.integer == GT_JEDIMASTER && !bs->cur_ps.isJediMaster) if (g_gametype.integer == GT_JEDIMASTER && !bs->cur_ps.isJediMaster)
{ //Then you may know no fear. { //Then you may know no fear.
//Well, unless he's strong. //Well, unless he's strong.
@ -3724,10 +3729,18 @@ void GetIdealDestination(bot_state_t *bs)
if (tempInt != -1 && TotalTrailDistance(bs->wpCurrent->index, tempInt, bs) != -1) if (tempInt != -1 && TotalTrailDistance(bs->wpCurrent->index, tempInt, bs) != -1)
{ {
bs->wpDestination = gWPArray[tempInt]; bs->wpDestination = gWPArray[tempInt];
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); bs->wpDestSwitchTime = level.time + Q_irand(1000, 5000);
} }
} }
} }
}
if (!bs->wpDestination && bs->wpDestSwitchTime < level.time) if (!bs->wpDestination && bs->wpDestSwitchTime < level.time)
{ {
@ -6439,6 +6452,8 @@ void StandardBotAI(bot_state_t *bs, float thinktime)
{ {
if (BotGetWeaponRange(bs) == BWEAPONRANGE_SABER) if (BotGetWeaponRange(bs) == BWEAPONRANGE_SABER)
{ {
int saberRange = SABER_ATTACK_RANGE;
VectorSubtract(bs->currentEnemy->client->ps.origin, bs->eye, a_fo); VectorSubtract(bs->currentEnemy->client->ps.origin, bs->eye, a_fo);
vectoangles(a_fo, 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); 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_WeaponLightsaber(void);
void PM_SetSaberMove(short newMove); 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 BG_LegalizedForcePowers
//to begin with and false if not.
//fpDisabled is actually only expected (needed) from the server, because the ui disables The magical function to end all functions.
//force power selection anyway when force powers are disabled on the server. 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) qboolean BG_LegalizedForcePowers(char *powerOut, int maxRank, qboolean freeSaber, int teamForce, int gametype, int fpDisabled)
{ {
char powerBuf[128]; char powerBuf[128];
@ -254,7 +260,6 @@ qboolean BG_LegalizedForcePowers(char *powerOut, int maxRank, qboolean freeSaber
{ {
final_Powers[i] = 0; final_Powers[i] = 0;
//This is only likely to happen with g_forceBasedTeams. Let it slide. //This is only likely to happen with g_forceBasedTeams. Let it slide.
//maintainsValidity = 0;
} }
if ( final_Powers[i] && if ( final_Powers[i] &&
@ -410,16 +415,16 @@ qboolean BG_LegalizedForcePowers(char *powerOut, int maxRank, qboolean freeSaber
final_Powers[FP_LEVITATION] = 1; final_Powers[FP_LEVITATION] = 1;
} }
/* i = 0;
if (fpDisabled) while (i < NUM_FORCE_POWERS)
{ {
final_Powers[FP_LEVITATION] = 1; if (final_Powers[i] > FORCE_LEVEL_3)
final_Powers[FP_SABERATTACK] = 3; {
final_Powers[FP_SABERDEFEND] = 3; final_Powers[i] = FORCE_LEVEL_3;
final_Powers[FP_SABERTHROW] = 0;
} }
*/ 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 (fpDisabled)
{ //If we specifically have attack or def disabled, force them up to level 3. It's the way { //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. //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 (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) power != FP_LEVITATION)
{ {
if (!ps->saberLockFrame || power != FP_PUSH) if (!ps->saberLockFrame || power != FP_PUSH)
@ -1466,68 +1471,68 @@ void BG_CycleForce(playerState_t *ps, int direction)
presel = x; presel = x;
if (direction == 1) if (direction == 1)
{ { //get the next power
x++; x++;
} }
else else
{ { //get the previous power
x--; x--;
} }
if (x >= NUM_FORCE_POWERS) if (x >= NUM_FORCE_POWERS)
{ { //cycled off the end.. cycle around to the first
x = 0; x = 0;
} }
if (x < 0) if (x < 0)
{ { //cycled off the beginning.. cycle around to the last
x = NUM_FORCE_POWERS-1; x = NUM_FORCE_POWERS-1;
} }
i = forcePowerSorted[x]; i = forcePowerSorted[x]; //the "sorted" value of this power
while (x != presel) while (x != presel)
{ { //loop around to the current force power
if (ps->fd.forcePowersKnown & (1 << i) && i != ps->fd.forcePowerSelected) if (ps->fd.forcePowersKnown & (1 << i) && i != ps->fd.forcePowerSelected)
{ { //we have the force power
if (i != FP_LEVITATION && if (i != FP_LEVITATION &&
i != FP_SABERATTACK && i != FP_SABERATTACK &&
i != FP_SABERDEFEND && i != FP_SABERDEFEND &&
i != FP_SABERTHROW) i != FP_SABERTHROW)
{ { //it's selectable
foundnext = i; foundnext = i;
break; break;
} }
} }
if (direction == 1) if (direction == 1)
{ { //next
x++; x++;
} }
else else
{ { //previous
x--; x--;
} }
if (x >= NUM_FORCE_POWERS) if (x >= NUM_FORCE_POWERS)
{ { //loop around
x = 0; x = 0;
} }
if (x < 0) if (x < 0)
{ { //loop around
x = NUM_FORCE_POWERS-1; x = NUM_FORCE_POWERS-1;
} }
i = forcePowerSorted[x]; i = forcePowerSorted[x]; //set to the sorted value again
} }
if (foundnext != -1) if (foundnext != -1)
{ { //found one, select it
ps->fd.forcePowerSelected = foundnext; ps->fd.forcePowerSelected = foundnext;
} }
} }
int BG_GetItemIndexByTag(int tag, int type) int BG_GetItemIndexByTag(int tag, int type)
{ { //Get the itemlist index from the tag and type
int i = 0; int i = 0;
while (i < bg_numItems) while (i < bg_numItems)
@ -1553,37 +1558,37 @@ void BG_CycleInven(playerState_t *ps, int direction)
original = i; original = i;
if (direction == 1) if (direction == 1)
{ { //next
i++; i++;
} }
else else
{ { //previous
i--; i--;
} }
while (i != original) while (i != original)
{ //go in a full loop until hitting something, if hit nothing then select nothing { //go in a full loop until hitting something, if hit nothing then select nothing
if (ps->stats[STAT_HOLDABLE_ITEMS] & (1 << i)) if (ps->stats[STAT_HOLDABLE_ITEMS] & (1 << i))
{ { //we have it, select it.
ps->stats[STAT_HOLDABLE_ITEM] = BG_GetItemIndexByTag(i, IT_HOLDABLE); ps->stats[STAT_HOLDABLE_ITEM] = BG_GetItemIndexByTag(i, IT_HOLDABLE);
break; break;
} }
if (direction == 1) if (direction == 1)
{ { //next
i++; i++;
} }
else else
{ { //previous
i--; i--;
} }
if (i < 0) if (i < 0)
{ { //wrap around to the last
i = HI_NUM_HOLDABLE; i = HI_NUM_HOLDABLE;
} }
else if (i >= HI_NUM_HOLDABLE) else if (i >= HI_NUM_HOLDABLE)
{ { //wrap around to the first
i = 0; i = 0;
} }
} }
@ -2039,7 +2044,6 @@ void BG_TouchJumpPad( playerState_t *ps, entityState_t *jumppad ) {
} else { } else {
effectNum = 1; effectNum = 1;
} }
//BG_AddPredictableEventToPlayerstate( EV_JUMP_PAD, effectNum, ps );
} }
// remember hitting this jumppad this frame // remember hitting this jumppad this frame
ps->jumppad_ent = jumppad->number; 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 #define MAX_POOL_SIZE 2048000 //1024000
static char bg_pool[MAX_POOL_SIZE]; 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 ); PM_StartTorsoAnim( anim );
if (setAnimFlags & SETANIM_FLAG_HOLD) if (setAnimFlags & SETANIM_FLAG_HOLD)
{//FIXME: allow to set a specific time? {
if (setAnimFlags & SETANIM_FLAG_HOLDLESS) if (setAnimFlags & SETANIM_FLAG_HOLDLESS)
{ // Make sure to only wait in full 1/20 sec server frame intervals. { // Make sure to only wait in full 1/20 sec server frame intervals.
int dur; int dur;
int speedDif; int speedDif;
dur = (animations[anim].numFrames-1) * fabs(animations[anim].frameLerp); 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); speedDif = dur - (dur * editAnimSpeed);
dur += speedDif; dur += speedDif;
if (dur > 1) if (dur > 1)
@ -1127,15 +1125,13 @@ setAnimLegs:
PM_StartLegsAnim(anim); PM_StartLegsAnim(anim);
if (setAnimFlags & SETANIM_FLAG_HOLD) if (setAnimFlags & SETANIM_FLAG_HOLD)
{//FIXME: allow to set a specific time? {
if (setAnimFlags & SETANIM_FLAG_HOLDLESS) if (setAnimFlags & SETANIM_FLAG_HOLDLESS)
{ // Make sure to only wait in full 1/20 sec server frame intervals. { // Make sure to only wait in full 1/20 sec server frame intervals.
int dur; int dur;
int speedDif; int speedDif;
dur = (animations[anim].numFrames-1) * fabs(animations[anim].frameLerp); 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); speedDif = dur - (dur * editAnimSpeed);
dur += speedDif; dur += speedDif;
if (dur > 1) if (dur > 1)
@ -1152,11 +1148,6 @@ setAnimLegs:
pm->ps->legsTimer = ((animations[anim].numFrames ) * fabs(animations[anim].frameLerp)); 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)) if (pm->ps->fd.forcePowersActive & (1 << FP_RAGE))
{ {
pm->ps->legsTimer /= 1.3; 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)) if (BG_InRoll(pm->ps, pm->ps->legsAnim))
{ { //never interrupt a roll
//setAnimFlags |= SETANIM_FLAG_RESTART;
return; return;
} }

View file

@ -467,7 +467,7 @@ qboolean PM_ForceJumpingUp(void)
} }
if ( pm->ps->groundEntityNum == ENTITYNUM_NONE && //in air 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->fd.forcePowerLevel[FP_LEVITATION] > FORCE_LEVEL_0 && //force-jump capable
pm->ps->velocity[2] > 0 )//going up pm->ps->velocity[2] > 0 )//going up
{ {
@ -506,7 +506,7 @@ static void PM_JumpForDir( void )
} }
if(!BG_InDeathAnim(pm->ps->legsAnim)) 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; int i;
// set the delta angle for (i=0 ; i<3 ; i++)
for (i=0 ; i<3 ; i++) { { // set the delta angle
int cmdAngle; int cmdAngle;
cmdAngle = ANGLE2SHORT(angle[i]); cmdAngle = ANGLE2SHORT(angle[i]);
ps->delta_angles[i] = cmdAngle - ucmd->angles[i]; ps->delta_angles[i] = cmdAngle - ucmd->angles[i];
} }
//VectorCopy( angle, ent->s.angles );
VectorCopy (angle, ps->viewangles); VectorCopy (angle, ps->viewangles);
} }
@ -555,8 +554,6 @@ qboolean PM_AdjustAngleForWallRun( playerState_t *ps, usercmd_t *ucmd, qboolean
if ( trace.fraction < 1.0f ) if ( trace.fraction < 1.0f )
{//still a wall there {//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 ) if ( (ps->legsAnim&~ANIM_TOGGLEBIT) == BOTH_WALL_RUN_RIGHT )
{ {
ucmd->rightmove = 127; ucmd->rightmove = 127;
@ -572,7 +569,6 @@ qboolean PM_AdjustAngleForWallRun( playerState_t *ps, usercmd_t *ucmd, qboolean
//make me face perpendicular to the wall //make me face perpendicular to the wall
ps->viewangles[YAW] = vectoyaw( trace.plane.normal )+yawAdjust; ps->viewangles[YAW] = vectoyaw( trace.plane.normal )+yawAdjust;
//SetClientViewAngle( ent, ent->client->ps.viewangles );
PM_SetPMViewAngle(ps, ps->viewangles, ucmd); PM_SetPMViewAngle(ps, ps->viewangles, ucmd);
ucmd->angles[YAW] = ANGLE2SHORT( ps->viewangles[YAW] ) - ps->delta_angles[YAW]; 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]; fwdAngles[YAW] = ps->viewangles[YAW];
AngleVectors( fwdAngles, fwd, NULL, NULL ); AngleVectors( fwdAngles, fwd, NULL, NULL );
//FIXME: or MA?
if ( ucmd->forwardmove < 0 ) if ( ucmd->forwardmove < 0 )
{//slower {//slower
speed = 100; speed = 100;
@ -621,12 +617,21 @@ qboolean PM_AdjustAngleForWallRun( playerState_t *ps, usercmd_t *ucmd, qboolean
return qfalse; 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 PM_CheckJump
============= =============
*/ */
static qboolean PM_CheckJump( void ) static qboolean PM_CheckJump( void )
{ {
if (pm->ps->usingATST) if (pm->ps->usingATST)
@ -653,15 +658,9 @@ static qboolean PM_CheckJump( void )
{ {
pm->ps->fd.forcePowersActive &= ~(1<<FP_LEVITATION); 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)) 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) if (pm->ps->fd.forcePowerDebounce[FP_LEVITATION] < pm->cmd.serverTime)
{ {
BG_ForcePowerDrain( pm->ps, FP_LEVITATION, 5 ); BG_ForcePowerDrain( pm->ps, FP_LEVITATION, 5 );
@ -677,7 +676,7 @@ static qboolean PM_CheckJump( void )
} }
if (pm->ps->forceJumpFlip) if (pm->ps->forceJumpFlip)
{ { //Forced jump anim
int anim = BOTH_FORCEINAIR1; int anim = BOTH_FORCEINAIR1;
int parts = SETANIM_BOTH; int parts = SETANIM_BOTH;
@ -711,18 +710,15 @@ static qboolean PM_CheckJump( void )
{ {
if ( pm->ps->gravity > 0 ) if ( pm->ps->gravity > 0 )
{//can't do this in zero-G {//can't do this in zero-G
//FIXME: still able to pogo-jump...
if ( PM_ForceJumpingUp() ) if ( PM_ForceJumpingUp() )
{//holding jump in air {//holding jump in air
float curHeight = pm->ps->origin[2] - pm->ps->fd.forceJumpZStart; float curHeight = pm->ps->origin[2] - pm->ps->fd.forceJumpZStart;
//check for max force jump level and cap off & cut z vel //check for max force jump level and cap off & cut z vel
if ( ( curHeight<=forceJumpHeight[0] ||//still below minimum jump height 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 (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 {//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] ) if ( curHeight > forceJumpHeight[0] )
{//passed normal jump height *2? {//passed normal jump height *2?
if ( !(pm->ps->fd.forcePowersActive&(1<<FP_LEVITATION)) )//haven't started forcejump yet 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.forcePowersActive |= (1<<FP_LEVITATION);
pm->ps->fd.forceJumpSound = 1; pm->ps->fd.forceJumpSound = 1;
//play flip //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 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_F &&//not already flipping
(pm->ps->legsAnim&~ANIM_TOGGLEBIT) != BOTH_FLIP_B && (pm->ps->legsAnim&~ANIM_TOGGLEBIT) != BOTH_FLIP_B &&
(pm->ps->legsAnim&~ANIM_TOGGLEBIT) != BOTH_FLIP_R && (pm->ps->legsAnim&~ANIM_TOGGLEBIT) != BOTH_FLIP_R &&
(pm->ps->legsAnim&~ANIM_TOGGLEBIT) != BOTH_FLIP_L ) (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 anim = BOTH_FORCEINAIR1;
int parts = SETANIM_BOTH; int parts = SETANIM_BOTH;
@ -758,15 +753,15 @@ static qboolean PM_CheckJump( void )
anim = BOTH_FLIP_L; anim = BOTH_FLIP_L;
} }
if ( pm->ps->weaponTime ) if ( pm->ps->weaponTime )
{//FIXME: really only care if we're in a saber attack anim... {
parts = SETANIM_LEGS; parts = SETANIM_LEGS;
} }
PM_SetAnim( parts, anim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 150 ); PM_SetAnim( parts, anim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 150 );
} }
else if ( pm->ps->fd.forcePowerLevel[FP_LEVITATION] > FORCE_LEVEL_1 ) 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; int anim = -1;
float dotR, dotF; float dotR, dotF;
@ -811,7 +806,7 @@ static qboolean PM_CheckJump( void )
} }
} }
else else
{ { //jump is already active (the anim has started)
if ( pm->ps->legsTimer < 1 ) if ( pm->ps->legsTimer < 1 )
{//not in the middle of a legsAnim {//not in the middle of a legsAnim
int anim = (pm->ps->legsAnim&~ANIM_TOGGLEBIT); int anim = (pm->ps->legsAnim&~ANIM_TOGGLEBIT);
@ -835,7 +830,7 @@ static qboolean PM_CheckJump( void )
{ {
int parts = SETANIM_BOTH; int parts = SETANIM_BOTH;
if ( pm->ps->weaponTime ) if ( pm->ps->weaponTime )
{//FIXME: really only care if we're in a saber attack anim... {
parts = SETANIM_LEGS; parts = SETANIM_LEGS;
} }
@ -871,16 +866,6 @@ static qboolean PM_CheckJump( void )
pm->cmd.upmove = 0; pm->cmd.upmove = 0;
return qfalse; 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 ) if ( trace.fraction <= 1.0f )
{ {
VectorMA( pm->ps->velocity, JUMP_VELOCITY*2, forward, pm->ps->velocity ); 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); 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 }//else no surf close enough to push off of
pm->cmd.upmove = 0; pm->cmd.upmove = 0;
} }
else if ( pm->cmd.upmove > 0 && pm->waterlevel < 2 && else if ( pm->cmd.upmove > 0 && pm->waterlevel < 2 &&
pm->ps->fd.forcePowerLevel[FP_LEVITATION] > FORCE_LEVEL_0 && pm->ps->fd.forcePowerLevel[FP_LEVITATION] > FORCE_LEVEL_0 &&
!(pm->ps->pm_flags&PMF_JUMP_HELD) /*&& !(pm->ps->pm_flags&PMF_JUMP_HELD) &&
WP_ForcePowerAvailable( pm->gent, FP_LEVITATION, 0 ) */ &&
pm->ps->weapon == WP_SABER && pm->ps->weapon == WP_SABER &&
!BG_HasYsalamiri(pm->gametype, pm->ps) && !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 ) if ( pm->ps->groundEntityNum != ENTITYNUM_NONE )
{//on the ground {//on the ground
@ -956,39 +938,21 @@ static qboolean PM_CheckJump( void )
anim = BOTH_WALL_FLIP_LEFT; 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) ) else if ( pm->cmd.forwardmove < 0 && !(pm->cmd.buttons&BUTTON_ATTACK) )
{//backflip {//backflip
vertPush = JUMP_VELOCITY; vertPush = JUMP_VELOCITY;
anim = BOTH_FLIP_BACK1;//PM_PickAnim( BOTH_FLIP_BACK1, BOTH_FLIP_BACK3 ); 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 fwd, right, traceto, mins, maxs, fwdAngles;
vec3_t idealNormal; vec3_t idealNormal;
trace_t trace; trace_t trace;
qboolean doTrace = qfalse; qboolean doTrace = qfalse;
int contents = /*CONTENTS_SOLID*/MASK_PLAYERSOLID; int contents = MASK_PLAYERSOLID;
VectorSet(mins, pm->mins[0],pm->mins[1],0); VectorSet(mins, pm->mins[0],pm->mins[1],0);
VectorSet(maxs, pm->maxs[0],pm->maxs[1],24); VectorSet(maxs, pm->maxs[0],pm->maxs[1],24);
@ -1002,7 +966,6 @@ static qboolean PM_CheckJump( void )
switch ( anim ) switch ( anim )
{ {
case BOTH_WALL_FLIP_LEFT: case BOTH_WALL_FLIP_LEFT:
//contents |= CONTENTS_BODY;
//NOTE: purposely falls through to next case! //NOTE: purposely falls through to next case!
case BOTH_WALL_RUN_LEFT: case BOTH_WALL_RUN_LEFT:
doTrace = qtrue; doTrace = qtrue;
@ -1010,7 +973,6 @@ static qboolean PM_CheckJump( void )
break; break;
case BOTH_WALL_FLIP_RIGHT: case BOTH_WALL_FLIP_RIGHT:
//contents |= CONTENTS_BODY;
//NOTE: purposely falls through to next case! //NOTE: purposely falls through to next case!
case BOTH_WALL_RUN_RIGHT: case BOTH_WALL_RUN_RIGHT:
doTrace = qtrue; doTrace = qtrue;
@ -1018,7 +980,6 @@ static qboolean PM_CheckJump( void )
break; break;
case BOTH_WALL_FLIP_BACK1: case BOTH_WALL_FLIP_BACK1:
//contents |= CONTENTS_BODY;
doTrace = qtrue; doTrace = qtrue;
VectorMA( pm->ps->origin, 16, fwd, traceto ); VectorMA( pm->ps->origin, 16, fwd, traceto );
break; break;
@ -1030,11 +991,9 @@ static qboolean PM_CheckJump( void )
VectorSubtract( pm->ps->origin, traceto, idealNormal ); VectorSubtract( pm->ps->origin, traceto, idealNormal );
VectorNormalize( 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)) ) 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; int parts;
//move me to side //move me to side
if ( anim == BOTH_WALL_FLIP_LEFT ) if ( anim == BOTH_WALL_FLIP_LEFT )
@ -1055,26 +1014,7 @@ static qboolean PM_CheckJump( void )
pm->ps->velocity[0] = pm->ps->velocity[1] = 0; pm->ps->velocity[0] = pm->ps->velocity[1] = 0;
VectorMA( pm->ps->velocity, -150, fwd, pm->ps->velocity ); 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 ( doTrace && anim != BOTH_WALL_RUN_LEFT && anim != BOTH_WALL_RUN_RIGHT )
{ {
if (trace.entityNum < MAX_CLIENTS) if (trace.entityNum < MAX_CLIENTS)
@ -1083,8 +1023,6 @@ static qboolean PM_CheckJump( void )
} }
} }
//FIXMEFIXME
//up //up
if ( vertPush ) if ( vertPush )
{ {
@ -1108,10 +1046,9 @@ static qboolean PM_CheckJump( void )
{ {
pm->ps->weaponTime = pm->ps->torsoTimer; 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_SetForceJumpZStart(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->ps->pm_flags |= PMF_JUMP_HELD;
pm->cmd.upmove = 0; pm->cmd.upmove = 0;
//WP_ForcePowerDrain( pm->gent, FP_LEVITATION, 0 );
pm->ps->fd.forceJumpSound = 1; pm->ps->fd.forceJumpSound = 1;
} }
} }
@ -1180,8 +1117,6 @@ static qboolean PM_CheckJump( void )
parts = SETANIM_BOTH; parts = SETANIM_BOTH;
} }
PM_SetAnim( parts, anim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0 ); 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; pm->cmd.upmove = 0;
} }
} }
@ -1193,10 +1128,9 @@ static qboolean PM_CheckJump( void )
else if ( pm->cmd.forwardmove > 0 //pushing forward else if ( pm->cmd.forwardmove > 0 //pushing forward
&& pm->ps->fd.forcePowerLevel[FP_LEVITATION] > FORCE_LEVEL_1 && pm->ps->fd.forcePowerLevel[FP_LEVITATION] > FORCE_LEVEL_1
&& pm->ps->velocity[2] > 200 && 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)) && !BG_InSpecialJump(pm->ps->legsAnim))
{//run up wall, flip backwards {//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; vec3_t fwd, traceto, mins, maxs, fwdAngles;
trace_t trace; trace_t trace;
vec3_t idealNormal; 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. 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. //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_SetForceJumpZStart(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->cmd.upmove = 0; pm->cmd.upmove = 0;
//G_SoundOnEnt( pm->gent, CHAN_BODY, "sound/weapons/force/jump.wav" );
pm->ps->fd.forceJumpSound = 1; pm->ps->fd.forceJumpSound = 1;
BG_ForcePowerDrain( pm->ps, FP_LEVITATION, 5 ); 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 ) && !BG_FlippingAnim( pm->ps->legsAnim )
&& !PM_SpinningAnim( pm->ps->legsAnim ) && !PM_SpinningAnim( pm->ps->legsAnim )
&& !BG_SaberInSpecialAttack( pm->ps->torsoAnim ) && !BG_SaberInSpecialAttack( pm->ps->torsoAnim )
&& ( BG_SaberInAttack( pm->ps->saberMove ) ) && ( BG_SaberInAttack( pm->ps->saberMove ) ) )
/*&& PM_InAnimForSaberMove( pm->ps->torsoAnim, pm->ps->saberMove )*/ )
{//not in an anim we shouldn't interrupt {//not in an anim we shouldn't interrupt
//see if it's not too late to start a special jump-attack //see if it's not too late to start a special jump-attack
float animLength = PM_AnimLength( 0, (animNumber_t)pm->ps->torsoAnim ); 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 //check for special-case jump attacks
if ( pm->ps->fd.saberAnimLevel == FORCE_LEVEL_2 ) if ( pm->ps->fd.saberAnimLevel == FORCE_LEVEL_2 )
{//using medium attacks {//using medium attacks
if (/*pm->ps->velocity[2] > 100 &&*/ if (PM_GroundDistance() < 32 &&
PM_GroundDistance() < 32 &&
!BG_InSpecialJump(pm->ps->legsAnim)) !BG_InSpecialJump(pm->ps->legsAnim))
{ //FLIP AND DOWNWARD ATTACK { //FLIP AND DOWNWARD ATTACK
trace_t tr; trace_t tr;
@ -1314,17 +1240,9 @@ static qboolean PM_CheckJump( void )
} }
if ( pm->cmd.upmove > 0 ) if ( pm->cmd.upmove > 0 )
{//no special jumps {//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->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_SetForceJumpZStart(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->ps->pm_flags |= PMF_JUMP_HELD;
} }
//Jumping //Jumping
@ -1332,7 +1250,7 @@ static qboolean PM_CheckJump( void )
pml.walking = qfalse; pml.walking = qfalse;
pm->ps->pm_flags |= PMF_JUMP_HELD; pm->ps->pm_flags |= PMF_JUMP_HELD;
pm->ps->groundEntityNum = ENTITYNUM_NONE; pm->ps->groundEntityNum = ENTITYNUM_NONE;
pm->ps->fd.forceJumpZStart = pm->ps->origin[2]; PM_SetForceJumpZStart(pm->ps->origin[2]);
PM_AddEvent( EV_JUMP ); PM_AddEvent( EV_JUMP );
@ -1696,7 +1614,6 @@ static void PM_WalkMove( void ) {
wishvel[i] = pml.forward[i]*fmove + pml.right[i]*smove; wishvel[i] = pml.forward[i]*fmove + pml.right[i]*smove;
} }
// when going up or down slopes the wish velocity should Not be zero // when going up or down slopes the wish velocity should Not be zero
// wishvel[2] = 0;
VectorCopy (wishvel, wishdir); VectorCopy (wishvel, wishdir);
wishspeed = VectorNormalize(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("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)); //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; 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); vel = VectorLength(pm->ps->velocity);
@ -1766,7 +1681,6 @@ static void PM_WalkMove( void ) {
PM_StepSlideMove( qfalse ); PM_StepSlideMove( qfalse );
//Com_Printf("velocity2 = %1.1f\n", VectorLength(pm->ps->velocity)); //Com_Printf("velocity2 = %1.1f\n", VectorLength(pm->ps->velocity));
} }
@ -1870,11 +1784,14 @@ PM_FootstepForSurface
Returns an event number apropriate for the groundsurface Returns an event number apropriate for the groundsurface
================ ================
*/ */
static int PM_FootstepForSurface( void ) { static int PM_FootstepForSurface( void )
if ( pml.groundTrace.surfaceFlags & SURF_NOSTEPS ) { {
if ( pml.groundTrace.surfaceFlags & SURF_NOSTEPS )
{
return 0; return 0;
} }
if ( pml.groundTrace.surfaceFlags & SURF_METALSTEPS ) { if ( pml.groundTrace.surfaceFlags & SURF_METALSTEPS )
{
return EV_FOOTSTEP_METAL; return EV_FOOTSTEP_METAL;
} }
return EV_FOOTSTEP; return EV_FOOTSTEP;
@ -1895,22 +1812,19 @@ static int PM_TryRoll( void )
if (pm->ps->weapon != WP_SABER || BG_HasYsalamiri(pm->gametype, pm->ps) || if (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))
{ { //Not using saber, or can't use jump
return 0; 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(mins, pm->mins[0],pm->mins[1],pm->mins[2]+STEPSIZE);
VectorSet(maxs, pm->maxs[0],pm->maxs[1],CROUCH_MAXS_2); VectorSet(maxs, pm->maxs[0],pm->maxs[1],CROUCH_MAXS_2);
VectorSet(fwdAngles, 0, pm->ps->viewangles[YAW], 0); VectorSet(fwdAngles, 0, pm->ps->viewangles[YAW], 0);
AngleVectors( fwdAngles, fwd, right, NULL ); AngleVectors( fwdAngles, fwd, right, NULL );
//FIXME: trace ahead for clearance to roll
if ( pm->cmd.forwardmove ) if ( pm->cmd.forwardmove )
{ { //check forward/backward rolls
if ( pm->ps->pm_flags & PMF_BACKWARDS_RUN ) if ( pm->ps->pm_flags & PMF_BACKWARDS_RUN )
{ {
anim = BOTH_ROLL_B; anim = BOTH_ROLL_B;
@ -1923,25 +1837,21 @@ static int PM_TryRoll( void )
} }
} }
else if ( pm->cmd.rightmove > 0 ) else if ( pm->cmd.rightmove > 0 )
{ { //right
anim = BOTH_ROLL_R; anim = BOTH_ROLL_R;
VectorMA( pm->ps->origin, 64, right, traceto ); VectorMA( pm->ps->origin, 64, right, traceto );
} }
else if ( pm->cmd.rightmove < 0 ) else if ( pm->cmd.rightmove < 0 )
{ { //left
anim = BOTH_ROLL_L; anim = BOTH_ROLL_L;
VectorMA( pm->ps->origin, -64, right, traceto ); VectorMA( pm->ps->origin, -64, right, traceto );
} }
else
{//???
}
if ( anim != -1 ) 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 ); pm->trace( &trace, pm->ps->origin, mins, maxs, traceto, pm->ps->clientNum, CONTENTS_SOLID );
if ( trace.fraction >= 1.0f ) if ( trace.fraction >= 1.0f )
{ {
//PM_AddEvent( EV_ROLL );
//Done later..
pm->ps->saberMove = LS_NONE; pm->ps->saberMove = LS_NONE;
return anim; 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) if (pm->ps->weapon != WP_SABER)
{ //saber handles its own anims { //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) if (pm->ps->weapon == WP_DISRUPTOR && pm->ps->zoomMode == 1)
{ {
PM_StartTorsoAnim( TORSO_WEAPONREADY4 ); 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) || if (!BG_InSpecialJump(pm->ps->legsAnim) ||
pm->ps->legsTimer < 1 || pm->ps->legsTimer < 1 ||
(pm->ps->legsAnim&~ANIM_TOGGLEBIT) == BOTH_WALL_RUN_LEFT || (pm->ps->legsAnim&~ANIM_TOGGLEBIT) == BOTH_WALL_RUN_LEFT ||
(pm->ps->legsAnim&~ANIM_TOGGLEBIT) == BOTH_WALL_RUN_RIGHT) (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_InRoll(pm->ps, pm->ps->legsAnim) && pm->ps->inAirAnim)
{ {
if (!BG_SaberInSpecial(pm->ps->saberMove) || pm->ps->weapon != WP_SABER) 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 ( 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! {//roll!
int anim = PM_TryRoll(); int anim = PM_TryRoll();
@ -2078,7 +1983,6 @@ static void PM_CrashLand( void ) {
if ( anim ) if ( anim )
{//absorb some impact {//absorb some impact
pm->ps->legsTimer = 0; 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 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->ps->legsAnim = 0;
PM_SetAnim(SETANIM_BOTH,anim,SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 150); 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 // SURF_NODAMAGE is used for bounce pads where you don't ever
// want to take damage or play a crunch sound // want to take damage or play a crunch sound
if ( !(pml.groundTrace.surfaceFlags & SURF_NODAMAGE) ) { if ( !(pml.groundTrace.surfaceFlags & SURF_NODAMAGE) ) {
@ -2135,7 +2037,7 @@ static void PM_CrashLand( void ) {
} }
if (didRoll) if (didRoll)
{ { //Add the appropriate event..
PM_AddEventWithParm( EV_ROLL, delta_send ); PM_AddEventWithParm( EV_ROLL, delta_send );
} }
else else
@ -2163,22 +2065,6 @@ static void PM_CrashLand( void ) {
pm->ps->bobCycle = 0; 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 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 //rww - don't want to do this when handextend_choke, because you can be standing on the ground
//while still holding your throat. //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 //we're assuming this is because you're being choked
int parts = SETANIM_LEGS; 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 //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. //a proper anim even when on the ground.
PM_SetAnim(parts, BOTH_CHOKE3, SETANIM_FLAG_OVERRIDE, 100); 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 //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 // we just transitioned into freefall
if ( pm->debugLevel ) { if ( pm->debugLevel ) {
Com_Printf("%i:lift\n", c_pmove); 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); 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 ( trace.fraction == 1.0 || pm->ps->pm_type == PM_FLOAT ) {
if ( pm->ps->velocity[2] <= 0 && !(pm->ps->pm_flags&PMF_JUMP_HELD)) 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; pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP;
} }
else if ( pm->cmd.forwardmove >= 0 ) 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; pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP;
} }
else 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; pm->ps->pm_flags |= PMF_BACKWARDS_JUMP;
} }
@ -2297,8 +2178,8 @@ static void PM_GroundTraceMissed( void ) {
} }
if (PM_InRollComplete(pm->ps, pm->ps->legsAnim)) 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 { //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) //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_SetAnim(SETANIM_BOTH,BOTH_INAIR1,SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 150);
pm->ps->inAirAnim = qtrue; pm->ps->inAirAnim = qtrue;
} }
@ -2372,8 +2253,6 @@ static void PM_GroundTrace( void ) {
if ( pm->debugLevel ) { if ( pm->debugLevel ) {
Com_Printf("%i:steep\n", c_pmove); 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; pm->ps->groundEntityNum = ENTITYNUM_NONE;
pml.groundPlane = qtrue; pml.groundPlane = qtrue;
pml.walking = qfalse; pml.walking = qfalse;
@ -2409,16 +2288,13 @@ static void PM_GroundTrace( void ) {
pm->ps->groundEntityNum = trace.entityNum; pm->ps->groundEntityNum = trace.entityNum;
pm->ps->lastOnGround = pm->cmd.serverTime; pm->ps->lastOnGround = pm->cmd.serverTime;
// don't reset the z velocity for slopes
// pm->ps->velocity[2] = 0;
PM_AddTouchEnt( trace.entityNum ); PM_AddTouchEnt( trace.entityNum );
} }
/* /*
============= =============
PM_SetWaterLevel FIXME: avoid this twice? certainly if not moving PM_SetWaterLevel
============= =============
*/ */
static void PM_SetWaterLevel( void ) { static void PM_SetWaterLevel( void ) {
@ -2690,7 +2566,8 @@ static void PM_Footsteps( void ) {
footstep = qfalse; footstep = qfalse;
if ( pm->ps->pm_flags & PMF_DUCKED ) { if ( pm->ps->pm_flags & PMF_DUCKED )
{
int rolled = 0; int rolled = 0;
bobmove = 0.5; // ducked characters bob much faster bobmove = 0.5; // ducked characters bob much faster
@ -2700,7 +2577,7 @@ static void PM_Footsteps( void ) {
rolled = PM_TryRoll(); rolled = PM_TryRoll();
} }
if ( !rolled ) 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->pm_flags & PMF_BACKWARDS_RUN ) {
if ((pm->ps->legsAnim&~ANIM_TOGGLEBIT) != BOTH_CROUCH1WALKBACK) if ((pm->ps->legsAnim&~ANIM_TOGGLEBIT) != BOTH_CROUCH1WALKBACK)
{ {
@ -2723,7 +2600,7 @@ static void PM_Footsteps( void ) {
} }
} }
else else
{ { //otherwise send us into the roll
pm->ps->legsTimer = 0; pm->ps->legsTimer = 0;
pm->ps->legsAnim = 0; pm->ps->legsAnim = 0;
PM_SetAnim(SETANIM_BOTH,rolled,SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 150); 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_DUCKED;
pm->ps->pm_flags |= PMF_ROLLING; 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) && else if ((pm->ps->pm_flags & PMF_ROLLING) && !BG_InRoll(pm->ps, pm->ps->legsAnim) &&
!PM_InRollComplete(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 we just crossed a cycle boundary, play an apropriate footstep event
if ( ( ( old + 64 ) ^ ( pm->ps->bobCycle + 64 ) ) & 128 ) 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; pm->ps->footstepTime = pm->cmd.serverTime + 300;
if ( pm->waterlevel == 1 ) { if ( pm->waterlevel == 1 ) {
// splashing // splashing
@ -3217,6 +3075,11 @@ int PM_ItemUsable(playerState_t *ps, int forcedUse)
return 0; return 0;
} }
if (ps->duelInProgress)
{ //not allowed to use holdables while in a private duel.
return 0;
}
if (!forcedUse) if (!forcedUse)
{ {
forcedUse = bg_itemlist[ps->stats[STAT_HOLDABLE_ITEM]].giTag; forcedUse = bg_itemlist[ps->stats[STAT_HOLDABLE_ITEM]].giTag;
@ -3314,7 +3177,8 @@ PM_Weapon
Generates weapon events and modifes the weapon counter Generates weapon events and modifes the weapon counter
============== ==============
*/ */
static void PM_Weapon( void ) { static void PM_Weapon( void )
{
int addTime; int addTime;
int amount; int amount;
int killAfterItem = 0; int killAfterItem = 0;
@ -3401,6 +3265,8 @@ static void PM_Weapon( void ) {
else if (pm->ps->forceHandExtend != HANDEXTEND_NONE) else if (pm->ps->forceHandExtend != HANDEXTEND_NONE)
{ //nothing else should be allowed to happen during this time, including weapon fire { //nothing else should be allowed to happen during this time, including weapon fire
int desiredAnim = 0; int desiredAnim = 0;
qboolean seperateOnTorso = qfalse;
int desiredOnTorso = 0;
switch(pm->ps->forceHandExtend) switch(pm->ps->forceHandExtend)
{ {
@ -3418,12 +3284,6 @@ static void PM_Weapon( void ) {
break; break;
case HANDEXTEND_CHOKE: case HANDEXTEND_CHOKE:
desiredAnim = BOTH_CHOKE3; //left-handed 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; break;
case HANDEXTEND_DODGE: case HANDEXTEND_DODGE:
desiredAnim = pm->ps->forceDodgeAnim; desiredAnim = pm->ps->forceDodgeAnim;
@ -3431,7 +3291,27 @@ static void PM_Weapon( void ) {
case HANDEXTEND_KNOCKDOWN: case HANDEXTEND_KNOCKDOWN:
if (pm->ps->forceDodgeAnim) 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; desiredAnim = BOTH_FORCE_GETUP_B1;
} }
@ -3471,14 +3351,28 @@ static void PM_Weapon( void ) {
break; break;
} }
if (!seperateOnTorso)
{ //of seperateOnTorso, handle it after setting the legs
PM_SetAnim(SETANIM_TORSO, desiredAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 100); PM_SetAnim(SETANIM_TORSO, desiredAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 100);
pm->ps->torsoTimer = 1; pm->ps->torsoTimer = 1;
}
if (pm->ps->forceHandExtend == HANDEXTEND_DODGE || pm->ps->forceHandExtend == HANDEXTEND_KNOCKDOWN || if (pm->ps->forceHandExtend == HANDEXTEND_DODGE || pm->ps->forceHandExtend == HANDEXTEND_KNOCKDOWN ||
(pm->ps->forceHandExtend == HANDEXTEND_CHOKE && pm->ps->groundEntityNum == ENTITYNUM_NONE) ) (pm->ps->forceHandExtend == HANDEXTEND_CHOKE && pm->ps->groundEntityNum == ENTITYNUM_NONE) )
{ //special case, play dodge anim on whole body, choke anim too if off ground { //special case, play dodge anim on whole body, choke anim too if off ground
if (seperateOnTorso)
{
PM_SetAnim(SETANIM_LEGS, desiredAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 100); PM_SetAnim(SETANIM_LEGS, desiredAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 100);
pm->ps->legsTimer = 1; 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; return;
@ -3876,10 +3770,6 @@ static void PM_Animate( void ) {
if ( pm->cmd.buttons & BUTTON_GESTURE ) { if ( pm->cmd.buttons & BUTTON_GESTURE ) {
if ( pm->ps->torsoTimer < 1 && pm->ps->forceHandExtend == HANDEXTEND_NONE && 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->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; 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 // set the firing flag for continuous beam weapons, saber will fire even if out of ammo
if ( !(pm->ps->pm_flags & PMF_RESPAWNED) && if ( !(pm->ps->pm_flags & PMF_RESPAWNED) &&
pm->ps->pm_type != PM_INTERMISSION && pm->ps->pm_type != PM_INTERMISSION &&
@ -4288,6 +4150,10 @@ void BG_AdjustClientSpeed(playerState_t *ps, usercmd_t *cmd, int svTime)
| BOTH_RUN1; | 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)) 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; ps->speed *= 0.85f;
break; break;
case FORCE_LEVEL_3: case FORCE_LEVEL_3:
//ps->speed *= 0.70f;
ps->speed *= 0.55f; ps->speed *= 0.55f;
break; break;
default: default:
@ -4479,7 +4344,6 @@ void PmoveSingle (pmove_t *pmove) {
if ((pm->ps->legsAnim&~ANIM_TOGGLEBIT) == (BOTH_A2_STABBACK1) || if ((pm->ps->legsAnim&~ANIM_TOGGLEBIT) == (BOTH_A2_STABBACK1) ||
(pm->ps->legsAnim&~ANIM_TOGGLEBIT) == (BOTH_ATTACK_BACK) || (pm->ps->legsAnim&~ANIM_TOGGLEBIT) == (BOTH_ATTACK_BACK) ||
(pm->ps->legsAnim&~ANIM_TOGGLEBIT) == (BOTH_CROUCHATTACKBACK1) || (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_FORCELEAP2_T__B_) ||
(pm->ps->legsAnim&~ANIM_TOGGLEBIT) == (BOTH_JUMPFLIPSTABDOWN) || (pm->ps->legsAnim&~ANIM_TOGGLEBIT) == (BOTH_JUMPFLIPSTABDOWN) ||
(pm->ps->legsAnim&~ANIM_TOGGLEBIT) == (BOTH_JUMPFLIPSLASHDOWN1)) (pm->ps->legsAnim&~ANIM_TOGGLEBIT) == (BOTH_JUMPFLIPSLASHDOWN1))
@ -4489,6 +4353,14 @@ void PmoveSingle (pmove_t *pmove) {
pm->cmd.upmove = 0; 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->ps->emplacedIndex)
{ {
if (pm->cmd.forwardmove < 0) if (pm->cmd.forwardmove < 0)
@ -4576,25 +4448,17 @@ void PmoveSingle (pmove_t *pmove) {
PM_AdjustAngleForWallRun(pm->ps, &pm->cmd, qtrue); 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;
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); 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); PM_SetPMViewAngle(pm->ps, pm->ps->viewangles, &pm->cmd);
} }
@ -4715,11 +4579,6 @@ void PmoveSingle (pmove_t *pmove) {
PM_Use(); PM_Use();
if (pm->ps->pm_flags & PMF_UPDATE_ANIM)
{
// PM_UpdateGhoul2AnimFromState();
}
// footstep events / legs animations // footstep events / legs animations
PM_Footsteps(); PM_Footsteps();
@ -4790,8 +4649,5 @@ void Pmove (pmove_t *pmove) {
pmove->cmd.upmove = 20; 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_PlayerStateToEntityState( playerState_t *ps, entityState_t *s, qboolean snap );
void BG_PlayerStateToEntityStateExtraPolate( playerState_t *ps, entityState_t *s, int time, 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 ); 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; return;
} }
*/ */
//No longer grant infinite force with boon.
if ( !drain ) if ( !drain )
{ {
@ -353,7 +354,6 @@ qboolean PM_SaberKataDone(int curmove, int newmove);
int PM_SaberAnimTransitionAnim( int curmove, int newmove ) int PM_SaberAnimTransitionAnim( int curmove, int newmove )
{ {
//FIXME: take FP_SABER_OFFENSE into account here somehow?
int retmove = newmove; int retmove = newmove;
if ( curmove == LS_READY ) if ( curmove == LS_READY )
{//just standing there {//just standing there
@ -401,10 +401,8 @@ int PM_SaberAnimTransitionAnim( int curmove, int newmove )
case LS_A_TR2BL: case LS_A_TR2BL:
case LS_A_T2B: case LS_A_T2B:
if ( newmove == curmove ) 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... //going into an 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?)
if ( PM_SaberKataDone( curmove, newmove ) ) if ( PM_SaberKataDone( curmove, newmove ) )
{//done with this kata, must return to ready before attack again {//done with this kata, must return to ready before attack again
retmove = LS_R_TL2BR + (newmove-LS_A_TL2BR); retmove = LS_R_TL2BR + (newmove-LS_A_TL2BR);
@ -555,12 +553,11 @@ int PM_SaberMoveQuadrantForMovement( usercmd_t *ucmd )
{//backward= T2B slash //or B2T uppercut? {//backward= T2B slash //or B2T uppercut?
return Q_T; return Q_T;
} }
else //if ( curmove == LS_READY )//??? else
{//Not moving at all {//Not moving at all
return Q_R; return Q_R;
} }
} }
//return Q_R;//????
} }
//=================================================================== //===================================================================
@ -702,7 +699,7 @@ qboolean PM_SaberKataDone(int curmove, int newmove)
} }
} }
else 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 || if (newmove == LS_A_TL2BR ||
newmove == LS_A_L2R || newmove == LS_A_L2R ||
newmove == LS_A_BL2TR || newmove == LS_A_BL2TR ||
@ -756,7 +753,6 @@ void PM_SaberLockBreak( playerState_t *genemy, qboolean victory )
} }
else else
{ {
//loseAnim = BOTH_KNOCKDOWN4;
punishLoser = qtrue; punishLoser = qtrue;
} }
break; break;
@ -770,7 +766,6 @@ void PM_SaberLockBreak( playerState_t *genemy, qboolean victory )
} }
else else
{ {
//loseAnim = BOTH_BF1BREAK;
punishLoser = qtrue; punishLoser = qtrue;
} }
break; break;
@ -782,9 +777,8 @@ void PM_SaberLockBreak( playerState_t *genemy, qboolean victory )
} }
else else
{ {
genemy->saberMove = /*genemy->saberBounceMove =*/ LS_H1_BL; genemy->saberMove = LS_H1_BL;
genemy->saberBlocked = BLOCKED_PARRY_BROKEN; genemy->saberBlocked = BLOCKED_PARRY_BROKEN;
//loseAnim = BOTH_H1_S1_BR;
punishLoser = qtrue; punishLoser = qtrue;
} }
break; break;
@ -796,9 +790,8 @@ void PM_SaberLockBreak( playerState_t *genemy, qboolean victory )
} }
else else
{ {
genemy->saberMove = /*genemy->saberBounceMove =*/ LS_H1_BR; genemy->saberMove = LS_H1_BR;
genemy->saberBlocked = BLOCKED_PARRY_BROKEN; genemy->saberBlocked = BLOCKED_PARRY_BROKEN;
//loseAnim = BOTH_H1_S1_BL;
punishLoser = qtrue; punishLoser = qtrue;
} }
break; 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 ); PM_SetAnim( SETANIM_BOTH, winAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, -1 );
if (punishLoser) if (punishLoser)
{ { //someone lost the lock, so punish them by knocking them down
vec3_t oppDir; vec3_t oppDir;
int strength = 8; int strength = 8;
@ -829,7 +822,7 @@ void PM_SaberLockBreak( playerState_t *genemy, qboolean victory )
pm->checkDuelLoss = genemy->clientNum+1; pm->checkDuelLoss = genemy->clientNum+1;
} }
else else
{ { //If no one lost, then shove each player away from the other
vec3_t oppDir; vec3_t oppDir;
int strength = 4; int strength = 4;
@ -849,8 +842,7 @@ void PM_SaberLockBreak( playerState_t *genemy, qboolean victory )
genemy->forceHandExtend = HANDEXTEND_WEAPONREADY; genemy->forceHandExtend = HANDEXTEND_WEAPONREADY;
} }
pm->ps->weaponTime = 0;//pm->ps->torsoTimer; pm->ps->weaponTime = 0;
//The enemy unfortunately has no valid torso animation time at this point, so just use ours
genemy->weaponTime = 0; genemy->weaponTime = 0;
pm->ps->saberLockTime = genemy->saberLockTime = 0; pm->ps->saberLockTime = genemy->saberLockTime = 0;
@ -877,12 +869,7 @@ extern qboolean ValidAnimFileIndex ( int index );
void PM_SaberLocked( void ) void PM_SaberLocked( void )
{ {
int remaining = 0; int remaining = 0;
/*
if ( pm->ps->weaponTime )
{//can't attack yet
return;
}
*/
playerState_t *genemy = pm->bgClients[pm->ps->saberLockEnemy]; playerState_t *genemy = pm->bgClients[pm->ps->saberLockEnemy];
if ( !genemy ) if ( !genemy )
{ {
@ -906,13 +893,15 @@ void PM_SaberLocked( void )
genemy->weaponTime = 0; genemy->weaponTime = 0;
dist = DistanceSquared(pm->ps->origin,genemy->origin); dist = DistanceSquared(pm->ps->origin,genemy->origin);
if ( dist < 64 || dist > 6400 )//( dist < 128 || dist > 2304 ) if ( dist < 64 || dist > 6400 )
{//between 8 and 80 from each other//was 16 and 48 {//between 8 and 80 from each other
PM_SaberLockBreak( genemy, qfalse ); PM_SaberLockBreak( genemy, qfalse );
return; return;
} }
if ( (pm->cmd.buttons & BUTTON_ATTACK) || pm->ps->saberLockAdvance ) if ( (pm->cmd.buttons & BUTTON_ATTACK) || pm->ps->saberLockAdvance )
{//holding attack {//holding attack
animation_t *anim;
if (pm->ps->saberLockAdvance) if (pm->ps->saberLockAdvance)
{//tapping {//tapping
animation_t *anim; animation_t *anim;
@ -968,9 +957,7 @@ void PM_SaberLocked( void )
{ {
return; return;
} }
if( 1/*ValidAnimFileIndex( genemy->client->clientInfo.animFileIndex )*/ )
{
animation_t *anim;
anim = &pm->animations[(genemy->torsoAnim&~ANIM_TOGGLEBIT)]; anim = &pm->animations[(genemy->torsoAnim&~ANIM_TOGGLEBIT)];
if ( (genemy->torsoAnim&~ANIM_TOGGLEBIT) == BOTH_CWCIRCLELOCK || if ( (genemy->torsoAnim&~ANIM_TOGGLEBIT) == BOTH_CWCIRCLELOCK ||
@ -988,7 +975,6 @@ void PM_SaberLocked( void )
} }
} }
} }
}
else else
{//something broke us out of it {//something broke us out of it
PM_SaberLockBreak( genemy, qfalse ); PM_SaberLockBreak( genemy, qfalse );
@ -1011,8 +997,6 @@ qboolean PM_SaberInBrokenParry( int move )
int PM_BrokenParryForParry( 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 ) switch ( move )
{ {
case LS_PARRY_UP: case LS_PARRY_UP:
@ -1031,13 +1015,13 @@ int PM_BrokenParryForParry( int move )
return LS_H1_BR; return LS_H1_BR;
break; break;
case LS_READY: case LS_READY:
return LS_H1_B_;//??? return LS_H1_B_;
break; break;
} }
return LS_NONE; return LS_NONE;
} }
#define BACK_STAB_DISTANCE 128//64 #define BACK_STAB_DISTANCE 128
qboolean PM_CanBackstab(void) qboolean PM_CanBackstab(void)
{ {
@ -1068,7 +1052,6 @@ qboolean PM_CanBackstab(void)
saberMoveName_t PM_SaberFlipOverAttackMove(trace_t *tr) saberMoveName_t PM_SaberFlipOverAttackMove(trace_t *tr)
{ {
//FIXME: check above for room enough to jump!
vec3_t fwdAngles, jumpFwd; vec3_t fwdAngles, jumpFwd;
float zDiff = 0; float zDiff = 0;
playerState_t *psData; playerState_t *psData;
@ -1076,13 +1059,11 @@ saberMoveName_t PM_SaberFlipOverAttackMove(trace_t *tr)
VectorCopy( pm->ps->viewangles, fwdAngles ); VectorCopy( pm->ps->viewangles, fwdAngles );
fwdAngles[PITCH] = fwdAngles[ROLL] = 0; fwdAngles[PITCH] = fwdAngles[ROLL] = 0;
AngleVectors( fwdAngles, jumpFwd, NULL, NULL ); AngleVectors( fwdAngles, jumpFwd, NULL, NULL );
VectorScale( jumpFwd, /*100*/50, pm->ps->velocity ); VectorScale( jumpFwd, 50, pm->ps->velocity );
pm->ps->velocity[2] = 400; pm->ps->velocity[2] = 400;
psData = pm->bgClients[tr->entityNum]; 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 //go higher for enemies higher than you, lower for those lower than you
if (psData) if (psData)
{ {
@ -1108,7 +1089,7 @@ saberMoveName_t PM_SaberFlipOverAttackMove(trace_t *tr)
pm->ps->velocity[2] = 400; 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_AddEvent( EV_JUMP );
pm->ps->fd.forceJumpSound = 1; pm->ps->fd.forceJumpSound = 1;
@ -1161,7 +1142,6 @@ saberMoveName_t PM_SaberLungeAttackMove( void )
//do the lunge //do the lunge
AngleVectors( fwdAngles, jumpFwd, NULL, NULL ); AngleVectors( fwdAngles, jumpFwd, NULL, NULL );
VectorScale( jumpFwd, 150, pm->ps->velocity ); VectorScale( jumpFwd, 150, pm->ps->velocity );
//pm->ps->velocity[2] = 50;
PM_AddEvent( EV_JUMP ); PM_AddEvent( EV_JUMP );
return LS_A_LUNGE; return LS_A_LUNGE;
@ -1174,9 +1154,9 @@ saberMoveName_t PM_SaberJumpAttackMove( void )
VectorCopy( pm->ps->viewangles, fwdAngles ); VectorCopy( pm->ps->viewangles, fwdAngles );
fwdAngles[PITCH] = fwdAngles[ROLL] = 0; fwdAngles[PITCH] = fwdAngles[ROLL] = 0;
AngleVectors( fwdAngles, jumpFwd, NULL, NULL ); AngleVectors( fwdAngles, jumpFwd, NULL, NULL );
VectorScale( jumpFwd, /*200*/300, pm->ps->velocity ); VectorScale( jumpFwd, 300, pm->ps->velocity );
pm->ps->velocity[2] = 280;//180; pm->ps->velocity[2] = 280;
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_AddEvent( EV_JUMP );
pm->ps->fd.forceJumpSound = 1; pm->ps->fd.forceJumpSound = 1;
@ -1240,10 +1220,10 @@ saberMoveName_t PM_SaberAttackForMovement(saberMoveName_t curmove)
if ( pm->cmd.forwardmove > 0 ) if ( pm->cmd.forwardmove > 0 )
{//forward= T2B slash {//forward= T2B slash
if (pm->ps->fd.saberAnimLevel == FORCE_LEVEL_2 && if (pm->ps->fd.saberAnimLevel == FORCE_LEVEL_2 &&
/*pm->ps->groundEntityNum != ENTITYNUM_NONE &&*/
pm->ps->velocity[2] > 100 && pm->ps->velocity[2] > 100 &&
PM_GroundDistance() < 32 && PM_GroundDistance() < 32 &&
!BG_InSpecialJump(pm->ps->legsAnim)) !BG_InSpecialJump(pm->ps->legsAnim) &&
!BG_SaberInSpecialAttack(pm->ps->torsoAnim))
{ //FLIP AND DOWNWARD ATTACK { //FLIP AND DOWNWARD ATTACK
trace_t tr; trace_t tr;
@ -1253,8 +1233,10 @@ saberMoveName_t PM_SaberAttackForMovement(saberMoveName_t curmove)
} }
} }
else if (pm->ps->fd.saberAnimLevel == FORCE_LEVEL_1 && else if (pm->ps->fd.saberAnimLevel == FORCE_LEVEL_1 &&
pm->ps->groundEntityNum != ENTITYNUM_NONE &&
(pm->ps->pm_flags & PMF_DUCKED) && (pm->ps->pm_flags & PMF_DUCKED) &&
pm->ps->weaponTime <= 0) pm->ps->weaponTime <= 0 &&
!BG_SaberInSpecialAttack(pm->ps->torsoAnim))
{ //LUNGE (weak) { //LUNGE (weak)
newmove = PM_SaberLungeAttackMove(); newmove = PM_SaberLungeAttackMove();
} }
@ -1265,7 +1247,7 @@ saberMoveName_t PM_SaberAttackForMovement(saberMoveName_t curmove)
} }
else if ( pm->cmd.forwardmove < 0 ) else if ( pm->cmd.forwardmove < 0 )
{//backward= T2B slash//B2T uppercut? {//backward= T2B slash//B2T uppercut?
if (PM_CanBackstab()) if (PM_CanBackstab() && !BG_SaberInSpecialAttack(pm->ps->torsoAnim))
{ //BACKSTAB (attack varies by level) { //BACKSTAB (attack varies by level)
if (pm->ps->fd.saberAnimLevel >= FORCE_LEVEL_2) if (pm->ps->fd.saberAnimLevel >= FORCE_LEVEL_2)
{//medium and higher attacks {//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 //prediction values. Under laggy conditions this will cause the appearance of rapid swing
//sequence changes. //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. 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: case BLOCKED_ATK_BOUNCE:
// If there is absolutely no blocked move in the chart, don't even mess with the animation. // 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. // 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? {//an actual bounce? Other bounces before this are actually transitions?
pm->ps->saberBlocked = BLOCKED_NONE; pm->ps->saberBlocked = BLOCKED_NONE;
} }
@ -1690,8 +1671,6 @@ weapChecks:
// Check for WEAPON ATTACK // 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) if(!delayed_fire)
{ {
// Start with the current move, and cross index it with the current control states. // Start with the current move, and cross index it with the current control states.
@ -1704,7 +1683,7 @@ weapChecks:
curmove = LS_READY; curmove = LS_READY;
} }
// check for fire // check for fire
if ( !(pm->cmd.buttons & (BUTTON_ATTACK/*|BUTTON_ALT_ATTACK*/)) ) if ( !(pm->cmd.buttons & (BUTTON_ATTACK)) )
{ {
if (pm->ps->weaponTime != 0) if (pm->ps->weaponTime != 0)
{//Still firing {//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? 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 {//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); saberMoveName_t checkMove = PM_SaberAttackForMovement(curmove);
if (checkMove != -1) if (checkMove != -1)
{ {
@ -1820,41 +1793,19 @@ weapChecks:
{//we came from a bounce and cannot chain to another attack because our kata is done {//we came from a bounce and cannot chain to another attack because our kata is done
newmove = saberMoveData[curmove].chain_idle; 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 ) if ( newmove != LS_NONE )
{ {
//Now get the proper transition move //Now get the proper transition move
newmove = PM_SaberAnimTransitionAnim( curmove, newmove ); 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 || assert( bgGlobalAnimations[saberMoveData[newmove].animToUse].firstFrame != 0 ||
bgGlobalAnimations[saberMoveData[newmove].animToUse].numFrames != 0); bgGlobalAnimations[saberMoveData[newmove].animToUse].numFrames != 0);
if (1)
{
anim = saberMoveData[newmove].animToUse; anim = saberMoveData[newmove].animToUse;
} }
} }
}
if (anim == -1) if (anim == -1)
{//not side-stepping, pick neutral anim {//not side-stepping, pick neutral anim
@ -1890,7 +1841,7 @@ weapChecks:
} }
if (anim == BOTH_RUN2 && !pm->cmd.forwardmove && !pm->cmd.rightmove) 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(); anim = PM_GetSaberStance();
} }
newmove = LS_READY; newmove = LS_READY;
@ -2021,8 +1972,6 @@ void PM_SetSaberMove(short newMove)
!PM_JumpingAnim( pm->ps->legsAnim ) && !PM_JumpingAnim( pm->ps->legsAnim ) &&
!BG_InSpecialJump( pm->ps->legsAnim ) && !BG_InSpecialJump( pm->ps->legsAnim ) &&
anim != PM_GetSaberStance() && anim != PM_GetSaberStance() &&
//!PM_CrouchAnim( pm->ps->legsAnim ) &&
//pm->cmd.upmove >= 0 &&
pm->ps->groundEntityNum != ENTITYNUM_NONE && pm->ps->groundEntityNum != ENTITYNUM_NONE &&
!(pm->ps->pm_flags & PMF_DUCKED)) !(pm->ps->pm_flags & PMF_DUCKED))
{ {
@ -2047,7 +1996,7 @@ void PM_SetSaberMove(short newMove)
pm->ps->saberMove = newMove; pm->ps->saberMove = newMove;
pm->ps->saberBlocking = saberMoveData[newMove].blocking; pm->ps->saberBlocking = saberMoveData[newMove].blocking;
pm->ps->torsoAnim = anim;//saberMoveData[newMove].animToUse; pm->ps->torsoAnim = anim;
if (pm->ps->weaponTime <= 0) 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 1, // int energyPerShot; // Amount of energy used per shot
100, // int fireTime; // Amount of time between firings 100, // int fireTime; // Amount of time between firings
8192, // int range; // Range of weapon 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 800, // int altFireTime; // Amount of time between alt-firings
8192, // int altRange; // Range of alt-fire 8192, // int altRange; // Range of alt-fire
0, // int chargeSubTime; // ms interval for subtracting ammo during charge 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 10, // int energyPerShot; // Amount of energy used per shot
700, // int fireTime; // Amount of time between firings 700, // int fireTime; // Amount of time between firings
8192, // int range; // Range of weapon 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 800, // int altFireTime; // Amount of time between alt-firings
8192, // int altRange; // Range of alt-fire 8192, // int altRange; // Range of alt-fire
0, // int chargeSubTime; // ms interval for subtracting ammo during charge 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; pm.tracemask = MASK_PLAYERSOLID & ~CONTENTS_BODY;
} }
else if ( ent->r.svFlags & SVF_BOT ) { else if ( ent->r.svFlags & SVF_BOT ) {
pm.tracemask = MASK_PLAYERSOLID | CONTENTS_BOTCLIP; pm.tracemask = MASK_PLAYERSOLID | CONTENTS_MONSTERCLIP;
} }
else { else {
pm.tracemask = MASK_PLAYERSOLID; pm.tracemask = MASK_PLAYERSOLID;
@ -1643,7 +1643,7 @@ void ClientThink_real( gentity_t *ent ) {
// check for respawning // check for respawning
if ( client->ps.stats[STAT_HEALTH] <= 0 ) { if ( client->ps.stats[STAT_HEALTH] <= 0 ) {
// wait for the attack button to be pressed // 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 // forcerespawn is to prevent users from waiting out powerups
if ( g_forcerespawn.integer > 0 && if ( g_forcerespawn.integer > 0 &&
( level.time - client->respawnTime ) > g_forcerespawn.integer * 1000 ) { ( level.time - client->respawnTime ) > g_forcerespawn.integer * 1000 ) {
@ -1656,6 +1656,10 @@ void ClientThink_real( gentity_t *ent ) {
respawn( ent ); respawn( ent );
} }
} }
else if (gDoSlowMoDuel)
{
client->respawnTime = level.time + 1000;
}
return; return;
} }

View file

@ -1277,7 +1277,10 @@ void ClientUserinfoChanged( int clientNum ) {
trap_SetConfigstring( CS_PLAYERS+clientNum, s ); 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 ) && !AllForceDisabled( g_forcePowerDisable.integer )
&& g_trueJedi.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 ) ) if ( WP_HasForcePowers( &client->ps ) )
{ {
client->ps.trueNonJedi = qfalse; client->ps.trueNonJedi = qfalse;
@ -1758,13 +1801,23 @@ void ClientSpawn(gentity_t *ent) {
{ {
client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_BRYAR_PISTOL ); 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_SABER);
client->ps.stats[STAT_WEAPONS] |= (1 << WP_STUN_BATON); client->ps.stats[STAT_WEAPONS] |= (1 << WP_STUN_BATON);
client->ps.ammo[AMMO_POWERCELL] = ammoData[AMMO_POWERCELL].max;
client->ps.weapon = WP_BRYAR_PISTOL; client->ps.weapon = WP_BRYAR_PISTOL;
} }
} }
else else
{ {//jediVmerc is incompatible with this gametype, turn it off!
trap_Cvar_Set( "g_jediVmerc", "0" );
if (g_gametype.integer == GT_HOLOCRON) if (g_gametype.integer == GT_HOLOCRON)
{ {
//always get free saber level 1 in holocron //always get free saber level 1 in holocron

View file

@ -502,10 +502,13 @@ void Cmd_Kill_f( gentity_t *ent ) {
} }
if (g_gametype.integer == GT_TOURNAMENT && level.numPlayingClients > 1 && !level.warmupTime) if (g_gametype.integer == GT_TOURNAMENT && level.numPlayingClients > 1 && !level.warmupTime)
{
if (!g_allowDuelSuicide.integer)
{ {
trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStripEdString("SVINGAME", "ATTEMPTDUELKILL")) ); trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStripEdString("SVINGAME", "ATTEMPTDUELKILL")) );
return; return;
} }
}
ent->flags &= ~FL_GODMODE; ent->flags &= ~FL_GODMODE;
ent->client->ps.stats[STAT_HEALTH] = ent->health = -999; ent->client->ps.stats[STAT_HEALTH] = ent->health = -999;
@ -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]; int counts[TEAM_NUM_TEAMS];
counts[TEAM_BLUE] = TeamCount( ent->client->ps.clientNum, TEAM_BLUE ); counts[TEAM_BLUE] = TeamCount( ent->client->ps.clientNum, TEAM_BLUE );
@ -1407,6 +1410,109 @@ static const char *gameNames[] = {
"Capture the Ysalamiri" "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 Cmd_CallVote_f
@ -1466,7 +1572,8 @@ void Cmd_CallVote_f( gentity_t *ent ) {
} }
// special case for g_gametype, check for bad values // special case for g_gametype, check for bad values
if ( !Q_stricmp( arg1, "g_gametype" ) ) { if ( !Q_stricmp( arg1, "g_gametype" ) )
{
i = atoi( arg2 ); i = atoi( arg2 );
if( i == GT_SINGLE_PLAYER || i < GT_FFA || i >= GT_MAX_GAME_TYPE) { if( i == GT_SINGLE_PLAYER || i < GT_FFA || i >= GT_MAX_GAME_TYPE) {
trap_SendServerCommand( ent-g_entities, "print \"Invalid gametype.\n\"" ); 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.voteString, sizeof( level.voteString ), "%s %d", arg1, i );
Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "%s %s", arg1, gameNames[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 // 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 // this allows a player to change maps, but not upset the map rotation
char s[MAX_STRING_CHARS]; 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.voteString, sizeof( level.voteString ), "%s %s", arg1, arg2 );
} }
Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "%s", level.voteString ); 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]; char s[MAX_STRING_CHARS];
trap_Cvar_VariableStringBuffer( "nextmap", s, sizeof(s) ); 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.voteString, sizeof( level.voteString ), "vstr nextmap");
Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "%s", level.voteString ); 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.voteString, sizeof( level.voteString ), "%s \"%s\"", arg1, arg2 );
Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "%s", level.voteString ); 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 #ifdef _DEBUG
extern stringID_table_t animTable[MAX_ANIMATIONS+1]; 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) 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); 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(); int argNum = trap_Argc();
char arg[MAX_STRING_CHARS]; char arg[MAX_STRING_CHARS];
@ -2249,12 +2400,28 @@ void Cmd_DebugSetBodyAnim_f(gentity_t *self)
pmv.gametype = g_gametype.integer; pmv.gametype = g_gametype.integer;
pm = &pmv; 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); Com_Printf("Set body anim to %s\n", arg);
} }
#endif #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); void DismembermentTest(gentity_t *self);
#ifdef _DEBUG #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. //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. //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 )) else if (Q_stricmp(cmd, "headexplodey") == 0 && CheatsOk( ent ))
{ {
Cmd_Kill_f (ent); Cmd_Kill_f (ent);
@ -2493,6 +2661,67 @@ void ClientCommand( int clientNum ) {
{ {
G_CreateExampleAnimEnt(ent); 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) 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); Cmd_ToggleSaber_f(ent);
@ -2521,7 +2750,7 @@ void ClientCommand( int clientNum ) {
} }
else if (Q_stricmp(cmd, "debugSetBodyAnim") == 0) 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) else if (Q_stricmp(cmd, "debugDismemberment") == 0)
{ {
@ -2544,6 +2773,21 @@ void ClientCommand( int clientNum ) {
DismembermentByNum(ent, iArg); 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 #endif
else else

View file

@ -890,6 +890,527 @@ void CheckAlmostCapture( gentity_t *self, gentity_t *attacker ) {
#endif #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 ) 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 {//FIXME: play dead flop anims on body if in an appropriate _DEAD anim when this func is called
int deathAnim = -1; int deathAnim = -1;
@ -1034,6 +1555,13 @@ int G_PickDeathAnim( gentity_t *self, vec3_t point, int damage, int mod, int hit
deathAnim = -2; deathAnim = -2;
break; break;
} }
if ( deathAnim == -1 )
{
if (self->client)
{
deathAnim = G_CheckSpecialDeathAnim( self, point, damage, mod, hitLoc );
}
if (deathAnim == -1) if (deathAnim == -1)
{ {
//death anims //death anims
@ -1236,6 +1764,7 @@ int G_PickDeathAnim( gentity_t *self, vec3_t point, int damage, int mod, int hit
break; break;
} }
} }
}
return deathAnim; return deathAnim;
} }
@ -1282,6 +1811,15 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int
return; 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 && if (inflictor && inflictor->activator && !inflictor->client && !attacker->client &&
inflictor->activator->client && inflictor->activator->inuse && inflictor->activator->client && inflictor->activator->inuse &&
inflictor->s.weapon == WP_TURRET) inflictor->s.weapon == WP_TURRET)
@ -2180,7 +2718,7 @@ void G_Dismember( gentity_t *ent, vec3_t point, int limbType, float limbRollBase
else else
{ {
limb->s.modelindex = -1; limb->s.modelindex = -1;
limb->s.modelindex2 = ent->s.number; limb->s.otherEntityNum2 = ent->s.number;
} }
trap_LinkEntity( limb ); 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 {//less explosive damage for jedi, more saber damage for non-jedi
if ( client->ps.trueJedi ) if ( client->ps.trueJedi )
{//if the target is a trueJedi, reduce splash and explosive damage to 1/2 {//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_TRIP_MINE_SPLASH:
case MOD_TIMED_MINE_SPLASH: case MOD_TIMED_MINE_SPLASH:
case MOD_DET_PACK_SPLASH: case MOD_DET_PACK_SPLASH:
damage *= 0.5; damage *= 0.75;
break; break;
} }
} }

View file

@ -792,6 +792,8 @@ void DeathmatchScoreboardMessage (gentity_t *client);
// g_main.c // g_main.c
// //
extern vmCvar_t g_ff_objectives; extern vmCvar_t g_ff_objectives;
extern qboolean gDoSlowMoDuel;
extern int gSlowMoDuelTime;
void FindIntermissionPoint( void ); void FindIntermissionPoint( void );
void SetLeader(int team, int client); void SetLeader(int team, int client);
@ -964,10 +966,22 @@ extern vmCvar_t g_saberGhoul2Collision;
extern vmCvar_t g_saberAlwaysBoxTrace; extern vmCvar_t g_saberAlwaysBoxTrace;
extern vmCvar_t g_saberBoxTraceSize; 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_forceRegenTime;
extern vmCvar_t g_spawnInvulnerability; extern vmCvar_t g_spawnInvulnerability;
extern vmCvar_t g_forcePowerDisable; extern vmCvar_t g_forcePowerDisable;
extern vmCvar_t g_weaponDisable; extern vmCvar_t g_weaponDisable;
extern vmCvar_t g_allowDuelSuicide;
extern vmCvar_t g_fraglimitVoteCorrection;
extern vmCvar_t g_duelWeaponDisable; extern vmCvar_t g_duelWeaponDisable;
extern vmCvar_t g_fraglimit; extern vmCvar_t g_fraglimit;
extern vmCvar_t g_duel_fraglimit; extern vmCvar_t g_duel_fraglimit;

View file

@ -40,11 +40,21 @@ vmCvar_t g_saberGhoul2Collision;
vmCvar_t g_saberAlwaysBoxTrace; vmCvar_t g_saberAlwaysBoxTrace;
vmCvar_t g_saberBoxTraceSize; 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_forceRegenTime;
vmCvar_t g_spawnInvulnerability; vmCvar_t g_spawnInvulnerability;
vmCvar_t g_forcePowerDisable; vmCvar_t g_forcePowerDisable;
vmCvar_t g_weaponDisable; vmCvar_t g_weaponDisable;
vmCvar_t g_duelWeaponDisable; vmCvar_t g_duelWeaponDisable;
vmCvar_t g_allowDuelSuicide;
vmCvar_t g_fraglimitVoteCorrection;
vmCvar_t g_fraglimit; vmCvar_t g_fraglimit;
vmCvar_t g_duel_fraglimit; vmCvar_t g_duel_fraglimit;
vmCvar_t g_timelimit; vmCvar_t g_timelimit;
@ -136,7 +146,7 @@ static cvarTable_t gameCvarTable[] = {
// change anytime vars // change anytime vars
{ &g_ff_objectives, "g_ff_objectives", "0", /*CVAR_SERVERINFO |*/ CVAR_NORESTART, 0, qtrue }, { &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_autoMapCycle, "g_autoMapCycle", "0", CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue },
{ &g_dmflags, "dmflags", "0", CVAR_SERVERINFO | CVAR_ARCHIVE, 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_saberAlwaysBoxTrace, "g_saberAlwaysBoxTrace", "0", 0, 0, qtrue },
{ &g_saberBoxTraceSize, "g_saberBoxTraceSize", "2", 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_forceRegenTime, "g_forceRegenTime", "200", CVAR_SERVERINFO | CVAR_ARCHIVE, 0, qtrue },
{ &g_spawnInvulnerability, "g_spawnInvulnerability", "3000", 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_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_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_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_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 }, { &g_timelimit, "timelimit", "0", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue },
@ -1685,6 +1707,11 @@ void CheckExitRules( void ) {
return; return;
} }
if (gDoSlowMoDuel)
{ //don't go to intermission while in slow motion
return;
}
if (gEscaping) if (gEscaping)
{ {
int i = 0; int i = 0;
@ -2001,6 +2028,28 @@ void CheckVote( void ) {
{ //otherwise, just leave the map until a restart { //otherwise, just leave the map until a restart
G_RefreshNextMap(level.votingGametypeTo, qfalse); 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.votingGametype = qfalse;
level.votingGametypeTo = 0; level.votingGametypeTo = 0;
} }
@ -2196,6 +2245,9 @@ void G_RunThink (gentity_t *ent) {
int g_LastFrameTime = 0; int g_LastFrameTime = 0;
int g_TimeSinceLastFrame = 0; int g_TimeSinceLastFrame = 0;
qboolean gDoSlowMoDuel = qfalse;
int gSlowMoDuelTime = 0;
/* /*
================ ================
G_RunFrame G_RunFrame
@ -2210,6 +2262,63 @@ void G_RunFrame( int levelTime ) {
int msec; 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 we are waiting for the level to restart, do nothing
if ( level.restarted ) { if ( level.restarted ) {
return; return;
@ -2295,7 +2404,7 @@ int start, end;
{ {
G_CheckClientTimeouts ( ent ); 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_ForcePowersUpdate(ent, &ent->client->pers.cmd );
WP_SaberPositionUpdate(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 //rww - here starts the main example g2animent stuff
#define ANIMENT_TYPE_STORMTROOPER 0 #define ANIMENT_TYPE_STORMTROOPER 0
#define ANIMENT_TYPE_RODIAN 1 #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_PAIN_SOUNDS 4
#define TROOPER_DEATH_SOUNDS 3 #define TROOPER_DEATH_SOUNDS 3
@ -1567,12 +1570,245 @@ int gRodianSound_Pain[RODIAN_PAIN_SOUNDS];
int gRodianSound_Death[RODIAN_DEATH_SOUNDS]; int gRodianSound_Death[RODIAN_DEATH_SOUNDS];
int gRodianSound_Alert[RODIAN_ALERT_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 ); int G_PickDeathAnim( gentity_t *self, vec3_t point, int damage, int mod, int hitLoc );
void AnimEntFireWeapon( gentity_t *ent, qboolean altFire ); void AnimEntFireWeapon( gentity_t *ent, qboolean altFire );
int GetNearestVisibleWP(vec3_t org, int ignore); int GetNearestVisibleWP(vec3_t org, int ignore);
int InFieldOfVision(vec3_t viewangles, float fov, vec3_t angles); int InFieldOfVision(vec3_t viewangles, float fov, vec3_t angles);
extern float gBotEdit; 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) void ExampleAnimEntAlertOthers(gentity_t *self)
{ {
//alert all the other animents in the area //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].s.eType == ET_GRAPPLE &&
g_entities[i].health > 0) 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].bolt_Motion = self->bolt_Motion;
g_entities[i].speed = level.time + 4000; //4 seconds til we forget about the enemy 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); 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) { //?! (bad)
self->s.torsoAnim = BOTH_DEATH1; 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)]); 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) if (mod == MOD_SABER)
{ //Set the velocity up a bit to make the limb fly up more than it otherwise would. { //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); 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) if (self->bolt_Motion != ENTITYNUM_NONE)
{ {
ExampleAnimEntAlertOthers(self); ExampleAnimEntAlertOthers(self);
@ -1671,6 +1922,11 @@ void ExampleAnimEnt_Pain(gentity_t *self, gentity_t *attacker, int damage)
self->s.legsAnim = painAnim; self->s.legsAnim = painAnim;
self->bolt_LArm = level.time + animLen; 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) if (self->watertype == ANIMENT_TYPE_STORMTROOPER)
{ {
G_Sound(self, CHAN_AUTO, gTrooperSound_Pain[Q_irand(0, TROOPER_PAIN_SOUNDS-1)]); G_Sound(self, CHAN_AUTO, gTrooperSound_Pain[Q_irand(0, TROOPER_PAIN_SOUNDS-1)]);
@ -1679,8 +1935,18 @@ 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)]); G_Sound(self, CHAN_AUTO, gRodianSound_Pain[Q_irand(0, RODIAN_PAIN_SOUNDS-1)]);
} }
else if (self->watertype == ANIMENT_TYPE_JAN)
{
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 && self->bolt_Motion == ENTITYNUM_NONE) 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->bolt_Motion = attacker->s.number;
self->speed = level.time + 4000; //4 seconds til we forget about the enemy self->speed = level.time + 4000; //4 seconds til we forget about the enemy
@ -1688,6 +1954,7 @@ void ExampleAnimEnt_Pain(gentity_t *self, gentity_t *attacker, int damage)
self->bolt_RArm = level.time + Q_irand(500, 1000); self->bolt_RArm = level.time + Q_irand(500, 1000);
} }
} }
}
void ExampleAnimEntTouch(gentity_t *self, gentity_t *other, trace_t *trace) void ExampleAnimEntTouch(gentity_t *self, gentity_t *other, trace_t *trace)
{ {
@ -1844,11 +2111,28 @@ qboolean ExampleAnimEntClearLOS(gentity_t *self, vec3_t point)
trap_Trace(&tr, self->r.currentOrigin, 0, 0, point, self->s.number, self->clipmask); trap_Trace(&tr, self->r.currentOrigin, 0, 0, point, self->s.number, self->clipmask);
if (ExampleAnimEntAlignment(self) == ANIMENT_ALIGNED_GOOD)
{
if (tr.fraction == 1 || if (tr.fraction == 1 ||
tr.entityNum < MAX_CLIENTS) (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. { //clear LOS, or would be hitting a client (they're all bad!), so fire.
return qtrue; return qtrue;
} }
}
return qfalse; return qfalse;
} }
@ -1872,10 +2156,22 @@ void ExampleAnimEntWeaponHandling(gentity_t *self)
{ {
AnimEntFireWeapon(self, qfalse); AnimEntFireWeapon(self, qfalse);
G_AddEvent(self, EV_FIRE_WEAPON, 0); G_AddEvent(self, EV_FIRE_WEAPON, 0);
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); self->bolt_RArm = level.time + Q_irand(700, 1000);
} }
} }
} }
}
qboolean ExampleAnimEntWayValidCheck(gentity_t *self) qboolean ExampleAnimEntWayValidCheck(gentity_t *self)
{ {
@ -2002,9 +2298,39 @@ void ExampleAnimEntEnemyHandling(gentity_t *self, float enDist)
int bestIndex = -1; int bestIndex = -1;
float minDist = enDist; float minDist = enDist;
if (ExampleAnimEntAlignment(self) == ANIMENT_ALIGNED_GOOD)
{
while (i < MAX_GENTITIES)
{
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 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++;
}
}
else
{
while (i < MAX_CLIENTS) while (i < MAX_CLIENTS)
{ {
if (g_entities[i].inuse && g_entities[i].client && g_entities[i].health > 0 && g_entities[i].client->sess.sessionTeam != TEAM_SPECTATOR) 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; vec3_t checkLen;
float fCheckLen; float fCheckLen;
@ -2028,6 +2354,38 @@ void ExampleAnimEntEnemyHandling(gentity_t *self, float enDist)
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++;
}
}
}
if (bestIndex != -1) if (bestIndex != -1)
{ {
self->bolt_Motion = bestIndex; self->bolt_Motion = bestIndex;
@ -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)]); 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 (gWPNum > 0)
{ {
if (self->bolt_Motion != ENTITYNUM_NONE && if (self->bolt_Motion != ENTITYNUM_NONE &&
@ -2123,6 +2507,19 @@ void ExampleAnimEntUpdateSelf(gentity_t *self)
hasEnemyLOS = ExampleAnimEntClearLOS(self, enemyOrigin); 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) if (hasEnemyLOS && enDist < 512 && self->splashRadius < level.time)
{ {
@ -2164,9 +2561,16 @@ void ExampleAnimEntUpdateSelf(gentity_t *self)
} }
if (self->bolt_Motion == ENTITYNUM_NONE) if (self->bolt_Motion == ENTITYNUM_NONE)
{
if (ExampleAnimEntAlignment(self) == ANIMENT_ALIGNED_GOOD)
{
runSpeed = 18;
}
else
{ {
runSpeed = 6; runSpeed = 6;
} }
}
didMove = ExampleAnimEntMove(self, goalPos, runSpeed); didMove = ExampleAnimEntMove(self, goalPos, runSpeed);
@ -2189,17 +2593,49 @@ 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); ExampleAnimEntEnemyHandling(self, enDist);
if (self->bolt_Motion != ENTITYNUM_NONE && if (self->bolt_Motion != ENTITYNUM_NONE &&
g_entities[self->bolt_Motion].inuse && 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) 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)
{
if (g_entities[self->bolt_Motion].client->pers.cmd.upmove < 0) if (g_entities[self->bolt_Motion].client->pers.cmd.upmove < 0)
{ {
enemyOrigin[2] -= 8; enemyOrigin[2] -= 8;
@ -2208,6 +2644,7 @@ void ExampleAnimEntUpdateSelf(gentity_t *self)
{ {
enemyOrigin[2] += 8; enemyOrigin[2] += 8;
} }
}
hasEnemyLOS = ExampleAnimEntClearLOS(self, enemyOrigin); hasEnemyLOS = ExampleAnimEntClearLOS(self, enemyOrigin);
} }
@ -2219,7 +2656,7 @@ void ExampleAnimEntUpdateSelf(gentity_t *self)
vec3_t selfAimOrg; vec3_t selfAimOrg;
vec3_t myZeroPitchAngles; vec3_t myZeroPitchAngles;
VectorCopy(g_entities[self->bolt_Motion].client->ps.origin, enAimOrg); VectorCopy(enOrigin, enAimOrg);
VectorCopy(self->r.currentOrigin, selfAimOrg); VectorCopy(self->r.currentOrigin, selfAimOrg);
enAimOrg[2] = selfAimOrg[2]; enAimOrg[2] = selfAimOrg[2];
@ -2271,8 +2708,8 @@ void ExampleAnimEntUpdateSelf(gentity_t *self)
if (didMove == 1) 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.torsoAnim = BOTH_WALK1;
self->s.legsAnim = BOTH_WALK1; self->s.legsAnim = BOTH_WALK1;
} }
@ -2306,7 +2743,7 @@ void ExampleAnimEntUpdateSelf(gentity_t *self)
VectorCopy(preserveAngles, self->s.apos.trBase); 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; gentity_t *animEnt;
vec3_t playerMins; 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"); 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 = G_Spawn();
animEnt->watertype = aeType; //set the animent type 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. animEnt->s.eType = ET_GRAPPLE; //ET_GRAPPLE is the reserved special type for G2 anim ents.
if (animEnt->watertype == ANIMENT_TYPE_STORMTROOPER) 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" ); 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 else
{ {
G_Error("Unknown AnimEnt type!\n"); 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. 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. 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; int gEscapeTime = 0;
#ifdef ANIMENT_SPAWNER #ifdef ANIMENT_SPAWNER
int AESpawner_CountAnimEnts(void) int AESpawner_CountAnimEnts(gentity_t *spawner, qboolean onlySameType)
{ {
int i = 0; int i = 0;
int count = 0; int count = 0;
@ -2441,9 +2938,29 @@ int AESpawner_CountAnimEnts(void)
while (i < MAX_GENTITIES) while (i < MAX_GENTITIES)
{ {
if (g_entities[i].inuse && g_entities[i].s.eType == ET_GRAPPLE) if (g_entities[i].inuse && g_entities[i].s.eType == ET_GRAPPLE)
{
if (!onlySameType)
{ {
count++; 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++; i++;
} }
@ -2500,6 +3017,7 @@ qboolean AESpawner_PassAnimEntPVSCheck(gentity_t *ent)
void AESpawner_Think(gentity_t *ent) void AESpawner_Think(gentity_t *ent)
{ {
int animEntCount; int animEntCount;
animentCustomInfo_t *aeInfo = NULL;
if (gBotEdit) if (gBotEdit)
{ {
@ -2513,7 +3031,13 @@ void AESpawner_Think(gentity_t *ent)
} }
else else
{ {
animEntCount = AESpawner_CountAnimEnts(); qboolean onlySameType = qfalse;
if (ent->bolt_RLeg)
{
onlySameType = qtrue;
}
animEntCount = AESpawner_CountAnimEnts(ent, onlySameType);
} }
if (animEntCount < ent->bolt_LLeg) if (animEntCount < ent->bolt_LLeg)
@ -2533,7 +3057,11 @@ void AESpawner_Think(gentity_t *ent)
{ {
if (AESpawner_PassAnimEntPVSCheck(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. //0 is unlimited, but that could cause horrible disaster.
G_SpawnInt( "spawntype", "0", &ent->watertype); G_SpawnInt( "spawntype", "0", &ent->watertype);
//Spawn type. 0 is stormtrooper, 1 is rodian. //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 //Just precache the assets now
if (ent->watertype == ANIMENT_TYPE_STORMTROOPER) 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" ); 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->think = AESpawner_Think;
ent->nextthink = level.time + Q_irand(50, 500); 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) void G_CreateExampleAnimEnt(gentity_t *ent)
{ {
vec3_t fwd, fwdPos; 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); 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[1] = ent->client->ps.origin[1] + fwd[1]*128;
fwdPos[2] = ent->client->ps.origin[2] + fwd[2]*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 //rww - here ends the main example g2animent stuff

View file

@ -189,9 +189,25 @@ qboolean OnSameTeam( gentity_t *ent1, gentity_t *ent2 ) {
} }
if (g_gametype.integer == GT_SINGLE_PLAYER) if (g_gametype.integer == GT_SINGLE_PLAYER)
{
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 qtrue;
} }
return qfalse;
}
if ( g_gametype.integer < GT_TEAM ) { if ( g_gametype.integer < GT_TEAM ) {
return qfalse; return qfalse;

View file

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

View file

@ -672,7 +672,7 @@ extern vec4_t colorDkBlue;
#define Q_COLOR_ESCAPE '^' #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!!!! // 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' #define COLOR_BLACK '0'

View file

@ -12,8 +12,8 @@
#define CONTENTS_WATER 0x00000004 #define CONTENTS_WATER 0x00000004
#define CONTENTS_FOG 0x00000008 #define CONTENTS_FOG 0x00000008
#define CONTENTS_PLAYERCLIP 0x00000010 #define CONTENTS_PLAYERCLIP 0x00000010
#define CONTENTS_MONSTERCLIP 0x00000020 #define CONTENTS_MONSTERCLIP 0x00000020 // Physically block bots
#define CONTENTS_BOTCLIP 0x00000040 #define CONTENTS_BOTCLIP 0x00000040 // A hint for bots - do not enter this brush by navigation (if possible)
#define CONTENTS_SHOTCLIP 0x00000080 #define CONTENTS_SHOTCLIP 0x00000080
#define CONTENTS_BODY 0x00000100 // should never be on a brush, only in game #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 #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... // 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) 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 // Current version of the multi player game
#define Q3_VERSION "JK2MP: v1.03" #define Q3_VERSION "JK2MP: v1.04"
//end //end

View file

@ -321,8 +321,8 @@ qboolean Netchan_Process( netchan_t *chan, msg_t *msg ) {
// read the fragment information // read the fragment information
if ( fragmented ) { if ( fragmented ) {
fragmentStart = MSG_ReadShort( msg ); fragmentStart = (unsigned short)MSG_ReadShort( msg );
fragmentLength = MSG_ReadShort( msg ); fragmentLength = (unsigned short)MSG_ReadShort( msg );
} else { } else {
fragmentStart = 0; // stop warning message fragmentStart = 0; // stop warning message
fragmentLength = 0; fragmentLength = 0;
@ -425,10 +425,10 @@ qboolean Netchan_Process( netchan_t *chan, msg_t *msg ) {
return qfalse; return qfalse;
} }
if ( chan->fragmentLength > msg->maxsize ) { if ( chan->fragmentLength+4 > msg->maxsize ) {
Com_Printf( "%s:fragmentLength %i > msg->maxsize\n" Com_Printf( "%s:fragmentLength %i > msg->maxsize\n"
, NET_AdrToString (chan->remoteAddress ), , NET_AdrToString (chan->remoteAddress ),
chan->fragmentLength ); chan->fragmentLength+4 );
return qfalse; return qfalse;
} }
@ -437,10 +437,6 @@ qboolean Netchan_Process( netchan_t *chan, msg_t *msg ) {
// make sure the sequence number is still there // make sure the sequence number is still there
*(int *)msg->data = LittleLong( sequence ); *(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 ); Com_Memcpy( msg->data + 4, chan->fragmentBuffer, chan->fragmentLength );
msg->cursize = chan->fragmentLength + 4; msg->cursize = chan->fragmentLength + 4;
chan->fragmentLength = 0; 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 UPDATE_SERVER_NAME "updatejk2.ravensoft.com"
#define MASTER_SERVER_NAME "masterjk2.ravensoft.com" #define MASTER_SERVER_NAME "masterjk2.ravensoft.com"

View file

@ -671,6 +671,7 @@ static void SV_Status_f( void )
const char *s; const char *s;
int ping; int ping;
char state[32]; char state[32];
qboolean avoidTruncation = qfalse;
// make sure server is running // make sure server is running
if ( !com_sv_running->integer ) if ( !com_sv_running->integer )
@ -679,6 +680,14 @@ static void SV_Status_f( void )
return; return;
} }
if ( Cmd_Argc() > 1 )
{
if (!Q_stricmp("notrunc", Cmd_Argv(1)))
{
avoidTruncation = qtrue;
}
}
Com_Printf ("map: %s\n", sv_mapname->string ); Com_Printf ("map: %s\n", sv_mapname->string );
Com_Printf ("num score ping name lastmsg address qport rate\n"); Com_Printf ("num score ping name lastmsg address qport rate\n");
@ -706,6 +715,9 @@ static void SV_Status_f( void )
ps = SV_GameClientNum( i ); ps = SV_GameClientNum( i );
s = NET_AdrToString( cl->netchan.remoteAddress ); s = NET_AdrToString( cl->netchan.remoteAddress );
if (!avoidTruncation)
{
Com_Printf ("%3i %5i %s %-15.15s %7i %21s %5i %5i\n", Com_Printf ("%3i %5i %s %-15.15s %7i %21s %5i %5i\n",
i, i,
ps->persistant[PERS_SCORE], ps->persistant[PERS_SCORE],
@ -717,6 +729,20 @@ static void SV_Status_f( void )
cl->rate 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"); 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_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 // NET_Sleep will give the OS time slices until either get a packet
// or time enough for a server frame has gone by // or time enough for a server frame has gone by
NET_Sleep(frameMsec - sv.timeResidual); 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 @if errorlevel 1 goto quit
%cc% ../ui_force.c %cc% ../ui_force.c
@if errorlevel 1 goto quit @if errorlevel 1 goto quit
%cc% ../ui_util.c
@if errorlevel 1 goto quit
%cc% ../ui_shared.c %cc% ../ui_shared.c
@if errorlevel 1 goto quit @if errorlevel 1 goto quit
%cc% ../ui_gameinfo.c %cc% ../ui_gameinfo.c

View file

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

View file

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

View file

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

View file

@ -1736,7 +1736,8 @@ void UpdateForceStatus()
} }
// Take the current team and force a skin color based on it. if ( !UI_TrueJediEnabled() )
{// Take the current team and force a skin color based on it.
switch((int)(trap_Cvar_VariableValue("ui_myteam"))) switch((int)(trap_Cvar_VariableValue("ui_myteam")))
{ {
case TEAM_RED: case TEAM_RED:
@ -1752,6 +1753,7 @@ void UpdateForceStatus()
break; break;
} }
} }
}
@ -2373,6 +2375,7 @@ static void UI_BuildPlayerList() {
if (info[0]) { if (info[0]) {
Q_strncpyz( uiInfo.playerNames[uiInfo.playerCount], Info_ValueForKey( info, "n" ), MAX_NAME_LENGTH ); Q_strncpyz( uiInfo.playerNames[uiInfo.playerCount], Info_ValueForKey( info, "n" ), MAX_NAME_LENGTH );
Q_CleanStr( uiInfo.playerNames[uiInfo.playerCount] ); Q_CleanStr( uiInfo.playerNames[uiInfo.playerCount] );
uiInfo.playerIndexes[uiInfo.playerCount] = n;
uiInfo.playerCount++; uiInfo.playerCount++;
team2 = atoi(Info_ValueForKey(info, "t")); team2 = atoi(Info_ValueForKey(info, "t"));
if (team2 == team && n != uiInfo.playerNumber) { if (team2 == team && n != uiInfo.playerNumber) {
@ -2991,13 +2994,15 @@ static qboolean UI_Handicap_HandleKey(int flags, float *special, int key) {
static qboolean UI_Effects_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) {
if ( !UI_TrueJediEnabled() )
{
int team = (int)(trap_Cvar_VariableValue("ui_myteam")); int team = (int)(trap_Cvar_VariableValue("ui_myteam"));
if (team == TEAM_RED || team==TEAM_BLUE) if (team == TEAM_RED || team==TEAM_BLUE)
{ {
return qfalse; return qfalse;
} }
}
if (key == A_MOUSE2) { if (key == A_MOUSE2) {
uiInfo.effectsColor--; uiInfo.effectsColor--;
@ -4419,7 +4424,8 @@ static void UI_RunMenuScript(char **args)
} }
} else if (Q_stricmp(name, "voteKick") == 0) { } else if (Q_stricmp(name, "voteKick") == 0) {
if (uiInfo.playerIndex >= 0 && uiInfo.playerIndex < uiInfo.playerCount) { 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) { } else if (Q_stricmp(name, "voteGame") == 0) {
if (ui_netGameType.integer >= 0 && ui_netGameType.integer < uiInfo.numGameTypes) { 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 ); //UI_DrawProportionalString( 320, 96, "Press Esc to abort", UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, menu_text_color );
// display global MOTD at bottom // 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) // print any server info (server full, bad version, etc)
if ( cstate.connState < CA_CONNECTED ) { if ( cstate.connState < CA_CONNECTED ) {
Text_PaintCenter(centerPoint, yStart + 176, scale, colorWhite, cstate.messageString, 0, FONT_MEDIUM); 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"); ptr = UI_Cvar_VariableString("debug_protocol");
if (strlen(ptr)) { 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 { 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; break;
} }
DC->keynumToStringBuf( b1, g_nameBind1, 32 ); 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; b2 = g_bindings[i].bind2;
if (b2 != -1) if (b2 != -1)
{ {
DC->keynumToStringBuf( b2, g_nameBind2, 32 ); 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)); 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; imageStartX = listPtr->columnInfo[j+1].pos;
} }
DC->setColor( NULL );
if (optionalImage3 >= 0) { if (optionalImage3 >= 0) {
DC->drawHandlePic(imageStartX - listPtr->elementHeight*3, y+2, listPtr->elementHeight, listPtr->elementHeight, optionalImage3); DC->drawHandlePic(imageStartX - listPtr->elementHeight*3, y+2, listPtr->elementHeight, listPtr->elementHeight, optionalImage3);
} }

View file

@ -5,4 +5,7 @@
// //
// memory, string alloc // 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 # DEBUG_CFLAGS=$(BASE_CFLAGS) -g -Wall -Werror -O
ifeq ($(ARCH),axp) ifeq ($(ARCH),axp)
CC=pgcc 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 else
ifeq ($(ARCH),ppc) ifeq ($(ARCH),ppc)
NEWPGCC=/loki/global/ppc/bin/gcc NEWPGCC=/loki/global/ppc/bin/gcc
CC=$(NEWPGCC) 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 else
#NEWPGCC=/usr/local/gcc-2.95.2/bin/gcc # bk001205 #NEWPGCC=/usr/local/gcc-2.95.2/bin/gcc # bk001205
#NEWPGCC=/loki/global/x86/bin/gcc #NEWPGCC=/loki/global/x86/bin/gcc
@ -112,7 +112,7 @@ DLL_ONLY=false
# TTimo: legacy RELEASE_CFLAGS # 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 # 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 # 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) # 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 # 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 endif
@ -129,7 +129,7 @@ DLL_ONLY=false
THREAD_LDFLAGS=-lpthread THREAD_LDFLAGS=-lpthread
#LDFLAGS=/opt/sxl/lib/sxlgcc3.a -lpthread -ldl -lm -lstdc++ -static -Wl --gc-sections #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 GLLDFLAGS=-L/usr/X11R6/lib -L$(MESADIR)/lib -lX11 -lXext -lXxf86dga -lXxf86vm
TARGETS=\ TARGETS=\
@ -213,7 +213,6 @@ Q3DOBJ = \
$(B)/ded/cm_polylib.o \ $(B)/ded/cm_polylib.o \
$(B)/ded/cm_test.o \ $(B)/ded/cm_test.o \
$(B)/ded/cm_trace.o \ $(B)/ded/cm_trace.o \
$(B)/ded/cm_shader.o \
$(B)/ded/cmd.o \ $(B)/ded/cmd.o \
$(B)/ded/common.o \ $(B)/ded/common.o \
$(B)/ded/cvar.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 // 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 // any local adresses of a different class than the address being tested will fail based on the first byte
/*
// Class A // Class A
if( (adr.ip[0] & 0x80) == 0x00 ) { if( (adr.ip[0] & 0x80) == 0x00 ) {
for ( i = 0 ; i < numIP ; i++ ) { for ( i = 0 ; i < numIP ; i++ ) {
@ -279,7 +279,8 @@ qboolean Sys_IsLANAddress (netadr_t adr) {
} }
return qfalse; 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 // Class C
for ( i = 0 ; i < numIP ; i++ ) { 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] ) { 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 ip;
int n; int n;
// Set this early so we can just return if there is an error
numIP = 0;
if ( gethostname( hostname, 256 ) == -1 ) { if ( gethostname( hostname, 256 ) == -1 ) {
return; return;
} }
@ -431,14 +435,14 @@ void NET_GetLocalAddress( void ) {
return; 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 ); ip = ntohl( *(int *)p );
localIP[ numIP ][0] = p[0]; localIP[ numIP ][0] = p[0];
localIP[ numIP ][1] = p[1]; localIP[ numIP ][1] = p[1];
localIP[ numIP ][2] = p[2]; localIP[ numIP ][2] = p[2];
localIP[ numIP ][3] = p[3]; localIP[ numIP ][3] = p[3];
Com_Printf( "IP: %i.%i.%i.%i\n", ( ip >> 24 ) & 0xff, ( ip >> 16 ) & 0xff, ( ip >> 8 ) & 0xff, ip & 0xff ); Com_Printf( "IP: %i.%i.%i.%i\n", ( ip >> 24 ) & 0xff, ( ip >> 16 ) & 0xff, ( ip >> 8 ) & 0xff, ip & 0xff );
numIP++;
} }
} }
#endif #endif

View file

@ -397,6 +397,7 @@ qboolean Sys_IsLANAddress( netadr_t adr ) {
return qtrue; return qtrue;
} }
/*
// Class A // Class A
if( (adr.ip[0] & 0x80) == 0x00 ) { if( (adr.ip[0] & 0x80) == 0x00 ) {
for ( i = 0 ; i < numIP ; i++ ) { for ( i = 0 ; i < numIP ; i++ ) {
@ -421,6 +422,8 @@ qboolean Sys_IsLANAddress( netadr_t adr ) {
} }
return qfalse; 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 // Class C
for ( i = 0 ; i < numIP ; i++ ) { for ( i = 0 ; i < numIP ; i++ ) {
@ -707,6 +710,9 @@ void NET_GetLocalAddress( void ) {
int ip; int ip;
int n; int n;
// Set this early so we can just return if there is an error
numIP = 0;
if( gethostname( hostname, 256 ) == SOCKET_ERROR ) { if( gethostname( hostname, 256 ) == SOCKET_ERROR ) {
error = WSAGetLastError(); error = WSAGetLastError();
return; return;
@ -728,7 +734,6 @@ void NET_GetLocalAddress( void ) {
return; 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 ); ip = ntohl( *(int *)p );
localIP[ numIP ][0] = p[0]; localIP[ numIP ][0] = p[0];