📄 be_aas_move.c
字号:
{
if (AAS_ClipToBBox(&trace, org, trace.endpos, presencetype, mins, maxs))
{
VectorCopy(trace.endpos, move->endpos);
move->endarea = AAS_PointAreaNum(move->endpos);
VectorScale(frame_test_vel, 1/frametime, move->velocity);
move->trace = trace;
move->stopevent = SE_HITBOUNDINGBOX;
move->presencetype = presencetype;
move->endcontents = 0;
move->time = n * frametime;
move->frames = n;
return qtrue;
} //end if
} //end if
//move the entity to the trace end point
VectorCopy(trace.endpos, org);
//if there was a collision
if (trace.fraction < 1.0)
{
//get the plane the bounding box collided with
plane = AAS_PlaneFromNum(trace.planenum);
//
if (stopevent & SE_HITGROUNDAREA)
{
if (DotProduct(plane->normal, up) > phys_maxsteepness)
{
VectorCopy(org, start);
start[2] += 0.5;
if (AAS_PointAreaNum(start) == stopareanum)
{
VectorCopy(start, move->endpos);
move->endarea = stopareanum;
VectorScale(frame_test_vel, 1/frametime, move->velocity);
move->trace = trace;
move->stopevent = SE_HITGROUNDAREA;
move->presencetype = presencetype;
move->endcontents = 0;
move->time = n * frametime;
move->frames = n;
return qtrue;
} //end if
} //end if
} //end if
//assume there's no step
step = qfalse;
//if it is a vertical plane and the bot didn't jump recently
if (plane->normal[2] == 0 && (jump_frame < 0 || n - jump_frame > 2))
{
//check for a step
VectorMA(org, -0.25, plane->normal, start);
VectorCopy(start, stepend);
start[2] += phys_maxstep;
steptrace = AAS_TraceClientBBox(start, stepend, presencetype, entnum);
//
if (!steptrace.startsolid)
{
plane2 = AAS_PlaneFromNum(steptrace.planenum);
if (DotProduct(plane2->normal, up) > phys_maxsteepness)
{
VectorSubtract(end, steptrace.endpos, left_test_vel);
left_test_vel[2] = 0;
frame_test_vel[2] = 0;
//#ifdef AAS_MOVE_DEBUG
if (visualize)
{
if (steptrace.endpos[2] - org[2] > 0.125)
{
VectorCopy(org, start);
start[2] = steptrace.endpos[2];
AAS_DebugLine(org, start, LINECOLOR_BLUE);
} //end if
} //end if
//#endif //AAS_MOVE_DEBUG
org[2] = steptrace.endpos[2];
step = qtrue;
} //end if
} //end if
} //end if
//
if (!step)
{
//velocity left to test for this frame is the projection
//of the current test velocity into the hit plane
VectorMA(left_test_vel, -DotProduct(left_test_vel, plane->normal),
plane->normal, left_test_vel);
//store the old velocity for landing check
VectorCopy(frame_test_vel, old_frame_test_vel);
//test velocity for the next frame is the projection
//of the velocity of the current frame into the hit plane
VectorMA(frame_test_vel, -DotProduct(frame_test_vel, plane->normal),
plane->normal, frame_test_vel);
//check for a landing on an almost horizontal floor
if (DotProduct(plane->normal, up) > phys_maxsteepness)
{
onground = qtrue;
} //end if
if (stopevent & SE_HITGROUNDDAMAGE)
{
delta = 0;
if (old_frame_test_vel[2] < 0 &&
frame_test_vel[2] > old_frame_test_vel[2] &&
!onground)
{
delta = old_frame_test_vel[2];
} //end if
else if (onground)
{
delta = frame_test_vel[2] - old_frame_test_vel[2];
} //end else
if (delta)
{
delta = delta * 10;
delta = delta * delta * 0.0001;
if (swimming) delta = 0;
// never take falling damage if completely underwater
/*
if (ent->waterlevel == 3) return;
if (ent->waterlevel == 2) delta *= 0.25;
if (ent->waterlevel == 1) delta *= 0.5;
*/
if (delta > 40)
{
VectorCopy(org, move->endpos);
move->endarea = AAS_PointAreaNum(org);
VectorCopy(frame_test_vel, move->velocity);
move->trace = trace;
move->stopevent = SE_HITGROUNDDAMAGE;
move->presencetype = presencetype;
move->endcontents = 0;
move->time = n * frametime;
move->frames = n;
return qtrue;
} //end if
} //end if
} //end if
} //end if
} //end if
//extra check to prevent endless loop
if (++j > 20) return qfalse;
//while there is a plane hit
} while(trace.fraction < 1.0);
//if going down
if (frame_test_vel[2] <= 10)
{
//check for a liquid at the feet of the bot
VectorCopy(org, feet);
feet[2] -= 22;
pc = AAS_PointContents(feet);
//get event from pc
event = SE_NONE;
if (pc & CONTENTS_LAVA) event |= SE_ENTERLAVA;
if (pc & CONTENTS_SLIME) event |= SE_ENTERSLIME;
if (pc & CONTENTS_WATER) event |= SE_ENTERWATER;
//
areanum = AAS_PointAreaNum(org);
if (aasworld.areasettings[areanum].contents & AREACONTENTS_LAVA)
event |= SE_ENTERLAVA;
if (aasworld.areasettings[areanum].contents & AREACONTENTS_SLIME)
event |= SE_ENTERSLIME;
if (aasworld.areasettings[areanum].contents & AREACONTENTS_WATER)
event |= SE_ENTERWATER;
//if in lava or slime
if (event & stopevent)
{
VectorCopy(org, move->endpos);
move->endarea = areanum;
VectorScale(frame_test_vel, 1/frametime, move->velocity);
move->stopevent = event & stopevent;
move->presencetype = presencetype;
move->endcontents = pc;
move->time = n * frametime;
move->frames = n;
return qtrue;
} //end if
} //end if
//
onground = AAS_OnGround(org, presencetype, entnum);
//if onground and on the ground for at least one whole frame
if (onground)
{
if (stopevent & SE_HITGROUND)
{
VectorCopy(org, move->endpos);
move->endarea = AAS_PointAreaNum(org);
VectorScale(frame_test_vel, 1/frametime, move->velocity);
move->trace = trace;
move->stopevent = SE_HITGROUND;
move->presencetype = presencetype;
move->endcontents = 0;
move->time = n * frametime;
move->frames = n;
return qtrue;
} //end if
} //end if
else if (stopevent & SE_LEAVEGROUND)
{
VectorCopy(org, move->endpos);
move->endarea = AAS_PointAreaNum(org);
VectorScale(frame_test_vel, 1/frametime, move->velocity);
move->trace = trace;
move->stopevent = SE_LEAVEGROUND;
move->presencetype = presencetype;
move->endcontents = 0;
move->time = n * frametime;
move->frames = n;
return qtrue;
} //end else if
else if (stopevent & SE_GAP)
{
aas_trace_t gaptrace;
VectorCopy(org, start);
VectorCopy(start, end);
end[2] -= 48 + aassettings.phys_maxbarrier;
gaptrace = AAS_TraceClientBBox(start, end, PRESENCE_CROUCH, -1);
//if solid is found the bot cannot walk any further and will not fall into a gap
if (!gaptrace.startsolid)
{
//if it is a gap (lower than one step height)
if (gaptrace.endpos[2] < org[2] - aassettings.phys_maxstep - 1)
{
if (!(AAS_PointContents(end) & CONTENTS_WATER))
{
VectorCopy(lastorg, move->endpos);
move->endarea = AAS_PointAreaNum(lastorg);
VectorScale(frame_test_vel, 1/frametime, move->velocity);
move->trace = trace;
move->stopevent = SE_GAP;
move->presencetype = presencetype;
move->endcontents = 0;
move->time = n * frametime;
move->frames = n;
return qtrue;
} //end if
} //end if
} //end if
} //end else if
} //end for
//
VectorCopy(org, move->endpos);
move->endarea = AAS_PointAreaNum(org);
VectorScale(frame_test_vel, 1/frametime, move->velocity);
move->stopevent = SE_NONE;
move->presencetype = presencetype;
move->endcontents = 0;
move->time = n * frametime;
move->frames = n;
//
return qtrue;
} //end of the function AAS_ClientMovementPrediction
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_PredictClientMovement(struct aas_clientmove_s *move,
int entnum, vec3_t origin,
int presencetype, int onground,
vec3_t velocity, vec3_t cmdmove,
int cmdframes,
int maxframes, float frametime,
int stopevent, int stopareanum, int visualize)
{
vec3_t mins, maxs;
return AAS_ClientMovementPrediction(move, entnum, origin, presencetype, onground,
velocity, cmdmove, cmdframes, maxframes,
frametime, stopevent, stopareanum,
mins, maxs, visualize);
} //end of the function AAS_PredictClientMovement
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int AAS_ClientMovementHitBBox(struct aas_clientmove_s *move,
int entnum, vec3_t origin,
int presencetype, int onground,
vec3_t velocity, vec3_t cmdmove,
int cmdframes,
int maxframes, float frametime,
vec3_t mins, vec3_t maxs, int visualize)
{
return AAS_ClientMovementPrediction(move, entnum, origin, presencetype, onground,
velocity, cmdmove, cmdframes, maxframes,
frametime, SE_HITBOUNDINGBOX, 0,
mins, maxs, visualize);
} //end of the function AAS_ClientMovementHitBBox
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AAS_TestMovementPrediction(int entnum, vec3_t origin, vec3_t dir)
{
vec3_t velocity, cmdmove;
aas_clientmove_t move;
VectorClear(velocity);
if (!AAS_Swimming(origin)) dir[2] = 0;
VectorNormalize(dir);
VectorScale(dir, 400, cmdmove);
cmdmove[2] = 224;
AAS_ClearShownDebugLines();
AAS_PredictClientMovement(&move, entnum, origin, PRESENCE_NORMAL, qtrue,
velocity, cmdmove, 13, 13, 0.1f, SE_HITGROUND, 0, qtrue);//SE_LEAVEGROUND);
if (move.stopevent & SE_LEAVEGROUND)
{
botimport.Print(PRT_MESSAGE, "leave ground\n");
} //end if
} //end of the function TestMovementPrediction
//===========================================================================
// calculates the horizontal velocity needed to perform a jump from start
// to end
//
// Parameter: zvel : z velocity for jump
// start : start position of jump
// end : end position of jump
// *speed : returned speed for jump
// Returns: qfalse if too high or too far from start to end
// Changes Globals: -
//===========================================================================
int AAS_HorizontalVelocityForJump(float zvel, vec3_t start, vec3_t end, float *velocity)
{
float phys_gravity, phys_maxvelocity;
float maxjump, height2fall, t, top;
vec3_t dir;
phys_gravity = aassettings.phys_gravity;
phys_maxvelocity = aassettings.phys_maxvelocity;
//maximum height a player can jump with the given initial z velocity
maxjump = 0.5 * phys_gravity * (zvel / phys_gravity) * (zvel / phys_gravity);
//top of the parabolic jump
top = start[2] + maxjump;
//height the bot will fall from the top
height2fall = top - end[2];
//if the goal is to high to jump to
if (height2fall < 0)
{
*velocity = phys_maxvelocity;
return 0;
} //end if
//time a player takes to fall the height
t = sqrt(height2fall / (0.5 * phys_gravity));
//direction from start to end
VectorSubtract(end, start, dir);
//
if ( (t + zvel / phys_gravity) == 0.0f ) {
*velocity = phys_maxvelocity;
return 0;
}
//calculate horizontal speed
*velocity = sqrt(dir[0]*dir[0] + dir[1]*dir[1]) / (t + zvel / phys_gravity);
//the horizontal speed must be lower than the max speed
if (*velocity > phys_maxvelocity)
{
*velocity = phys_maxvelocity;
return 0;
} //end if
return 1;
} //end of the function AAS_HorizontalVelocityForJump
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -