Merge remote-tracking branch 'refs/remotes/origin/master' into democracy

This commit is contained in:
TehRealSalt 2018-02-07 22:34:33 -05:00
commit e6c040b844
19 changed files with 508 additions and 80 deletions

View File

@ -118,6 +118,9 @@ static UINT8 resynch_local_inprogress = false; // WE are desynched and getting p
static UINT8 player_joining = false;
UINT8 hu_resynching = 0;
// kart, true when a player is connecting or disconnecting so that the gameplay has stopped in its tracks
UINT8 hu_stopped = 0;
// Client specific
static ticcmd_t localcmds;
static ticcmd_t localcmds2;
@ -4737,8 +4740,16 @@ void TryRunTics(tic_t realtics)
}
#endif
if (neededtic > gametic)
{
hu_stopped = false;
}
if (player_joining)
{
hu_stopped = true;
return;
}
if (neededtic > gametic)
{
@ -4756,6 +4767,10 @@ void TryRunTics(tic_t realtics)
consistancy[gametic%BACKUPTICS] = Consistancy();
}
}
else
{
hu_stopped = true;
}
}
#ifdef NEWPING

View File

@ -553,4 +553,5 @@ tic_t GetLag(INT32 node);
UINT8 GetFreeXCmdSize(void);
extern UINT8 hu_resynching;
extern UINT8 hu_stopped; // kart, true when the game is stopped for players due to a disconnecting or connecting player
#endif

View File

@ -702,6 +702,7 @@ void D_SRB2Loop(void)
else if (rendertimeout < entertic) // in case the server hang or netsplit
{
// Lagless camera! Yay!
/*
if (gamestate == GS_LEVEL && netgame)
{
if (camera.chase)
@ -713,6 +714,7 @@ void D_SRB2Loop(void)
if (splitscreen > 2 && camera4.chase)
P_MoveChaseCamera(&players[fourthdisplayplayer], &camera4, false);
}
*/
D_Display();
if (moviemode)

View File

@ -6360,6 +6360,31 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_BOMBITEM",
"S_BOMBAIR",
"S_BOMBEXPLODE",
"S_BOMBEXPLOSION1",
"S_BOMBEXPLOSION2",
// New explosion
"S_QUICKBOOM1",
"S_QUICKBOOM2",
"S_QUICKBOOM3",
"S_QUICKBOOM4",
"S_QUICKBOOM5",
"S_QUICKBOOM6",
"S_QUICKBOOM7",
"S_QUICKBOOM8",
"S_QUICKBOOM9",
"S_QUICKBOOM10",
"S_SLOWBOOM1",
"S_SLOWBOOM2",
"S_SLOWBOOM3",
"S_SLOWBOOM4",
"S_SLOWBOOM5",
"S_SLOWBOOM6",
"S_SLOWBOOM7",
"S_SLOWBOOM8",
"S_SLOWBOOM9",
"S_SLOWBOOM10",
// Blue Shell - Blue Lightning for now...
"S_BLUELIGHTNING1",
@ -6991,6 +7016,9 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_BOMBEXPLOSION",
"MT_BOMBEXPLOSIONSOUND",
"MT_SMOLDERING", // New explosion
"MT_BOOMPARTICLE",
"MT_BLUELIGHTNING", // Lightning stuff
"MT_BLUEEXPLOSION",
"MT_LIGHTNING",

View File

@ -1252,7 +1252,8 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
// why build a ticcmd if we're paused?
// Or, for that matter, if we're being reborn.
if (paused || P_AutoPause() || (gamestate == GS_LEVEL && player->playerstate == PST_REBORN))
// Kart, don't build a ticcmd if someone is resynching or the server is stopped too so we don't fly off course in bad conditions
if (paused || P_AutoPause() || (gamestate == GS_LEVEL && player->playerstate == PST_REBORN) || hu_resynching)
{
cmd->angleturn = (INT16)(lang >> 16);
cmd->aiming = G_ClipAimingPitch(&laim);
@ -1578,8 +1579,10 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
cmd->angleturn = (INT16)(lang >> 16);
}
switch (ssplayer)
if (!hu_stopped)
{
switch (ssplayer)
{
case 2:
localangle2 = lang;
localaiming2 = laim;
@ -1609,6 +1612,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
turnheld = th;
camspin = InputDown(gc_lookback, ssplayer);
break;
}
}
//Reset away view if a command is given.

View File

@ -5276,7 +5276,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
// New colormap stuff for skins Tails 06-07-2002
if (thing->skin && thing->sprite == SPR_PLAY) // This thing is a player!
{
if (thing->player && thing->player->kartstuff[k_startimer])
if (thing->colorized)
vis->colormap = R_GetTranslationColormap(TC_STARMAN, thing->color, GTC_CACHE);
else
{
@ -5285,7 +5285,12 @@ static void HWR_ProjectSprite(mobj_t *thing)
}
}
else
vis->colormap = R_GetTranslationColormap(TC_DEFAULT, vis->mobj->color ? vis->mobj->color : SKINCOLOR_CYAN, GTC_CACHE);
{
if (vis->mobj && vis->mobj->colorized)
vis->colormap = R_GetTranslationColormap(TC_STARMAN, vis->mobj->color ? vis->mobj->color : SKINCOLOR_CYAN, GTC_CACHE);
else
vis->colormap = R_GetTranslationColormap(TC_DEFAULT, vis->mobj->color ? vis->mobj->color : SKINCOLOR_CYAN, GTC_CACHE);
}
}
else
vis->colormap = colormaps;

View File

