diff --git a/src/p_enemy.c b/src/p_enemy.c index 1c27e73c81c55a5f0cd131fb3004570e70d5f921..43ce161e600a6d5c2fc32d57057ca34c90671d24 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -13614,12 +13614,12 @@ static boolean PIT_DustDevilLaunch(mobj_t *thing) } else { //Player on the top of the tornado. + P_ResetPlayer(player); thing->z = dustdevil->z + dustdevil->height; thrust = 20 * FRACUNIT; player->powers[pw_nocontrol] = 0; S_StartSound(thing, sfx_wdjump); P_SetPlayerMobjState(thing, S_PLAY_FALL); - player->pflags &= ~PF_JUMPED; } thing->momz = thrust; diff --git a/src/p_mobj.c b/src/p_mobj.c index 6ee615cddc69d72247b0256cf30450618d614e5a..a10e6b3baa256d7c40a9aa1d6efee8770d1d080a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11598,13 +11598,21 @@ static fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* case MT_EMERALDSPAWN: case MT_TOKEN: case MT_EMBLEM: + case MT_RING: + case MT_REDTEAMRING: + case MT_BLUETEAMRING: + case MT_COIN: + case MT_BLUESPHERE: + case MT_BOMBSPHERE: + case MT_NIGHTSCHIP: + case MT_NIGHTSSTAR: offset += mthing->options & MTF_AMBUSH ? 24*FRACUNIT : 0; break; // Remaining objects. default: if (P_WeaponOrPanel(mobjtype)) - offset += mthing->options & MTF_AMBUSH ? 24 * FRACUNIT : 0; + offset += mthing->options & MTF_AMBUSH ? 24*FRACUNIT : 0; } if (!offset) // Snap to the surfaces when there's no offset set. @@ -13061,557 +13069,371 @@ ML_EFFECT5 : Don't stop thinking when too far away mthing->mobj = mobj; } -void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) +static void P_SpawnHoop(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t z, sector_t* sec, INT32 hoopsize, fixed_t sizefactor) { - mobjtype_t ringthing = MT_RING; mobj_t *mobj = NULL; - INT32 r, i; - fixed_t x, y, z, finalx, finaly, finalz; - sector_t *sec; + mobj_t *nextmobj = NULL; + mobj_t *hoopcenter; + TMatrix *pitchmatrix, *yawmatrix; + fixed_t radius = hoopsize*sizefactor; + INT32 i; + angle_t fa; TVector v, *res; - angle_t closestangle, fa; - boolean nightsreplace = ((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)); - - x = mthing->x << FRACBITS; - y = mthing->y << FRACBITS; - sec = R_PointInSubsector(x, y)->sector; - - // NiGHTS hoop! - if (mthing->type == 1705) - { - mobj_t *nextmobj = NULL; - mobj_t *hoopcenter; - INT16 spewangle; - - z = mthing->z << FRACBITS; - - hoopcenter = P_SpawnMobj(x, y, z, MT_HOOPCENTER); - - hoopcenter->spawnpoint = mthing; - - // Screw these damn hoops, I need this thinker. - //hoopcenter->flags |= MF_NOTHINK; - - z += + z += #ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : + sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : #endif - sec->floorheight; - - hoopcenter->z = z - hoopcenter->height/2; - - P_UnsetThingPosition(hoopcenter); - hoopcenter->x = x; - hoopcenter->y = y; - P_SetThingPosition(hoopcenter); + sec->floorheight; - // Scale 0-255 to 0-359 =( - closestangle = FixedAngle(FixedMul((mthing->angle>>8)*FRACUNIT, - 360*(FRACUNIT/256))); + hoopcenter = P_SpawnMobj(x, y, z, MT_HOOPCENTER); + hoopcenter->spawnpoint = mthing; + hoopcenter->z -= hoopcenter->height/2; - hoopcenter->movedir = FixedInt(FixedMul((mthing->angle&255)*FRACUNIT, - 360*(FRACUNIT/256))); - hoopcenter->movecount = FixedInt(AngleFixed(closestangle)); + P_UnsetThingPosition(hoopcenter); + hoopcenter->x = x; + hoopcenter->y = y; + P_SetThingPosition(hoopcenter); - // For the hoop when it flies away - hoopcenter->extravalue1 = 32; - hoopcenter->extravalue2 = 8 * FRACUNIT; + // Scale 0-255 to 0-359 =( + hoopcenter->movedir = ((mthing->angle & 255)*360)/256; // Pitch + pitchmatrix = RotateXMatrix(FixedAngle(hoopcenter->movedir << FRACBITS)); + hoopcenter->movecount = (((UINT16)mthing->angle >> 8)*360)/256; // Yaw + yawmatrix = RotateZMatrix(FixedAngle(hoopcenter->movecount << FRACBITS)); - spewangle = (INT16)hoopcenter->movedir; + // For the hoop when it flies away + hoopcenter->extravalue1 = hoopsize; + hoopcenter->extravalue2 = radius/12; - // Create the hoop! - for (i = 0; i < 32; i++) - { - fa = i*(FINEANGLES/32); - v[0] = FixedMul(FINECOSINE(fa),96*FRACUNIT); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa),96*FRACUNIT); - v[3] = FRACUNIT; - - res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(spewangle*FRACUNIT))); - M_Memcpy(&v, res, sizeof (v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); - M_Memcpy(&v, res, sizeof (v)); - - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; - - mobj = P_SpawnMobj(finalx, finaly, finalz, MT_HOOP); + // Create the hoop! + for (i = 0; i < hoopsize; i++) + { + fa = i*(FINEANGLES/hoopsize); + v[0] = FixedMul(FINECOSINE(fa), radius); + v[1] = 0; + v[2] = FixedMul(FINESINE(fa), radius); + v[3] = FRACUNIT; - if (maptol & TOL_XMAS) - P_SetMobjState(mobj, mobj->info->seestate + (i & 1)); + res = VectorMatrixMultiply(v, *pitchmatrix); + M_Memcpy(&v, res, sizeof(v)); + res = VectorMatrixMultiply(v, *yawmatrix); + M_Memcpy(&v, res, sizeof(v)); - mobj->z -= mobj->height/2; - P_SetTarget(&mobj->target, hoopcenter); // Link the sprite to the center. - mobj->fuse = 0; + mobj = P_SpawnMobj(x + v[0], y + v[1], z + v[2], MT_HOOP); + mobj->z -= mobj->height/2; - // Link all the sprites in the hoop together - if (nextmobj) - { - P_SetTarget(&mobj->hprev, nextmobj); - P_SetTarget(&mobj->hprev->hnext, mobj); - } - else - P_SetTarget(&mobj->hprev, P_SetTarget(&mobj->hnext, NULL)); + if (maptol & TOL_XMAS) + P_SetMobjState(mobj, mobj->info->seestate + (i & 1)); - nextmobj = mobj; - } + P_SetTarget(&mobj->target, hoopcenter); // Link the sprite to the center. + mobj->fuse = 0; - // Create the collision detectors! - for (i = 0; i < 16; i++) + // Link all the sprites in the hoop together + if (nextmobj) { - fa = i*FINEANGLES/16; - v[0] = FixedMul(FINECOSINE(fa),32*FRACUNIT); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa),32*FRACUNIT); - v[3] = FRACUNIT; - res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(spewangle*FRACUNIT))); - M_Memcpy(&v, res, sizeof (v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); - M_Memcpy(&v, res, sizeof (v)); - - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; - - mobj = P_SpawnMobj(finalx, finaly, finalz, MT_HOOPCOLLIDE); - mobj->z -= mobj->height/2; - - // Link all the collision sprites together. - P_SetTarget(&mobj->hnext, NULL); P_SetTarget(&mobj->hprev, nextmobj); P_SetTarget(&mobj->hprev->hnext, mobj); - - nextmobj = mobj; } - // Create the collision detectors! - for (i = 0; i < 16; i++) - { - fa = i*FINEANGLES/16; - v[0] = FixedMul(FINECOSINE(fa),64*FRACUNIT); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa),64*FRACUNIT); - v[3] = FRACUNIT; - res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(spewangle*FRACUNIT))); - M_Memcpy(&v, res, sizeof (v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); - M_Memcpy(&v, res, sizeof (v)); - - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; - - mobj = P_SpawnMobj(finalx, finaly, finalz, MT_HOOPCOLLIDE); - mobj->z -= mobj->height/2; - - // Link all the collision sprites together. - P_SetTarget(&mobj->hnext, NULL); - P_SetTarget(&mobj->hprev, nextmobj); - P_SetTarget(&mobj->hprev->hnext, mobj); + else + P_SetTarget(&mobj->hprev, P_SetTarget(&mobj->hnext, NULL)); - nextmobj = mobj; - } - return; + nextmobj = mobj; } - // CUSTOMIZABLE NiGHTS hoop! - else if (mthing->type == 1713) - { - mobj_t *nextmobj = NULL; - mobj_t *hoopcenter; - INT16 spewangle; - INT32 hoopsize; - INT32 hoopplacement; - - z = mthing->z << FRACBITS; - - hoopcenter = P_SpawnMobj(x, y, z, MT_HOOPCENTER); - hoopcenter->spawnpoint = mthing; - - z += -#ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : -#endif - sec->floorheight; - hoopcenter->z = z - hoopcenter->height/2; - P_UnsetThingPosition(hoopcenter); - hoopcenter->x = x; - hoopcenter->y = y; - P_SetThingPosition(hoopcenter); - - // Scale 0-255 to 0-359 =( - closestangle = FixedAngle(FixedMul((mthing->angle>>8)*FRACUNIT, - 360*(FRACUNIT/256))); - - hoopcenter->movedir = FixedInt(FixedMul((mthing->angle&255)*FRACUNIT, - 360*(FRACUNIT/256))); - hoopcenter->movecount = FixedInt(AngleFixed(closestangle)); - - spewangle = (INT16)hoopcenter->movedir; - - // Super happy fun time - // For each flag add 4 fracunits to the size - // Default (0 flags) is 8 fracunits - hoopsize = 8 + (4 * (mthing->options & 0xF)); - hoopplacement = hoopsize * (4*FRACUNIT); + // Create the collision detectors! + // Create them until the size is less than 8 + // But always create at least ONE set of collision detectors + do + { + if (hoopsize >= 32) + hoopsize -= 16; + else + hoopsize /= 2; - // For the hoop when it flies away - hoopcenter->extravalue1 = hoopsize; - hoopcenter->extravalue2 = FixedDiv(hoopplacement, 12*FRACUNIT); + radius = hoopsize*sizefactor; - // Create the hoop! for (i = 0; i < hoopsize; i++) { fa = i*(FINEANGLES/hoopsize); - v[0] = FixedMul(FINECOSINE(fa), hoopplacement); + v[0] = FixedMul(FINECOSINE(fa), radius); v[1] = 0; - v[2] = FixedMul(FINESINE(fa), hoopplacement); + v[2] = FixedMul(FINESINE(fa), radius); v[3] = FRACUNIT; - res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(spewangle*FRACUNIT))); - M_Memcpy(&v, res, sizeof (v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); - M_Memcpy(&v, res, sizeof (v)); - - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; - - mobj = P_SpawnMobj(finalx, finaly, finalz, MT_HOOP); - - if (maptol & TOL_XMAS) - P_SetMobjState(mobj, mobj->info->seestate + (i & 1)); + res = VectorMatrixMultiply(v, *pitchmatrix); + M_Memcpy(&v, res, sizeof(v)); + res = VectorMatrixMultiply(v, *yawmatrix); + M_Memcpy(&v, res, sizeof(v)); + mobj = P_SpawnMobj(x + v[0], y + v[1], z + v[2], MT_HOOPCOLLIDE); mobj->z -= mobj->height/2; - P_SetTarget(&mobj->target, hoopcenter); // Link the sprite to the center. - mobj->fuse = 0; - // Link all the sprites in the hoop together - if (nextmobj) - { - P_SetTarget(&mobj->hprev, nextmobj); - P_SetTarget(&mobj->hprev->hnext, mobj); - } - else - P_SetTarget(&mobj->hprev, P_SetTarget(&mobj->hnext, NULL)); + // Link all the collision sprites together. + P_SetTarget(&mobj->hnext, NULL); + P_SetTarget(&mobj->hprev, nextmobj); + P_SetTarget(&mobj->hprev->hnext, mobj); nextmobj = mobj; } + } while (hoopsize >= 8); +} - // Create the collision detectors! - // Create them until the size is less than 8 - // But always create at least ONE set of collision detectors - do - { - if (hoopsize >= 32) - hoopsize -= 16; - else - hoopsize /= 2; - - hoopplacement = hoopsize * (4*FRACUNIT); - - for (i = 0; i < hoopsize; i++) - { - fa = i*FINEANGLES/hoopsize; - v[0] = FixedMul(FINECOSINE(fa), hoopplacement); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa), hoopplacement); - v[3] = FRACUNIT; - res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(spewangle*FRACUNIT))); - M_Memcpy(&v, res, sizeof (v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); - M_Memcpy(&v, res, sizeof (v)); - - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; - - mobj = P_SpawnMobj(finalx, finaly, finalz, MT_HOOPCOLLIDE); - mobj->z -= mobj->height/2; - - // Link all the collision sprites together. - P_SetTarget(&mobj->hnext, NULL); - P_SetTarget(&mobj->hprev, nextmobj); - P_SetTarget(&mobj->hprev->hnext, mobj); - - nextmobj = mobj; - } - } while (hoopsize >= 8); - - return; - } - // *** - // Special placement patterns - // *** +static void P_SpawnRingItem(mapthing_t *mthing, fixed_t x, fixed_t y, boolean bonustime, boolean nightsreplace) +{ + mobjtype_t ringthing = MT_RING; + mobj_t *mobj = NULL; + fixed_t z; - // Vertical Rings - Stack of 5 (handles both red and yellow) - else if (mthing->type == 600 || mthing->type == 601) + // Which ringthing to use + if (mthing->type == mobjinfo[MT_BLUESPHERE].doomednum) + ringthing = (nightsreplace) ? MT_NIGHTSCHIP : MT_BLUESPHERE; + else if (mthing->type == mobjinfo[MT_BOMBSPHERE].doomednum) + ringthing = MT_BOMBSPHERE; + else { - INT32 dist = 64*FRACUNIT; - if (mthing->type == 601) - dist = 128*FRACUNIT; - if (ultimatemode) return; // No rings in Ultimate! if (nightsreplace) ringthing = MT_NIGHTSSTAR; + else if (mthing->type == mobjinfo[MT_COIN].doomednum) + ringthing = MT_COIN; + else if (mthing->type == mobjinfo[MT_REDTEAMRING].doomednum) // No team rings in non-CTF + ringthing = (gametyperules & GTR_TEAMFLAGS) ? MT_REDTEAMRING : MT_RING; + else if (mthing->type == mobjinfo[MT_BLUETEAMRING].doomednum) // Ditto + ringthing = (gametyperules & GTR_TEAMFLAGS) ? MT_BLUETEAMRING : MT_RING; + } - if (mthing->options & MTF_OBJECTFLIP) - { - z = ( -#ifdef ESLOPE - sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : -#endif - sec->ceilingheight) - mobjinfo[ringthing].height; - if (mthing->z) - z -= (mthing->z << FRACBITS); - } - else - { - z = ( -#ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : -#endif - sec->floorheight); - if (mthing->z) - z += (mthing->z << FRACBITS); - } - - for (r = 1; r <= 5; r++) - { - if (mthing->options & MTF_OBJECTFLIP) - z -= dist; - else - z += dist; + z = P_GetMobjSpawnHeight(ringthing, mthing, x, y); + mobj = P_SpawnMobj(x, y, z, ringthing); + mobj->spawnpoint = mthing; - mobj = P_SpawnMobj(x, y, z, ringthing); + if (mthing->options & MTF_OBJECTFLIP) + { + mobj->eflags |= MFE_VERTICALFLIP; + mobj->flags2 |= MF2_OBJECTFLIP; + } - if (mthing->options & MTF_OBJECTFLIP) - { - mobj->eflags |= MFE_VERTICALFLIP; - mobj->flags2 |= MF2_OBJECTFLIP; - } + mobj->angle = FixedAngle(mthing->angle << FRACBITS); + mthing->mobj = mobj; + if (mthing->options & MTF_AMBUSH) + mobj->flags2 |= MF2_AMBUSH; - mobj->angle = FixedAngle(mthing->angle*FRACUNIT); - if (mthing->options & MTF_AMBUSH) - mobj->flags2 |= MF2_AMBUSH; + if (bonustime && (ringthing == MT_BLUESPHERE || ringthing == MT_NIGHTSCHIP)) + P_SetMobjState(mobj, mobj->info->raisestate); + else if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) + P_SetMobjState(mobj, mobj->info->seestate); +} - if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) - P_SetMobjState(mobj, mobj->info->seestate); - } - } - // Diagonal rings (handles both types) - else if (mthing->type == 602 || mthing->type == 603) // Diagonal rings (5) - { - INT32 iterations = 5; - if (mthing->type == 603) - iterations = 10; +static void P_SpawnVerticalSpringRings(mapthing_t *mthing, fixed_t x, fixed_t y, sector_t* sec, boolean nightsreplace) +{ + mobjtype_t ringthing = MT_RING; + mobj_t* mobj = NULL; + fixed_t z; + INT32 r; - if (ultimatemode) - return; // No rings in Ultimate! + INT32 dist = 64*FRACUNIT; + if (mthing->type == 601) + dist = 128*FRACUNIT; - if (nightsreplace) - ringthing = MT_NIGHTSSTAR; + if (ultimatemode) + return; // No rings in Ultimate! - closestangle = FixedAngle(mthing->angle*FRACUNIT); - fa = (closestangle >> ANGLETOFINESHIFT); + if (nightsreplace) + ringthing = MT_NIGHTSSTAR; - if (mthing->options & MTF_OBJECTFLIP) - { - z = ( -#ifdef ESLOPE - sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : -#endif - sec->ceilingheight) - mobjinfo[ringthing].height; - if (mthing->z) - z -= (mthing->z << FRACBITS); - } - else - { - z = ( + if (mthing->options & MTF_OBJECTFLIP) + { + z = ( #ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : + sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : #endif - sec->floorheight); - if (mthing->z) - z += (mthing->z << FRACBITS); - } - - for (r = 1; r <= iterations; r++) - { - x += FixedMul(64*FRACUNIT, FINECOSINE(fa)); - y += FixedMul(64*FRACUNIT, FINESINE(fa)); - - if (mthing->options & MTF_OBJECTFLIP) - z -= 64*FRACUNIT; - else - z += 64*FRACUNIT; - - mobj = P_SpawnMobj(x, y, z, ringthing); - - if (mthing->options & MTF_OBJECTFLIP) - { - mobj->eflags |= MFE_VERTICALFLIP; - mobj->flags2 |= MF2_OBJECTFLIP; - } - - mobj->angle = closestangle; - if (mthing->options & MTF_AMBUSH) - mobj->flags2 |= MF2_AMBUSH; - - if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) - P_SetMobjState(mobj, mobj->info->seestate); - } + sec->ceilingheight) - mobjinfo[ringthing].height; + if (mthing->z) + z -= (mthing->z << FRACBITS); } - // Rings of items (all six of them) - else if (mthing->type >= 604 && mthing->type <= 609) + else { - INT32 numitems = 8; - INT32 size = 96*FRACUNIT; - - if (mthing->type & 1) - { - numitems = 16; - size = 192*FRACUNIT; - } - - z = + z = ( #ifdef ESLOPE sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : #endif - sec->floorheight; + sec->floorheight); if (mthing->z) z += (mthing->z << FRACBITS); + } + + for (r = 1; r <= 5; r++) + { + if (mthing->options & MTF_OBJECTFLIP) + z -= dist; + else + z += dist; - closestangle = FixedAngle(mthing->angle*FRACUNIT); + mobj = P_SpawnMobj(x, y, z, ringthing); - switch (mthing->type) + if (mthing->options & MTF_OBJECTFLIP) { - case 604: - case 605: - if (ultimatemode) - return; // No rings in Ultimate! - if (nightsreplace) - ringthing = MT_NIGHTSSTAR; - break; - case 608: - case 609: - /*ringthing = (i & 1) ? MT_RING : MT_BLUESPHERE; -- i == 0 is bluesphere - break;*/ - case 606: - case 607: - ringthing = (nightsreplace) ? MT_NIGHTSCHIP : MT_BLUESPHERE; - break; - default: - break; + mobj->eflags |= MFE_VERTICALFLIP; + mobj->flags2 |= MF2_OBJECTFLIP; } - // Create the hoop! - for (i = 0; i < numitems; i++) - { - if (mthing->type == 608 || mthing->type == 609) - { - if (i & 1) - { - if (ultimatemode) - continue; // No rings in Ultimate! - ringthing = (nightsreplace) ? MT_NIGHTSSTAR : MT_RING; - } - else - ringthing = (nightsreplace) ? MT_NIGHTSCHIP : MT_BLUESPHERE; - } + mobj->angle = FixedAngle(mthing->angle << FRACBITS); + if (mthing->options & MTF_AMBUSH) + mobj->flags2 |= MF2_AMBUSH; - fa = i*FINEANGLES/numitems; - v[0] = FixedMul(FINECOSINE(fa),size); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa),size); - v[3] = FRACUNIT; + if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) + P_SetMobjState(mobj, mobj->info->seestate); + } +} - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); - M_Memcpy(&v, res, sizeof (v)); +static void P_SpawnDiagonalSpringRings(mapthing_t* mthing, fixed_t x, fixed_t y, sector_t* sec, boolean nightsreplace) +{ + mobjtype_t ringthing = MT_RING; + mobj_t *mobj = NULL; + fixed_t z; + INT32 r; + angle_t closestangle, fa; - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; + INT32 iterations = 5; + if (mthing->type == 603) + iterations = 10; - mobj = P_SpawnMobj(finalx, finaly, finalz, ringthing); - mobj->z -= mobj->height/2; + if (ultimatemode) + return; // No rings in Ultimate! - if (mthing->options & MTF_OBJECTFLIP) - { - mobj->eflags |= MFE_VERTICALFLIP; - mobj->flags2 |= MF2_OBJECTFLIP; - } + if (nightsreplace) + ringthing = MT_NIGHTSSTAR; - mobj->angle = closestangle; - if (mthing->options & MTF_AMBUSH) - mobj->flags2 |= MF2_AMBUSH; + closestangle = FixedAngle(mthing->angle << FRACBITS); + fa = (closestangle >> ANGLETOFINESHIFT); - if (bonustime && (ringthing == MT_BLUESPHERE || ringthing == MT_NIGHTSCHIP)) - P_SetMobjState(mobj, mobj->info->raisestate); - else if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) - P_SetMobjState(mobj, mobj->info->seestate); - } + if (mthing->options & MTF_OBJECTFLIP) + { + z = ( +#ifdef ESLOPE + sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : +#endif + sec->ceilingheight) - mobjinfo[ringthing].height; + if (mthing->z) + z -= (mthing->z << FRACBITS); } - // All manners of rings and coins else { + z = ( +#ifdef ESLOPE + sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : +#endif + sec->floorheight); + if (mthing->z) + z += (mthing->z << FRACBITS); + } + + for (r = 1; r <= iterations; r++) + { + x += FixedMul(64*FRACUNIT, FINECOSINE(fa)); + y += FixedMul(64*FRACUNIT, FINESINE(fa)); - // Which ringthing to use - if (mthing->type == mobjinfo[MT_BLUESPHERE].doomednum) - ringthing = (nightsreplace) ? MT_NIGHTSCHIP : MT_BLUESPHERE; - else if (mthing->type == mobjinfo[MT_BOMBSPHERE].doomednum) - ringthing = MT_BOMBSPHERE; + if (mthing->options & MTF_OBJECTFLIP) + z -= 64*FRACUNIT; else - { - if (ultimatemode) - return; // No rings in Ultimate! + z += 64*FRACUNIT; - if (nightsreplace) - ringthing = MT_NIGHTSSTAR; - else if (mthing->type == mobjinfo[MT_COIN].doomednum) - ringthing = MT_COIN; - else if (mthing->type == mobjinfo[MT_REDTEAMRING].doomednum) // No team rings in non-CTF - ringthing = (gametyperules & GTR_TEAMFLAGS) ? MT_REDTEAMRING : MT_RING; - else if (mthing->type == mobjinfo[MT_BLUETEAMRING].doomednum) // Ditto - ringthing = (gametyperules & GTR_TEAMFLAGS) ? MT_BLUETEAMRING : MT_RING; - } + mobj = P_SpawnMobj(x, y, z, ringthing); - // Set proper height if (mthing->options & MTF_OBJECTFLIP) { - z = ( -#ifdef ESLOPE - sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : -#endif - sec->ceilingheight) - mobjinfo[ringthing].height; - if (mthing->z) - z -= (mthing->z << FRACBITS); + mobj->eflags |= MFE_VERTICALFLIP; + mobj->flags2 |= MF2_OBJECTFLIP; } - else - { - z = + + mobj->angle = closestangle; + if (mthing->options & MTF_AMBUSH) + mobj->flags2 |= MF2_AMBUSH; + + if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) + P_SetMobjState(mobj, mobj->info->seestate); + } +} + +static void P_SpawnItemCircle(mapthing_t* mthing, fixed_t x, fixed_t y, sector_t* sec, boolean bonustime, boolean nightsreplace) +{ + mobjtype_t ringthing = MT_RING; + mobj_t *mobj = NULL; + fixed_t z, finalx, finaly, finalz; + angle_t closestangle, fa; + INT32 i; + TVector v, *res; + INT32 numitems = 8; + INT32 size = 96*FRACUNIT; + + if (mthing->type & 1) + { + numitems = 16; + size = 192*FRACUNIT; + } + + z = #ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : + sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : #endif - sec->floorheight; - if (mthing->z) - z += (mthing->z << FRACBITS); - } + sec->floorheight; + if (mthing->z) + z += (mthing->z << FRACBITS); - if (mthing->options & MTF_AMBUSH) // Special flag for rings + closestangle = FixedAngle(mthing->angle << FRACBITS); + + switch (mthing->type) + { + case 604: + case 605: + if (ultimatemode) + return; // No rings in Ultimate! + if (nightsreplace) + ringthing = MT_NIGHTSSTAR; + break; + case 608: + case 609: + /*ringthing = (i & 1) ? MT_RING : MT_BLUESPHERE; -- i == 0 is bluesphere + break;*/ + case 606: + case 607: + ringthing = (nightsreplace) ? MT_NIGHTSCHIP : MT_BLUESPHERE; + break; + default: + break; + } + + // Create the hoop! + for (i = 0; i < numitems; i++) + { + if (mthing->type == 608 || mthing->type == 609) { - if (mthing->options & MTF_OBJECTFLIP) - z -= 24*FRACUNIT; + if (i & 1) + { + if (ultimatemode) + continue; // No rings in Ultimate! + ringthing = (nightsreplace) ? MT_NIGHTSSTAR : MT_RING; + } else - z += 24*FRACUNIT; + ringthing = (nightsreplace) ? MT_NIGHTSCHIP : MT_BLUESPHERE; } - mobj = P_SpawnMobj(x, y, z, ringthing); - mobj->spawnpoint = mthing; + fa = i * FINEANGLES/numitems; + v[0] = FixedMul(FINECOSINE(fa), size); + v[1] = 0; + v[2] = FixedMul(FINESINE(fa), size); + v[3] = FRACUNIT; + + res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); + M_Memcpy(&v, res, sizeof(v)); + + finalx = x + v[0]; + finaly = y + v[1]; + finalz = z + v[2]; + + mobj = P_SpawnMobj(finalx, finaly, finalz, ringthing); + mobj->z -= mobj->height/2; if (mthing->options & MTF_OBJECTFLIP) { @@ -13619,8 +13441,7 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) mobj->flags2 |= MF2_OBJECTFLIP; } - mobj->angle = FixedAngle(mthing->angle*FRACUNIT); - mthing->mobj = mobj; + mobj->angle = closestangle; if (mthing->options & MTF_AMBUSH) mobj->flags2 |= MF2_AMBUSH; @@ -13631,6 +13452,47 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) } } +void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) +{ + fixed_t x = mthing->x << FRACBITS; + fixed_t y = mthing->y << FRACBITS; + fixed_t z = mthing->z << FRACBITS; + sector_t *sec = R_PointInSubsector(x, y)->sector; + boolean nightsreplace = ((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)); + + switch (mthing->type) + { + // Special placement patterns + case 600: // 5 vertical rings (yellow spring) + case 601: // 5 vertical rings (red spring) + P_SpawnVerticalSpringRings(mthing, x, y, sec, nightsreplace); + return; + case 602: // 5 diagonal rings (yellow spring) + case 603: // 10 diagonal rings (red spring) + P_SpawnDiagonalSpringRings(mthing, x, y, sec, nightsreplace); + return; + case 604: // Circle of rings (8 items) + case 605: // Circle of rings (16 bits) + case 606: // Circle of blue spheres (8 items) + case 607: // Circle of blue spheres (16 items) + case 608: // Circle of rings and blue spheres (8 items) + case 609: // Circle of rings and blue spheres (16 items) + P_SpawnItemCircle(mthing, x, y, sec, bonustime, nightsreplace); + return; + // Hoops + case 1705: // Generic NiGHTS hoop + P_SpawnHoop(mthing, x, y, z, sec, 24, 4*FRACUNIT); + return; + case 1713: // Customizable NiGHTS hoop + // For each flag add 16 fracunits to the size + // Default (0 flags) is 32 fracunits + P_SpawnHoop(mthing, x, y, z, sec, 8 + (4*(mthing->options & 0xF)), 4*FRACUNIT); + return; + default: // All manners of rings and coins + P_SpawnRingItem(mthing, x, y, bonustime, nightsreplace); + } +} + // // P_CheckMissileSpawn // Moves the missile forward a bit and possibly explodes it right there. diff --git a/src/p_saveg.c b/src/p_saveg.c index 89447db80ae08d844d3259c0717f4916f7a380c5..5af72cd46cc9d7f8f6d2837413775b51fc8b898e 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -777,14 +777,13 @@ static void P_NetArchiveWorld(void) size_t i; INT32 statsec = 0, statline = 0; const line_t *li = lines; + const line_t *spawnli = spawnlines; const side_t *si; + const side_t *spawnsi; UINT8 *put; - // reload the map just to see difference - mapsector_t *ms; - mapsidedef_t *msd; - maplinedef_t *mld; const sector_t *ss = sectors; + const sector_t *spawnss = spawnsectors; UINT8 diff, diff2, diff3; // initialize colormap vars because paranoia @@ -793,65 +792,45 @@ static void P_NetArchiveWorld(void) WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD); put = save_p; - if (W_IsLumpWad(lastloadedmaplumpnum)) // welp it's a map wad in a pk3 - { // HACK: Open wad file rather quickly so we can get the data from the relevant lumps - UINT8 *wadData = W_CacheLumpNum(lastloadedmaplumpnum, PU_STATIC); - filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs); -#define retrieve_mapdata(d, f)\ - d = Z_Malloc((f)->size, PU_CACHE, NULL); \ - M_Memcpy(d, wadData + (f)->filepos, (f)->size) - retrieve_mapdata(ms, fileinfo + ML_SECTORS); - retrieve_mapdata(mld, fileinfo + ML_LINEDEFS); - retrieve_mapdata(msd, fileinfo + ML_SIDEDEFS); -#undef retrieve_mapdata - Z_Free(wadData); // we're done with this now - } - else // phew it's just a WAD - { - ms = W_CacheLumpNum(lastloadedmaplumpnum+ML_SECTORS, PU_CACHE); - mld = W_CacheLumpNum(lastloadedmaplumpnum+ML_LINEDEFS, PU_CACHE); - msd = W_CacheLumpNum(lastloadedmaplumpnum+ML_SIDEDEFS, PU_CACHE); - } - - for (i = 0; i < numsectors; i++, ss++, ms++) + for (i = 0; i < numsectors; i++, ss++, spawnss++) { diff = diff2 = diff3 = 0; - if (ss->floorheight != SHORT(ms->floorheight)<<FRACBITS) + if (ss->floorheight != spawnss->floorheight) diff |= SD_FLOORHT; - if (ss->ceilingheight != SHORT(ms->ceilingheight)<<FRACBITS) + if (ss->ceilingheight != spawnss->ceilingheight) diff |= SD_CEILHT; // // flats // - if (ss->floorpic != P_CheckLevelFlat(ms->floorpic)) + if (ss->floorpic != spawnss->floorpic) diff |= SD_FLOORPIC; - if (ss->ceilingpic != P_CheckLevelFlat(ms->ceilingpic)) + if (ss->ceilingpic != spawnss->ceilingpic) diff |= SD_CEILPIC; - if (ss->lightlevel != SHORT(ms->lightlevel)) + if (ss->lightlevel != spawnss->lightlevel) diff |= SD_LIGHT; - if (ss->special != SHORT(ms->special)) + if (ss->special != spawnss->special) diff |= SD_SPECIAL; - if (ss->floor_xoffs != ss->spawn_flr_xoffs) + if (ss->floor_xoffs != spawnss->floor_xoffs) diff2 |= SD_FXOFFS; - if (ss->floor_yoffs != ss->spawn_flr_yoffs) + if (ss->floor_yoffs != spawnss->floor_yoffs) diff2 |= SD_FYOFFS; - if (ss->ceiling_xoffs != ss->spawn_ceil_xoffs) + if (ss->ceiling_xoffs != spawnss->ceiling_xoffs) diff2 |= SD_CXOFFS; - if (ss->ceiling_yoffs != ss->spawn_ceil_yoffs) + if (ss->ceiling_yoffs != spawnss->ceiling_yoffs) diff2 |= SD_CYOFFS; - if (ss->floorpic_angle != ss->spawn_flrpic_angle) + if (ss->floorpic_angle != spawnss->floorpic_angle) diff2 |= SD_FLOORANG; - if (ss->ceilingpic_angle != ss->spawn_flrpic_angle) + if (ss->ceilingpic_angle != spawnss->ceilingpic_angle) diff2 |= SD_CEILANG; - if (ss->tag != SHORT(ms->tag)) + if (ss->tag != spawnss->tag) diff2 |= SD_TAG; - if (ss->nexttag != ss->spawn_nexttag || ss->firsttag != ss->spawn_firsttag) + if (ss->nexttag != spawnss->nexttag || ss->firsttag != spawnss->firsttag) diff3 |= SD_TAGLIST; - if (ss->extra_colormap != ss->spawn_extra_colormap) + if (ss->extra_colormap != spawnss->extra_colormap) diff3 |= SD_COLORMAP; // Check if any of the sector's FOFs differ from how they spawned @@ -955,45 +934,41 @@ static void P_NetArchiveWorld(void) WRITEUINT16(put, 0xffff); // do lines - for (i = 0; i < numlines; i++, mld++, li++) + for (i = 0; i < numlines; i++, spawnli++, li++) { diff = diff2 = diff3 = 0; - if (li->special != SHORT(mld->special)) + if (li->special != spawnli->special) diff |= LD_SPECIAL; - if (SHORT(mld->special) == 321 || SHORT(mld->special) == 322) // only reason li->callcount would be non-zero is if either of these are involved + if (spawnli->special == 321 || spawnli->special == 322) // only reason li->callcount would be non-zero is if either of these are involved diff |= LD_CLLCOUNT; if (li->sidenum[0] != 0xffff) { si = &sides[li->sidenum[0]]; - if (si->textureoffset != SHORT(msd[li->sidenum[0]].textureoffset)<<FRACBITS) + spawnsi = &spawnsides[li->sidenum[0]]; + if (si->textureoffset != spawnsi->textureoffset) diff |= LD_S1TEXOFF; //SoM: 4/1/2000: Some textures are colormaps. Don't worry about invalid textures. - if (R_CheckTextureNumForName(msd[li->sidenum[0]].toptexture) != -1 - && si->toptexture != R_TextureNumForName(msd[li->sidenum[0]].toptexture)) + if (si->toptexture != spawnsi->toptexture) diff |= LD_S1TOPTEX; - if (R_CheckTextureNumForName(msd[li->sidenum[0]].bottomtexture) != -1 - && si->bottomtexture != R_TextureNumForName(msd[li->sidenum[0]].bottomtexture)) + if (si->bottomtexture != spawnsi->bottomtexture) diff |= LD_S1BOTTEX; - if (R_CheckTextureNumForName(msd[li->sidenum[0]].midtexture) != -1 - && si->midtexture != R_TextureNumForName(msd[li->sidenum[0]].midtexture)) + if (si->midtexture != spawnsi->midtexture) diff |= LD_S1MIDTEX; } if (li->sidenum[1] != 0xffff) { si = &sides[li->sidenum[1]]; - if (si->textureoffset != SHORT(msd[li->sidenum[1]].textureoffset)<<FRACBITS) + spawnsi = &spawnsides[li->sidenum[1]]; + if (si->textureoffset != spawnsi->textureoffset) diff2 |= LD_S2TEXOFF; - if (R_CheckTextureNumForName(msd[li->sidenum[1]].toptexture) != -1 - && si->toptexture != R_TextureNumForName(msd[li->sidenum[1]].toptexture)) + if (si->toptexture != spawnsi->toptexture) diff2 |= LD_S2TOPTEX; - if (R_CheckTextureNumForName(msd[li->sidenum[1]].bottomtexture) != -1 - && si->bottomtexture != R_TextureNumForName(msd[li->sidenum[1]].bottomtexture)) + if (si->bottomtexture != spawnsi->bottomtexture) diff2 |= LD_S2BOTTEX; - if (R_CheckTextureNumForName(msd[li->sidenum[1]].midtexture) != -1 - && si->midtexture != R_TextureNumForName(msd[li->sidenum[1]].midtexture)) + if (si->midtexture != spawnsi->midtexture) diff2 |= LD_S2MIDTEX; if (diff2) diff |= LD_DIFF2; diff --git a/src/p_setup.c b/src/p_setup.c index 34f0cf882162f5c6fd4f214abec7029f21c33505..b8b82e7f3171445a66bae7f812930682031d0f83 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -103,6 +103,9 @@ node_t *nodes; line_t *lines; side_t *sides; mapthing_t *mapthings; +sector_t *spawnsectors; +line_t *spawnlines; +side_t *spawnsides; INT32 numstarposts; UINT16 bossdisabled; boolean stoppedclock; @@ -367,27 +370,12 @@ UINT32 P_GetScoreForGrade(INT16 map, UINT8 mare, UINT8 grade) return mapheaderinfo[map-1]->grades[mare].grade[grade-1]; } -/** Loads the vertexes for a level. - * - * \param lump VERTEXES lump number. - * \sa ML_VERTEXES - */ - -static inline void P_LoadRawVertexes(UINT8 *data, size_t i) +// Loads the vertexes for a level. +static inline void P_LoadRawVertexes(UINT8 *data) { - mapvertex_t *ml; - vertex_t *li; - - numvertexes = i / sizeof (mapvertex_t); - - if (numvertexes <= 0) - I_Error("Level has no vertices"); // instead of crashing - - // Allocate zone memory for buffer. - vertexes = Z_Calloc(numvertexes * sizeof (*vertexes), PU_LEVEL, NULL); - - ml = (mapvertex_t *)data; - li = vertexes; + mapvertex_t *ml = (mapvertex_t *)data; + vertex_t *li = vertexes; + size_t i; // Copy and convert vertex coordinates, internal representation as fixed. for (i = 0; i < numvertexes; i++, li++, ml++) @@ -397,13 +385,6 @@ static inline void P_LoadRawVertexes(UINT8 *data, size_t i) } } -static inline void P_LoadVertexes(lumpnum_t lumpnum) -{ - UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); - P_LoadRawVertexes(data, W_LumpLength(lumpnum)); - Z_Free(data); -} - /** Computes the length of a seg in fracunits. * * \param seg Seg to compute length for. @@ -435,25 +416,15 @@ static inline float P_SegLengthFloat(seg_t *seg) } #endif -/** Loads the SEGS resource from a level. - * - * \param lump Lump number of the SEGS resource. - * \sa ::ML_SEGS - */ -static void P_LoadRawSegs(UINT8 *data, size_t i) +// Loads the SEGS resource from a level. +static void P_LoadRawSegs(UINT8 *data) { INT32 linedef, side; - mapseg_t *ml; - seg_t *li; + mapseg_t *ml = (mapseg_t*)data; + seg_t *li = segs; line_t *ldef; + size_t i; - numsegs = i / sizeof (mapseg_t); - if (numsegs <= 0) - I_Error("Level has no segs"); // instead of crashing - segs = Z_Calloc(numsegs * sizeof (*segs), PU_LEVEL, NULL); - - ml = (mapseg_t *)data; - li = segs; for (i = 0; i < numsegs; i++, li++, ml++) { li->v1 = &vertexes[SHORT(ml->v1)]; @@ -478,7 +449,7 @@ static void P_LoadRawSegs(UINT8 *data, size_t i) li->side = side = SHORT(ml->side); li->sidedef = &sides[ldef->sidenum[side]]; li->frontsector = sides[ldef->sidenum[side]].sector; - if (ldef-> flags & ML_TWOSIDED) + if (ldef->flags & ML_TWOSIDED) li->backsector = sides[ldef->sidenum[side^1]].sector; else li->backsector = 0; @@ -488,30 +459,12 @@ static void P_LoadRawSegs(UINT8 *data, size_t i) } } -static void P_LoadSegs(lumpnum_t lumpnum) +// Loads the SSECTORS resource from a level. +static inline void P_LoadRawSubsectors(void *data) { - UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); - P_LoadRawSegs(data, W_LumpLength(lumpnum)); - Z_Free(data); -} - - -/** Loads the SSECTORS resource from a level. - * - * \param lump Lump number of the SSECTORS resource. - * \sa ::ML_SSECTORS - */ -static inline void P_LoadRawSubsectors(void *data, size_t i) -{ - mapsubsector_t *ms; - subsector_t *ss; - - numsubsectors = i / sizeof (mapsubsector_t); - if (numsubsectors <= 0) - I_Error("Level has no subsectors (did you forget to run it through a nodesbuilder?)"); - ss = subsectors = Z_Calloc(numsubsectors * sizeof (*subsectors), PU_LEVEL, NULL); - - ms = (mapsubsector_t *)data; + mapsubsector_t *ms = (mapsubsector_t*)data; + subsector_t *ss = subsectors; + size_t i; for (i = 0; i < numsubsectors; i++, ss++, ms++) { @@ -525,13 +478,6 @@ static inline void P_LoadRawSubsectors(void *data, size_t i) } } -static void P_LoadSubsectors(lumpnum_t lumpnum) -{ - UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); - P_LoadRawSubsectors(data, W_LumpLength(lumpnum)); - Z_Free(data); -} - // // levelflats // @@ -698,20 +644,12 @@ INT32 P_CheckLevelFlat(const char *flatname) } // Sets up the ingame sectors structures. -// Lumpnum is the lumpnum of a SECTORS lump. -static void P_LoadRawSectors(UINT8 *data, size_t i) +static void P_LoadRawSectors(UINT8 *data) { - mapsector_t *ms; - sector_t *ss; + mapsector_t *ms = (mapsector_t *)data; + sector_t *ss = sectors; levelflat_t *foundflats; - - // We count how many sectors we got. - numsectors = i / sizeof (mapsector_t); - if (numsectors <= 0) - I_Error("Level has no sectors"); - - // Allocate as much memory as we need into the global sectors table. - sectors = Z_Calloc(numsectors*sizeof (*sectors), PU_LEVEL, NULL); + size_t i; // Allocate a big chunk of memory as big as our MAXLEVELFLATS limit. //Fab : FIXME: allocate for whatever number of flats - 512 different flats per level should be plenty @@ -722,8 +660,6 @@ static void P_LoadRawSectors(UINT8 *data, size_t i) numlevelflats = 0; // For each counted sector, copy the sector raw data from our cache pointer ms, to the global table pointer ss. - ms = (mapsector_t *)data; - ss = sectors; for (i = 0; i < numsectors; i++, ss++, ms++) { ss->floorheight = SHORT(ms->floorheight)<<FRACBITS; @@ -733,11 +669,9 @@ static void P_LoadRawSectors(UINT8 *data, size_t i) ss->ceilingpic = P_AddLevelFlat(ms->ceilingpic, foundflats); ss->lightlevel = SHORT(ms->lightlevel); - ss->spawn_lightlevel = SHORT(ms->lightlevel); ss->special = SHORT(ms->special); ss->tag = SHORT(ms->tag); ss->nexttag = ss->firsttag = -1; - ss->spawn_nexttag = ss->spawn_firsttag = -1; memset(&ss->soundorg, 0, sizeof(ss->soundorg)); ss->validcount = 0; @@ -772,9 +706,7 @@ static void P_LoadRawSectors(UINT8 *data, size_t i) ss->spawn_extra_colormap = NULL; ss->floor_xoffs = ss->ceiling_xoffs = ss->floor_yoffs = ss->ceiling_yoffs = 0; - ss->spawn_flr_xoffs = ss->spawn_ceil_xoffs = ss->spawn_flr_yoffs = ss->spawn_ceil_yoffs = 0; ss->floorpic_angle = ss->ceilingpic_angle = 0; - ss->spawn_flrpic_angle = ss->spawn_ceilpic_angle = 0; ss->gravity = NULL; ss->cullheight = NULL; ss->verticalflip = false; @@ -805,29 +737,15 @@ static void P_LoadRawSectors(UINT8 *data, size_t i) P_SetupLevelFlatAnims(); } -static void P_LoadSectors(lumpnum_t lumpnum) -{ - UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); - P_LoadRawSectors(data, W_LumpLength(lumpnum)); - Z_Free(data); -} - // // P_LoadNodes // -static void P_LoadRawNodes(UINT8 *data, size_t i) +static void P_LoadRawNodes(UINT8 *data) { UINT8 j, k; - mapnode_t *mn; - node_t *no; - - numnodes = i / sizeof (mapnode_t); - if (numnodes <= 0) - I_Error("Level has no nodes"); - nodes = Z_Calloc(numnodes * sizeof (*nodes), PU_LEVEL, NULL); - - mn = (mapnode_t *)data; - no = nodes; + mapnode_t *mn = (mapnode_t*)data; + node_t *no = nodes; + size_t i; for (i = 0; i < numnodes; i++, no++, mn++) { @@ -844,13 +762,6 @@ static void P_LoadRawNodes(UINT8 *data, size_t i) } } -static void P_LoadNodes(lumpnum_t lumpnum) -{ - UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); - P_LoadRawNodes(data, W_LumpLength(lumpnum)); - Z_Free(data); -} - // // P_ReloadRings // Used by NiGHTS, clears all ring/wing/etc items and respawns them @@ -1002,12 +913,10 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum) } #endif -static void P_PrepareRawThings(UINT8 *data, size_t i) +static void P_PrepareRawThings(UINT8 *data) { mapthing_t *mt; - - nummapthings = i / (5 * sizeof (INT16)); - mapthings = Z_Calloc(nummapthings * sizeof (*mapthings), PU_LEVEL, NULL); + size_t i; for (i = 0, mt = mapthings; i < nummapthings; i++, mt++) { @@ -1028,13 +937,6 @@ static void P_PrepareRawThings(UINT8 *data, size_t i) } } -static void P_PrepareThings(lumpnum_t lumpnum) -{ - UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); - P_PrepareRawThings(data, W_LumpLength(lumpnum)); - Z_Free(data); -} - static void P_SpawnEmeraldHunt(void) { INT32 emer1, emer2, emer3; @@ -1085,7 +987,7 @@ static void P_LoadThings(boolean loademblems) size_t i; mapthing_t *mt; - // Spawn axis points first so they are at the front of the list for fast searching. + // Spawn axis points first so they are at the front of the list for fast searching. for (i = 0, mt = mapthings; i < nummapthings; i++, mt++) { switch (mt->type) @@ -1183,33 +1085,46 @@ void P_WriteThings(lumpnum_t lumpnum) CONS_Printf(M_GetText("newthings%d.lmp saved.\n"), gamemap); } -static void P_LoadRawLineDefs(UINT8 *data, size_t i) +static void P_LoadRawLineDefs(UINT8 *data) { - maplinedef_t *mld; - line_t *ld; - vertex_t *v1, *v2; - - numlines = i / sizeof (maplinedef_t); - if (numlines <= 0) - I_Error("Level has no linedefs"); - lines = Z_Calloc(numlines * sizeof (*lines), PU_LEVEL, NULL); + maplinedef_t *mld = (maplinedef_t *)data; + line_t *ld = lines; + size_t i; - mld = (maplinedef_t *)data; - ld = lines; for (i = 0; i < numlines; i++, mld++, ld++) { ld->flags = SHORT(mld->flags); ld->special = SHORT(mld->special); ld->tag = SHORT(mld->tag); - v1 = ld->v1 = &vertexes[SHORT(mld->v1)]; - v2 = ld->v2 = &vertexes[SHORT(mld->v2)]; - ld->dx = v2->x - v1->x; - ld->dy = v2->y - v1->y; + ld->v1 = &vertexes[SHORT(mld->v1)]; + ld->v2 = &vertexes[SHORT(mld->v2)]; + + ld->sidenum[0] = SHORT(mld->sidenum[0]); + ld->sidenum[1] = SHORT(mld->sidenum[1]); + } +} + +static void P_SetupLines(void) +{ + line_t *ld = lines; + size_t i; + + for (i = 0; i < numlines; i++, ld++) + { + vertex_t *v1 = ld->v1; + vertex_t *v2 = ld->v2; #ifdef WALLSPLATS ld->splats = NULL; #endif +#ifdef POLYOBJECTS + ld->polyobj = NULL; +#endif + + ld->dx = v2->x - v1->x; + ld->dy = v2->y - v1->y; + if (!ld->dx) ld->slopetype = ST_VERTICAL; else if (!ld->dy) @@ -1241,62 +1156,46 @@ static void P_LoadRawLineDefs(UINT8 *data, size_t i) ld->bbox[BOXTOP] = v1->y; } - ld->sidenum[0] = SHORT(mld->sidenum[0]); - ld->sidenum[1] = SHORT(mld->sidenum[1]); - { // cph 2006/09/30 - fix sidedef errors right away. // cph 2002/07/20 - these errors are fatal if not fixed, so apply them UINT8 j; for (j=0; j < 2; j++) - { if (ld->sidenum[j] != 0xffff && ld->sidenum[j] >= (UINT16)numsides) { ld->sidenum[j] = 0xffff; CONS_Debug(DBG_SETUP, "P_LoadRawLineDefs: linedef %s has out-of-range sidedef number\n", sizeu1(numlines-i-1)); } - } } ld->frontsector = ld->backsector = NULL; ld->validcount = 0; ld->firsttag = ld->nexttag = -1; ld->callcount = 0; - // killough 11/98: fix common wad errors (missing sidedefs): + // killough 11/98: fix common wad errors (missing sidedefs): if (ld->sidenum[0] == 0xffff) { ld->sidenum[0] = 0; // Substitute dummy sidedef for missing right side // cph - print a warning about the bug - CONS_Debug(DBG_SETUP, "P_LoadRawLineDefs: linedef %s missing first sidedef\n", sizeu1(numlines-i-1)); + CONS_Debug(DBG_SETUP, "Linedef %s missing first sidedef\n", sizeu1(numlines-i-1)); } if ((ld->sidenum[1] == 0xffff) && (ld->flags & ML_TWOSIDED)) { ld->flags &= ~ML_TWOSIDED; // Clear 2s flag for missing left side // cph - print a warning about the bug - CONS_Debug(DBG_SETUP, "P_LoadRawLineDefs: linedef %s has two-sided flag set, but no second sidedef\n", sizeu1(numlines-i-1)); + CONS_Debug(DBG_SETUP, "Linedef %s has two-sided flag set, but no second sidedef\n", sizeu1(numlines-i-1)); } if (ld->sidenum[0] != 0xffff && ld->special) sides[ld->sidenum[0]].special = ld->special; if (ld->sidenum[1] != 0xffff && ld->special) sides[ld->sidenum[1]].special = ld->special; - -#ifdef POLYOBJECTS - ld->polyobj = NULL; -#endif } } -static void P_LoadLineDefs(lumpnum_t lumpnum) -{ - UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); - P_LoadRawLineDefs(data, W_LumpLength(lumpnum)); - Z_Free(data); -} - static void P_LoadLineDefs2(void) { size_t i = numlines; @@ -1399,22 +1298,6 @@ static void P_LoadLineDefs2(void) } } - - -static inline void P_LoadRawSideDefs(size_t i) -{ - numsides = i / sizeof (mapsidedef_t); - if (numsides <= 0) - I_Error("Level has no sidedefs"); - sides = Z_Calloc(numsides * sizeof (*sides), PU_LEVEL, NULL); -} - -static inline void P_LoadSideDefs(lumpnum_t lumpnum) -{ - P_LoadRawSideDefs(W_LumpLength(lumpnum)); -} - - static void P_LoadRawSideDefs2(void *data) { UINT16 i; @@ -1575,15 +1458,6 @@ static void P_LoadRawSideDefs2(void *data) R_ClearTextureNumCache(true); } -// Delay loading texture names until after loaded linedefs. -static void P_LoadSideDefs2(lumpnum_t lumpnum) -{ - UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); - P_LoadRawSideDefs2(data); - Z_Free(data); -} - - static boolean LineInBlock(fixed_t cx1, fixed_t cy1, fixed_t cx2, fixed_t cy2, fixed_t bx1, fixed_t by1) { fixed_t bbox[4]; @@ -1863,84 +1737,11 @@ static void P_ReadBlockMapLump(INT16 *wadblockmaplump, size_t count) } } -// -// P_LoadBlockMap -// -// Levels might not have a blockmap, so if one does not exist -// this should return false. -static boolean P_LoadBlockMap(lumpnum_t lumpnum) -{ -#if 0 - (void)lumpnum; - return false; -#else - size_t count; - const char *lumpname = W_CheckNameForNum(lumpnum); - - // Check if the lump exists, and if it's named "BLOCKMAP" - if (!lumpname || memcmp(lumpname, "BLOCKMAP", 8) != 0) - { - return false; - } - - count = W_LumpLength(lumpnum); - - if (!count || count >= 0x20000) - return false; - - { - INT16 *wadblockmaplump = malloc(count); //INT16 *wadblockmaplump = W_CacheLumpNum (lump, PU_LEVEL); - if (!wadblockmaplump) - return false; - W_ReadLump(lumpnum, wadblockmaplump); - count /= 2; - P_ReadBlockMapLump(wadblockmaplump, count); - free(wadblockmaplump); - } - - bmaporgx = blockmaplump[0]<<FRACBITS; - bmaporgy = blockmaplump[1]<<FRACBITS; - bmapwidth = blockmaplump[2]; - bmapheight = blockmaplump[3]; - - // clear out mobj chains - count = sizeof (*blocklinks)* bmapwidth*bmapheight; - blocklinks = Z_Calloc(count, PU_LEVEL, NULL); - blockmap = blockmaplump+4; - -#ifdef POLYOBJECTS - // haleyjd 2/22/06: setup polyobject blockmap - count = sizeof(*polyblocklinks) * bmapwidth * bmapheight; - polyblocklinks = Z_Calloc(count, PU_LEVEL, NULL); -#endif - return true; -/* Original - blockmaplump = W_CacheLumpNum(lump, PU_LEVEL); - blockmap = blockmaplump+4; - count = W_LumpLength (lump)/2; - - for (i = 0; i < count; i++) - blockmaplump[i] = SHORT(blockmaplump[i]); - - bmaporgx = blockmaplump[0]<<FRACBITS; - bmaporgy = blockmaplump[1]<<FRACBITS; - bmapwidth = blockmaplump[2]; - bmapheight = blockmaplump[3]; - } - - // clear out mobj chains - count = sizeof (*blocklinks)*bmapwidth*bmapheight; - blocklinks = Z_Calloc(count, PU_LEVEL, NULL); - return true; - */ -#endif -} - // This needs to be a separate function // because making both the WAD and PK3 loading code use // the same functions is trickier than it looks for blockmap // -- Monster Iestyn 09/01/18 -static boolean P_LoadRawBlockMap(UINT8 *data, size_t count, const char *lumpname) +static boolean P_LoadRawBlockMap(UINT8 *data, size_t count) { #if 0 (void)data; @@ -1948,12 +1749,6 @@ static boolean P_LoadRawBlockMap(UINT8 *data, size_t count, const char *lumpname (void)lumpname; return false; #else - // Check if the lump is named "BLOCKMAP" - if (!lumpname || memcmp(lumpname, "BLOCKMAP", 8) != 0) - { - CONS_Printf("No blockmap lump found for pk3!\n"); - return false; - } if (!count || count >= 0x20000) return false; @@ -2079,56 +1874,139 @@ static void P_GroupLines(void) } } -// -// P_LoadReject -// -// Detect if the REJECT lump is valid, -// if not, rejectmatrix will be NULL -static void P_LoadReject(lumpnum_t lumpnum) +// PK3 version +// -- Monster Iestyn 09/01/18 +static void P_LoadRawReject(UINT8 *data, size_t count) { - size_t count; - const char *lumpname = W_CheckNameForNum(lumpnum); - - // Check if the lump exists, and if it's named "REJECT" - if (!lumpname || memcmp(lumpname, "REJECT\0\0", 8) != 0) + if (!count) // zero length, someone probably used ZDBSP { rejectmatrix = NULL; - CONS_Debug(DBG_SETUP, "P_LoadReject: No valid REJECT lump found\n"); - return; + CONS_Debug(DBG_SETUP, "P_LoadRawReject: REJECT lump has size 0, will not be loaded\n"); } - - count = W_LumpLength(lumpnum); - - if (!count) // zero length, someone probably used ZDBSP + else { - rejectmatrix = NULL; - CONS_Debug(DBG_SETUP, "P_LoadReject: REJECT lump has size 0, will not be loaded\n"); + rejectmatrix = Z_Malloc(count, PU_LEVEL, NULL); // allocate memory for the reject matrix + M_Memcpy(rejectmatrix, data, count); // copy the data into it } +} + +static void P_LoadMapBSP(const virtres_t* virt) +{ + virtlump_t* virtssectors = vres_Find(virt, "SSECTORS"); + virtlump_t* virtsegs = vres_Find(virt, "SEGS"); + virtlump_t* virtnodes = vres_Find(virt, "NODES"); + + numsubsectors = virtssectors->size / sizeof(mapsubsector_t); + numnodes = virtnodes->size / sizeof(mapnode_t); + numsegs = virtsegs->size / sizeof(mapseg_t); + + if (numsubsectors <= 0) + I_Error("Level has no subsectors (did you forget to run it through a nodesbuilder?)"); + if (numnodes <= 0) + I_Error("Level has no nodes"); + if (numsegs <= 0) + I_Error("Level has no segs"); + + subsectors = Z_Calloc(numsubsectors * sizeof(*subsectors), PU_LEVEL, NULL); + nodes = Z_Calloc(numnodes * sizeof(*nodes), PU_LEVEL, NULL); + segs = Z_Calloc(numsegs * sizeof(*segs), PU_LEVEL, NULL); + + // Nodes + P_LoadRawSubsectors(virtssectors->data); + P_LoadRawNodes(virtnodes->data); + P_LoadRawSegs(virtsegs->data); +} + +static void P_LoadMapLUT(const virtres_t* virt) +{ + virtlump_t* virtblockmap = vres_Find(virt, "BLOCKMAP"); + virtlump_t* virtreject = vres_Find(virt, "REJECT"); + + // Lookup tables + if (virtreject) + P_LoadRawReject(virtreject->data, virtreject->size); else - rejectmatrix = W_CacheLumpNum(lumpnum, PU_LEVEL); + rejectmatrix = NULL; + + if (!(virtblockmap && P_LoadRawBlockMap(virtblockmap->data, virtblockmap->size))) + P_CreateBlockMap(); } -// PK3 version -// -- Monster Iestyn 09/01/18 -static void P_LoadRawReject(UINT8 *data, size_t count, const char *lumpname) +static void P_LoadMapData(const virtres_t* virt) { - // Check if the lump is named "REJECT" - if (!lumpname || memcmp(lumpname, "REJECT\0\0", 8) != 0) + virtlump_t* virtvertexes = NULL, * virtsectors = NULL, * virtsidedefs = NULL, * virtlinedefs = NULL, * virtthings = NULL; +#ifdef UDMF + virtlump_t* textmap = vres_Find(virt, "TEXTMAP"); + + // Count map data. + if (textmap) { - rejectmatrix = NULL; - CONS_Debug(DBG_SETUP, "P_LoadRawReject: No valid REJECT lump found\n"); - return; + nummapthings = 0; + numlines = 0; + numsides = 0; + numvertexes = 0; + numsectors = 0; + + // Count how many entries for each type we got in textmap. + //TextmapCount(vtextmap->data, vtextmap->size); + } + else +#endif + { + virtthings = vres_Find(virt, "THINGS"); + virtvertexes = vres_Find(virt, "VERTEXES"); + virtsectors = vres_Find(virt, "SECTORS"); + virtsidedefs = vres_Find(virt, "SIDEDEFS"); + virtlinedefs = vres_Find(virt, "LINEDEFS"); + + if (!virtthings) + I_Error("THINGS lump not found"); + if (!virtvertexes) + I_Error("VERTEXES lump not found"); + if (!virtsectors) + I_Error("SECTORS lump not found"); + if (!virtsidedefs) + I_Error("SIDEDEFS lump not found"); + if (!virtlinedefs) + I_Error("LINEDEFS lump not found"); + + // Traditional doom map format just assumes the number of elements from the lump sizes. + numvertexes = virtvertexes->size / sizeof (mapvertex_t); + numsectors = virtsectors->size / sizeof (mapsector_t); + numsides = virtsidedefs->size / sizeof (mapsidedef_t); + numlines = virtlinedefs->size / sizeof (maplinedef_t); + nummapthings = virtthings->size / (5 * sizeof (INT16)); } - if (!count) // zero length, someone probably used ZDBSP + if (numvertexes <= 0) + I_Error("Level has no vertices"); + if (numsectors <= 0) + I_Error("Level has no sectors"); + if (numsides <= 0) + I_Error("Level has no sidedefs"); + if (numlines <= 0) + I_Error("Level has no linedefs"); + + vertexes = Z_Calloc(numvertexes * sizeof (*vertexes), PU_LEVEL, NULL); + sectors = Z_Calloc(numsectors * sizeof (*sectors), PU_LEVEL, NULL); + sides = Z_Calloc(numsides * sizeof (*sides), PU_LEVEL, NULL); + lines = Z_Calloc(numlines * sizeof (*lines), PU_LEVEL, NULL); + mapthings = Z_Calloc(nummapthings * sizeof (*mapthings), PU_LEVEL, NULL); + +#ifdef UDMF + if (textmap) { - rejectmatrix = NULL; - CONS_Debug(DBG_SETUP, "P_LoadRawReject: REJECT lump has size 0, will not be loaded\n"); + } else +#endif { - rejectmatrix = Z_Malloc(count, PU_LEVEL, NULL); // allocate memory for the reject matrix - M_Memcpy(rejectmatrix, data, count); // copy the data into it + // Strict map data + P_LoadRawVertexes(virtvertexes->data); + P_LoadRawSectors(virtsectors->data); + P_LoadRawLineDefs(virtlinedefs->data); + P_SetupLines(); + P_LoadRawSideDefs2(virtsidedefs->data); } } @@ -2307,6 +2185,8 @@ void P_LoadThingsOnly(void) // Search through all the thinkers. thinker_t *think; INT32 i, viewid = -1, centerid = -1; // for skyboxes + virtres_t* virt = vres_GetMap(lastloadedmaplumpnum); + virtlump_t* vth = vres_Find(virt, "THINGS"); // check if these are any of the normal viewpoint/centerpoint mobjs in the level or not if (skyboxmo[0] || skyboxmo[1]) @@ -2318,7 +2198,6 @@ void P_LoadThingsOnly(void) centerid = i; // save id just in case } - for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) @@ -2328,18 +2207,11 @@ void P_LoadThingsOnly(void) P_LevelInitStuff(); - if (W_IsLumpWad(lastloadedmaplumpnum)) // welp it's a map wad in a pk3 - { // HACK: Open wad file rather quickly so we can use the things lump - UINT8 *wadData = W_CacheLumpNum(lastloadedmaplumpnum, PU_STATIC); - filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs); - fileinfo += ML_THINGS; // we only need the THINGS lump - P_PrepareRawThings(wadData + fileinfo->filepos, fileinfo->size); - Z_Free(wadData); // we're done with this now - } - else // phew it's just a WAD - P_PrepareThings(lastloadedmaplumpnum + ML_THINGS); + P_PrepareRawThings(vth->data); P_LoadThings(true); + vres_Free(virt); + // restore skybox viewpoint/centerpoint if necessary, set them to defaults if we can't do that skyboxmo[0] = skyboxviewpnts[(viewid >= 0) ? viewid : 0]; skyboxmo[1] = skyboxcenterpnts[(centerid >= 0) ? centerid : 0]; @@ -2371,7 +2243,7 @@ static INT32 P_MakeBufferMD5(const char *buffer, size_t len, void *resblock) #endif } -static void P_MakeMapMD5(lumpnum_t maplumpnum, void *dest) +static void P_MakeMapMD5(virtres_t* virt, void *dest) { unsigned char linemd5[16]; unsigned char sectormd5[16]; @@ -2382,20 +2254,15 @@ static void P_MakeMapMD5(lumpnum_t maplumpnum, void *dest) // Create a hash for the current map // get the actual lumps! - UINT8 *datalines = W_CacheLumpNum(maplumpnum + ML_LINEDEFS, PU_CACHE); - UINT8 *datasectors = W_CacheLumpNum(maplumpnum + ML_SECTORS, PU_CACHE); - UINT8 *datathings = W_CacheLumpNum(maplumpnum + ML_THINGS, PU_CACHE); - UINT8 *datasides = W_CacheLumpNum(maplumpnum + ML_SIDEDEFS, PU_CACHE); + virtlump_t* virtlines = vres_Find(virt, "LINEDEFS"); + virtlump_t* virtsectors = vres_Find(virt, "SECTORS"); + virtlump_t* virtmthings = vres_Find(virt, "THINGS"); + virtlump_t* virtsides = vres_Find(virt, "SIDEDEFS"); - P_MakeBufferMD5((char*)datalines, W_LumpLength(maplumpnum + ML_LINEDEFS), linemd5); - P_MakeBufferMD5((char*)datasectors, W_LumpLength(maplumpnum + ML_SECTORS), sectormd5); - P_MakeBufferMD5((char*)datathings, W_LumpLength(maplumpnum + ML_THINGS), thingmd5); - P_MakeBufferMD5((char*)datasides, W_LumpLength(maplumpnum + ML_SIDEDEFS), sidedefmd5); - - Z_Free(datalines); - Z_Free(datasectors); - Z_Free(datathings); - Z_Free(datasides); + P_MakeBufferMD5((char*)virtlines->data, virtlines->size, linemd5); + P_MakeBufferMD5((char*)virtsectors->data, virtsectors->size, sectormd5); + P_MakeBufferMD5((char*)virtmthings->data, virtmthings->size, thingmd5); + P_MakeBufferMD5((char*)virtsides->data, virtsides->size, sidedefmd5); for (i = 0; i < 16; i++) resmd5[i] = (linemd5[i] + sectormd5[i] + thingmd5[i] + sidedefmd5[i]) & 0xFF; @@ -2631,7 +2498,6 @@ boolean P_SetupLevel(boolean skipprecip) INT32 i, loadprecip = 1, ranspecialwipe = 0; INT32 loademblems = 1; INT32 fromnetsave = 0; - boolean loadedbm = false; sector_t *ss; boolean chase; levelloading = true; @@ -2879,110 +2745,48 @@ boolean P_SetupLevel(boolean skipprecip) // SRB2 determines the sky texture to be used depending on the map header. P_SetupLevelSky(mapheaderinfo[gamemap-1]->skynum, true); - P_MakeMapMD5(lastloadedmaplumpnum, &mapmd5); - - // HACK ALERT: Cache the WAD, get the map data into the tables, free memory. - // As it is implemented right now, we're assuming an uncompressed WAD. - // (As in, a normal PWAD, not ZWAD or anything. The lump itself can be compressed.) - // We're not accounting for extra lumps and scrambled lump positions. Any additional data will cause an error. - if (W_IsLumpWad(lastloadedmaplumpnum)) - { - // Remember that we're assuming that the WAD will have a specific set of lumps in a specific order. - UINT8 *wadData = W_CacheLumpNum(lastloadedmaplumpnum, PU_STATIC); - //filelump_t *fileinfo = wadData + ((wadinfo_t *)wadData)->infotableofs; - filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs); - UINT32 numlumps = ((wadinfo_t *)wadData)->numlumps; - - if (numlumps < ML_REJECT) // at least 9 lumps should be in the wad for a map to be loaded - { - I_Error("Bad WAD file for map %s!\n", maplumpname); - } + numdmstarts = numredctfstarts = numbluectfstarts = 0; - if (numlumps > ML_BLOCKMAP) // enough room for a BLOCKMAP lump at least - { - loadedbm = P_LoadRawBlockMap( - wadData + (fileinfo + ML_BLOCKMAP)->filepos, - (fileinfo + ML_BLOCKMAP)->size, - (fileinfo + ML_BLOCKMAP)->name); - } - P_LoadRawVertexes(wadData + (fileinfo + ML_VERTEXES)->filepos, (fileinfo + ML_VERTEXES)->size); - P_LoadRawSectors(wadData + (fileinfo + ML_SECTORS)->filepos, (fileinfo + ML_SECTORS)->size); - P_LoadRawSideDefs((fileinfo + ML_SIDEDEFS)->size); - P_LoadRawLineDefs(wadData + (fileinfo + ML_LINEDEFS)->filepos, (fileinfo + ML_LINEDEFS)->size); - P_LoadRawSideDefs2(wadData + (fileinfo + ML_SIDEDEFS)->filepos); - P_LoadRawSubsectors(wadData + (fileinfo + ML_SSECTORS)->filepos, (fileinfo + ML_SSECTORS)->size); - P_LoadRawNodes(wadData + (fileinfo + ML_NODES)->filepos, (fileinfo + ML_NODES)->size); - P_LoadRawSegs(wadData + (fileinfo + ML_SEGS)->filepos, (fileinfo + ML_SEGS)->size); - if (numlumps > ML_REJECT) // enough room for a REJECT lump at least - { - P_LoadRawReject( - wadData + (fileinfo + ML_REJECT)->filepos, - (fileinfo + ML_REJECT)->size, - (fileinfo + ML_REJECT)->name); - } + // reset the player starts + for (i = 0; i < MAXPLAYERS; i++) + playerstarts[i] = bluectfstarts[i] = redctfstarts[i] = NULL; - // Important: take care of the ordering of the next functions. - if (!loadedbm) - P_CreateBlockMap(); // Graue 02-29-2004 - P_LoadLineDefs2(); - P_GroupLines(); - numdmstarts = numredctfstarts = numbluectfstarts = 0; + for (i = 0; i < MAX_DM_STARTS; i++) + deathmatchstarts[i] = NULL; - // reset the player starts - for (i = 0; i < MAXPLAYERS; i++) - playerstarts[i] = bluectfstarts[i] = redctfstarts[i] = NULL; + for (i = 0; i < 2; i++) + skyboxmo[i] = NULL; - for (i = 0; i < MAX_DM_STARTS; i++) - deathmatchstarts[i] = NULL; + for (i = 0; i < 16; i++) + skyboxviewpnts[i] = skyboxcenterpnts[i] = NULL; - for (i = 0; i < 2; i++) - skyboxmo[i] = NULL; + P_MapStart(); - for (i = 0; i < 16; i++) - skyboxviewpnts[i] = skyboxcenterpnts[i] = NULL; + if (lastloadedmaplumpnum) + { + virtres_t* virt = vres_GetMap(lastloadedmaplumpnum); - P_MapStart(); + P_LoadMapData(virt); + P_LoadMapBSP(virt); + P_LoadMapLUT(virt); - P_PrepareRawThings(wadData + (fileinfo + ML_THINGS)->filepos, (fileinfo + ML_THINGS)->size); - Z_Free(wadData); - } - else - { - // Important: take care of the ordering of the next functions. - loadedbm = P_LoadBlockMap(lastloadedmaplumpnum + ML_BLOCKMAP); - P_LoadVertexes(lastloadedmaplumpnum + ML_VERTEXES); - P_LoadSectors(lastloadedmaplumpnum + ML_SECTORS); - P_LoadSideDefs(lastloadedmaplumpnum + ML_SIDEDEFS); - P_LoadLineDefs(lastloadedmaplumpnum + ML_LINEDEFS); - P_LoadSideDefs2(lastloadedmaplumpnum + ML_SIDEDEFS); - P_LoadSubsectors(lastloadedmaplumpnum + ML_SSECTORS); - P_LoadNodes(lastloadedmaplumpnum + ML_NODES); - P_LoadSegs(lastloadedmaplumpnum + ML_SEGS); - P_LoadReject(lastloadedmaplumpnum + ML_REJECT); - - // Important: take care of the ordering of the next functions. - if (!loadedbm) - P_CreateBlockMap(); // Graue 02-29-2004 P_LoadLineDefs2(); P_GroupLines(); - numdmstarts = numredctfstarts = numbluectfstarts = 0; - // reset the player starts - for (i = 0; i < MAXPLAYERS; i++) - playerstarts[i] = bluectfstarts[i] = redctfstarts[i] = NULL; - - for (i = 0; i < MAX_DM_STARTS; i++) - deathmatchstarts[i] = NULL; + // Copy relevant map data for NetArchive purposes. + spawnsectors = Z_Calloc(numsectors * sizeof (*sectors), PU_LEVEL, NULL); + spawnlines = Z_Calloc(numlines * sizeof (*lines), PU_LEVEL, NULL); + spawnsides = Z_Calloc(numsides * sizeof (*sides), PU_LEVEL, NULL); - for (i = 0; i < 2; i++) - skyboxmo[i] = NULL; + memcpy(spawnsectors, sectors, numsectors * sizeof (*sectors)); + memcpy(spawnlines, lines, numlines * sizeof (*lines)); + memcpy(spawnsides, sides, numsides * sizeof (*sides)); - for (i = 0; i < 16; i++) - skyboxviewpnts[i] = skyboxcenterpnts[i] = NULL; + P_PrepareRawThings(vres_Find(virt, "THINGS")->data); - P_MapStart(); + P_MakeMapMD5(virt, &mapmd5); - P_PrepareThings(lastloadedmaplumpnum + ML_THINGS); + vres_Free(virt); } // init gravity, tag lists, diff --git a/src/p_spec.c b/src/p_spec.c index 202c658fc63016154f9b74b9c51977d9f3529817..0b0ba940d699a7725969787bcd6796a92943f5be 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1603,8 +1603,6 @@ static inline void P_InitTagLists(void) size_t j = (unsigned)sectors[i].tag % numsectors; sectors[i].nexttag = sectors[j].firsttag; sectors[j].firsttag = (INT32)i; - sectors[i].spawn_nexttag = sectors[i].nexttag; - sectors[j].spawn_firsttag = sectors[j].firsttag; } for (i = numlines - 1; i != (size_t)-1; i--) @@ -6405,22 +6403,16 @@ static void P_ApplyFlatAlignment(line_t *master, sector_t *sector, angle_t flata { if (!(master->flags & ML_NETONLY)) // Modify floor flat alignment unless ML_NETONLY flag is set { - sector->spawn_flrpic_angle = sector->floorpic_angle = flatangle; + sector->floorpic_angle = flatangle; sector->floor_xoffs += xoffs; sector->floor_yoffs += yoffs; - // saved for netgames - sector->spawn_flr_xoffs = sector->floor_xoffs; - sector->spawn_flr_yoffs = sector->floor_yoffs; } if (!(master->flags & ML_NONET)) // Modify ceiling flat alignment unless ML_NONET flag is set { - sector->spawn_ceilpic_angle = sector->ceilingpic_angle = flatangle; + sector->ceilingpic_angle = flatangle; sector->ceiling_xoffs += xoffs; sector->ceiling_yoffs += yoffs; - // saved for netgames - sector->spawn_ceil_xoffs = sector->ceiling_xoffs; - sector->spawn_ceil_yoffs = sector->ceiling_yoffs; } } @@ -6441,7 +6433,7 @@ void P_SpawnSpecials(INT32 fromnetsave) INT32 j; thinkerlist_t *secthinkers; thinker_t *th; - + virtres_t* virt = NULL; // This used to be used, and *should* be used in the future, // but currently isn't. (void)fromnetsave; @@ -7193,17 +7185,10 @@ void P_SpawnSpecials(INT32 fromnetsave) UINT8 *data; UINT16 b; - if (W_IsLumpWad(lastloadedmaplumpnum)) // welp it's a map wad in a pk3 - { // HACK: Open wad file rather quickly so we can get the data from the sidedefs lump - UINT8 *wadData = W_CacheLumpNum(lastloadedmaplumpnum, PU_STATIC); - filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs); - fileinfo += ML_SIDEDEFS; // we only need the SIDEDEFS lump - data = Z_Malloc(fileinfo->size, PU_STATIC, NULL); - M_Memcpy(data, wadData + fileinfo->filepos, fileinfo->size); // copy data - Z_Free(wadData); // we're done with this now - } - else // phew it's just a WAD - data = W_CacheLumpNum(lastloadedmaplumpnum + ML_SIDEDEFS,PU_STATIC); + if (!virt) + virt = vres_GetMap(lastloadedmaplumpnum); + + data = (UINT8*) vres_Find(virt, "SIDEDEFS")->data; for (b = 0; b < (INT16)numsides; b++) { @@ -7223,7 +7208,6 @@ void P_SpawnSpecials(INT32 fromnetsave) I_Error("Make-Your-Own-FOF (tag %d) needs a value in the linedef's second side upper texture field.", lines[i].tag); } } - Z_Free(data); } else I_Error("Make-Your-Own FOF (tag %d) found without a 2nd linedef side!", lines[i].tag); @@ -7449,6 +7433,9 @@ void P_SpawnSpecials(INT32 fromnetsave) } } + if (virt) + vres_Free(virt); + // Allocate each list for (i = 0; i < numsectors; i++) if(secthinkers[i].thinkers) diff --git a/src/p_user.c b/src/p_user.c index 4dbea87e3facdb4ec046d72017ffd61c6874ae68..5b0140032a66ea9b610e1ea9eb0ff6b6bb106873 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1600,7 +1600,7 @@ void P_RestoreMusic(player_t *player) P_PlayJingle(player, JT_SUPER); // Invulnerability - else if (player->powers[pw_invulnerability] > 1) + else if (player->powers[pw_invulnerability] > 1 && !player->powers[pw_super]) { strlcpy(S_sfx[sfx_None].caption, "Invincibility", 14); S_StartCaption(sfx_None, -1, player->powers[pw_invulnerability]); @@ -5128,11 +5128,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) boolean elem = ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL); player->pflags |= PF_THOKKED|PF_SHIELDABILITY; if (elem) - { - player->pflags |= PF_NOJUMPDAMAGE; - P_SetPlayerMobjState(player->mo, S_PLAY_FALL); S_StartSound(player->mo, sfx_s3k43); - } else { player->pflags &= ~PF_NOJUMPDAMAGE; diff --git a/src/r_defs.h b/src/r_defs.h index 3cc780545446509c55d0eaffcabaf5e77521b7bf..353dc572b6e6422337869b1871aa7ca674f05273 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -384,17 +384,6 @@ typedef struct sector_s // for fade thinker INT16 spawn_lightlevel; - // these are saved for netgames, so do not let Lua touch these! - INT32 spawn_nexttag, spawn_firsttag; // the actual nexttag/firsttag values may differ if the sector's tag was changed - - // offsets sector spawned with (via linedef type 7) - fixed_t spawn_flr_xoffs, spawn_flr_yoffs; - fixed_t spawn_ceil_xoffs, spawn_ceil_yoffs; - - // flag angles sector spawned with (via linedef type 7) - angle_t spawn_flrpic_angle; - angle_t spawn_ceilpic_angle; - // colormap structure extracolormap_t *spawn_extra_colormap; } sector_t; diff --git a/src/r_state.h b/src/r_state.h index 75566923b140adfdffb47a3f64282e3f4ea3a3b5..4e1eb388e7d0a05d46a9c5ee80970c7b2545d2c9 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -63,6 +63,7 @@ extern seg_t *segs; extern size_t numsectors; extern sector_t *sectors; +extern sector_t *spawnsectors; extern size_t numsubsectors; extern subsector_t *subsectors; @@ -72,9 +73,11 @@ extern node_t *nodes; extern size_t numlines; extern line_t *lines; +extern line_t *spawnlines; extern size_t numsides; extern side_t *sides; +extern side_t *spawnsides; // // POV data. diff --git a/src/w_wad.c b/src/w_wad.c index 950294b1f4ce263224fca3868add4889697f8110..a86e99237bf7f0bbeef2aea99033b85605f469fc 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1888,3 +1888,101 @@ int W_VerifyNMUSlumps(const char *filename) }; return W_VerifyFile(filename, NMUSlist, false); } + +/** \brief Generates a virtual resource used for level data loading. + * + * \param lumpnum_t reference + * \return Virtual resource + * + */ +virtres_t* vres_GetMap(lumpnum_t lumpnum) +{ + UINT32 i; + virtres_t* vres = NULL; + virtlump_t* vlumps = NULL; + size_t numlumps = 0; + + if (W_IsLumpWad(lumpnum)) + { + // Remember that we're assuming that the WAD will have a specific set of lumps in a specific order. + UINT8 *wadData = W_CacheLumpNum(lumpnum, PU_LEVEL); + filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs); + numlumps = ((wadinfo_t *)wadData)->numlumps; + vlumps = Z_Malloc(sizeof(virtlump_t)*numlumps, PU_LEVEL, NULL); + + // Build the lumps. + for (i = 0; i < numlumps; i++) + { + vlumps[i].size = (size_t)(((filelump_t *)(fileinfo + i))->size); + // Play it safe with the name in this case. + memcpy(vlumps[i].name, (fileinfo + i)->name, 8); + vlumps[i].name[8] = '\0'; + vlumps[i].data = Z_Malloc(vlumps[i].size, PU_LEVEL, NULL); // This is memory inefficient, sorry about that. + memcpy(vlumps[i].data, wadData + (fileinfo + i)->filepos, vlumps[i].size); + } + + Z_Free(wadData); + } + else + { + // Count number of lumps until the end of resource OR up until next "MAPXX" lump. + lumpnum_t lumppos = lumpnum + 1; + for (i = LUMPNUM(lumppos); i < wadfiles[WADFILENUM(lumpnum)]->numlumps; i++, lumppos++, numlumps++) + if (memcmp(W_CheckNameForNum(lumppos), "MAP", 3) == 0) + break; + numlumps++; + + vlumps = Z_Malloc(sizeof(virtlump_t)*numlumps, PU_LEVEL, NULL); + for (i = 0; i < numlumps; i++, lumpnum++) + { + vlumps[i].size = W_LumpLength(lumpnum); + memcpy(vlumps[i].name, W_CheckNameForNum(lumpnum), 8); + vlumps[i].name[8] = '\0'; + vlumps[i].data = W_CacheLumpNum(lumpnum, PU_LEVEL); + } + } + vres = Z_Malloc(sizeof(virtres_t), PU_LEVEL, NULL); + vres->vlumps = vlumps; + vres->numlumps = numlumps; + + return vres; +} + +/** \brief Frees zone memory for a given virtual resource. + * + * \param Virtual resource + */ +void vres_Free(virtres_t* vres) +{ + while (vres->numlumps--) + Z_Free(vres->vlumps[vres->numlumps].data); + Z_Free(vres->vlumps); + Z_Free(vres); +} + +/** (Debug) Prints lumps from a virtual resource into console. + */ +/* +static void vres_Diag(const virtres_t* vres) +{ + UINT32 i; + for (i = 0; i < vres->numlumps; i++) + CONS_Printf("%s\n", vres->vlumps[i].name); +} +*/ + +/** \brief Finds a lump in a given virtual resource. + * + * \param Virtual resource + * \param Lump name to look for + * \return Virtual lump if found, NULL otherwise + * + */ +virtlump_t* vres_Find(const virtres_t* vres, const char* name) +{ + UINT32 i; + for (i = 0; i < vres->numlumps; i++) + if (fastcmp(name, vres->vlumps[i].name)) + return &vres->vlumps[i]; + return NULL; +} diff --git a/src/w_wad.h b/src/w_wad.h index a8be13ece29c17511a7dc5579faccdfa0789d9ad..8008a577cf9f5f92631bdd91d7a440ca2688dd68 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -72,6 +72,25 @@ typedef struct compmethod compression; // lump compression method } lumpinfo_t; +// ========================================================================= +// 'VIRTUAL' RESOURCES +// ========================================================================= + +typedef struct { + char name[9]; + UINT8* data; + size_t size; +} virtlump_t; + +typedef struct { + size_t numlumps; + virtlump_t* vlumps; +} virtres_t; + +virtres_t* vres_GetMap(lumpnum_t); +void vres_Free(virtres_t*); +virtlump_t* vres_Find(const virtres_t*, const char*); + // ========================================================================= // DYNAMIC WAD LOADING // =========================================================================