cl_battlescape.c

Go to the documentation of this file.
00001 
00005 /*
00006 Copyright (C) 2002-2010 UFO: Alien Invasion.
00007 
00008 This program is free software; you can redistribute it and/or
00009 modify it under the terms of the GNU General Public License
00010 as published by the Free Software Foundation; either version 2
00011 of the License, or (at your option) any later version.
00012 
00013 This program is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00016 
00017 See the GNU General Public License for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with this program; if not, write to the Free Software
00021 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00022 
00023 */
00024 
00025 #include "../client.h"
00026 #include "cl_battlescape.h"
00027 #include "cl_actor.h"
00028 
00029 client_state_t cl;
00030 
00036 qboolean CL_BattlescapeRunning (void)
00037 {
00038     return cl.spawned;
00039 }
00040 
00049 qboolean CL_OnBattlescape (void)
00050 {
00051     /* server_state is set to zero (ss_dead) on every battlefield shutdown */
00052     if (Com_ServerState())
00053         return qtrue; /* server */
00054 
00055     /* client */
00056     if (cls.state >= ca_connected)
00057         return qtrue;
00058 
00059     return qfalse;
00060 }
00061 
00062 
00063 #define LOOKUP_EPSILON 0.0001f
00064 
00069 static const float lookup[30]= {
00070     0.0f,    0.1125f, 0.2227f, 0.3286f, 0.4284f, 0.5205f, 0.6039f,
00071     0.6778f, 0.7421f, 0.7969f, 0.8427f, 0.8802f, 0.9103f, 0.9340f,
00072     0.9523f, 0.9661f, 0.9763f, 0.9838f, 0.9891f, 0.9928f, 0.9953f,
00073     0.9970f, 0.9981f, 0.9989f, 0.9993f, 0.9996f, 0.9998f, 0.9999f,
00074     0.9999f, 1.0000f
00075 };
00076 
00081 static const float lookupdiff[30]= {
00082     1.1246f, 1.1024f, 1.0592f, 0.9977f, 0.9211f, 0.8336f, 0.7395f,
00083     0.6430f, 0.5481f, 0.4579f, 0.3750f, 0.3011f, 0.2369f, 0.1828f,
00084     0.1382f, 0.1024f, 0.0744f, 0.0530f, 0.0370f, 0.0253f, 0.0170f,
00085     0.0112f, 0.0072f, 0.0045f, 0.0028f, 0.0017f, 0.0010f, 0.0006f,
00086     0.0003f, 0.0002f
00087 };
00088 
00098 static float CL_LookupErrorFunction (float z)
00099 {
00100     float ifloat;
00101     int iint;
00102 
00103     /* erf(-z)=-erf(z), but erf of -ve number should never be used here
00104      * so return 0 here */
00105     if (z < LOOKUP_EPSILON)
00106         return 0.0f;
00107     if (z > 2.8f)
00108         return 1.0f;
00109     ifloat = floor(z * 10.0f);
00110     iint = (int)ifloat;
00111     assert(iint < 30);
00112     return lookup[iint] + (z - ifloat / 10.0f) * lookupdiff[iint];
00113 }
00114 
00115 static inline qboolean CL_TestLine (const vec3_t start, const vec3_t stop, const int levelmask)
00116 {
00117     return TR_TestLine(cl.mapTiles, start, stop, levelmask);
00118 }
00119 
00130 int CL_GetHitProbability (const le_t* actor)
00131 {
00132     vec3_t shooter, target;
00133     float distance, pseudosin, width, height, acc, perpX, perpY, hitchance,
00134         stdevupdown, stdevleftright, crouch, commonfactor;
00135     int distx, disty, n;
00136     le_t *le;
00137     const character_t *chr;
00138     pos3_t toPos;
00139 
00140     assert(actor);
00141     assert(actor->fd);
00142 
00143     if (IS_MODE_FIRE_PENDING(actor->actorMode))
00144         VectorCopy(actor->mousePendPos, toPos);
00145     else
00146         VectorCopy(mousePos, toPos);
00147 
00149     le = LE_GetFromPos(toPos);
00150     if (!le)
00151         return 0;
00152 
00153     /* or suicide attempted */
00154     if (le->selected && !FIRESH_IsMedikit(le->fd))
00155         return 0;
00156 
00157     VectorCopy(actor->origin, shooter);
00158     VectorCopy(le->origin, target);
00159 
00160     /* Calculate HitZone: */
00161     distx = fabs(shooter[0] - target[0]);
00162     disty = fabs(shooter[1] - target[1]);
00163     distance = sqrt(distx * distx + disty * disty);
00164     if (distx > disty)
00165         pseudosin = distance / distx;
00166     else
00167         pseudosin = distance / disty;
00168     width = 2 * PLAYER_WIDTH * pseudosin;
00169     height = LE_IsCrouched(le) ? PLAYER_CROUCHING_HEIGHT : PLAYER_STANDING_HEIGHT;
00170 
00171     chr = CL_ActorGetChr(actor);
00172     if (!chr)
00173         Com_Error(ERR_DROP, "No character given for local entity");
00174 
00175     acc = GET_ACC(chr->score.skills[ABILITY_ACCURACY],
00176             actor->fd->weaponSkill ? chr->score.skills[actor->fd->weaponSkill] : 0);
00177 
00178     crouch = (LE_IsCrouched(actor) && actor->fd->crouch) ? actor->fd->crouch : 1;
00179 
00180     commonfactor = crouch * torad * distance * GET_INJURY_MULT(chr->score.skills[ABILITY_MIND], actor->HP, actor->maxHP);
00181     stdevupdown = (actor->fd->spread[0] * (WEAPON_BALANCE + SKILL_BALANCE * acc)) * commonfactor;
00182     stdevleftright = (actor->fd->spread[1] * (WEAPON_BALANCE + SKILL_BALANCE * acc)) * commonfactor;
00183     hitchance = (stdevupdown > LOOKUP_EPSILON ? CL_LookupErrorFunction(height * 0.3536f / stdevupdown) : 1.0f)
00184               * (stdevleftright > LOOKUP_EPSILON ? CL_LookupErrorFunction(width * 0.3536f / stdevleftright) : 1.0f);
00185     /* 0.3536=sqrt(2)/4 */
00186 
00187     /* Calculate cover: */
00188     n = 0;
00189     height = height / 18;
00190     width = width / 18;
00191     target[2] -= UNIT_HEIGHT / 2;
00192     target[2] += height * 9;
00193     perpX = disty / distance * width;
00194     perpY = 0 - distx / distance * width;
00195 
00196     target[0] += perpX;
00197     perpX *= 2;
00198     target[1] += perpY;
00199     perpY *= 2;
00200     target[2] += 6 * height;
00201     if (!CL_TestLine(shooter, target, TL_FLAG_NONE))
00202         n++;
00203     target[0] += perpX;
00204     target[1] += perpY;
00205     target[2] -= 6 * height;
00206     if (!CL_TestLine(shooter, target, TL_FLAG_NONE))
00207         n++;
00208     target[0] += perpX;
00209     target[1] += perpY;
00210     target[2] += 4 * height;
00211     if (!CL_TestLine(shooter, target, TL_FLAG_NONE))
00212         n++;
00213     target[2] += 4 * height;
00214     if (!CL_TestLine(shooter, target, TL_FLAG_NONE))
00215         n++;
00216     target[0] -= perpX * 3;
00217     target[1] -= perpY * 3;
00218     target[2] -= 12 * height;
00219     if (!CL_TestLine(shooter, target, TL_FLAG_NONE))
00220         n++;
00221     target[0] -= perpX;
00222     target[1] -= perpY;
00223     target[2] += 6 * height;
00224     if (!CL_TestLine(shooter, target, TL_FLAG_NONE))
00225         n++;
00226     target[0] -= perpX;
00227     target[1] -= perpY;
00228     target[2] -= 4 * height;
00229     if (!CL_TestLine(shooter, target, TL_FLAG_NONE))
00230         n++;
00231     target[0] -= perpX;
00232     target[1] -= perpY;
00233     target[2] += 10 * height;
00234     if (!CL_TestLine(shooter, target, TL_FLAG_NONE))
00235         n++;
00236 
00237     return 100 * (hitchance * (0.125) * n);
00238 }
00239 
00240 static const float mapZBorder = -(UNIT_HEIGHT * 5);
00250 qboolean CL_OutsideMap (const vec3_t position, const float delta)
00251 {
00252     if (position[0] < cl.mapData->mapMin[0] - delta || position[0] > cl.mapData->mapMax[0] + delta)
00253         return qtrue;
00254 
00255     if (position[1] < cl.mapData->mapMin[1] - delta || position[1] > cl.mapData->mapMax[1] + delta)
00256         return qtrue;
00257 
00258     /* if a le is deeper than 5 levels below the latest walkable level (0) then
00259      * we can assume that it is outside the world
00260      * This is needed because some maps (e.g. the dam map) has unwalkable levels
00261      * that just exists for detail reasons */
00262     if (position[2] < mapZBorder)
00263         return qtrue;
00264 
00265     /* still inside the map borders */
00266     return qfalse;
00267 }
00268 
00269 #ifdef DEBUG
00270 
00271 #include "../../common/routing.h"
00272 
00277 void Grid_DumpWholeClientMap_f (void)
00278 {
00279     int i;
00280 
00281     for (i = 0; i < ACTOR_MAX_SIZE; i++)
00282         RT_DumpWholeMap(cl.mapTiles, &(cl.mapData->map[i]));
00283 }
00284 
00289 void Grid_DumpClientRoutes_f (void)
00290 {
00291     ipos3_t wpMins, wpMaxs;
00292     VecToPos(cl.mapData->mapMin, wpMins);
00293     VecToPos(cl.mapData->mapMax, wpMaxs);
00294     RT_WriteCSVFiles(cl.mapData->map, "ufoaiclient", wpMins, wpMaxs);
00295 }
00296 #endif
00297 
00298 char *CL_GetConfigString (int index)
00299 {
00300     if (index < 0 || index >= MAX_CONFIGSTRINGS)
00301         Com_Error(ERR_DROP, "Invalid config string index given");
00302     return cl.configstrings[index];
00303 }
00304 
00305 int CL_GetConfigStringInteger (int index)
00306 {
00307     if (index < 0 || index >= MAX_CONFIGSTRINGS)
00308         Com_Error(ERR_DROP, "Invalid config string index given");
00309     return atoi(cl.configstrings[index]);
00310 }
00311 
00312 char *CL_SetConfigString (int index, struct dbuffer *msg)
00313 {
00314     if (index < 0 || index >= MAX_CONFIGSTRINGS)
00315         Com_Error(ERR_DROP, "Invalid config string index given");
00316 
00317     /* change the string in cl
00318      * there may be overflows in i==CS_TILES - but thats ok
00319      * see definition of configstrings and MAX_TILESTRINGS */
00320     if (index == CS_TILES || index == CS_POSITIONS)
00321         NET_ReadString(msg, cl.configstrings[index], MAX_TOKEN_CHARS * MAX_TILESTRINGS);
00322     else
00323         NET_ReadString(msg, cl.configstrings[index], sizeof(cl.configstrings[index]));
00324 
00325     return cl.configstrings[index];
00326 }

Generated by  doxygen 1.6.2