@ -39,6 +39,8 @@
#include "../w_wad.h"
#include "../z_zone.h"
#include "../r_things.h"
#include "../r_draw.h"
#include "../p_tick.h"
#include "hw_main.h"
#include "../v_video.h"
@ -934,7 +936,7 @@ spritemd2found:
fclose(f);
}
static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, GLMipmap_t *grmip, skincolors_t color)
static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, GLMipmap_t *grmip, INT32 skinnum, skincolors_t color)
{
UINT16 w = gpatch->width, h = gpatch->height;
UINT32 size = w*h;
@ -1205,45 +1207,83 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch,
break;
}
while (size--)
// starman support, could theoretically support boss ones too
if (skinnum == TC_STARMAN)
{
if (blendimage->s.alpha == 0)
while (size--)
{
// Don't bother with blending the pixel if the alpha of the blend pixel is 0
cur->rgba = image->rgba;
if (image->s.alpha == 0 && blendimage->s.alpha == 0)
{
// Don't bother with blending the pixel if the alpha of the blend pixel is 0
cur->rgba = image->rgba;
}
else
{
UINT32 tempcolor;
UINT16 imagebright, blendbright, finalbright, colorbright;
imagebright = (image->s.red+image->s.green+image->s.blue)/3;
blendbright = (blendimage->s.red+blendimage->s.green+blendimage->s.blue)/3;
// slightly dumb average between the blend image color and base image colour, usually one or the other will be fully opaque anyway
finalbright = (imagebright*(255-blendimage->s.alpha))/255 + (blendbright*blendimage->s.alpha)/255;
colorbright = (blendcolor.s.red+blendcolor.s.green+blendcolor.s.blue)/3;
tempcolor = (finalbright*blendcolor.s.red)/colorbright;
tempcolor = min(255, max(0, tempcolor));
cur->s.red = (UINT8)tempcolor;
tempcolor = (finalbright*blendcolor.s.green)/colorbright;
tempcolor = min(255, max(0, tempcolor));
cur->s.green = (UINT8)tempcolor;
tempcolor = (finalbright*blendcolor.s.blue)/colorbright;
tempcolor = min(255, max(0, tempcolor));
cur->s.blue = (UINT8)tempcolor;
cur->s.alpha = image->s.alpha;
}
cur++; image++; blendimage++;
}
else
}
else
{
while (size--)
{
INT32 tempcolor;
INT16 tempmult, tempalpha;
tempalpha = -(abs(blendimage->s.red-127)-127)*2;
if (tempalpha > 255)
tempalpha = 255;
else if (tempalpha < 0)
tempalpha = 0;
if (blendimage->s.alpha == 0)
{
// Don't bother with blending the pixel if the alpha of the blend pixel is 0
cur->rgba = image->rgba;
}
else
{
INT32 tempcolor;
INT16 tempmult, tempalpha;
tempalpha = -(abs(blendimage->s.red-127)-127)*2;
if (tempalpha > 255)
tempalpha = 255;
else if (tempalpha < 0)
tempalpha = 0;
tempmult = (blendimage->s.red-127)*2;
if (tempmult > 255)
tempmult = 255;
else if (tempmult < 0)
tempmult = 0;
tempmult = (blendimage->s.red-127)*2;
if (tempmult > 255)
tempmult = 255;
else if (tempmult < 0)
tempmult = 0;
tempcolor = (image->s.red*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.red)/255)) * blendimage->s.alpha)/255;
cur->s.red = (UINT8)tempcolor;
tempcolor = (image->s.green*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.green)/255)) * blendimage->s.alpha)/255;
cur->s.green = (UINT8)tempcolor;
tempcolor = (image->s.blue*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.blue)/255)) * blendimage->s.alpha)/255;
cur->s.blue = (UINT8)tempcolor;
cur->s.alpha = image->s.alpha;
tempcolor = (image->s.red*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.red)/255)) * blendimage->s.alpha)/255;
cur->s.red = (UINT8)tempcolor;
tempcolor = (image->s.green*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.green)/255)) * blendimage->s.alpha)/255;
cur->s.green = (UINT8)tempcolor;
tempcolor = (image->s.blue*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.blue)/255)) * blendimage->s.alpha)/255;
cur->s.blue = (UINT8)tempcolor;
cur->s.alpha = image->s.alpha;
}
cur++; image++; blendimage++;
}
cur++; image++; blendimage++;
}
return;
}
static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, const UINT8 *colormap, skincolors_t color)
static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT32 skinnum, const UINT8 *colormap, skincolors_t color)
{
// mostly copied from HWR_GetMappedPatch, hence the similarities and comment
GLMipmap_t *grmip, *newmip;
@ -1284,7 +1324,7 @@ static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, con
grmip->nextcolormap = newmip;
newmip->colormap = colormap;
HWR_CreateBlendedTexture(gpatch, blendgpatch, newmip, color);
HWR_CreateBlendedTexture(gpatch, blendgpatch, newmip, skinnum, color);
HWD.pfnSetTexture(newmip);
Z_ChangeTag(newmip->grInfo.data, PU_HWRCACHE_UNLOCKED);
@ -1435,7 +1475,30 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
md2->blendgrpatch && ((GLPatch_t *)md2->blendgrpatch)->mipmap.grInfo.format
&& gpatch->width == ((GLPatch_t *)md2->blendgrpatch)->width && gpatch->height == ((GLPatch_t *)md2->blendgrpatch)->height)
{
HWR_GetBlendedTexture(gpatch, (GLPatch_t *)md2->blendgrpatch, spr->colormap, (skincolors_t)spr->mobj->color);
INT32 skinnum;
if ((spr->mobj->flags & MF_BOSS) && (spr->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash"
{
if (spr->mobj->type == MT_CYBRAKDEMON)
skinnum = TC_ALLWHITE;
else if (spr->mobj->type == MT_METALSONIC_BATTLE)
skinnum = TC_METALSONIC;
else
skinnum = TC_BOSS;
}
else if (spr->mobj->color)
{
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
{
if (spr->mobj->colorized)
skinnum = TC_STARMAN;
else
{
skinnum = (INT32)((skin_t*)spr->mobj->skin-skins);
}
}
else skinnum = TC_DEFAULT;
}
HWR_GetBlendedTexture(gpatch, (GLPatch_t *)md2->blendgrpatch, skinnum, spr->colormap, (skincolors_t)spr->mobj->color);
}
else
{

View File

@ -56,9 +56,10 @@ char sprnames[NUMSPRITES + 1][5] =
"SRBJ","SRBK","SRBL","SRBM","SRBN","SRBO",
//SRB2kart Sprites
"SPRG","BSPR","RNDM","RPOP","KFRE","DRIF","DSMO","FITM","DFAK","BANA",
"DBAN","GSHE","DGSH","RSHE","DRSH","BOMB","BLIG","LIGH","SINK","SITR",
"KBLN","LAKI","POKE","AUDI","DECO","DOOD","SNES","GBAS","SPRS","BUZB",
"CHOM","SACO","CRAB","SHAD","BUMP","FLEN","CLAS","PSHW","ARRO","PBOM"
"DBAN","GSHE","DGSH","RSHE","DRSH","BOMB","KRBM","BLIG","LIGH","SINK",
"SITR","KBLN","LAKI","POKE","AUDI","DECO","DOOD","SNES","GBAS","SPRS",
"BUZB","CHOM","SACO","CRAB","SHAD","BUMP","FLEN","CLAS","PSHW","ARRO",
"PBOM"
};
// Doesn't work with g++, needs actionf_p1 (don't modify this comment)
@ -2687,6 +2688,30 @@ state_t states[NUMSTATES] =
{SPR_BOMB, 0, 1, {A_GrenadeRing}, 0, 0, S_BOMBITEM}, // S_BOMBITEM
{SPR_BOMB, 0, 1, {NULL}, 0, 0, S_BOMBAIR}, // S_BOMBAIR
{SPR_BOMB, 0, 1, {A_BobombExplode}, MT_BOMBEXPLOSION, 0, S_NULL}, // S_BOMBEXPLODE
{SPR_NULL, 0, 6, {NULL}, 0, 0, S_BOMBEXPLOSION2}, // S_BOMBEXPLOSION1
{SPR_NULL, 1, 22, {A_ForceStop}, 0, 0, S_NULL}, // S_BOMBEXPLOSION2
{SPR_KRBM, 0, 1, {NULL}, 0, 0, S_QUICKBOOM2}, // S_QUICKBOOM1
{SPR_KRBM, 1, 1, {NULL}, 0, 0, S_QUICKBOOM3}, // S_QUICKBOOM2
{SPR_KRBM, 2, 1, {NULL}, 0, 0, S_QUICKBOOM4}, // S_QUICKBOOM3
{SPR_KRBM, 3, 1, {NULL}, 0, 0, S_QUICKBOOM5}, // S_QUICKBOOM4
{SPR_KRBM, 4, 1, {NULL}, 0, 0, S_QUICKBOOM6}, // S_QUICKBOOM5
{SPR_KRBM, 5, 1, {NULL}, 0, 0, S_QUICKBOOM7}, // S_QUICKBOOM6
{SPR_KRBM, 6, 1, {NULL}, 0, 0, S_QUICKBOOM8}, // S_QUICKBOOM7
{SPR_KRBM, 7, 2, {NULL}, 0, 0, S_QUICKBOOM9}, // S_QUICKBOOM8
{SPR_KRBM, 8, 2, {NULL}, 0, 0, S_QUICKBOOM10}, // S_QUICKBOOM9
{SPR_KRBM, 9, 2, {NULL}, 0, 0, S_NULL}, // S_QUICKBOOM10
{SPR_KRBM, 0, 3, {NULL}, 0, 0, S_SLOWBOOM2}, // S_SLOWBOOM1
{SPR_KRBM, 1, 3, {NULL}, 0, 0, S_SLOWBOOM3}, // S_SLOWBOOM2
{SPR_KRBM, 2, 3, {NULL}, 0, 0, S_SLOWBOOM4}, // S_SLOWKBOOM3
{SPR_KRBM, 3, 3, {NULL}, 0, 0, S_SLOWBOOM5}, // S_SLOWBOOM4
{SPR_KRBM, 4, 3, {NULL}, 0, 0, S_SLOWBOOM6}, // S_SLOWBOOM5
{SPR_KRBM, 5, 3, {NULL}, 0, 0, S_SLOWBOOM7}, // S_SLOWBOOM6
{SPR_KRBM, 6, 3, {NULL}, 0, 0, S_SLOWBOOM8}, // S_SLOWBOOM7
{SPR_KRBM, 7, 5, {NULL}, 0, 0, S_SLOWBOOM9}, // S_SLOWBOOM8
{SPR_KRBM, 8, 5, {NULL}, 0, 0, S_SLOWBOOM10}, // S_SLOWBOOM9
{SPR_KRBM, 9, 5, {NULL}, 0, 0, S_NULL}, // S_SLOWBOOM10
{SPR_BLIG, 0, 2, {NULL}, 0, 0, S_BLUELIGHTNING2}, // S_BLUELIGHTNING1
{SPR_BLIG, 1, 2, {NULL}, 0, 0, S_BLUELIGHTNING3}, // S_BLUELIGHTNING2
@ -14932,7 +14957,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
256*FRACUNIT, // painchance
288*FRACUNIT, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
@ -14946,13 +14971,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
1, // damage
sfx_bomb, // activesound
MF_BOUNCE|MF_FLOAT|MF_NOCLIPTHING|MF_MISSILE|MF_SHOOTABLE, // flags
MF_BOUNCE|MF_NOCLIPTHING|MF_MISSILE|MF_SHOOTABLE, // flags
S_NULL // raisestate
},
{ // MT_BOMBEXPLOSION
-1, // doomednum
S_BPLD1, // spawnstate
S_BOMBEXPLOSION1, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
@ -15004,6 +15029,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_SMOLDERING
-1, // doomednum
S_INVISIBLE, // spawnstate
1, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
0, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
35*FRACUNIT, // radius
70*FRACUNIT, // height
0, // display offset
0, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_SCENERY, // flags
S_NULL // raisestate
},
{ // MT_BOOMPARTICLE
-1, // doomednum
S_INVISIBLE, // spawnstate
1, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
0, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
0, // display offset
0, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_BOUNCE|MF_SCENERY, // flags
S_NULL // raisestate
},
{ // MT_BLUELIGHTNING
-1, // doomednum
S_BLUELIGHTNING1, // spawnstate

View File

@ -594,6 +594,7 @@ typedef enum sprite
SPR_RSHE, // Red Shell
SPR_DRSH, // Dead Red Shell
SPR_BOMB, // Bob-omb
SPR_KRBM,
SPR_BLIG, // Blue Lightning
SPR_LIGH, // Lightning
SPR_SINK, // Kitchen Sink
@ -3197,6 +3198,31 @@ typedef enum state
S_BOMBITEM,
S_BOMBAIR,
S_BOMBEXPLODE,
S_BOMBEXPLOSION1,
S_BOMBEXPLOSION2,
// New explosion
S_QUICKBOOM1,
S_QUICKBOOM2,
S_QUICKBOOM3,
S_QUICKBOOM4,
S_QUICKBOOM5,
S_QUICKBOOM6,
S_QUICKBOOM7,
S_QUICKBOOM8,
S_QUICKBOOM9,
S_QUICKBOOM10,
S_SLOWBOOM1,
S_SLOWBOOM2,
S_SLOWBOOM3,
S_SLOWBOOM4,
S_SLOWBOOM5,
S_SLOWBOOM6,
S_SLOWBOOM7,
S_SLOWBOOM8,
S_SLOWBOOM9,
S_SLOWBOOM10,
// Blue Shell - Blue Lightning for now...
S_BLUELIGHTNING1,
@ -3972,6 +3998,9 @@ typedef enum mobj_type
MT_BOMBEXPLOSION,
MT_BOMBEXPLOSIONSOUND,
MT_SMOLDERING, // New explosion
MT_BOOMPARTICLE,
MT_BLUELIGHTNING, // Lightning stuff
MT_BLUEEXPLOSION,
MT_LIGHTNING,

View File

@ -197,6 +197,11 @@ void K_StarmanColormap(UINT8 *dest_colormap, UINT8 skincolor)
// next, for every colour in the palette, choose the transcolor that has the closest brightness
for (i = 0; i < NUM_PALETTE_ENTRIES; i++)
{
if (i == 0 || i == 31 || i == 120) // pure black and pure white don't change
{
dest_colormap[i] = (UINT8)i;
continue;
}
color = V_GetColor(i);
brightness = (UINT8)(((UINT16)color.s.red + (UINT16)color.s.green + (UINT16)color.s.blue)/3);
brightdif = 256;
@ -1454,6 +1459,20 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
{
K_UpdateOffroad(player);
// setting players to use the star colormap and spawning afterimages
if (player->kartstuff[k_startimer])
{
mobj_t *ghost;
player->mo->colorized = true;
ghost = P_SpawnGhostMobj(player->mo);
ghost->fuse = 4;
ghost->frame |= FF_FULLBRIGHT;
}
else
{
player->mo->colorized = false;
}
if (player->kartstuff[k_itemclose])
player->kartstuff[k_itemclose]--;
@ -1616,6 +1635,19 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
S_ChangeMusicInternal(mapmusname, true);
}
void K_KartPlayerAfterThink(player_t *player)
{
if (player->kartstuff[k_startimer])
{
player->mo->frame |= FF_FULLBRIGHT;
}
else
{
if (!(player->mo->state->frame & FF_FULLBRIGHT))
player->mo->frame &= ~FF_FULLBRIGHT;
}
}
static void K_PlayTauntSound(mobj_t *source)
{
switch (P_RandomFixed() % 4)
@ -2056,6 +2088,7 @@ void K_StealBalloon(player_t *player, player_t *victim, boolean force)
}
// source is the mobj that originally threw the bomb that exploded etc.
// Spawns the sphere around the explosion that handles spinout
void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle, boolean spawncenter, boolean ghostit, mobj_t *source)
{
mobj_t *mobj;
@ -2076,8 +2109,6 @@ void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32
degrees = FINEANGLES/number;
radius = FixedDiv(radius,5*(FRACUNIT/4));
closestangle = 0;
// Create the hoop!
@ -2122,10 +2153,6 @@ void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32
mobj = ghost;
}
mobj->momx = FixedMul(FixedDiv(mobjx - x, dist), 2*FRACUNIT);
mobj->momy = FixedMul(FixedDiv(mobjy - y, dist), 2*FRACUNIT);
mobj->momz = FixedMul(FixedDiv(mobjz - z, dist), 2*FRACUNIT);
if (spawncenter)
{
mobj->x = x;
@ -2133,6 +2160,10 @@ void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32
mobj->z = z;
}
mobj->momx = FixedMul(FixedDiv(mobjx - x, dist), FixedDiv(dist, 6*FRACUNIT));
mobj->momy = FixedMul(FixedDiv(mobjy - y, dist), FixedDiv(dist, 6*FRACUNIT));
mobj->momz = FixedMul(FixedDiv(mobjz - z, dist), FixedDiv(dist, 6*FRACUNIT));
mobj->flags |= MF_NOCLIPTHING;
mobj->flags &= ~MF_SPECIAL;
@ -2140,6 +2171,67 @@ void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32
}
}
// Spawns the purely visual explosion
void K_SpawnBobombExplosion(mobj_t *source)
{
INT32 i, radius, height;
mobj_t *smoldering = P_SpawnMobj(source->x, source->y, source->z, MT_SMOLDERING);
mobj_t *dust;
mobj_t *truc;
smoldering->tics = TICRATE*3;
INT32 speed, speed2;
radius = source->radius>>FRACBITS;
height = source->height>>FRACBITS;
for (i = 0; i < 32; i++)
{
dust = P_SpawnMobj(source->x, source->y, source->z, MT_SMOKE);
dust->angle = (ANGLE_180/16) * i;
dust->scale = source->scale;
dust->destscale = source->scale*10;
P_InstaThrust(dust, dust->angle, FixedMul(20*FRACUNIT, source->scale));
truc = P_SpawnMobj(source->x + P_RandomRange(-radius, radius)*FRACUNIT,
source->y + P_RandomRange(-radius, radius)*FRACUNIT,
source->z + P_RandomRange(0, height)*FRACUNIT, MT_BOSSEXPLODE);
truc->scale = source->scale*2;
truc->destscale = source->scale*6;
P_SetMobjState(truc, S_SLOWBOOM1);
speed = FixedMul(10*FRACUNIT, source->scale)>>FRACBITS;
truc->momx = P_RandomRange(-speed, speed)*FRACUNIT;
truc->momy = P_RandomRange(-speed, speed)*FRACUNIT;
speed = FixedMul(20*FRACUNIT, source->scale)>>FRACBITS;
truc->momz = P_RandomRange(-speed, speed)*FRACUNIT;
}
for (i = 0; i < 16; i++)
{
dust = P_SpawnMobj(source->x + P_RandomRange(-radius, radius)*FRACUNIT,
source->y + P_RandomRange(-radius, radius)*FRACUNIT,
source->z + P_RandomRange(0, height)*FRACUNIT, MT_SMOKE);
dust->scale = source->scale;
dust->destscale = source->scale*10;
dust->tics = 30;
dust->momz = P_RandomRange(FixedMul(3*FRACUNIT, source->scale)>>FRACBITS, FixedMul(7*FRACUNIT, source->scale)>>FRACBITS)*FRACUNIT;
truc = P_SpawnMobj(source->x + P_RandomRange(-radius, radius)*FRACUNIT,
source->y + P_RandomRange(-radius, radius)*FRACUNIT,
source->z + P_RandomRange(0, height)*FRACUNIT, MT_BOOMPARTICLE);
truc->scale = source->scale;
truc->destscale = source->scale*5;
speed = FixedMul(20*FRACUNIT, source->scale)>>FRACBITS;
truc->momx = P_RandomRange(-speed, speed)*FRACUNIT;
truc->momy = P_RandomRange(-speed, speed)*FRACUNIT;
speed = FixedMul(15*FRACUNIT, source->scale)>>FRACBITS;
speed2 = FixedMul(45*FRACUNIT, source->scale)>>FRACBITS;
truc->momz = P_RandomRange(speed, speed2)*FRACUNIT;
if (P_RandomChance(FRACUNIT/2))
truc->momz = -truc->momz;
truc->tics = TICRATE*2;
}
}
static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t angle, INT32 flags2, fixed_t speed)
{
mobj_t *th;
@ -4154,7 +4246,7 @@ static void K_initKartHUD(void)
// CHECK graphic
CHEK_Y = BASEVIDHEIGHT; // 200
// Minimap
MINI_X = BASEVIDWIDTH - 58; // 262
MINI_X = BASEVIDWIDTH - 50; // 270
MINI_Y = BASEVIDHEIGHT/2; // 100
if (splitscreen) // Splitscreen
@ -4740,6 +4832,15 @@ static void K_drawKartPositionFaces(void)
else
{
colormap = R_GetTranslationColormap(players[rankplayer[i]].skin, players[rankplayer[i]].mo->color, GTC_CACHE);
if (players[rankplayer[i]].mo->colorized)
{
colormap = R_GetTranslationColormap(TC_STARMAN, players[rankplayer[i]].mo->color, GTC_CACHE);
}
else
{
colormap = R_GetTranslationColormap(players[rankplayer[i]].skin, players[rankplayer[i]].mo->color, GTC_CACHE);
}
if (rankplayer[i] != myplayer)
{
V_DrawSmallTranslucentMappedPatch(FACE_X, Y, V_HUDTRANS|V_SNAPTOLEFT, faceprefix[players[rankplayer[i]].skin], colormap);
@ -5019,16 +5120,16 @@ static void K_drawKartMinimap(void)
else
return; // no pic, just get outta here
x = MINI_X - (AutomapPic->width/4);
y = MINI_Y - (AutomapPic->height/4);
x = MINI_X - (AutomapPic->width/2);
y = MINI_Y - (AutomapPic->height/2);
if (splitscreen == 2)
splitflags = 0;
if (mirrormode)
V_DrawSmallScaledPatch(x+(AutomapPic->width/2), y, splitflags|V_FLIP, AutomapPic);
V_DrawScaledPatch(x+(AutomapPic->width), y, splitflags|V_FLIP, AutomapPic);
else
V_DrawSmallScaledPatch(x, y, splitflags, AutomapPic);
V_DrawScaledPatch(x, y, splitflags, AutomapPic);
splitflags &= ~V_HUDTRANSHALF; // Head icons won't be transparent
@ -5065,41 +5166,67 @@ static void K_drawKartMinimap(void)
if (bsp->bbox[1][BOXTOP] > maxy)
maxy = bsp->bbox[1][BOXTOP];
// You might be wondering why these are being bitshift here
// it's because mapwidth and height would otherwise overflow for maps larger than half the size possible...
// map boundaries and sizes will ALWAYS be whole numbers thankfully
// later calculations take into consideration that these are actually not in terms of FRACUNIT though
minx >>= FRACBITS;
maxx >>= FRACBITS;
miny >>= FRACBITS;
maxy >>= FRACBITS;
fixed_t mapwidth = maxx - minx;
fixed_t mapheight = maxy - miny;
fixed_t xoffset = minx + mapwidth/2;
fixed_t yoffset = miny + mapheight/2;
// These should always be small enough to be bitshift back right now
fixed_t xoffset = (minx + mapwidth/2)<<FRACBITS;
fixed_t yoffset = (miny + mapheight/2)<<FRACBITS;
fixed_t xscale = FixedDiv((AutomapPic->width<<FRACBITS)/2, mapwidth);
fixed_t yscale = FixedDiv((AutomapPic->height<<FRACBITS)/2, mapheight);
fixed_t xscale = FixedDiv(AutomapPic->width, mapwidth);
fixed_t yscale = FixedDiv(AutomapPic->height, mapheight);
fixed_t zoom = FixedMul(min(xscale, yscale), FRACUNIT-FRACUNIT/20);
amnumxpos = (FixedMul(players[i].mo->x, zoom) - FixedMul(xoffset, zoom));
amnumypos = -(FixedMul(players[i].mo->y, zoom) - FixedMul(yoffset, zoom));
amxpos = amnumxpos + ((x + AutomapPic->width/4 - (iconprefix[players[i].skin]->width/4))<<FRACBITS);
amypos = amnumypos + ((y + AutomapPic->height/4 - (iconprefix[players[i].skin]->height/4))<<FRACBITS);
amxpos = amnumxpos + ((x + AutomapPic->width/2 - (iconprefix[players[i].skin]->width/2))<<FRACBITS);
amypos = amnumypos + ((y + AutomapPic->height/2 - (iconprefix[players[i].skin]->height/2))<<FRACBITS);
if (mirrormode)
{
amxpos = -amnumxpos + ((x + AutomapPic->width/4 + (iconprefix[players[i].skin]->width/4))<<FRACBITS);
amxpos = -amnumxpos + ((x + AutomapPic->width/2 + (iconprefix[players[i].skin]->width/2))<<FRACBITS);
if (!players[i].skincolor) // 'default' color
V_DrawSciencePatch(amxpos, amypos, splitflags|V_FLIP, iconprefix[players[i].skin], FRACUNIT/2);
V_DrawSciencePatch(amxpos, amypos, splitflags|V_FLIP, iconprefix[players[i].skin], FRACUNIT);
else
{
UINT8 *colormap = R_GetTranslationColormap(players[i].skin, players[i].skincolor, 0); //transtables[players[i].skin] - 256 + (players[i].skincolor<<8);
V_DrawFixedPatch(amxpos, amypos, FRACUNIT/2, splitflags|V_FLIP, iconprefix[players[i].skin], colormap);
UINT8 *colormap;
if (players[i].mo->colorized)
{
colormap = R_GetTranslationColormap(TC_STARMAN, players[i].mo->color, 0);
}
else
{
colormap = R_GetTranslationColormap(players[i].skin, players[i].mo->color, 0);
}
V_DrawFixedPatch(amxpos, amypos, FRACUNIT, splitflags|V_FLIP, iconprefix[players[i].skin], colormap);
}
}
else
{
if (!players[i].skincolor) // 'default' color
V_DrawSciencePatch(amxpos, amypos, splitflags, iconprefix[players[i].skin], FRACUNIT/2);
V_DrawSciencePatch(amxpos, amypos, splitflags, iconprefix[players[i].skin], FRACUNIT);
else
{
UINT8 *colormap = R_GetTranslationColormap(players[i].skin, players[i].skincolor, 0); //transtables[players[i].skin] - 256 + (players[i].skincolor<<8);
V_DrawFixedPatch(amxpos, amypos, FRACUNIT/2, splitflags, iconprefix[players[i].skin], colormap);
UINT8 *colormap;
if (players[i].mo->colorized)
{
colormap = R_GetTranslationColormap(TC_STARMAN, players[i].mo->color, 0);
}
else
{
colormap = R_GetTranslationColormap(players[i].skin, players[i].mo->color, 0);
}
V_DrawFixedPatch(amxpos, amypos, FRACUNIT, splitflags, iconprefix[players[i].skin], colormap);
}
}
}

View File

@ -21,11 +21,13 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid)
void K_LakituChecker(player_t *player);
void K_KartMoveAnimation(player_t *player);
void K_KartPlayerThink(player_t *player, ticcmd_t *cmd);
void K_KartPlayerAfterThink(player_t *player);
void K_SpinPlayer(player_t *player, mobj_t *source);
void K_SquishPlayer(player_t *player, mobj_t *source);
void K_ExplodePlayer(player_t *player, mobj_t *source);
void K_StealBalloon(player_t *player, player_t *victim, boolean force);
void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle, boolean spawncenter, boolean ghostit, mobj_t *source);
void K_SpawnBobombExplosion(mobj_t *source);
void K_SpawnDriftTrail(player_t *player);
void K_DoMushroom(player_t *player, boolean doPFlag, boolean startboost);
void K_DoBouncePad(mobj_t *mo, fixed_t vertispeed);

