Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

be_aas_move.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 
00023 /*****************************************************************************
00024  * name:        be_aas_move.c
00025  *
00026  * desc:        AAS
00027  *
00028  * $Archive: /MissionPack/code/botlib/be_aas_move.c $
00029  *
00030  *****************************************************************************/
00031 
00032 #include "../game/q_shared.h"
00033 #include "l_memory.h"
00034 #include "l_script.h"
00035 #include "l_precomp.h"
00036 #include "l_struct.h"
00037 #include "l_libvar.h"
00038 #include "aasfile.h"
00039 #include "../game/botlib.h"
00040 #include "../game/be_aas.h"
00041 #include "be_aas_funcs.h"
00042 #include "be_aas_def.h"
00043 
00044 extern botlib_import_t botimport;
00045 
00046 aas_settings_t aassettings;
00047 
00048 //#define AAS_MOVE_DEBUG
00049 
00050 //===========================================================================
00051 //
00052 // Parameter:           -
00053 // Returns:             -
00054 // Changes Globals:     -
00055 //===========================================================================
00056 int AAS_DropToFloor(vec3_t origin, vec3_t mins, vec3_t maxs)
00057 {
00058     vec3_t end;
00059     bsp_trace_t trace;
00060 
00061     VectorCopy(origin, end);
00062     end[2] -= 100;
00063     trace = AAS_Trace(origin, mins, maxs, end, 0, CONTENTS_SOLID);
00064     if (trace.startsolid) return qfalse;
00065     VectorCopy(trace.endpos, origin);
00066     return qtrue;
00067 } //end of the function AAS_DropToFloor
00068 //===========================================================================
00069 //
00070 // Parameter:           -
00071 // Returns:             -
00072 // Changes Globals:     -
00073 //===========================================================================
00074 void AAS_InitSettings(void)
00075 {
00076     aassettings.phys_gravitydirection[0]    = 0;
00077     aassettings.phys_gravitydirection[1]    = 0;
00078     aassettings.phys_gravitydirection[2]    = -1;
00079     aassettings.phys_friction               = LibVarValue("phys_friction", "6");
00080     aassettings.phys_stopspeed              = LibVarValue("phys_stopspeed", "100");
00081     aassettings.phys_gravity                = LibVarValue("phys_gravity", "800");
00082     aassettings.phys_waterfriction          = LibVarValue("phys_waterfriction", "1");
00083     aassettings.phys_watergravity           = LibVarValue("phys_watergravity", "400");
00084     aassettings.phys_maxvelocity            = LibVarValue("phys_maxvelocity", "320");
00085     aassettings.phys_maxwalkvelocity        = LibVarValue("phys_maxwalkvelocity", "320");
00086     aassettings.phys_maxcrouchvelocity      = LibVarValue("phys_maxcrouchvelocity", "100");
00087     aassettings.phys_maxswimvelocity        = LibVarValue("phys_maxswimvelocity", "150");
00088     aassettings.phys_walkaccelerate         = LibVarValue("phys_walkaccelerate", "10");
00089     aassettings.phys_airaccelerate          = LibVarValue("phys_airaccelerate", "1");
00090     aassettings.phys_swimaccelerate         = LibVarValue("phys_swimaccelerate", "4");
00091     aassettings.phys_maxstep                = LibVarValue("phys_maxstep", "19");
00092     aassettings.phys_maxsteepness           = LibVarValue("phys_maxsteepness", "0.7");
00093     aassettings.phys_maxwaterjump           = LibVarValue("phys_maxwaterjump", "18");
00094     aassettings.phys_maxbarrier             = LibVarValue("phys_maxbarrier", "33");
00095     aassettings.phys_jumpvel                = LibVarValue("phys_jumpvel", "270");
00096     aassettings.phys_falldelta5             = LibVarValue("phys_falldelta5", "40");
00097     aassettings.phys_falldelta10            = LibVarValue("phys_falldelta10", "60");
00098     aassettings.rs_waterjump                = LibVarValue("rs_waterjump", "400");
00099     aassettings.rs_teleport                 = LibVarValue("rs_teleport", "50");
00100     aassettings.rs_barrierjump              = LibVarValue("rs_barrierjump", "100");
00101     aassettings.rs_startcrouch              = LibVarValue("rs_startcrouch", "300");
00102     aassettings.rs_startgrapple             = LibVarValue("rs_startgrapple", "500");
00103     aassettings.rs_startwalkoffledge        = LibVarValue("rs_startwalkoffledge", "70");
00104     aassettings.rs_startjump                = LibVarValue("rs_startjump", "300");
00105     aassettings.rs_rocketjump               = LibVarValue("rs_rocketjump", "500");
00106     aassettings.rs_bfgjump                  = LibVarValue("rs_bfgjump", "500");
00107     aassettings.rs_jumppad                  = LibVarValue("rs_jumppad", "250");
00108     aassettings.rs_aircontrolledjumppad     = LibVarValue("rs_aircontrolledjumppad", "300");
00109     aassettings.rs_funcbob                  = LibVarValue("rs_funcbob", "300");
00110     aassettings.rs_startelevator            = LibVarValue("rs_startelevator", "50");
00111     aassettings.rs_falldamage5              = LibVarValue("rs_falldamage5", "300");
00112     aassettings.rs_falldamage10             = LibVarValue("rs_falldamage10", "500");
00113     aassettings.rs_maxfallheight            = LibVarValue("rs_maxfallheight", "0");
00114     aassettings.rs_maxjumpfallheight        = LibVarValue("rs_maxjumpfallheight", "450");
00115 } //end of the function AAS_InitSettings
00116 //===========================================================================
00117 // returns qtrue if the bot is against a ladder
00118 //
00119 // Parameter:           -
00120 // Returns:             -
00121 // Changes Globals:     -
00122 //===========================================================================
00123 int AAS_AgainstLadder(vec3_t origin)
00124 {
00125     int areanum, i, facenum, side;
00126     vec3_t org;
00127     aas_plane_t *plane;
00128     aas_face_t *face;
00129     aas_area_t *area;
00130 
00131     VectorCopy(origin, org);
00132     areanum = AAS_PointAreaNum(org);
00133     if (!areanum)
00134     {
00135         org[0] += 1;
00136         areanum = AAS_PointAreaNum(org);
00137         if (!areanum)
00138         {
00139             org[1] += 1;
00140             areanum = AAS_PointAreaNum(org);
00141             if (!areanum)
00142             {
00143                 org[0] -= 2;
00144                 areanum = AAS_PointAreaNum(org);
00145                 if (!areanum)
00146                 {
00147                     org[1] -= 2;
00148                     areanum = AAS_PointAreaNum(org);
00149                 } //end if
00150             } //end if
00151         } //end if
00152     } //end if
00153     //if in solid... wrrr shouldn't happen
00154     if (!areanum) return qfalse;
00155     //if not in a ladder area
00156     if (!(aasworld.areasettings[areanum].areaflags & AREA_LADDER)) return qfalse;
00157     //if a crouch only area
00158     if (!(aasworld.areasettings[areanum].presencetype & PRESENCE_NORMAL)) return qfalse;
00159     //
00160     area = &aasworld.areas[areanum];
00161     for (i = 0; i < area->numfaces; i++)
00162     {
00163         facenum = aasworld.faceindex[area->firstface + i];
00164         side = facenum < 0;
00165         face = &aasworld.faces[abs(facenum)];
00166         //if the face isn't a ladder face
00167         if (!(face->faceflags & FACE_LADDER)) continue;
00168         //get the plane the face is in
00169         plane = &aasworld.planes[face->planenum ^ side];
00170         //if the origin is pretty close to the plane
00171         if (abs(DotProduct(plane->normal, origin) - plane->dist) < 3)
00172         {
00173             if (AAS_PointInsideFace(abs(facenum), origin, 0.1f)) return qtrue;
00174         } //end if
00175     } //end for
00176     return qfalse;
00177 } //end of the function AAS_AgainstLadder
00178 //===========================================================================
00179 // returns qtrue if the bot is on the ground
00180 //
00181 // Parameter:           -
00182 // Returns:             -
00183 // Changes Globals:     -
00184 //===========================================================================
00185 int AAS_OnGround(vec3_t origin, int presencetype, int passent)
00186 {
00187     aas_trace_t trace;
00188     vec3_t end, up = {0, 0, 1};
00189     aas_plane_t *plane;
00190 
00191     VectorCopy(origin, end);
00192     end[2] -= 10;
00193 
00194     trace = AAS_TraceClientBBox(origin, end, presencetype, passent);
00195 
00196     //if in solid
00197     if (trace.startsolid) return qfalse;
00198     //if nothing hit at all
00199     if (trace.fraction >= 1.0) return qfalse;
00200     //if too far from the hit plane
00201     if (origin[2] - trace.endpos[2] > 10) return qfalse;
00202     //check if the plane isn't too steep
00203     plane = AAS_PlaneFromNum(trace.planenum);
00204     if (DotProduct(plane->normal, up) < aassettings.phys_maxsteepness) return qfalse;
00205     //the bot is on the ground
00206     return qtrue;
00207 } //end of the function AAS_OnGround
00208 //===========================================================================
00209 // returns qtrue if a bot at the given position is swimming
00210 //
00211 // Parameter:               -
00212 // Returns:                 -
00213 // Changes Globals:     -
00214 //===========================================================================
00215 int AAS_Swimming(vec3_t origin)
00216 {
00217     vec3_t testorg;
00218 
00219     VectorCopy(origin, testorg);
00220     testorg[2] -= 2;
00221     if (AAS_PointContents(testorg) & (CONTENTS_LAVA|CONTENTS_SLIME|CONTENTS_WATER)) return qtrue;
00222     return qfalse;
00223 } //end of the function AAS_Swimming
00224 //===========================================================================
00225 //
00226 // Parameter:           -
00227 // Returns:             -
00228 // Changes Globals:     -
00229 //===========================================================================
00230 static vec3_t VEC_UP            = {0, -1,  0};
00231 static vec3_t MOVEDIR_UP        = {0,  0,  1};
00232 static vec3_t VEC_DOWN      = {0, -2,  0};
00233 static vec3_t MOVEDIR_DOWN  = {0,  0, -1};
00234 
00235 void AAS_SetMovedir(vec3_t angles, vec3_t movedir)
00236 {
00237     if (VectorCompare(angles, VEC_UP))
00238     {
00239         VectorCopy(MOVEDIR_UP, movedir);
00240     } //end if
00241     else if (VectorCompare(angles, VEC_DOWN))
00242     {
00243         VectorCopy(MOVEDIR_DOWN, movedir);
00244     } //end else if
00245     else
00246     {
00247         AngleVectors(angles, movedir, NULL, NULL);
00248     } //end else
00249 } //end of the function AAS_SetMovedir
00250 //===========================================================================
00251 //
00252 // Parameter:               -
00253 // Returns:                 -
00254 // Changes Globals:     -
00255 //===========================================================================
00256 void AAS_JumpReachRunStart(aas_reachability_t *reach, vec3_t runstart)
00257 {
00258     vec3_t hordir, start, cmdmove;
00259     aas_clientmove_t move;
00260 
00261     //
00262     hordir[0] = reach->start[0] - reach->end[0];
00263     hordir[1] = reach->start[1] - reach->end[1];
00264     hordir[2] = 0;
00265     VectorNormalize(hordir);
00266     //start point
00267     VectorCopy(reach->start, start);
00268     start[2] += 1;
00269     //get command movement
00270     VectorScale(hordir, 400, cmdmove);
00271     //
00272     AAS_PredictClientMovement(&move, -1, start, PRESENCE_NORMAL, qtrue,
00273                                 vec3_origin, cmdmove, 1, 2, 0.1f,
00274                                 SE_ENTERWATER|SE_ENTERSLIME|SE_ENTERLAVA|
00275                                 SE_HITGROUNDDAMAGE|SE_GAP, 0, qfalse);
00276     VectorCopy(move.endpos, runstart);
00277     //don't enter slime or lava and don't fall from too high
00278     if (move.stopevent & (SE_ENTERSLIME|SE_ENTERLAVA|SE_HITGROUNDDAMAGE))
00279     {
00280         VectorCopy(start, runstart);
00281     } //end if
00282 } //end of the function AAS_JumpReachRunStart
00283 //===========================================================================
00284 // returns the Z velocity when rocket jumping at the origin
00285 //
00286 // Parameter:           -
00287 // Returns:             -
00288 // Changes Globals:     -
00289 //===========================================================================
00290 float AAS_WeaponJumpZVelocity(vec3_t origin, float radiusdamage)
00291 {
00292     vec3_t kvel, v, start, end, forward, right, viewangles, dir;
00293     float   mass, knockback, points;
00294     vec3_t rocketoffset = {8, 8, -8};
00295     vec3_t botmins = {-16, -16, -24};
00296     vec3_t botmaxs = {16, 16, 32};
00297     bsp_trace_t bsptrace;
00298 
00299     //look down (90 degrees)
00300     viewangles[PITCH] = 90;
00301     viewangles[YAW] = 0;
00302     viewangles[ROLL] = 0;
00303     //get the start point shooting from
00304     VectorCopy(origin, start);
00305     start[2] += 8; //view offset Z
00306     AngleVectors(viewangles, forward, right, NULL);
00307     start[0] += forward[0] * rocketoffset[0] + right[0] * rocketoffset[1];
00308     start[1] += forward[1] * rocketoffset[0] + right[1] * rocketoffset[1];
00309     start[2] += forward[2] * rocketoffset[0] + right[2] * rocketoffset[1] + rocketoffset[2];
00310     //end point of the trace
00311     VectorMA(start, 500, forward, end);
00312     //trace a line to get the impact point
00313     bsptrace = AAS_Trace(start, NULL, NULL, end, 1, CONTENTS_SOLID);
00314     //calculate the damage the bot will get from the rocket impact
00315     VectorAdd(botmins, botmaxs, v);
00316     VectorMA(origin, 0.5, v, v);
00317     VectorSubtract(bsptrace.endpos, v, v);
00318     //
00319     points = radiusdamage - 0.5 * VectorLength(v);
00320     if (points < 0) points = 0;
00321     //the owner of the rocket gets half the damage
00322     points *= 0.5;
00323     //mass of the bot (p_client.c: PutClientInServer)
00324     mass = 200;
00325     //knockback is the same as the damage points
00326     knockback = points;
00327     //direction of the damage (from trace.endpos to bot origin)
00328     VectorSubtract(origin, bsptrace.endpos, dir);
00329     VectorNormalize(dir);
00330     //damage velocity
00331     VectorScale(dir, 1600.0 * (float)knockback / mass, kvel);   //the rocket jump hack...
00332     //rocket impact velocity + jump velocity
00333     return kvel[2] + aassettings.phys_jumpvel;
00334 } //end of the function AAS_WeaponJumpZVelocity
00335 //===========================================================================
00336 //
00337 // Parameter:           -
00338 // Returns:             -
00339 // Changes Globals:     -
00340 //===========================================================================
00341 float AAS_RocketJumpZVelocity(vec3_t origin)
00342 {
00343     //rocket radius damage is 120 (p_weapon.c: Weapon_RocketLauncher_Fire)
00344     return AAS_WeaponJumpZVelocity(origin, 120);
00345 } //end of the function AAS_RocketJumpZVelocity
00346 //===========================================================================
00347 //
00348 // Parameter:           -
00349 // Returns:             -
00350 // Changes Globals:     -
00351 //===========================================================================
00352 float AAS_BFGJumpZVelocity(vec3_t origin)
00353 {
00354     //bfg radius damage is 1000 (p_weapon.c: weapon_bfg_fire)
00355     return AAS_WeaponJumpZVelocity(origin, 120);
00356 } //end of the function AAS_BFGJumpZVelocity
00357 //===========================================================================
00358 // applies ground friction to the given velocity
00359 //
00360 // Parameter:           -
00361 // Returns:             -
00362 // Changes Globals:     -
00363 //===========================================================================
00364 void AAS_Accelerate(vec3_t velocity, float frametime, vec3_t wishdir, float wishspeed, float accel)
00365 {
00366     // q2 style
00367     int         i;
00368     float       addspeed, accelspeed, currentspeed;
00369 
00370     currentspeed = DotProduct(velocity, wishdir);
00371     addspeed = wishspeed - currentspeed;
00372     if (addspeed <= 0) {
00373         return;
00374     }
00375     accelspeed = accel*frametime*wishspeed;
00376     if (accelspeed > addspeed) {
00377         accelspeed = addspeed;
00378     }
00379     
00380     for (i=0 ; i<3 ; i++) {
00381         velocity[i] += accelspeed*wishdir[i];   
00382     }
00383 } //end of the function AAS_Accelerate
00384 //===========================================================================
00385 //
00386 // Parameter:           -
00387 // Returns:             -
00388 // Changes Globals:     -
00389 //===========================================================================
00390 void AAS_AirControl(vec3_t start, vec3_t end, vec3_t velocity, vec3_t cmdmove)
00391 {
00392     vec3_t dir;
00393 
00394     VectorSubtract(end, start, dir);
00395 } //end of the function AAS_AirControl
00396 //===========================================================================
00397 // applies ground friction to the given velocity
00398 //
00399 // Parameter:           -
00400 // Returns:             -
00401 // Changes Globals:     -
00402 //===========================================================================
00403 void AAS_ApplyFriction(vec3_t vel, float friction, float stopspeed,
00404                                                     float frametime)
00405 {
00406     float speed, control, newspeed;
00407 
00408     //horizontal speed
00409     speed = sqrt(vel[0] * vel[0] + vel[1] * vel[1]);
00410     if (speed)
00411     {
00412         control = speed < stopspeed ? stopspeed : speed;
00413         newspeed = speed - frametime * control * friction;
00414         if (newspeed < 0) newspeed = 0;
00415         newspeed /= speed;
00416         vel[0] *= newspeed;
00417         vel[1] *= newspeed;
00418     } //end if
00419 } //end of the function AAS_ApplyFriction
00420 //===========================================================================
00421 //
00422 // Parameter:           -
00423 // Returns:             -
00424 // Changes Globals:     -
00425 //===========================================================================
00426 int AAS_ClipToBBox(aas_trace_t *trace, vec3_t start, vec3_t end, int presencetype, vec3_t mins, vec3_t maxs)
00427 {
00428     int i, j, side;
00429     float front, back, frac, planedist;
00430     vec3_t bboxmins, bboxmaxs, absmins, absmaxs, dir, mid;
00431 
00432     AAS_PresenceTypeBoundingBox(presencetype, bboxmins, bboxmaxs);
00433     VectorSubtract(mins, bboxmaxs, absmins);
00434     VectorSubtract(maxs, bboxmins, absmaxs);
00435     //
00436     VectorCopy(end, trace->endpos);
00437     trace->fraction = 1;
00438     for (i = 0; i < 3; i++)
00439     {
00440         if (start[i] < absmins[i] && end[i] < absmins[i]) return qfalse;
00441         if (start[i] > absmaxs[i] && end[i] > absmaxs[i]) return qfalse;
00442     } //end for
00443     //check bounding box collision
00444     VectorSubtract(end, start, dir);
00445     frac = 1;
00446     for (i = 0; i < 3; i++)
00447     {
00448         //get plane to test collision with for the current axis direction
00449         if (dir[i] > 0) planedist = absmins[i];
00450         else planedist = absmaxs[i];
00451         //calculate collision fraction
00452         front = start[i] - planedist;
00453         back = end[i] - planedist;
00454         frac = front / (front-back);
00455         //check if between bounding planes of next axis
00456         side = i + 1;
00457         if (side > 2) side = 0;
00458         mid[side] = start[side] + dir[side] * frac;
00459         if (mid[side] > absmins[side] && mid[side] < absmaxs[side])
00460         {
00461             //check if between bounding planes of next axis
00462             side++;
00463             if (side > 2) side = 0;
00464             mid[side] = start[side] + dir[side] * frac;
00465             if (mid[side] > absmins[side] && mid[side] < absmaxs[side])
00466             {
00467                 mid[i] = planedist;
00468                 break;
00469             } //end if
00470         } //end if
00471     } //end for
00472     //if there was a collision
00473     if (i != 3)
00474     {
00475         trace->startsolid = qfalse;
00476         trace->fraction = frac;
00477         trace->ent = 0;
00478         trace->planenum = 0;
00479         trace->area = 0;
00480         trace->lastarea = 0;
00481         //trace endpos
00482         for (j = 0; j < 3; j++) trace->endpos[j] = start[j] + dir[j] * frac;
00483         return qtrue;
00484     } //end if
00485     return qfalse;
00486 } //end of the function AAS_ClipToBBox
00487 //===========================================================================
00488 // predicts the movement
00489 // assumes regular bounding box sizes
00490 // NOTE: out of water jumping is not included
00491 // NOTE: grappling hook is not included
00492 //
00493 // Parameter:           origin          : origin to start with
00494 //                      presencetype    : presence type to start with
00495 //                      velocity        : velocity to start with
00496 //                      cmdmove         : client command movement
00497 //                      cmdframes       : number of frame cmdmove is valid
00498 //                      maxframes       : maximum number of predicted frames
00499 //                      frametime       : duration of one predicted frame
00500 //                      stopevent       : events that stop the prediction
00501 //                      stopareanum     : stop as soon as entered this area
00502 // Returns:             aas_clientmove_t
00503 // Changes Globals:     -
00504 //===========================================================================
00505 int AAS_ClientMovementPrediction(struct aas_clientmove_s *move,
00506                                 int entnum, vec3_t origin,
00507                                 int presencetype, int onground,
00508                                 vec3_t velocity, vec3_t cmdmove,
00509                                 int cmdframes,
00510                                 int maxframes, float frametime,
00511                                 int stopevent, int stopareanum,
00512                                 vec3_t mins, vec3_t maxs, int visualize)
00513 {
00514     float phys_friction, phys_stopspeed, phys_gravity, phys_waterfriction;
00515     float phys_watergravity;
00516     float phys_walkaccelerate, phys_airaccelerate, phys_swimaccelerate;
00517     float phys_maxwalkvelocity, phys_maxcrouchvelocity, phys_maxswimvelocity;
00518     float phys_maxstep, phys_maxsteepness, phys_jumpvel, friction;
00519     float gravity, delta, maxvel, wishspeed, accelerate;
00520     //float velchange, newvel;
00521     int n, i, j, pc, step, swimming, ax, crouch, event, jump_frame, areanum;
00522     int areas[20], numareas;
00523     vec3_t points[20];
00524     vec3_t org, end, feet, start, stepend, lastorg, wishdir;
00525     vec3_t frame_test_vel, old_frame_test_vel, left_test_vel;
00526     vec3_t up = {0, 0, 1};
00527     aas_plane_t *plane, *plane2;
00528     aas_trace_t trace, steptrace;
00529     
00530     if (frametime <= 0) frametime = 0.1f;
00531     //
00532     phys_friction = aassettings.phys_friction;
00533     phys_stopspeed = aassettings.phys_stopspeed;
00534     phys_gravity = aassettings.phys_gravity;
00535     phys_waterfriction = aassettings.phys_waterfriction;
00536     phys_watergravity = aassettings.phys_watergravity;
00537     phys_maxwalkvelocity = aassettings.phys_maxwalkvelocity;// * frametime;
00538     phys_maxcrouchvelocity = aassettings.phys_maxcrouchvelocity;// * frametime;
00539     phys_maxswimvelocity = aassettings.phys_maxswimvelocity;// * frametime;
00540     phys_walkaccelerate = aassettings.phys_walkaccelerate;
00541     phys_airaccelerate = aassettings.phys_airaccelerate;
00542     phys_swimaccelerate = aassettings.phys_swimaccelerate;
00543     phys_maxstep = aassettings.phys_maxstep;
00544     phys_maxsteepness = aassettings.phys_maxsteepness;
00545     phys_jumpvel = aassettings.phys_jumpvel * frametime;
00546     //
00547     Com_Memset(move, 0, sizeof(aas_clientmove_t));
00548     Com_Memset(&trace, 0, sizeof(aas_trace_t));
00549     //start at the current origin
00550     VectorCopy(origin, org);
00551     org[2] += 0.25;
00552     //velocity to test for the first frame
00553     VectorScale(velocity, frametime, frame_test_vel);
00554     //
00555     jump_frame = -1;
00556     //predict a maximum of 'maxframes' ahead
00557     for (n = 0; n < maxframes; n++)
00558     {
00559         swimming = AAS_Swimming(org);
00560         //get gravity depending on swimming or not
00561         gravity = swimming ? phys_watergravity : phys_gravity;
00562         //apply gravity at the START of the frame
00563         frame_test_vel[2] = frame_test_vel[2] - (gravity * 0.1 * frametime);
00564         //if on the ground or swimming
00565         if (onground || swimming)
00566         {
00567             friction = swimming ? phys_friction : phys_waterfriction;
00568             //apply friction
00569             VectorScale(frame_test_vel, 1/frametime, frame_test_vel);
00570             AAS_ApplyFriction(frame_test_vel, friction, phys_stopspeed, frametime);
00571             VectorScale(frame_test_vel, frametime, frame_test_vel);
00572         } //end if
00573         crouch = qfalse;
00574         //apply command movement
00575         if (n < cmdframes)
00576         {
00577             ax = 0;
00578             maxvel = phys_maxwalkvelocity;
00579             accelerate = phys_airaccelerate;
00580             VectorCopy(cmdmove, wishdir);
00581             if (onground)
00582             {
00583                 if (cmdmove[2] < -300)
00584                 {
00585                     crouch = qtrue;
00586                     maxvel = phys_maxcrouchvelocity;
00587                 } //end if
00588                 //if not swimming and upmove is positive then jump
00589                 if (!swimming && cmdmove[2] > 1)
00590                 {
00591                     //jump velocity minus the gravity for one frame + 5 for safety
00592                     frame_test_vel[2] = phys_jumpvel - (gravity * 0.1 * frametime) + 5;
00593                     jump_frame = n;
00594                     //jumping so air accelerate
00595                     accelerate = phys_airaccelerate;
00596                 } //end if
00597                 else
00598                 {
00599                     accelerate = phys_walkaccelerate;
00600                 } //end else
00601                 ax = 2;
00602             } //end if
00603             if (swimming)
00604             {
00605                 maxvel = phys_maxswimvelocity;
00606                 accelerate = phys_swimaccelerate;
00607                 ax = 3;
00608             } //end if
00609             else
00610             {
00611                 wishdir[2] = 0;
00612             } //end else
00613             //
00614             wishspeed = VectorNormalize(wishdir);
00615             if (wishspeed > maxvel) wishspeed = maxvel;
00616             VectorScale(frame_test_vel, 1/frametime, frame_test_vel);
00617             AAS_Accelerate(frame_test_vel, frametime, wishdir, wishspeed, accelerate);
00618             VectorScale(frame_test_vel, frametime, frame_test_vel);
00619             /*
00620             for (i = 0; i < ax; i++)
00621             {
00622                 velchange = (cmdmove[i] * frametime) - frame_test_vel[i];
00623                 if (velchange > phys_maxacceleration) velchange = phys_maxacceleration;
00624                 else if (velchange < -phys_maxacceleration) velchange = -phys_maxacceleration;
00625                 newvel = frame_test_vel[i] + velchange;
00626                 //
00627                 if (frame_test_vel[i] <= maxvel && newvel > maxvel) frame_test_vel[i] = maxvel;
00628                 else if (frame_test_vel[i] >= -maxvel && newvel < -maxvel) frame_test_vel[i] = -maxvel;
00629                 else frame_test_vel[i] = newvel;
00630             } //end for
00631             */
00632         } //end if
00633         if (crouch)
00634         {
00635             presencetype = PRESENCE_CROUCH;
00636         } //end if
00637         else if (presencetype == PRESENCE_CROUCH)
00638         {
00639             if (AAS_PointPresenceType(org) & PRESENCE_NORMAL)
00640             {
00641                 presencetype = PRESENCE_NORMAL;
00642             } //end if
00643         } //end else
00644         //save the current origin
00645         VectorCopy(org, lastorg);
00646         //move linear during one frame
00647         VectorCopy(frame_test_vel, left_test_vel);
00648         j = 0;
00649         do
00650         {
00651             VectorAdd(org, left_test_vel, end);
00652             //trace a bounding box
00653             trace = AAS_TraceClientBBox(org, end, presencetype, entnum);
00654             //
00655 //#ifdef AAS_MOVE_DEBUG
00656             if (visualize)
00657             {
00658                 if (trace.startsolid) botimport.Print(PRT_MESSAGE, "PredictMovement: start solid\n");
00659                 AAS_DebugLine(org, trace.endpos, LINECOLOR_RED);
00660             } //end if
00661 //#endif //AAS_MOVE_DEBUG
00662             //
00663             if (stopevent & (SE_ENTERAREA|SE_TOUCHJUMPPAD|SE_TOUCHTELEPORTER|SE_TOUCHCLUSTERPORTAL))
00664             {
00665                 numareas = AAS_TraceAreas(org, trace.endpos, areas, points, 20);
00666                 for (i = 0; i < numareas; i++)
00667                 {
00668                     if (stopevent & SE_ENTERAREA)
00669                     {
00670                         if (areas[i] == stopareanum)
00671                         {
00672                             VectorCopy(points[i], move->endpos);
00673                             VectorScale(frame_test_vel, 1/frametime, move->velocity);
00674                             move->endarea = areas[i];
00675                             move->trace = trace;
00676                             move->stopevent = SE_ENTERAREA;
00677                             move->presencetype = presencetype;
00678                             move->endcontents = 0;
00679                             move->time = n * frametime;
00680                             move->frames = n;
00681                             return qtrue;
00682                         } //end if
00683                     } //end if
00684                     //NOTE: if not the first frame
00685                     if ((stopevent & SE_TOUCHJUMPPAD) && n)
00686                     {
00687                         if (aasworld.areasettings[areas[i]].contents & AREACONTENTS_JUMPPAD)
00688                         {
00689                             VectorCopy(points[i], move->endpos);
00690                             VectorScale(frame_test_vel, 1/frametime, move->velocity);
00691                             move->endarea = areas[i];
00692                             move->trace = trace;
00693                             move->stopevent = SE_TOUCHJUMPPAD;
00694                             move->presencetype = presencetype;
00695                             move->endcontents = 0;
00696                             move->time = n * frametime;
00697                             move->frames = n;
00698                             return qtrue;
00699                         } //end if
00700                     } //end if
00701                     if (stopevent & SE_TOUCHTELEPORTER)
00702                     {
00703                         if (aasworld.areasettings[areas[i]].contents & AREACONTENTS_TELEPORTER)
00704                         {
00705                             VectorCopy(points[i], move->endpos);
00706                             move->endarea = areas[i];
00707                             VectorScale(frame_test_vel, 1/frametime, move->velocity);
00708                             move->trace = trace;
00709                             move->stopevent = SE_TOUCHTELEPORTER;
00710                             move->presencetype = presencetype;
00711                             move->endcontents = 0;
00712                             move->time = n * frametime;
00713                             move->frames = n;
00714                             return qtrue;
00715                         } //end if
00716                     } //end if
00717                     if (stopevent & SE_TOUCHCLUSTERPORTAL)
00718                     {
00719                         if (aasworld.areasettings[areas[i]].contents & AREACONTENTS_CLUSTERPORTAL)
00720                         {
00721                             VectorCopy(points[i], move->endpos);
00722                             move->endarea = areas[i];
00723                             VectorScale(frame_test_vel, 1/frametime, move->velocity);
00724                             move->trace = trace;
00725                             move->stopevent = SE_TOUCHCLUSTERPORTAL;
00726                             move->presencetype = presencetype;
00727                             move->endcontents = 0;
00728                             move->time = n * frametime;
00729                             move->frames = n;
00730                             return qtrue;
00731                         } //end if
00732                     } //end if
00733                 } //end for
00734             } //end if
00735             //
00736             if (stopevent & SE_HITBOUNDINGBOX)
00737             {
00738                 if (AAS_ClipToBBox(&trace, org, trace.endpos, presencetype, mins, maxs))
00739                 {
00740                     VectorCopy(trace.endpos, move->endpos);
00741                     move->endarea = AAS_PointAreaNum(move->endpos);
00742                     VectorScale(frame_test_vel, 1/frametime, move->velocity);
00743                     move->trace = trace;
00744                     move->stopevent = SE_HITBOUNDINGBOX;
00745                     move->presencetype = presencetype;
00746                     move->endcontents = 0;
00747                     move->time = n * frametime;
00748                     move->frames = n;
00749                     return qtrue;
00750                 } //end if
00751             } //end if
00752             //move the entity to the trace end point
00753             VectorCopy(trace.endpos, org);
00754             //if there was a collision
00755             if (trace.fraction < 1.0)
00756             {
00757                 //get the plane the bounding box collided with
00758                 plane = AAS_PlaneFromNum(trace.planenum);
00759                 //
00760                 if (stopevent & SE_HITGROUNDAREA)
00761                 {
00762                     if (DotProduct(plane->normal, up) > phys_maxsteepness)
00763                     {
00764                         VectorCopy(org, start);
00765                         start[2] += 0.5;
00766                         if (AAS_PointAreaNum(start) == stopareanum)
00767                         {
00768                             VectorCopy(start, move->endpos);
00769                             move->endarea = stopareanum;
00770                             VectorScale(frame_test_vel, 1/frametime, move->velocity);
00771                             move->trace = trace;
00772                             move->stopevent = SE_HITGROUNDAREA;
00773                             move->presencetype = presencetype;
00774                             move->endcontents = 0;
00775                             move->time = n * frametime;
00776                             move->frames = n;
00777                             return qtrue;
00778                         } //end if
00779                     } //end if
00780                 } //end if
00781                 //assume there's no step
00782                 step = qfalse;
00783                 //if it is a vertical plane and the bot didn't jump recently
00784                 if (plane->normal[2] == 0 && (jump_frame < 0 || n - jump_frame > 2))
00785                 {
00786                     //check for a step
00787                     VectorMA(org, -0.25, plane->normal, start);
00788                     VectorCopy(start, stepend);
00789                     start[2] += phys_maxstep;
00790                     steptrace = AAS_TraceClientBBox(start, stepend, presencetype, entnum);
00791                     //
00792                     if (!steptrace.startsolid)
00793                     {
00794                         plane2 = AAS_PlaneFromNum(steptrace.planenum);
00795                         if (DotProduct(plane2->normal, up) > phys_maxsteepness)
00796                         {
00797                             VectorSubtract(end, steptrace.endpos, left_test_vel);
00798                             left_test_vel[2] = 0;
00799                             frame_test_vel[2] = 0;
00800 //#ifdef AAS_MOVE_DEBUG
00801                             if (visualize)
00802                             {
00803                                 if (steptrace.endpos[2] - org[2] > 0.125)
00804                                 {
00805                                     VectorCopy(org, start);
00806                                     start[2] = steptrace.endpos[2];
00807                                     AAS_DebugLine(org, start, LINECOLOR_BLUE);
00808                                 } //end if
00809                             } //end if
00810 //#endif //AAS_MOVE_DEBUG
00811                             org[2] = steptrace.endpos[2];
00812                             step = qtrue;
00813                         } //end if
00814                     } //end if
00815                 } //end if
00816                 //
00817                 if (!step)
00818                 {
00819                     //velocity left to test for this frame is the projection
00820                     //of the current test velocity into the hit plane 
00821                     VectorMA(left_test_vel, -DotProduct(left_test_vel, plane->normal),
00822                                         plane->normal, left_test_vel);
00823                     //store the old velocity for landing check
00824                     VectorCopy(frame_test_vel, old_frame_test_vel);
00825                     //test velocity for the next frame is the projection
00826                     //of the velocity of the current frame into the hit plane 
00827                     VectorMA(frame_test_vel, -DotProduct(frame_test_vel, plane->normal),
00828                                         plane->normal, frame_test_vel);
00829                     //check for a landing on an almost horizontal floor
00830                     if (DotProduct(plane->normal, up) > phys_maxsteepness)
00831                     {
00832                         onground = qtrue;
00833                     } //end if
00834                     if (stopevent & SE_HITGROUNDDAMAGE)
00835                     {
00836                         delta = 0;
00837                         if (old_frame_test_vel[2] < 0 &&
00838                                 frame_test_vel[2] > old_frame_test_vel[2] &&
00839                                 !onground)
00840                         {
00841                             delta = old_frame_test_vel[2];
00842                         } //end if
00843                         else if (onground)
00844                         {
00845                             delta = frame_test_vel[2] - old_frame_test_vel[2];
00846                         } //end else
00847                         if (delta)
00848                         {
00849                             delta = delta * 10;
00850                             delta = delta * delta * 0.0001;
00851                             if (swimming) delta = 0;
00852                             // never take falling damage if completely underwater
00853                             /*
00854                             if (ent->waterlevel == 3) return;
00855                             if (ent->waterlevel == 2) delta *= 0.25;
00856                             if (ent->waterlevel == 1) delta *= 0.5;
00857                             */
00858                             if (delta > 40)
00859                             {
00860                                 VectorCopy(org, move->endpos);
00861                                 move->endarea = AAS_PointAreaNum(org);
00862                                 VectorCopy(frame_test_vel, move->velocity);
00863                                 move->trace = trace;
00864                                 move->stopevent = SE_HITGROUNDDAMAGE;
00865                                 move->presencetype = presencetype;
00866                                 move->endcontents = 0;
00867                                 move->time = n * frametime;
00868                                 move->frames = n;
00869                                 return qtrue;
00870                             } //end if
00871                         } //end if
00872                     } //end if
00873                 } //end if
00874             } //end if
00875             //extra check to prevent endless loop
00876             if (++j > 20) return qfalse;
00877         //while there is a plane hit
00878         } while(trace.fraction < 1.0);
00879         //if going down
00880         if (frame_test_vel[2] <= 10)
00881         {
00882             //check for a liquid at the feet of the bot
00883             VectorCopy(org, feet);
00884             feet[2] -= 22;
00885             pc = AAS_PointContents(feet);
00886             //get event from pc
00887             event = SE_NONE;
00888             if (pc & CONTENTS_LAVA) event |= SE_ENTERLAVA;
00889             if (pc & CONTENTS_SLIME) event |= SE_ENTERSLIME;
00890             if (pc & CONTENTS_WATER) event |= SE_ENTERWATER;
00891             //
00892             areanum = AAS_PointAreaNum(org);
00893             if (aasworld.areasettings[areanum].contents & AREACONTENTS_LAVA)
00894                 event |= SE_ENTERLAVA;
00895             if (aasworld.areasettings[areanum].contents & AREACONTENTS_SLIME)
00896                 event |= SE_ENTERSLIME;
00897             if (aasworld.areasettings[areanum].contents & AREACONTENTS_WATER)
00898                 event |= SE_ENTERWATER;
00899             //if in lava or slime
00900             if (event & stopevent)
00901             {
00902                 VectorCopy(org, move->endpos);
00903                 move->endarea = areanum;
00904                 VectorScale(frame_test_vel, 1/frametime, move->velocity);
00905                 move->stopevent = event & stopevent;
00906                 move->presencetype = presencetype;
00907                 move->endcontents = pc;
00908                 move->time = n * frametime;
00909                 move->frames = n;
00910                 return qtrue;
00911             } //end if
00912         } //end if
00913         //
00914         onground = AAS_OnGround(org, presencetype, entnum);
00915         //if onground and on the ground for at least one whole frame
00916         if (onground)
00917         {
00918             if (stopevent & SE_HITGROUND)
00919             {
00920                 VectorCopy(org, move->endpos);
00921                 move->endarea = AAS_PointAreaNum(org);
00922                 VectorScale(frame_test_vel, 1/frametime, move->velocity);
00923                 move->trace = trace;
00924                 move->stopevent = SE_HITGROUND;
00925                 move->presencetype = presencetype;
00926                 move->endcontents = 0;
00927                 move->time = n * frametime;
00928                 move->frames = n;
00929                 return qtrue;
00930             } //end if
00931         } //end if
00932         else if (stopevent & SE_LEAVEGROUND)
00933         {
00934             VectorCopy(org, move->endpos);
00935             move->endarea = AAS_PointAreaNum(org);
00936             VectorScale(frame_test_vel, 1/frametime, move->velocity);
00937             move->trace = trace;
00938             move->stopevent = SE_LEAVEGROUND;
00939             move->presencetype = presencetype;
00940             move->endcontents = 0;
00941             move->time = n * frametime;
00942             move->frames = n;
00943             return qtrue;
00944         } //end else if
00945         else if (stopevent & SE_GAP)
00946         {
00947             aas_trace_t gaptrace;
00948 
00949             VectorCopy(org, start);
00950             VectorCopy(start, end);
00951             end[2] -= 48 + aassettings.phys_maxbarrier;
00952             gaptrace = AAS_TraceClientBBox(start, end, PRESENCE_CROUCH, -1);
00953             //if solid is found the bot cannot walk any further and will not fall into a gap
00954             if (!gaptrace.startsolid)
00955             {
00956                 //if it is a gap (lower than one step height)
00957                 if (gaptrace.endpos[2] < org[2] - aassettings.phys_maxstep - 1)
00958                 {
00959                     if (!(AAS_PointContents(end) & CONTENTS_WATER))
00960                     {
00961                         VectorCopy(lastorg, move->endpos);
00962                         move->endarea = AAS_PointAreaNum(lastorg);
00963                         VectorScale(frame_test_vel, 1/frametime, move->velocity);
00964                         move->trace = trace;
00965                         move->stopevent = SE_GAP;
00966                         move->presencetype = presencetype;
00967                         move->endcontents = 0;
00968                         move->time = n * frametime;
00969                         move->frames = n;
00970                         return qtrue;
00971                     } //end if
00972                 } //end if
00973             } //end if
00974         } //end else if
00975     } //end for
00976     //
00977     VectorCopy(org, move->endpos);
00978     move->endarea = AAS_PointAreaNum(org);
00979     VectorScale(frame_test_vel, 1/frametime, move->velocity);
00980     move->stopevent = SE_NONE;
00981     move->presencetype = presencetype;
00982     move->endcontents = 0;
00983     move->time = n * frametime;
00984     move->frames = n;
00985     //
00986     return qtrue;
00987 } //end of the function AAS_ClientMovementPrediction
00988 //===========================================================================
00989 //
00990 // Parameter:           -
00991 // Returns:             -
00992 // Changes Globals:     -
00993 //===========================================================================
00994 int AAS_PredictClientMovement(struct aas_clientmove_s *move,
00995                                 int entnum, vec3_t origin,
00996                                 int presencetype, int onground,
00997                                 vec3_t velocity, vec3_t cmdmove,
00998                                 int cmdframes,
00999                                 int maxframes, float frametime,
01000                                 int stopevent, int stopareanum, int visualize)
01001 {
01002     vec3_t mins, maxs;
01003     return AAS_ClientMovementPrediction(move, entnum, origin, presencetype, onground,
01004                                         velocity, cmdmove, cmdframes, maxframes,
01005                                         frametime, stopevent, stopareanum,
01006                                         mins, maxs, visualize);
01007 } //end of the function AAS_PredictClientMovement
01008 //===========================================================================
01009 //
01010 // Parameter:           -
01011 // Returns:             -
01012 // Changes Globals:     -
01013 //===========================================================================
01014 int AAS_ClientMovementHitBBox(struct aas_clientmove_s *move,
01015                                 int entnum, vec3_t origin,
01016                                 int presencetype, int onground,
01017                                 vec3_t velocity, vec3_t cmdmove,
01018                                 int cmdframes,
01019                                 int maxframes, float frametime,
01020                                 vec3_t mins, vec3_t maxs, int visualize)
01021 {
01022     return AAS_ClientMovementPrediction(move, entnum, origin, presencetype, onground,
01023                                         velocity, cmdmove, cmdframes, maxframes,
01024                                         frametime, SE_HITBOUNDINGBOX, 0,
01025                                         mins, maxs, visualize);
01026 } //end of the function AAS_ClientMovementHitBBox
01027 //===========================================================================
01028 //
01029 // Parameter:           -
01030 // Returns:             -
01031 // Changes Globals:     -
01032 //===========================================================================
01033 void AAS_TestMovementPrediction(int entnum, vec3_t origin, vec3_t dir)
01034 {
01035     vec3_t velocity, cmdmove;
01036     aas_clientmove_t move;
01037 
01038     VectorClear(velocity);
01039     if (!AAS_Swimming(origin)) dir[2] = 0;
01040     VectorNormalize(dir);
01041     VectorScale(dir, 400, cmdmove);
01042     cmdmove[2] = 224;
01043     AAS_ClearShownDebugLines();
01044     AAS_PredictClientMovement(&move, entnum, origin, PRESENCE_NORMAL, qtrue,
01045                                     velocity, cmdmove, 13, 13, 0.1f, SE_HITGROUND, 0, qtrue);//SE_LEAVEGROUND);
01046     if (move.stopevent & SE_LEAVEGROUND)
01047     {
01048         botimport.Print(PRT_MESSAGE, "leave ground\n");
01049     } //end if
01050 } //end of the function TestMovementPrediction
01051 //===========================================================================
01052 // calculates the horizontal velocity needed to perform a jump from start
01053 // to end
01054 //
01055 // Parameter:           zvel    : z velocity for jump
01056 //                      start   : start position of jump
01057 //                      end     : end position of jump
01058 //                      *speed  : returned speed for jump
01059 // Returns:             qfalse if too high or too far from start to end
01060 // Changes Globals:     -
01061 //===========================================================================
01062 int AAS_HorizontalVelocityForJump(float zvel, vec3_t start, vec3_t end, float *velocity)
01063 {
01064     float phys_gravity, phys_maxvelocity;
01065     float maxjump, height2fall, t, top;
01066     vec3_t dir;
01067 
01068     phys_gravity = aassettings.phys_gravity;
01069     phys_maxvelocity = aassettings.phys_maxvelocity;
01070 
01071     //maximum height a player can jump with the given initial z velocity
01072     maxjump = 0.5 * phys_gravity * (zvel / phys_gravity) * (zvel / phys_gravity);
01073     //top of the parabolic jump
01074     top = start[2] + maxjump;
01075     //height the bot will fall from the top
01076     height2fall = top - end[2];
01077     //if the goal is to high to jump to
01078     if (height2fall < 0)
01079     {
01080         *velocity = phys_maxvelocity;
01081         return 0;
01082     } //end if
01083     //time a player takes to fall the height
01084     t = sqrt(height2fall / (0.5 * phys_gravity));
01085     //direction from start to end
01086     VectorSubtract(end, start, dir);
01087     //
01088     if ( (t + zvel / phys_gravity) == 0.0f ) {
01089         *velocity = phys_maxvelocity;
01090         return 0;
01091     }
01092     //calculate horizontal speed
01093     *velocity = sqrt(dir[0]*dir[0] + dir[1]*dir[1]) / (t + zvel / phys_gravity);
01094     //the horizontal speed must be lower than the max speed
01095     if (*velocity > phys_maxvelocity)
01096     {
01097         *velocity = phys_maxvelocity;
01098         return 0;
01099     } //end if
01100     return 1;
01101 } //end of the function AAS_HorizontalVelocityForJump

Generated on Thu Aug 25 12:37:09 2005 for Quake III Arena by  doxygen 1.3.9.1