Cuando la salud del jugador cambia entre los rangos correspondientes a las seis diferentes animaciones de la Cara de la barra de estado, los cambios porcentuales de salud en la barra aparecen de inmediato, pero el propio rostro no se actualiza hasta alcanzar el final de la secuencia de animación que esté realizando en ese momento.
Por ejemplo, si un jugador que está gravemente herido con su nivel de salud por debajo del 20%, obtiene una nueva arma, seguido inmediatamente por una recolección grande de salud tal como sucede al obtener una megaesfera, la barra de estado muestra durante un lapso muy breve un porcentaje muy elevado de la salud junto con una cara muy ensangrentada, tal como como se muestra en la captura de pantalla.
Aspectos técnicos[]
El fenómeno se debe a que el motor elige la siguiente gráfica para la Cara de acuerdo con una jerarquía estricta, y luego trata de evitar la actualización de la cara de nuevo hasta haber pasado un cierto número de tics.
De st_stuff.c:
#define ST_EVILGRINCOUNT (2*TICRATE) #define ST_STRAIGHTFACECOUNT (TICRATE/2) #define ST_TURNCOUNT (1*TICRATE) #define ST_OUCHCOUNT (1*TICRATE) #define ST_RAMPAGEDELAY (2*TICRATE)
void ST_updateFaceWidget(void) { int i; angle_t badguyangle; angle_t diffang; static int lastattackdown = -1; static int priority = 0; boolean doevilgrin; if (priority < 10) { // dead if (!plyr->health) { priority = 9; st_faceindex = ST_DEADFACE; st_facecount = 1; } } if (priority < 9) { if (plyr->bonuscount) { // picking up bonus doevilgrin = false; for (i=0;i<NUMWEAPONS;i++) { if (oldweaponsowned[i] != plyr->weaponowned[i]) { doevilgrin = true; oldweaponsowned[i] = plyr->weaponowned[i]; } } if (doevilgrin) { // evil grin if just picked up weapon priority = 8; st_facecount = ST_EVILGRINCOUNT; st_faceindex = ST_calcPainOffset() + ST_EVILGRINOFFSET; } } } if (priority < 8) { if (plyr->damagecount && plyr->attacker && plyr->attacker != plyr->mo) { // being attacked priority = 7; if (plyr->health - st_oldhealth > ST_MUCHPAIN) { st_facecount = ST_TURNCOUNT; st_faceindex = ST_calcPainOffset() + ST_OUCHOFFSET; } else { badguyangle = R_PointToAngle2(plyr->mo->x, plyr->mo->y, plyr->attacker->x, plyr->attacker->y); if (badguyangle > plyr->mo->angle) { // whether right or left diffang = badguyangle - plyr->mo->angle; i = diffang > ANG180; } else { // whether left or right diffang = plyr->mo->angle - badguyangle; i = diffang <= ANG180; } // confusing, aint it? st_facecount = ST_TURNCOUNT; st_faceindex = ST_calcPainOffset(); if (diffang < ANG45) { // head-on st_faceindex += ST_RAMPAGEOFFSET; } else if (i) { // turn face right st_faceindex += ST_TURNOFFSET; } else { // turn face left st_faceindex += ST_TURNOFFSET+1; } } } } if (priority < 7) { // getting hurt because of your own damn stupidity if (plyr->damagecount) { if (plyr->health - st_oldhealth > ST_MUCHPAIN) { priority = 7; st_facecount = ST_TURNCOUNT; st_faceindex = ST_calcPainOffset() + ST_OUCHOFFSET; } else { priority = 6; st_facecount = ST_TURNCOUNT; st_faceindex = ST_calcPainOffset() + ST_RAMPAGEOFFSET; } } } if (priority < 6) { // rapid firing if (plyr->attackdown) { if (lastattackdown==-1) lastattackdown = ST_RAMPAGEDELAY; else if (!--lastattackdown) { priority = 5; st_faceindex = ST_calcPainOffset() + ST_RAMPAGEOFFSET; st_facecount = 1; lastattackdown = 1; } } else lastattackdown = -1; } if (priority < 5) { // invulnerability if ((plyr->cheats & CF_GODMODE) || plyr->powers[pw_invulnerability]) { priority = 4; st_faceindex = ST_GODFACE; st_facecount = 1; } } // look left or look right if the facecount has timed out if (!st_facecount) { st_faceindex = ST_calcPainOffset() + (st_randomnumber % 3); st_facecount = ST_STRAIGHTFACECOUNT; priority = 0; } st_facecount--; }
Cada cambio en el gráfico de la cara aumenta la variable contador st_facecount (en negrita para enfatizar), que luego disminuye en 1 a cada tic. A fin de que la cara pueda ser renovada, st_facecount debe llegar a cero o bien ocurrir un evento en el juego con mayor precedencia; por ejemplo, la muerte del jugador reemplaza una cara sonriente con la cara "muerte" de inmediato.
Algunos tipos de cara, como el valor por defecto "cara adelante" o la cara de invulnerabilidad, se pueden sustituir por un daño o una recolección de armas en la siguiente convocatoria (st_facecount = 1), pero otros permanecen durante medio segundo o así (TICRATE es 35); las recolecciones de salud posteriores, por lo tanto no pueden ser representadas en la cara durante todo ese intervalo.