View File

@ -80,7 +80,8 @@ enum mobj_e {
mobj_extravalue1,
mobj_extravalue2,
mobj_cusval,
mobj_cvmem
mobj_cvmem,
mobj_colorized
};
static const char *const mobj_opt[] = {
@ -140,6 +141,7 @@ static const char *const mobj_opt[] = {
"extravalue2",
"cusval",
"cvmem",
"colorized",
NULL};
#define UNIMPLEMENTED luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", mobj_opt[field])
@ -343,6 +345,9 @@ static int mobj_get(lua_State *L)
case mobj_cvmem:
lua_pushinteger(L, mo->cvmem);
break;
case mobj_colorized:
lua_pushboolean(L, mo->colorized);
break;
default: // extra custom variables in Lua memory
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
I_Assert(lua_istable(L, -1));
@ -638,6 +643,9 @@ static int mobj_set(lua_State *L)
case mobj_cvmem:
mo->cvmem = luaL_checkinteger(L, 3);
break;
case mobj_colorized:
mo->colorized = luaL_checkboolean(L, 3);
break;
default:
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
I_Assert(lua_istable(L, -1));

View File

@ -3922,11 +3922,11 @@ static inline boolean PIT_GrenadeRing(mobj_t *thing)
if (thing->type != MT_PLAYER) // Don't explode for anything but an actual player.
return true;
if (thing == grenade->target && !(grenade->threshold == 0)) // Don't blow up at your owner.
if (thing == grenade->target && grenade->threshold != 0) // Don't blow up at your owner.
return true;
if (thing->player && (thing->player->kartstuff[k_bootimer]
|| (thing->player->kartstuff[k_balloon] <= 0 && thing->player->kartstuff[k_comebacktimer])))
|| (gametype == GT_MATCH && thing->player && thing->player->kartstuff[k_balloon] <= 0 && thing->player->kartstuff[k_comebacktimer])))
return true;
if ((gametype == GT_CTF || gametype == GT_TEAMMATCH)
@ -8268,7 +8268,9 @@ void A_BobombExplode(mobj_t *actor)
type = (mobjtype_t)locvar1;
for (d = 0; d < 16; d++)
K_SpawnKartExplosion(actor->x, actor->y, actor->z, actor->info->painchance + 32*FRACUNIT, 32, type, d*(ANGLE_45/4), false, false, actor->target); // 32 <-> 64
K_SpawnKartExplosion(actor->x, actor->y, actor->z, actor->info->painchance + 32*FRACUNIT, 32, type, d*(ANGLE_45/4), true, false, actor->target); // 32 <-> 64
K_SpawnBobombExplosion(actor);
P_SpawnMobj(actor->x, actor->y, actor->z, MT_BOMBEXPLOSIONSOUND);
@ -8284,7 +8286,7 @@ void A_BobombExplode(mobj_t *actor)
if (mo2 == actor || mo2->type == MT_BOMBEXPLOSIONSOUND) // Don't explode yourself! Endless loop!
continue;
if (actor->target && actor->target->player && actor->target->player->kartstuff[k_balloon] <= 0 && mo2 == actor->target)
if (gametype == GT_MATCH && actor->target && actor->target->player && actor->target->player->kartstuff[k_balloon] <= 0 && mo2 == actor->target)
continue;
if (P_AproxDistance(P_AproxDistance(mo2->x - actor->x, mo2->y - actor->y), mo2->z - actor->z) > actor->info->painchance)

View File

@ -848,9 +848,12 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->player && thing->player->powers[pw_flashing])
return true;
if (thing->type == MT_PLAYER)
if (thing->type == MT_PLAYER && thing->player)
{
K_SpinPlayer(thing->player, tmthing->target);
if (tmthing->state == &states[S_BOMBEXPLOSION1])
K_ExplodePlayer(thing->player, tmthing->target);
else
K_SpinPlayer(thing->player, tmthing->target);
}
return true; // This doesn't collide with anything, but we want it to effect the player anyway.
@ -1180,10 +1183,13 @@ static boolean PIT_CheckThing(mobj_t *thing)
P_KillMobj(thing, tmthing, tmthing);
}
else if (thing->type == MT_BOMBEXPLOSION)
else if (thing->type == MT_BOMBEXPLOSION && tmthing->player)
{
// Player Damage
K_SpinPlayer(tmthing->player, thing->target);
if (thing->state == &states[S_BOMBEXPLOSION1])
K_ExplodePlayer(tmthing->player, thing->target);
else
K_SpinPlayer(tmthing->player, thing->target);
return true;
}

