From efdd31d5a9868eac76eef4e00d4247f33d3316a0 Mon Sep 17 00:00:00 2001 From: helixhorned Date: Sat, 28 Dec 2013 17:04:27 +0000 Subject: [PATCH] Guard retrieval of player index (.yvel) from APLAYER sprite. It is unacceptable that yvel is on one hand modifiable without restriction from scripting, but can be used as an array index without prior bound check in the C code. Because that member has an overloaded meaning and is also used for innocuous purposes such as the green color intensity of an SE light, it's infeasible to restrict access from scripting. Consequently, we must add bound checks on the C side. This is the first part of the effort to make .yvel safe, adding two functions P_Get() and P_GetP(). There are a couple of other uses as some kind of index. git-svn-id: https://svn.eduke32.com/eduke32@4226 1a8010ca-5511-0410-912e-c29ae57300e0 --- polymer/eduke32/source/actors.c | 56 +++++++------ polymer/eduke32/source/game.c | 98 ++++++++++++---------- polymer/eduke32/source/gameexec.c | 10 +-- polymer/eduke32/source/gameexec.h | 2 +- polymer/eduke32/source/lunatic/control.lua | 4 +- polymer/eduke32/source/player.c | 64 +++++++------- polymer/eduke32/source/player.h | 30 ++++++- polymer/eduke32/source/premap.c | 3 +- polymer/eduke32/source/sector.c | 5 +- polymer/eduke32/source/sounds.c | 6 +- 10 files changed, 164 insertions(+), 114 deletions(-) diff --git a/polymer/eduke32/source/actors.c b/polymer/eduke32/source/actors.c index d3f02f283..75e284da2 100644 --- a/polymer/eduke32/source/actors.c +++ b/polymer/eduke32/source/actors.c @@ -294,7 +294,7 @@ SKIPWALLCHECK: { if (sj->picnum == APLAYER) { - DukePlayer_t *ps = g_player[sj->yvel].ps; + DukePlayer_t *ps = g_player[P_GetP(sj)].ps; if (ps->newowner >= 0) G_ClearCameraView(ps); @@ -1015,25 +1015,27 @@ int32_t A_IncurDamage(int32_t sn) if (targ->picnum == APLAYER) { - int32_t p = targ->yvel; + int32_t p = P_GetP(targ); if (ud.god && dmg->picnum != SHRINKSPARK) return -1; if (dmg->owner >= 0 && ud.ffire == 0 && sprite[dmg->owner].picnum == APLAYER && (GametypeFlags[ud.coop] & GAMETYPE_PLAYERSFRIENDLY || - (GametypeFlags[ud.coop] & GAMETYPE_TDM && g_player[p].ps->team == g_player[sprite[dmg->owner].yvel].ps->team))) + (GametypeFlags[ud.coop] & GAMETYPE_TDM && g_player[p].ps->team == g_player[P_Get(dmg->owner)].ps->team))) return -1; targ->extra -= dmg->extra; if (dmg->owner >= 0 && targ->extra <= 0 && dmg->picnum != FREEZEBLAST) { + const int32_t ow = dmg->owner; + targ->extra = 0; - g_player[p].ps->wackedbyactor = dmg->owner; + g_player[p].ps->wackedbyactor = ow; - if (sprite[dmg->owner].picnum == APLAYER && p != sprite[dmg->owner].yvel) - g_player[p].ps->frag_ps = sprite[dmg->owner].yvel; + if (sprite[ow].picnum == APLAYER && p != P_Get(ow)) + g_player[p].ps->frag_ps = P_Get(ow); dmg->owner = g_player[p].ps->i; } @@ -1120,7 +1122,7 @@ void A_MoveDummyPlayers(void) while (i >= 0) { - const int32_t p = sprite[OW].yvel; + const int32_t p = P_Get(OW); DukePlayer_t *const ps = g_player[p].ps; const int32_t nexti = nextspritestat[i]; @@ -1172,7 +1174,7 @@ ACTOR_STATIC void G_MovePlayers(void) const int32_t nexti = nextspritestat[i]; spritetype *const s = &sprite[i]; - DukePlayer_t *const p = g_player[s->yvel].ps; + DukePlayer_t *const p = g_player[P_GetP(s)].ps; if (s->owner >= 0) { @@ -1200,24 +1202,24 @@ ACTOR_STATIC void G_MovePlayers(void) p->on_warping_sector = 1; if (slotag==ST_1_ABOVE_WATER) - k = P_Submerge(i, s->yvel, p, psect, othersect); + k = P_Submerge(i, P_GetP(s), p, psect, othersect); else - k = P_Emerge(i, s->yvel, p, psect, othersect); + k = P_Emerge(i, P_GetP(s), p, psect, othersect); if (k == 1) P_FinishWaterChange(i, p, slotag, -1, othersect); } #endif if (g_netServer || ud.multimode > 1) - otherp = P_FindOtherPlayer(s->yvel,&otherx); + otherp = P_FindOtherPlayer(P_GetP(s), &otherx); else { - otherp = s->yvel; + otherp = P_GetP(s); otherx = 0; } if (G_HaveActor(sprite[i].picnum)) - A_Execute(i,s->yvel,otherx); + A_Execute(i, P_GetP(s), otherx); if (g_netServer || ud.multimode > 1) if (sprite[g_player[otherp].ps->i].extra > 0) @@ -2845,7 +2847,7 @@ ACTOR_STATIC void Proj_MoveCustom(int32_t i) if (sprite[j].picnum == APLAYER) { - int32_t p = sprite[j].yvel; + int32_t p = P_Get(j); A_PlaySound(PISTOL_BODYHIT, j); @@ -3117,7 +3119,7 @@ ACTOR_STATIC void G_MoveWeapons(void) if (sprite[j].picnum == APLAYER) { - int32_t p = sprite[j].yvel; + int32_t p = P_Get(j); A_PlaySound(PISTOL_BODYHIT, j); if (s->picnum == SPIT) @@ -3410,7 +3412,7 @@ ACTOR_STATIC void G_MoveTransports(void) case STAT_PLAYER: if (sprite[j].owner != -1) { - const int32_t p = sprite[j].yvel; + const int32_t p = P_Get(j); DukePlayer_t *const ps = g_player[p].ps; ps->on_warping_sector = 1; @@ -4645,7 +4647,7 @@ ACTOR_STATIC void G_MoveActors(void) } if (sprite[s->owner].picnum == APLAYER) - l = sprite[s->owner].yvel; + l = P_Get(s->owner); else l = -1; if (s->xvel > 0) @@ -5069,9 +5071,9 @@ ACTOR_STATIC void G_MoveMisc(void) // STATNUM 5 else if (t[0] == 16) { s->picnum = NUKEBUTTON+2; - g_player[sprite[s->owner].yvel].ps->fist_incs = 1; + g_player[P_Get(s->owner)].ps->fist_incs = 1; } - if (g_player[sprite[s->owner].yvel].ps->fist_incs == GAMETICSPERSEC) + if (g_player[P_Get(s->owner)].ps->fist_incs == GAMETICSPERSEC) s->picnum = NUKEBUTTON+3; } goto BOLT; @@ -5596,8 +5598,8 @@ static void HandleSE31(int32_t i, int32_t setfloorzp, int32_t zref, int32_t t2va for (SPRITES_OF_SECT(s->sectnum, j)) { if (sprite[j].picnum == APLAYER && sprite[j].owner >= 0) - if (g_player[sprite[j].yvel].ps->on_ground == 1) - g_player[sprite[j].yvel].ps->pos.z += l; + if (g_player[P_Get(j)].ps->on_ground == 1) + g_player[P_Get(j)].ps->pos.z += l; if (sprite[j].zvel == 0 && sprite[j].statnum != STAT_EFFECTOR && sprite[j].statnum != STAT_PROJECTILE) { @@ -6877,7 +6879,7 @@ ACTOR_STATIC void G_MoveEffectors(void) //STATNUM 3 { if (sprite[j].statnum == STAT_PLAYER && sprite[j].owner >= 0) { - const int32_t p = sprite[j].yvel; + const int32_t p = P_Get(j); DukePlayer_t *const ps = g_player[p].ps; if (numplayers < 2 && !g_netServer) @@ -6931,7 +6933,7 @@ ACTOR_STATIC void G_MoveEffectors(void) //STATNUM 3 { if (sprite[k].statnum == STAT_PLAYER && sprite[k].owner >= 0) { - const int32_t p = sprite[k].yvel; + const int32_t p = P_Get(k); DukePlayer_t *const ps = g_player[p].ps; ps->pos.x += sprite[j].x-s->x; @@ -6993,8 +6995,8 @@ ACTOR_STATIC void G_MoveEffectors(void) //STATNUM 3 for (SPRITES_OF_SECT(s->sectnum, j)) { if (sprite[j].picnum == APLAYER && sprite[j].owner >= 0) - if (g_player[sprite[j].yvel].ps->on_ground == 1) - g_player[sprite[j].yvel].ps->pos.z += sc->extra; + if (g_player[P_Get(j)].ps->on_ground == 1) + g_player[P_Get(j)].ps->pos.z += sc->extra; if (sprite[j].zvel == 0 && sprite[j].statnum != STAT_EFFECTOR && sprite[j].statnum != STAT_PROJECTILE) { @@ -7028,8 +7030,8 @@ ACTOR_STATIC void G_MoveEffectors(void) //STATNUM 3 for (SPRITES_OF_SECT(s->sectnum, j)) { if (sprite[j].picnum == APLAYER && sprite[j].owner >= 0) - if (g_player[sprite[j].yvel].ps->on_ground == 1) - g_player[sprite[j].yvel].ps->pos.z -= sc->extra; + if (g_player[P_Get(j)].ps->on_ground == 1) + g_player[P_Get(j)].ps->pos.z -= sc->extra; if (sprite[j].zvel == 0 && sprite[j].statnum != STAT_EFFECTOR && sprite[j].statnum != STAT_PROJECTILE) { diff --git a/polymer/eduke32/source/game.c b/polymer/eduke32/source/game.c index 5210286b4..f26b18219 100644 --- a/polymer/eduke32/source/game.c +++ b/polymer/eduke32/source/game.c @@ -3633,8 +3633,8 @@ void G_DisplayRest(int32_t smoothratio) } if (I_EscapeTrigger() && ud.overhead_on == 0 - && ud.show_help == 0 - && g_player[myconnectindex].ps->newowner == -1) + && ud.show_help == 0 + && g_player[myconnectindex].ps->newowner == -1) { if ((g_player[myconnectindex].ps->gm&MODE_MENU) == MODE_MENU && g_currentMenu < 51) { @@ -3763,7 +3763,7 @@ void G_DisplayRest(int32_t smoothratio) (myps->player_par/(REALGAMETICSPERSEC*60)), (myps->player_par/REALGAMETICSPERSEC)%60, ((myps->player_par%REALGAMETICSPERSEC)*33)/10 - ); + ); G_PrintGameText(8+4+1,STARTALPHANUM, j,scale(200-i,ud.config.ScreenHeight,200)-textsc(21), tempbuf,0,10,26,0, 0, xdim-1, ydim-1, 65536); @@ -3853,7 +3853,7 @@ static void G_DoThirdPerson(const DukePlayer_t *pp, vec3_t *vect, int16_t *vsect vec3_t n = { (sintable[(ang+1536)&2047]>>4), (sintable[(ang+1024)&2047]>>4), (horiz-100)*128 - }; + }; sp->cstat &= (int16_t)~0x101; @@ -3941,15 +3941,15 @@ void G_DrawBackground(void) #if !defined LUNATIC if (Gv_GetVarByLabel("MENU_TILE", !fstilep, -1, -1)) #else - if (!fstilep) + if (!fstilep) #endif - { - if ((unsigned)bgtile < MAXTILES) - for (y=y1; ycstat = 32+((g_player[sprite[j].yvel].ps->footprintcount&1)<<2); + sp->cstat = 32+((g_player[P_Get(j)].ps->footprintcount&1)<<2); sp->ang = sprite[j].ang; } @@ -5596,7 +5596,7 @@ int32_t A_Spawn(int32_t j, int32_t pn) sp->xrepeat = sprite[j].xrepeat; sp->yrepeat = sprite[j].yrepeat; sp->shade = sprite[j].shade; - sp->pal = g_player[sprite[j].yvel].ps->palookup; + sp->pal = g_player[P_Get(j)].ps->palookup; } case DUKECAR__STATIC: case HELECOPT__STATIC: @@ -5658,16 +5658,17 @@ int32_t A_Spawn(int32_t j, int32_t pn) case SHOTGUNSHELL__STATIC: if (j >= 0) { - int32_t snum,a; + int32_t a; if (sprite[j].picnum == APLAYER) { - snum = sprite[j].yvel; - a = g_player[snum].ps->ang-(krand()&63)+8; //Fine tune + int32_t snum = P_Get(j); + const DukePlayer_t *const ps = g_player[snum].ps; + + a = ps->ang-(krand()&63)+8; //Fine tune T1 = krand()&1; - sp->z = (3<<8)+g_player[snum].ps->pyoff+g_player[snum].ps->pos.z- - ((g_player[snum].ps->horizoff+g_player[snum].ps->horiz-100)<<4); + sp->z = (3<<8) + ps->pyoff + ps->pos.z - ((ps->horizoff + ps->horiz-100)<<4); if (sp->picnum == SHOTGUNSHELL) sp->z += (3<<8); sp->zvel = -(krand()&255); @@ -7235,21 +7236,26 @@ void G_DoSpriteAnimations(int32_t ourx, int32_t oury, int32_t oura, int32_t smoo if (t->statnum == TSPR_TEMP) continue; - if (s->statnum != STAT_ACTOR && s->picnum == APLAYER && g_player[s->yvel].ps->newowner == -1 && s->owner >= 0) { - t->x -= mulscale16(65536-smoothratio,g_player[s->yvel].ps->pos.x-g_player[s->yvel].ps->opos.x); - t->y -= mulscale16(65536-smoothratio,g_player[s->yvel].ps->pos.y-g_player[s->yvel].ps->opos.y); - // dirty hack - if (g_player[s->yvel].ps->dead_flag) t->z = g_player[s->yvel].ps->opos.z; - t->z += mulscale16(smoothratio,g_player[s->yvel].ps->pos.z-g_player[s->yvel].ps->opos.z) - - (g_player[s->yvel].ps->dead_flag ? 0 : PHEIGHT) + PHEIGHT; - } - else if ((s->statnum == STAT_DEFAULT && s->picnum != CRANEPOLE) || s->statnum == STAT_PLAYER || - s->statnum == STAT_STANDABLE || s->statnum == STAT_PROJECTILE || s->statnum == STAT_MISC || s->statnum == STAT_ACTOR) - { - t->x -= mulscale16(65536-smoothratio,s->x-actor[i].bpos.x); - t->y -= mulscale16(65536-smoothratio,s->y-actor[i].bpos.y); - t->z -= mulscale16(65536-smoothratio,s->z-actor[i].bpos.z); + int32_t snum = P_GetP(s); + const DukePlayer_t *const ps = g_player[snum].ps; + + if (s->statnum != STAT_ACTOR && s->picnum == APLAYER && ps->newowner == -1 && s->owner >= 0) + { + t->x -= mulscale16(65536-smoothratio,ps->pos.x-ps->opos.x); + t->y -= mulscale16(65536-smoothratio,ps->pos.y-ps->opos.y); + // dirty hack + if (ps->dead_flag) t->z = ps->opos.z; + t->z += mulscale16(smoothratio,ps->pos.z-ps->opos.z) - + (ps->dead_flag ? 0 : PHEIGHT) + PHEIGHT; + } + else if ((s->statnum == STAT_DEFAULT && s->picnum != CRANEPOLE) || s->statnum == STAT_PLAYER || + s->statnum == STAT_STANDABLE || s->statnum == STAT_PROJECTILE || s->statnum == STAT_MISC || s->statnum == STAT_ACTOR) + { + t->x -= mulscale16(65536-smoothratio,s->x-actor[i].bpos.x); + t->y -= mulscale16(65536-smoothratio,s->y-actor[i].bpos.y); + t->z -= mulscale16(65536-smoothratio,s->z-actor[i].bpos.z); + } } sect = s->sectnum; @@ -7320,7 +7326,9 @@ void G_DoSpriteAnimations(int32_t ourx, int32_t oury, int32_t oura, int32_t smoo case BURNING2__STATIC: if (sprite[s->owner].statnum == STAT_PLAYER) { - if (display_mirror == 0 && sprite[s->owner].yvel == screenpeek && g_player[sprite[s->owner].yvel].ps->over_shoulder_on == 0) + const int32_t snum = P_Get(s->owner); + + if (display_mirror == 0 && snum == screenpeek && g_player[snum].ps->over_shoulder_on == 0) t->xrepeat = 0; else { @@ -7393,7 +7401,7 @@ void G_DoSpriteAnimations(int32_t ourx, int32_t oury, int32_t oura, int32_t smoo break; case APLAYER__STATIC: - p = s->yvel; + p = P_GetP(s); if (t->pal == 1) t->z -= (18<<8); @@ -7851,7 +7859,7 @@ skip: { if (sprite[s->owner].picnum == APLAYER) if (ud.camerasprite == -1) - if (screenpeek == sprite[s->owner].yvel && display_mirror == 0) + if (screenpeek == P_Get(s->owner) && display_mirror == 0) { t->owner = -1; break; @@ -12009,18 +12017,22 @@ int32_t G_DoMoveThings(void) sprite[g_player[i].ps->holoduke_on].cstat ^= 256; if ((hit.sprite >= 0) && !(g_player[myconnectindex].ps->gm & MODE_MENU) && - sprite[hit.sprite].picnum == APLAYER && sprite[hit.sprite].yvel != screenpeek && - g_player[sprite[hit.sprite].yvel].ps->dead_flag == 0) + sprite[hit.sprite].picnum == APLAYER) { - if (p->fta == 0 || p->ftq == QUOTE_RESERVED3) + const int32_t snum = P_Get(hit.sprite); + + if (snum != screenpeek && g_player[snum].ps->dead_flag == 0) { - if (ldist(&sprite[p->i],&sprite[hit.sprite]) < 9216) + if (p->fta == 0 || p->ftq == QUOTE_RESERVED3) { - Bsprintf(ScriptQuotes[QUOTE_RESERVED3],"%s",&g_player[sprite[hit.sprite].yvel].user_name[0]); - p->fta = 12, p->ftq = QUOTE_RESERVED3; + if (ldist(&sprite[p->i], &sprite[hit.sprite]) < 9216) + { + Bsprintf(ScriptQuotes[QUOTE_RESERVED3], "%s", &g_player[snum].user_name[0]); + p->fta = 12, p->ftq = QUOTE_RESERVED3; + } } + else if (p->fta > 2) p->fta -= 3; } - else if (p->fta > 2) p->fta -= 3; } } diff --git a/polymer/eduke32/source/gameexec.c b/polymer/eduke32/source/gameexec.c index b1af48eb7..cf51021c9 100644 --- a/polymer/eduke32/source/gameexec.c +++ b/polymer/eduke32/source/gameexec.c @@ -804,7 +804,7 @@ static void P_AddWeaponMaybeSwitch(DukePlayer_t *ps, int32_t weap) { if ((ps->weaponswitch & 1) && (ps->weaponswitch & 4)) { - int32_t snum = sprite[ps->i].yvel; + const int32_t snum = P_Get(ps->i); int32_t i, new_wchoice = -1, curr_wchoice = -1; for (i=0; i<=FREEZE_WEAPON && (new_wchoice < 0 || curr_wchoice < 0); i++) @@ -1428,7 +1428,7 @@ skip_check: case CON_GETLASTPAL: insptr++; if (vm.g_sp->picnum == APLAYER) - vm.g_sp->pal = g_player[vm.g_sp->yvel].ps->palookup; + vm.g_sp->pal = g_player[P_GetP(vm.g_sp)].ps->palookup; else { if (vm.g_sp->pal == 1 && vm.g_sp->extra == 0) // hack for frozen @@ -1440,7 +1440,7 @@ skip_check: case CON_TOSSWEAPON: insptr++; - P_DropWeapon(g_player[vm.g_sp->yvel].ps); + P_DropWeapon(g_player[P_GetP(vm.g_sp)].ps); continue; case CON_NULLOP: @@ -5318,7 +5318,7 @@ void A_LoadActor(int32_t iActor) #endif // NORECURSE -void A_Execute(int32_t iActor,int32_t iPlayer,int32_t lDist) +void A_Execute(int32_t iActor, int32_t iPlayer, int32_t lDist) { #ifdef LUNATIC int32_t killit=0; @@ -5697,7 +5697,7 @@ void G_RestoreMapState(void) // - walk backward to the door leading to Shadowpine Forest --> crash. for (SPRITES_OF(STAT_PLAYER, i)) { - int32_t snum = sprite[i].yvel; + int32_t snum = P_Get(i); Bassert((unsigned)snum < MAXPLAYERS); g_player[snum].ps->i = i; } diff --git a/polymer/eduke32/source/gameexec.h b/polymer/eduke32/source/gameexec.h index 234a11f49..6cc190870 100644 --- a/polymer/eduke32/source/gameexec.h +++ b/polymer/eduke32/source/gameexec.h @@ -143,7 +143,7 @@ extern int32_t g_currentEventExec; void A_LoadActor(int32_t iActor); #endif -void A_Execute(int32_t iActor,int32_t iPlayer,int32_t lDist); +void A_Execute(int32_t iActor, int32_t iPlayer, int32_t lDist); void A_Fall(int32_t iActor); int32_t A_FurthestVisiblePoint(int32_t iActor,spritetype *ts,int32_t *dax,int32_t *day); int32_t A_GetFurthestAngle(int32_t iActor,int32_t angs); diff --git a/polymer/eduke32/source/lunatic/control.lua b/polymer/eduke32/source/lunatic/control.lua index 2aee7d799..1472dcfad 100644 --- a/polymer/eduke32/source/lunatic/control.lua +++ b/polymer/eduke32/source/lunatic/control.lua @@ -1573,7 +1573,9 @@ end function _getlastpal(spritenum) local spr = sprite[spritenum] if (ispic(spr.picnum, "APLAYER")) then - spr.pal = player[spr.yvel].palookup + local pidx = spr.yvel + check_player_idx(pidx) + spr.pal = player[pidx].palookup else if (spr.pal == 1 and spr.extra == 0) then -- hack for frozen spr.extra = spr.extra+1 diff --git a/polymer/eduke32/source/player.c b/polymer/eduke32/source/player.c index ec94b1866..436395de1 100644 --- a/polymer/eduke32/source/player.c +++ b/polymer/eduke32/source/player.c @@ -63,7 +63,7 @@ static void P_IncurDamage(DukePlayer_t *p) { int32_t damage; - if (VM_OnEvent(EVENT_INCURDAMAGE, p->i, sprite[p->i].yvel, -1, 0) != 0) + if (VM_OnEvent(EVENT_INCURDAMAGE, p->i, P_Get(p->i), -1, 0) != 0) return; sprite[p->i].extra -= p->extra_extra8>>8; @@ -199,12 +199,14 @@ static int32_t A_FindTargetSprite(const spritetype *s, int32_t aang, int32_t atw int32_t dx1, dy1, dx2, dy2, dx3, dy3, smax, sdist; int32_t xv, yv; + const int32_t snum = s->picnum == APLAYER ? P_GetP(s) : -1; + if (s->picnum == APLAYER) { - if (!g_player[s->yvel].ps->auto_aim) + if (!g_player[snum].ps->auto_aim) return -1; - if (g_player[s->yvel].ps->auto_aim == 2) + if (g_player[snum].ps->auto_aim == 2) { if (A_CheckSpriteTileFlags(atwith,SPRITE_PROJECTILE) && (ProjectileData[atwith].workslike & PROJECTILE_RPG)) return -1; @@ -230,8 +232,8 @@ static int32_t A_FindTargetSprite(const spritetype *s, int32_t aang, int32_t atw j = -1; - gotshrinker = (s->picnum == APLAYER && PWEAPON(0, g_player[s->yvel].ps->curr_weapon, WorksLike) == SHRINKER_WEAPON); - gotfreezer = (s->picnum == APLAYER && PWEAPON(0, g_player[s->yvel].ps->curr_weapon, WorksLike) == FREEZE_WEAPON); + gotshrinker = (s->picnum == APLAYER && PWEAPON(0, g_player[snum].ps->curr_weapon, WorksLike) == SHRINKER_WEAPON); + gotfreezer = (s->picnum == APLAYER && PWEAPON(0, g_player[snum].ps->curr_weapon, WorksLike) == FREEZE_WEAPON); smax = INT32_MAX; @@ -253,12 +255,10 @@ static int32_t A_FindTargetSprite(const spritetype *s, int32_t aang, int32_t atw { if (A_CheckEnemySprite(&sprite[i]) || PN == APLAYER || PN == SHARK) { - if (PN == APLAYER && + if (PN == APLAYER && s->picnum == APLAYER && s != &sprite[i] && // ud.ffire == 0 && (GTFLAGS(GAMETYPE_PLAYERSFRIENDLY) || (GTFLAGS(GAMETYPE_TDM) && - g_player[sprite[i].yvel].ps->team == g_player[s->yvel].ps->team)) && - s->picnum == APLAYER && - s != &sprite[i]) + g_player[P_Get(i)].ps->team == g_player[snum].ps->team))) continue; if (gotshrinker && sprite[i].xrepeat < 30) @@ -284,7 +284,10 @@ static int32_t A_FindTargetSprite(const spritetype *s, int32_t aang, int32_t atw if (sdist > 512 && sdist < smax) { if (s->picnum == APLAYER) - a = (klabs(scale(SZ-s->z,10,sdist)-(g_player[s->yvel].ps->horiz+g_player[s->yvel].ps->horizoff-100)) < 100); + { + const DukePlayer_t *const ps = g_player[P_GetP(s)].ps; + a = (klabs(scale(SZ-s->z,10,sdist)-(ps->horiz+ps->horizoff-100)) < 100); + } else a = 1; if (PN == ORGANTIC || PN == ROTATEGUN) @@ -660,7 +663,7 @@ static int32_t P_PostFireHitscan(int32_t p, int32_t k, hitdata_t *hit, int32_t i if (sprite[hit->sprite].picnum == APLAYER && (ud.ffire == 1 || (!GTFLAGS(GAMETYPE_PLAYERSFRIENDLY) && GTFLAGS(GAMETYPE_TDM) && - g_player[sprite[hit->sprite].yvel].ps->team != g_player[sprite[i].yvel].ps->team))) + g_player[P_Get(hit->sprite)].ps->team != g_player[P_Get(i)].ps->team))) { int32_t l = A_Spawn(k, JIBS6); sprite[k].xrepeat = sprite[k].yrepeat = 0; @@ -857,7 +860,7 @@ static int32_t A_ShootCustom(const int32_t i, const int32_t atwith, int16_t sa, hitdata_t hit; spritetype *const s = &sprite[i]; const int16_t sect = s->sectnum; - const int32_t p = (s->picnum == APLAYER) ? s->yvel : -1; + const int32_t p = (s->picnum == APLAYER) ? P_GetP(s) : -1; DukePlayer_t *const ps = p >= 0 ? g_player[p].ps : NULL; #ifdef POLYMER @@ -1103,7 +1106,7 @@ int32_t A_ShootWithZvel(int32_t i, int32_t atwith, int32_t override_zvel) int16_t sa; vec3_t srcvect; spritetype *const s = &sprite[i]; - const int32_t p = (s->picnum == APLAYER) ? s->yvel : -1; + const int32_t p = (s->picnum == APLAYER) ? P_GetP(s) : -1; DukePlayer_t *const ps = p >= 0 ? g_player[p].ps : NULL; Bassert(atwith >= 0); @@ -1901,7 +1904,7 @@ void P_SetWeaponGamevars(int32_t snum, const DukePlayer_t *p) static void P_FireWeapon(DukePlayer_t *p) { - int32_t i, snum = sprite[p->i].yvel; + int32_t i, snum = P_Get(p->i); // TODO: PASS_SNUM? if (VM_OnEvent(EVENT_DOFIRE, p->i, snum, -1, 0) == 0) { @@ -1958,7 +1961,7 @@ static void P_FireWeapon(DukePlayer_t *p) static void P_DoWeaponSpawn(const DukePlayer_t *p) { - int32_t j, snum = sprite[p->i].yvel; + int32_t j, snum = P_Get(p->i); // TODO: PASS_SNUM? // NOTE: For the 'Spawn' member, 0 means 'none', too (originally so, // i.e. legacy). The check for <0 was added to the check because mod @@ -2952,7 +2955,7 @@ void P_GetInput(int32_t snum) static int32_t P_DoCounters(DukePlayer_t *p) { - int32_t snum = sprite[p->i].yvel; + int32_t snum = P_Get(p->i); // j = g_player[snum].sync->avel; // p->weapon_ang = -(j/5); @@ -3159,10 +3162,11 @@ int16_t WeaponPickupSprites[MAX_WEAPONS] = { KNEE__STATIC, FIRSTGUNSPRITE__STATI // this is used for player deaths void P_DropWeapon(DukePlayer_t *p) { - int32_t snum = sprite[p->i].yvel, - cw = PWEAPON(snum, p->curr_weapon, WorksLike); + int32_t snum = P_Get(p->i); // TODO: PASS_SNUM? + int32_t cw = PWEAPON(snum, p->curr_weapon, WorksLike); - if ((unsigned)cw >= MAX_WEAPONS) return; + if ((unsigned)cw >= MAX_WEAPONS) + return; if (krand()&1) A_Spawn(p->i, WeaponPickupSprites[cw]); @@ -3185,7 +3189,7 @@ void P_AddAmmo(int32_t weapon,DukePlayer_t *p,int32_t amount) static void P_AddWeaponNoSwitch(DukePlayer_t *p, int32_t weapon) { - int32_t snum = sprite[p->i].yvel; + int32_t snum = P_Get(p->i); // PASS_SNUM? if ((p->gotweapon & (1<i].yvel; + int32_t i = 0, snum = P_Get(p->i); // PASS_SNUM? const int8_t curr_weapon = p->curr_weapon; - if (p->reloading) return; + if (p->reloading) + return; if (p->curr_weapon != weapon && G_HaveEvent(EVENT_CHANGEWEAPON)) i = VM_OnEvent(EVENT_CHANGEWEAPON,p->i, snum, -1, weapon); @@ -3291,7 +3296,7 @@ void P_CheckWeapon(DukePlayer_t *p) if ((p->gotweapon & (1<ammo_amount[weapon] > 0 || !(p->weaponswitch & 2))) return; - snum = sprite[p->i].yvel; + snum = P_Get(p->i); for (i=0; i<=FREEZE_WEAPON; i++) { @@ -3335,7 +3340,7 @@ static void DoWallTouchDamage(const DukePlayer_t *p, int32_t obj) static void P_CheckTouchDamage(DukePlayer_t *p, int32_t obj) { - if ((obj = VM_OnEvent(EVENT_CHECKTOUCHDAMAGE, p->i, sprite[p->i].yvel, -1, obj)) == -1) + if ((obj = VM_OnEvent(EVENT_CHECKTOUCHDAMAGE, p->i, P_Get(p->i), -1, obj)) == -1) return; if ((obj&49152) == 49152) @@ -3396,7 +3401,7 @@ static int32_t P_CheckFloorDamage(DukePlayer_t *p, int32_t tex) { spritetype *s = &sprite[p->i]; - if ((unsigned)(tex = VM_OnEvent(EVENT_CHECKFLOORDAMAGE, p->i, sprite[p->i].yvel, -1, tex)) >= MAXTILES) + if ((unsigned)(tex = VM_OnEvent(EVENT_CHECKFLOORDAMAGE, p->i, P_Get(p->i), -1, tex)) >= MAXTILES) return 0; switch (DYNAMICTILEMAP(tex)) @@ -3461,7 +3466,7 @@ static int32_t P_CheckFloorDamage(DukePlayer_t *p, int32_t tex) } -int32_t P_FindOtherPlayer(int32_t p,int32_t *d) +int32_t P_FindOtherPlayer(int32_t p, int32_t *d) { int32_t j, closest_player = p; int32_t x, closest = INT32_MAX; @@ -5292,9 +5297,12 @@ HORIZONLY: A_DeleteSprite(p->actorsqu); break; case APLAYER__STATIC: - P_QuickKill(g_player[sprite[p->actorsqu].yvel].ps); - g_player[sprite[p->actorsqu].yvel].ps->frag_ps = snum; + { + int32_t snum = P_Get(p->actorsqu); + P_QuickKill(g_player[snum].ps); + g_player[snum].ps->frag_ps = snum; break; + } default: if (A_CheckEnemySprite(&sprite[p->actorsqu])) p->actors_killed++; diff --git a/polymer/eduke32/source/player.h b/polymer/eduke32/source/player.h index 734a8fa05..a7fcfd26e 100644 --- a/polymer/eduke32/source/player.h +++ b/polymer/eduke32/source/player.h @@ -23,6 +23,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifndef __player_h__ #define __player_h__ +extern int32_t playerswhenstarted; + #define MOVEFIFOSIZ 2 #define NAM_GRENADE_LIFETIME 120 @@ -368,7 +370,7 @@ void P_CheckWeapon(DukePlayer_t *p); void P_DisplayScuba(int32_t snum); void P_DisplayWeapon(int32_t snum); void P_DropWeapon(DukePlayer_t *p); -int32_t P_FindOtherPlayer(int32_t p,int32_t *d); +int32_t P_FindOtherPlayer(int32_t p, int32_t *d); void P_FragPlayer(int32_t snum); void P_UpdatePosWhenViewingCam(DukePlayer_t *p); void P_ProcessInput(int32_t snum); @@ -386,4 +388,30 @@ static inline void P_SetWeaponGamevars(int32_t snum, const DukePlayer_t *p) } #endif +// Get the player index given an APLAYER sprite pointer. +static inline int32_t P_GetP(const spritetype *spr) +{ +#if 0 // unprotected player index retrieval + return spr->yvel; +#elif defined NETCODE_DISABLE + UNREFERENCED_PARAMETER(spr); // for NDEBUG build + // NOTE: In the no-netcode build, there's no point to pass player indices + // at all since there is ever only one player. However, merely returning 0 + // would mean making this build less strict than the normal one. + Bassert(spr->yvel == 0); + return 0; +#else + int32_t pidx = spr->yvel; + if ((unsigned)pidx >= (unsigned)playerswhenstarted) + pidx = 0; + return pidx; +#endif +} + +// Get the player index given an APLAYER sprite index. +static inline int32_t P_Get(int32_t spritenum) +{ + return P_GetP(&sprite[spritenum]); +} + #endif diff --git a/polymer/eduke32/source/premap.c b/polymer/eduke32/source/premap.c index 7ac1c79d4..768644fa8 100644 --- a/polymer/eduke32/source/premap.c +++ b/polymer/eduke32/source/premap.c @@ -503,7 +503,7 @@ void G_CacheMapData(void) k = 0; for (k=0; kloogcnt = 0; p->angvel = 0; p->weapon_sway = 0; - // p->select_dir = 0; p->extra_extra8 = 0; p->show_empty_weapon= 0; p->dummyplayersprite=-1; diff --git a/polymer/eduke32/source/sector.c b/polymer/eduke32/source/sector.c index 662fde3a5..d097b6838 100644 --- a/polymer/eduke32/source/sector.c +++ b/polymer/eduke32/source/sector.c @@ -631,7 +631,6 @@ void G_OperateSectors(int32_t sn, int32_t ii) case ST_15_WARP_ELEVATOR://Warping elevators if (sprite[ii].picnum != APLAYER) return; - // if(ps[sprite[ii].yvel].select_dir == 1) return; i = headspritesect[sn]; while (i >= 0) @@ -2371,7 +2370,7 @@ void A_DamageObject(int32_t i,int32_t sn) j = sprite[sn].owner; if (j >= 0 && sprite[j].picnum == APLAYER && PN != ROTATEGUN && PN != DRONE) - if (g_player[sprite[j].yvel].ps->curr_weapon == SHOTGUN_WEAPON) + if (g_player[P_Get(j)].ps->curr_weapon == SHOTGUN_WEAPON) { A_Shoot(i,BLOODSPLAT3); A_Shoot(i,BLOODSPLAT1); @@ -2415,7 +2414,7 @@ void A_DamageObject(int32_t i,int32_t sn) if (sprite[i].statnum == STAT_PLAYER) { - DukePlayer_t *ps = g_player[sprite[i].yvel].ps; + DukePlayer_t *ps = g_player[P_Get(i)].ps; if (ps->newowner >= 0) G_ClearCameraView(ps); diff --git a/polymer/eduke32/source/sounds.c b/polymer/eduke32/source/sounds.c index 0436ef20c..a0ada60db 100644 --- a/polymer/eduke32/source/sounds.c +++ b/polymer/eduke32/source/sounds.c @@ -474,7 +474,7 @@ static int32_t S_CalcDistAndAng(int32_t i, int32_t num, int32_t camsect, int32_t int32_t sndang, sndist; int32_t explosion = 0; - if (PN == APLAYER && sprite[i].yvel == screenpeek) + if (PN == APLAYER && P_Get(i) == screenpeek) { sndang = sndist = 0; goto sound_further_processing; @@ -489,7 +489,7 @@ static int32_t S_CalcDistAndAng(int32_t i, int32_t num, int32_t camsect, int32_t // HACK for splitscreen mod: take the min of sound distances // to 1st and 2nd player. - if (PN == APLAYER && sprite[i].yvel==1) + if (PN == APLAYER && P_Get(i) == 1) { sndist = sndang = 0; goto sound_further_processing; @@ -588,7 +588,7 @@ int32_t S_PlaySound3D(int32_t num, int32_t i, const vec3_t *pos) // Duke talk if (g_sounds[num].m & SF_TALK) { - if ((g_netServer || ud.multimode > 1) && PN == APLAYER && sprite[i].yvel != screenpeek) // other player sound + if ((g_netServer || ud.multimode > 1) && PN == APLAYER && P_Get(i) != screenpeek) // other player sound { if (!(ud.config.VoiceToggle&4)) return -1;