View File

@ -2296,7 +2296,6 @@ static boolean P_ZMovement(mobj_t *mo)
mo->fuse += ((5 - mo->threshold) * TICRATE);
}
break;
case MT_SKIM:
// skims don't bounce
if (mo->z > mo->watertop && mo->z - mo->momz <= mo->watertop)
@ -3039,6 +3038,14 @@ static boolean P_SceneryZMovement(mobj_t *mo)
switch (mo->type)
{
case MT_BOOMPARTICLE:
if ((mo->flags & MF_BOUNCE) && (mo->z <= mo->floorz || mo->z+mo->height >= mo->ceilingz))
{
mo->momz = -mo->momz;
mo->z += mo->momz;
S_StartSound(mo, mo->info->activesound);
}
break;
case MT_SMALLBUBBLE:
if (mo->z <= mo->floorz || mo->z+mo->height >= mo->ceilingz) // Hit the floor, so POP!
{
@ -6697,6 +6704,42 @@ void P_MobjThinker(mobj_t *mobj)
return;
}
break;
case MT_SMOLDERING:
if (leveltime % 2 == 0)
{
fixed_t x = P_RandomRange(-35, 35)*mobj->scale;
fixed_t y = P_RandomRange(-35, 35)*mobj->scale;
fixed_t z = P_RandomRange(0, 70)*mobj->scale;
mobj_t *smoke = P_SpawnMobj(mobj->x + x, mobj->y + y, mobj->z + z, MT_SMOKE);
smoke->scale = mobj->scale * 2;
smoke->destscale = mobj->scale * 6;
smoke->momz = P_RandomRange(4, 9)*FRACUNIT;
}
break;
case MT_BOOMPARTICLE:
{
fixed_t x = P_RandomRange(-16, 16)*mobj->scale;
fixed_t y = P_RandomRange(-16, 16)*mobj->scale;
fixed_t z = P_RandomRange(0, 32)*mobj->scale;
if (leveltime % 2 == 0)
{
mobj_t *smoke = P_SpawnMobj(mobj->x + x, mobj->y + y, mobj->z + z, MT_BOSSEXPLODE);
P_SetMobjState(smoke, S_QUICKBOOM1);
smoke->scale = mobj->scale/2;
smoke->destscale = mobj->scale;
}
else
{
mobj_t *smoke = P_SpawnMobj(mobj->x + x, mobj->y + y, mobj->z + z, MT_SMOKE);
smoke->scale = mobj->scale;
smoke->destscale = mobj->scale*2;
}
if (mobj->tics <= TICRATE)
{
mobj->destscale = FixedDiv(mobj->scale, 100*FRACUNIT);
}
}
break;
case MT_BATTLEBALLOON:
if (mobj->health > 0 && mobj->target && mobj->target->player && mobj->target->player->mo
&& mobj->target->player->health > 0 && !mobj->target->player->spectator)
@ -8547,6 +8590,8 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
else
mobj->z = z;
mobj->colorized = false;
#ifdef HAVE_BLUA
// DANGER! This can cause P_SpawnMobj to return NULL!
// Avoid using P_RemoveMobj on the newly created mobj in "MobjSpawn" Lua hooks!

View File

@ -360,6 +360,8 @@ typedef struct mobj_s
struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?)
#endif
boolean colorized; // Whether the mobj uses the starman colormap
// WARNING: New fields must be added separately to savegame and Lua.
} mobj_t;

View File

@ -946,9 +946,11 @@ typedef enum
MD2_HNEXT = 1<<7,
#ifdef ESLOPE
MD2_HPREV = 1<<8,
MD2_SLOPE = 1<<9
MD2_SLOPE = 1<<9,
MD2_COLORIZED = 1<<10
#else
MD2_HPREV = 1<<8
MD2_HPREV = 1<<8,
MD2_COLORIZED = 1<<9
#endif
} mobj_diff2_t;
@ -1143,6 +1145,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
if (mobj->standingslope)
diff2 |= MD2_SLOPE;
#endif
if (mobj->colorized)
diff2 |= MD2_COLORIZED;
if (diff2 != 0)
diff |= MD_MORE;
@ -1262,6 +1266,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
if (diff2 & MD2_SLOPE)
WRITEUINT16(save_p, mobj->standingslope->id);
#endif
if (diff2 & MD2_COLORIZED)
WRITEUINT8(save_p, mobj->colorized);
WRITEUINT32(save_p, mobj->mobjnum);
}
@ -2131,7 +2137,8 @@ static void LoadMobjThinker(actionf_p1 thinker)
if (diff2 & MD2_SLOPE)
mobj->standingslope = P_SlopeById(READUINT16(save_p));
#endif
if (diff2 & MD2_COLORIZED)
mobj->colorized = READUINT8(save_p);
if (diff & MD_REDFLAG)
{

View File

@ -1513,6 +1513,7 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj)
}
ghost->color = mobj->color;
ghost->colorized = mobj->colorized; // Kart: they should also be colorized if their origin is
ghost->angle = mobj->angle;
ghost->sprite = mobj->sprite;
@ -9518,7 +9519,7 @@ void P_PlayerThink(player_t *player)
#if 1
// "Blur" a bit when you have speed shoes and are going fast enough
if ((player->powers[pw_super] || player->powers[pw_sneakers]
|| player->kartstuff[k_driftboost] || player->kartstuff[k_mushroomtimer]) // SRB2kart
|| player->kartstuff[k_driftboost] || player->kartstuff[k_mushroomtimer]) && !player->kartstuff[k_startimer] // SRB2kart
&& (player->speed + abs(player->mo->momz)) > FixedMul(20*FRACUNIT,player->mo->scale))
{
mobj_t *gmobj = P_SpawnGhostMobj(player->mo);
@ -10073,4 +10074,6 @@ void P_PlayerAfterThink(player_t *player)
if (P_IsObjectOnGround(player->mo))
player->mo->pmomz = 0;
K_KartPlayerAfterThink(player);
}

View File

@ -827,7 +827,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
dc_transmap = vis->transmap;
if (vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // MT_GHOST LOOKS LIKE A PLAYER SO USE THE PLAYER TRANSLATION TABLES. >_>
{
if (vis->mobj->player && vis->mobj->player->kartstuff[k_startimer])
if (vis->mobj->colorized)
dc_translation = R_GetTranslationColormap(TC_STARMAN, vis->mobj->color, GTC_CACHE);
else
{
@ -851,7 +851,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
// New colormap stuff for skins Tails 06-07-2002
if (vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player!
{
if (vis->mobj->player && vis->mobj->player->kartstuff[k_startimer])
if (vis->mobj->colorized)
dc_translation = R_GetTranslationColormap(TC_STARMAN, vis->mobj->color, GTC_CACHE);
else
{