Merge pull request 'SRB2Kart Skin support' (#17) from skincompat into ACS2
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/17
This commit is contained in:
commit
ccca144494
16 changed files with 367 additions and 124 deletions
|
|
@ -12,13 +12,14 @@
|
|||
/* Manually defined asset hashes
|
||||
* Last updated 2019 / 01 / 18 - Kart v1.0.2 - Main assets
|
||||
* Last updated 2020 / 08 / 30 - Kart v1.3 - patch.kart
|
||||
* updated 2025 - BlanKart Indev -
|
||||
*/
|
||||
|
||||
#define ASSET_HASH_MAIN_PK3 "daf9a1a67b5e465c13789e96a09f7171"
|
||||
#define ASSET_HASH_SRB2_SRB "c1b9577687f8a795104aef4600720ea7"
|
||||
#define ASSET_HASH_GFX_KART "06f86ee16136eb8a7043b15001797034"
|
||||
#define ASSET_HASH_TEXTURES_KART "abb53d56aba47c3a8cb0f764da1c8b80"
|
||||
#define ASSET_HASH_CHARS_PK3 "bf014478cdda5e9208e3dea3c51f58c5"
|
||||
#define ASSET_HASH_CHARS_KART "e2c428347dde52858a3dacd29fc5b964"
|
||||
#define ASSET_HASH_MAPS_KART "d051e55141ba736582228c456953cd98"
|
||||
#define ASSET_HASH_FOLLOWERS_PK3 "00000000000000000000000000000000"
|
||||
#ifdef USE_PATCH_FILE
|
||||
|
|
|
|||
|
|
@ -1191,7 +1191,7 @@ static void IdentifyVersion(void)
|
|||
#define PATCHNAME "patch.pk3"
|
||||
#define MUSICNAME "music.kart"
|
||||
#define FOLLOWERSNAME "followers.pk3"
|
||||
#define CHARSNAME "chars.pk3"
|
||||
#define CHARSNAME "chars.kart"
|
||||
#define GRAPHICSNAME "gfx.kart"
|
||||
#define SOUNDSNAME "sounds.kart"
|
||||
|
||||
|
|
@ -1487,7 +1487,7 @@ void D_SRB2Main(void)
|
|||
mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_MAIN_PK3); // main.pk3
|
||||
mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_GFX_KART); // gfx.pk3
|
||||
mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_TEXTURES_KART); // textures.pk3
|
||||
mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_CHARS_PK3); // chars.pk3
|
||||
mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_CHARS_KART); // chars.kart
|
||||
mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_MAPS_KART); // maps.pk3 -- 4 - If you touch this, make sure to touch up the majormods stuff below.
|
||||
//mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_FOLLOWERS_PK3); // followers.pk3
|
||||
#ifdef USE_PATCH_FILE
|
||||
|
|
@ -1497,7 +1497,7 @@ void D_SRB2Main(void)
|
|||
mainwads++; // main.pk3
|
||||
mainwads++; // gfx.kart
|
||||
mainwads++; // textures.kart
|
||||
mainwads++; // chars.pk3
|
||||
mainwads++; // chars.kart
|
||||
mainwads++; // maps.kart
|
||||
//mainwads++; // followers.pk3
|
||||
#ifdef USE_PATCH_FILE
|
||||
|
|
|
|||
|
|
@ -1422,7 +1422,7 @@ void PT_FileFragment(void)
|
|||
|| !strcmp(filename, "srb2.srb")
|
||||
|| !strcmp(filename, "gfx.kart")
|
||||
|| !strcmp(filename, "textures.kart")
|
||||
|| !strcmp(filename, "chars.pk3")
|
||||
|| !strcmp(filename, "chars.kart")
|
||||
|| !strcmp(filename, "maps.kart")
|
||||
|| !strcmp(filename, "patch.pk3")
|
||||
|| !strcmp(filename, "sounds.kart")
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ typedef enum
|
|||
{
|
||||
SF_HIRES = 1, // Draw the sprite at different size?
|
||||
SF_MACHINE = 1<<1, // Beep boop. Are you a robot?
|
||||
SF_NOGIBS = 1<<2, // Does this kart smash into pieces?
|
||||
SF_OLDDEATH = 1<<3, // Kart V1 styled death animation
|
||||
// free up to and including 1<<31
|
||||
} skinflags_t;
|
||||
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = {
|
|||
|
||||
0, // SPR2_SIGN
|
||||
0, // SPR2_XTRA
|
||||
0, // SPR2_KART
|
||||
};
|
||||
|
||||
// Doesn't work with g++, needs actionf_p1 (don't modify this comment)
|
||||
|
|
|
|||
|
|
@ -22,3 +22,5 @@ _(DEAD) // Dead
|
|||
|
||||
_(SIGN) // Finish signpost
|
||||
_(XTRA) // Three Faces of Darkness
|
||||
|
||||
_(KART) // Extra frames from Kart skins
|
||||
|
|
|
|||
|
|
@ -2602,7 +2602,7 @@ void K_KartMoveAnimation(player_t *player)
|
|||
}
|
||||
|
||||
// Sliptides: drift -> lookback frames
|
||||
if (abs(player->aizdriftturn) >= ANGLE_90)
|
||||
if (abs(player->aizdriftturn) >= ANGLE_90 && !wadfiles[((skin_t *)player->mo->skin)->wadnum]->compatmode)
|
||||
{
|
||||
destGlanceDir = -(2*intsign(player->aizdriftturn));
|
||||
player->glanceDir = destGlanceDir;
|
||||
|
|
|
|||
|
|
@ -501,6 +501,69 @@ static int mobj_get(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
#define F(x) case x - 'A':
|
||||
static void frame2spr2(mobj_t *mo, UINT32 inframe)
|
||||
{
|
||||
UINT8 spr2, outframe = 0;
|
||||
switch (inframe & FF_FRAMEMASK)
|
||||
{
|
||||
F('A') F('B')
|
||||
spr2 = SPR2_STIN;
|
||||
outframe = inframe & 1;
|
||||
break;
|
||||
F('C') F('D')
|
||||
spr2 = SPR2_STIL;
|
||||
outframe = inframe & 1;
|
||||
break;
|
||||
F('E') F('F')
|
||||
spr2 = SPR2_STIR;
|
||||
outframe = inframe & 1;
|
||||
break;
|
||||
F('G')
|
||||
spr2 = SPR2_SLWN;
|
||||
break;
|
||||
F('H')
|
||||
spr2 = SPR2_SLWL;
|
||||
break;
|
||||
F('I')
|
||||
spr2 = SPR2_SLWR;
|
||||
break;
|
||||
F('J')
|
||||
spr2 = SPR2_FSTN;
|
||||
break;
|
||||
F('K')
|
||||
spr2 = SPR2_FSTL;
|
||||
break;
|
||||
F('L')
|
||||
spr2 = SPR2_FSTR;
|
||||
break;
|
||||
F('M') F('N')
|
||||
spr2 = SPR2_DRLN;
|
||||
outframe = inframe & 1;
|
||||
break;
|
||||
F('O') F('P')
|
||||
spr2 = SPR2_DRRN;
|
||||
outframe = inframe & 1;
|
||||
break;
|
||||
F('Q')
|
||||
spr2 = SPR2_SPIN;
|
||||
break;
|
||||
F('R')
|
||||
spr2 = SPR2_KART;
|
||||
break;
|
||||
F('S')
|
||||
spr2 = SPR2_SIGN;
|
||||
break;
|
||||
default:
|
||||
spr2 = SPR2_KART;
|
||||
outframe = inframe - 18; // not 19! frame 0 is squish
|
||||
break;
|
||||
}
|
||||
mo->frame = (inframe & ~FF_FRAMEMASK) | outframe;
|
||||
mo->sprite2 = P_GetSkinSprite2((skin_t *)mo->skin, spr2, mo->player);
|
||||
}
|
||||
#undef F
|
||||
|
||||
#define NOSET luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " should not be set directly.", mobj_opt[field])
|
||||
#define NOSETPOS luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " should not be set directly. Use " LUA_QL("P_Move") ", " LUA_QL("P_TryMove") ", or " LUA_QL("P_SetOrigin") ", or " LUA_QL("P_MoveOrigin") " instead.", mobj_opt[field])
|
||||
static int mobj_set(lua_State *L)
|
||||
|
|
@ -559,64 +622,15 @@ static int mobj_set(lua_State *L)
|
|||
mo->rollangle = luaL_checkangle(L, 3);
|
||||
break;
|
||||
case mobj_sprite:
|
||||
mo->sprite = luaL_checkinteger(L, 3);
|
||||
if (mo->sprite == SPR_PLAY)
|
||||
mo->sprite2 = P_GetSkinSprite2(((skin_t *)mo->skin), SPR2_STIN, mo->player);
|
||||
spritenum_t newsprite = luaL_checkinteger(L, 3);
|
||||
if (lua_compatmode && mo->sprite != SPR_PLAY && newsprite == SPR_PLAY)
|
||||
frame2spr2(mo, mo->frame);
|
||||
mo->sprite = newsprite;
|
||||
break;
|
||||
case mobj_frame:
|
||||
// Check for SPR2
|
||||
if (mo->sprite == SPR_PLAY)
|
||||
{
|
||||
UINT32 frame = (UINT32)luaL_checkinteger(L, 3);
|
||||
switch (frame)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
mo->sprite2 = P_GetSkinSprite2(((skin_t *)mo->skin), SPR2_STIN, mo->player);
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
mo->sprite2 = P_GetSkinSprite2(((skin_t *)mo->skin), SPR2_STIL, mo->player);
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
mo->sprite2 = P_GetSkinSprite2(((skin_t *)mo->skin), SPR2_STIR, mo->player);
|
||||
break;
|
||||
case 6:
|
||||
mo->sprite2 = P_GetSkinSprite2(((skin_t *)mo->skin), SPR2_SLWN, mo->player);
|
||||
break;
|
||||
case 7:
|
||||
mo->sprite2 = P_GetSkinSprite2(((skin_t *)mo->skin), SPR2_SLWL, mo->player);
|
||||
break;
|
||||
case 8:
|
||||
mo->sprite2 = P_GetSkinSprite2(((skin_t *)mo->skin), SPR2_SLWR, mo->player);
|
||||
break;
|
||||
case 9:
|
||||
mo->sprite2 = P_GetSkinSprite2(((skin_t *)mo->skin), SPR2_FSTN, mo->player);
|
||||
break;
|
||||
case 10:
|
||||
mo->sprite2 = P_GetSkinSprite2(((skin_t *)mo->skin), SPR2_FSTL, mo->player);
|
||||
break;
|
||||
case 11:
|
||||
mo->sprite2 = P_GetSkinSprite2(((skin_t *)mo->skin), SPR2_FSTR, mo->player);
|
||||
break;
|
||||
case 12:
|
||||
case 13:
|
||||
mo->sprite2 = P_GetSkinSprite2(((skin_t *)mo->skin), SPR2_DRLN, mo->player);
|
||||
break;
|
||||
case 14:
|
||||
case 15:
|
||||
mo->sprite2 = P_GetSkinSprite2(((skin_t *)mo->skin), SPR2_DRRN, mo->player);
|
||||
break;
|
||||
case 16:
|
||||
case 17: // squish technically doesnt really exist
|
||||
mo->sprite2 = P_GetSkinSprite2(((skin_t *)mo->skin), SPR2_SPIN, mo->player);
|
||||
break;
|
||||
case 18:
|
||||
mo->sprite2 = P_GetSkinSprite2(((skin_t *)mo->skin), SPR2_SIGN, mo->player);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lua_compatmode && mo->sprite == SPR_PLAY)
|
||||
frame2spr2(mo, (UINT32)luaL_checkinteger(L, 3));
|
||||
else
|
||||
mo->frame = (UINT32)luaL_checkinteger(L, 3);
|
||||
break;
|
||||
|
|
|
|||
116
src/p_inter.c
116
src/p_inter.c
|
|
@ -1394,76 +1394,84 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
|||
target->fuse = 2*TICRATE; // timer before mobj disappears from view (even if not an actual player)
|
||||
target->momx = target->momy = target->momz = 0;
|
||||
|
||||
angle_t playerFlingAngle;
|
||||
angle_t kartFlingAngle;
|
||||
|
||||
if (source && !P_MobjWasRemoved(source))
|
||||
if (target->player && !(skins[target->player->skin].flags & SF_NOGIBS))
|
||||
{
|
||||
playerFlingAngle = kartFlingAngle = R_PointToAngle2(
|
||||
source->x - source->momx, source->y - source->momy,
|
||||
target->x, target->y
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
kartFlingAngle = target->angle;
|
||||
angle_t playerFlingAngle;
|
||||
angle_t kartFlingAngle;
|
||||
|
||||
if (P_RandomByte() & 1)
|
||||
if (source && !P_MobjWasRemoved(source))
|
||||
{
|
||||
kartFlingAngle -= ANGLE_45;
|
||||
playerFlingAngle = kartFlingAngle = R_PointToAngle2(
|
||||
source->x - source->momx, source->y - source->momy,
|
||||
target->x, target->y
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
kartFlingAngle += ANGLE_45;
|
||||
kartFlingAngle = target->angle;
|
||||
|
||||
if (P_RandomByte() & 1)
|
||||
{
|
||||
kartFlingAngle -= ANGLE_45;
|
||||
}
|
||||
else
|
||||
{
|
||||
kartFlingAngle += ANGLE_45;
|
||||
}
|
||||
|
||||
playerFlingAngle = kartFlingAngle + ANGLE_180;
|
||||
}
|
||||
|
||||
playerFlingAngle = kartFlingAngle + ANGLE_180;
|
||||
}
|
||||
// Spawn kart frame
|
||||
mobj_t *kart = P_SpawnMobjFromMobj(target, 0, 0, 0, MT_KART_LEFTOVER);
|
||||
|
||||
// Spawn kart frame
|
||||
mobj_t *kart = P_SpawnMobjFromMobj(target, 0, 0, 0, MT_KART_LEFTOVER);
|
||||
|
||||
if (kart && !P_MobjWasRemoved(kart))
|
||||
{
|
||||
kart->angle = target->angle;
|
||||
kart->color = target->color;
|
||||
kart->extravalue1 = target->player->kartweight;
|
||||
kart->fuse = 2*TICRATE;
|
||||
|
||||
// Copy interp data
|
||||
kart->old_angle = target->old_angle;
|
||||
kart->old_x = target->old_x;
|
||||
kart->old_y = target->old_y;
|
||||
kart->old_z = target->old_z;
|
||||
|
||||
P_InstaThrust(kart, kartFlingAngle, 1 * kart->scale);
|
||||
P_SetObjectMomZ(kart, 10*FRACUNIT, false);
|
||||
|
||||
const angle_t aOffset = ANGLE_22h;
|
||||
|
||||
UINT8 i;
|
||||
angle_t tireAngle;
|
||||
mobj_t *tire;
|
||||
|
||||
// Spawn tires
|
||||
tireAngle = kartFlingAngle - ANGLE_90 - ANGLE_22h;
|
||||
for (i = 0; i < 4; i++)
|
||||
if (kart && !P_MobjWasRemoved(kart))
|
||||
{
|
||||
if (i == 2) tireAngle += ANGLE_90;
|
||||
kart->angle = target->angle;
|
||||
kart->color = target->color;
|
||||
kart->extravalue1 = target->player->kartweight;
|
||||
kart->fuse = 2*TICRATE;
|
||||
|
||||
tire = P_SpawnMobjFromMobj(kart, 0, 0, 0, MT_KART_TIRE);
|
||||
tire->fuse = 2*TICRATE;
|
||||
// Copy interp data
|
||||
kart->old_angle = target->old_angle;
|
||||
kart->old_x = target->old_x;
|
||||
kart->old_y = target->old_y;
|
||||
kart->old_z = target->old_z;
|
||||
|
||||
tire->angle = tireAngle;
|
||||
P_InstaThrust(tire, tireAngle, 3 * tire->scale);
|
||||
P_SetObjectMomZ(tire, 10*FRACUNIT, false);
|
||||
P_InstaThrust(kart, kartFlingAngle, 1 * kart->scale);
|
||||
P_SetObjectMomZ(kart, 10*FRACUNIT, false);
|
||||
|
||||
tireAngle += (aOffset * 2);
|
||||
const angle_t aOffset = ANGLE_22h;
|
||||
|
||||
UINT8 i;
|
||||
angle_t tireAngle;
|
||||
mobj_t *tire;
|
||||
|
||||
// Spawn tires
|
||||
tireAngle = kartFlingAngle - ANGLE_90 - ANGLE_22h;
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (i == 2) tireAngle += ANGLE_90;
|
||||
|
||||
tire = P_SpawnMobjFromMobj(kart, 0, 0, 0, MT_KART_TIRE);
|
||||
tire->fuse = 2*TICRATE;
|
||||
|
||||
tire->angle = tireAngle;
|
||||
P_InstaThrust(tire, tireAngle, 3 * tire->scale);
|
||||
P_SetObjectMomZ(tire, 10*FRACUNIT, false);
|
||||
|
||||
tireAngle += (aOffset * 2);
|
||||
}
|
||||
}
|
||||
|
||||
P_InstaThrust(target, playerFlingAngle, 4 * target->scale);
|
||||
P_SetObjectMomZ(target, 14*FRACUNIT, false);
|
||||
}
|
||||
|
||||
P_InstaThrust(target, playerFlingAngle, 4 * target->scale);
|
||||
P_SetObjectMomZ(target, 14*FRACUNIT, false);
|
||||
if (target->player && (skins[target->player->skin].flags & SF_OLDDEATH))
|
||||
{
|
||||
P_SetObjectMomZ(target, 14*FRACUNIT, false);
|
||||
}
|
||||
|
||||
P_PlayDeathSound(target);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6427,6 +6427,11 @@ static boolean P_MobjDeadThink(mobj_t *mobj)
|
|||
else // Apply gravity to fall downwards.
|
||||
{
|
||||
P_SetObjectMomZ(mobj, -2*FRACUNIT/3, true);
|
||||
|
||||
if (mobj->player && (skins[mobj->player->skin].flags && SF_OLDDEATH))
|
||||
{
|
||||
mobj->player->drawangle -= ANGLE_22h;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MT_METALSONIC_RACE:
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include "r_fps.h"
|
||||
|
||||
#include "r_main.h"
|
||||
#include "r_skins.h"
|
||||
#include "g_game.h"
|
||||
#include "i_video.h"
|
||||
#include "r_plane.h"
|
||||
|
|
@ -287,6 +288,9 @@ void R_InterpolateMobjState(mobj_t *mobj, fixed_t frac, interpmobjstate_t *out)
|
|||
if (mobj->player && mobj->player->aizdriftturn)
|
||||
{
|
||||
addangle += mobj->player->aizdriftturn;
|
||||
if (mobj->skin && wadfiles[((skin_t *)mobj->skin)->wadnum]->compatmode)
|
||||
// don't turn too much in compatmode
|
||||
addangle = (INT32)addangle / 4;
|
||||
}
|
||||
if (mobj->state == &states[S_KART_DRIFT_L]
|
||||
|| mobj->state == &states[S_KART_DRIFT_L_OUT]
|
||||
|
|
|
|||
164
src/r_skins.c
164
src/r_skins.c
|
|
@ -109,6 +109,9 @@ static void Sk_SetDefaultValue(skin_t *skin)
|
|||
skin->flags = 0;
|
||||
|
||||
strcpy(skin->realname, "Someone");
|
||||
strncpy(skin->facerank, "MISSING", 9);
|
||||
strncpy(skin->facewant, "MISSING", 9);
|
||||
strncpy(skin->facemmap, "MISSING", 9);
|
||||
skin->starttranscolor = 96;
|
||||
skin->prefcolor = SKINCOLOR_GREEN;
|
||||
skin->supercolor = SKINCOLOR_SUPERGOLD1;
|
||||
|
|
@ -126,6 +129,8 @@ static void Sk_SetDefaultValue(skin_t *skin)
|
|||
skin->soundsid[S_sfx[i].skinsound] = i;
|
||||
}
|
||||
|
||||
static void R_IHateThatHedgehog(UINT16 wadnum);
|
||||
|
||||
//
|
||||
// Initialize the basic skins
|
||||
//
|
||||
|
|
@ -148,6 +153,8 @@ void R_InitSkins(void)
|
|||
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
{
|
||||
if (i == 4) // chars.kart
|
||||
R_IHateThatHedgehog((UINT16)i);
|
||||
R_AddSkins((UINT16)i);
|
||||
R_PatchSkins((UINT16)i);
|
||||
R_LoadSpriteInfoLumps(i, wadfiles[i]->numlumps);
|
||||
|
|
@ -396,6 +403,38 @@ static UINT16 W_CheckForPatchSkinMarkerInPwad(UINT16 wadid, UINT16 startlump)
|
|||
return INT16_MAX; // not found
|
||||
}
|
||||
|
||||
#define NUMKARTFRAMES 19
|
||||
#define S(f, s) { f - 'A', SPR2_##s },
|
||||
static UINT8 KART_TO_SPR2[][2] = {
|
||||
S('A', STIN)
|
||||
S('B', STIN)
|
||||
S('C', STIL)
|
||||
S('D', STIL)
|
||||
S('E', STIR)
|
||||
S('F', STIR)
|
||||
S('J', SLWN)
|
||||
S('G', SLWN)
|
||||
S('K', SLWL)
|
||||
S('H', SLWL)
|
||||
S('L', SLWR)
|
||||
S('I', SLWR)
|
||||
S('A', FSTN)
|
||||
S('J', FSTN)
|
||||
S('C', FSTL)
|
||||
S('K', FSTL)
|
||||
S('E', FSTR)
|
||||
S('L', FSTR)
|
||||
S('M', DRLN)
|
||||
S('N', DRLN)
|
||||
S('O', DRRN)
|
||||
S('P', DRRN)
|
||||
S('Q', SPIN)
|
||||
S('Q', DEAD)
|
||||
S('R', KART)
|
||||
S('S', SIGN)
|
||||
};
|
||||
#undef S
|
||||
|
||||
static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, skin_t *skin)
|
||||
{
|
||||
UINT16 newlastlump;
|
||||
|
|
@ -427,20 +466,126 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski
|
|||
*lastlump = newlastlump; // okay, make the normal sprite set loading end there
|
||||
}*/
|
||||
|
||||
// load all sprite sets we are aware of... for normal stuff.
|
||||
for (sprite2 = 0; sprite2 < free_spr2; sprite2++)
|
||||
R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[sprite2], wadnum, *lump, *lastlump);
|
||||
if (!wadfiles[wadnum]->compatmode)
|
||||
{
|
||||
// load all sprite sets we are aware of... for normal stuff.
|
||||
for (sprite2 = 0; sprite2 < free_spr2; sprite2++)
|
||||
R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[sprite2], wadnum, *lump, *lastlump);
|
||||
}
|
||||
else
|
||||
{
|
||||
// okay, now we have to get fancy...
|
||||
// first, just dump all the frames in a temporary def
|
||||
size_t i;
|
||||
spritedef_t *sd;
|
||||
spriteframe_t *sf;
|
||||
spritedef_t tmp = {};
|
||||
const char *sprname = W_CheckNameForNumPwad(wadnum, *lump);
|
||||
R_AddSingleSpriteDef(sprname, &tmp, wadnum, *lump, *lastlump);
|
||||
|
||||
if (tmp.numframes < NUMKARTFRAMES)
|
||||
I_Error("R_LoadSkinSprites: too few frames for kart skin");
|
||||
|
||||
// now shuffle them around to fit the new SPR2 system
|
||||
// iterate over KART_TO_SPR2, then add any excess frames to SPR2_KART
|
||||
#define SPR2COUNT sizeof(KART_TO_SPR2)/sizeof(*KART_TO_SPR2)
|
||||
for (i = 0; i < SPR2COUNT - NUMKARTFRAMES + tmp.numframes; i++)
|
||||
{
|
||||
boolean excess = i >= SPR2COUNT;
|
||||
sf = &tmp.spriteframes[excess ? i - SPR2COUNT + NUMKARTFRAMES : KART_TO_SPR2[i][0]];
|
||||
sd = &skin->sprites[excess ? SPR2_KART : KART_TO_SPR2[i][1]];
|
||||
sd->spriteframes = Z_Realloc(sd->spriteframes, sizeof(*sd->spriteframes) * (sd->numframes+1), PU_STATIC, NULL);
|
||||
sd->spriteframes[sd->numframes++] = *sf;
|
||||
}
|
||||
Z_Free(tmp.spriteframes);
|
||||
#undef SPR2COUNT
|
||||
|
||||
// now we have to rotate the drift frames. i hate this.
|
||||
sd = &skin->sprites[SPR2_DRRN];
|
||||
for (i = 0; i < sd->numframes; i++)
|
||||
{
|
||||
sf = &sd->spriteframes[i];
|
||||
if (sf->rotate != SRF_3D)
|
||||
continue;
|
||||
lumpnum_t lastpat = sf->lumppat[7];
|
||||
size_t lastid = sf->lumpid[7];
|
||||
for (int r = 7; r >= 1; r--)
|
||||
{
|
||||
sf->lumppat[r] = sf->lumppat[r-1];
|
||||
sf->lumpid[r] = sf->lumpid[r-1];
|
||||
}
|
||||
sf->lumppat[0] = lastpat;
|
||||
sf->lumpid[0] = lastid;
|
||||
}
|
||||
sd = &skin->sprites[SPR2_DRLN];
|
||||
for (i = 0; i < sd->numframes; i++)
|
||||
{
|
||||
sf = &sd->spriteframes[i];
|
||||
if (sf->rotate != SRF_3D)
|
||||
continue;
|
||||
lumpnum_t firstpat = sf->lumppat[0];
|
||||
size_t firstid = sf->lumpid[0];
|
||||
for (int r = 0; r < 8; r++)
|
||||
{
|
||||
sf->lumppat[r] = sf->lumppat[r+1];
|
||||
sf->lumpid[r] = sf->lumpid[r+1];
|
||||
}
|
||||
sf->lumppat[7] = firstpat;
|
||||
sf->lumpid[7] = firstid;
|
||||
}
|
||||
|
||||
R_AddKartFaces(skin);
|
||||
|
||||
skin->flags |= SF_OLDDEATH|SF_NOGIBS;
|
||||
|
||||
}
|
||||
|
||||
if (skin->sprites[0].numframes == 0)
|
||||
I_Error("R_LoadSkinSprites: no frames found for sprite SPR2_%s\n", spr2names[0]);
|
||||
}
|
||||
#undef NUMKARTFRAMES
|
||||
|
||||
static void R_IHateThatHedgehog(UINT16 wadnum)
|
||||
{
|
||||
skin_t *skin = &skins[0];
|
||||
Sk_SetDefaultValue(skin);
|
||||
skin->wadnum = wadnum;
|
||||
strcpy(skin->name, "sonic");
|
||||
strcpy(skin->realname, "Sonic");
|
||||
strcpy(skin->facerank, "PLAYRANK");
|
||||
strcpy(skin->facewant, "PLAYWANT");
|
||||
strcpy(skin->facemmap, "PLAYMMAP");
|
||||
skin->prefcolor = SKINCOLOR_BLUE;
|
||||
skin->starttranscolor = R_GetPaletteRemap(160);
|
||||
skin->kartspeed = 8;
|
||||
skin->kartweight = 2;
|
||||
|
||||
UINT16 lump = W_CheckNumForNamePwad("S_START", wadnum, 0);
|
||||
if (lump == INT16_MAX)
|
||||
I_Error("R_IHateThatHedgehog: could not find the hedgehog");
|
||||
R_LoadSkinSprites(wadnum, &lump, &(UINT16){}, skin);
|
||||
|
||||
#ifdef SKINVALUES
|
||||
skin_cons_t[0].value = 0;
|
||||
skin_cons_t[0].strvalue = skin->name;
|
||||
#endif
|
||||
Forceskin_cons_t[1].value = 0;
|
||||
Forceskin_cons_t[1].strvalue = skin->name;
|
||||
|
||||
#ifdef HWRENDER
|
||||
if (rendermode == render_opengl)
|
||||
HWR_AddPlayerModel(0);
|
||||
#endif
|
||||
|
||||
numskins = (UINT8)('r'+'a'+'c'+'e'+' '+'a'+'s'+' '+'a'+' '+'r'+'i'+'n'+'g'+'!');
|
||||
}
|
||||
|
||||
// returns whether found appropriate property
|
||||
static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value)
|
||||
static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value, boolean compat)
|
||||
{
|
||||
// custom translation table
|
||||
if (!stricmp(stoken, "startcolor"))
|
||||
skin->starttranscolor = atoi(value);
|
||||
skin->starttranscolor = compat ? R_GetPaletteRemap(atoi(value)) : atoi(value);
|
||||
|
||||
#define FULLPROCESS(field) else if (!stricmp(stoken, #field)) skin->field = get_number(value);
|
||||
// character type identification
|
||||
|
|
@ -492,6 +637,11 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value)
|
|||
GETFLAG(MACHINE)
|
||||
#undef GETFLAG
|
||||
|
||||
#define GETPATCH(field) else if (compat && !stricmp(stoken, #field)) strncpy(skin->field, value, 8);
|
||||
GETPATCH(facerank)
|
||||
GETPATCH(facewant)
|
||||
GETPATCH(facemmap)
|
||||
|
||||
else // let's check if it's a sound, otherwise error out
|
||||
{
|
||||
boolean found = false;
|
||||
|
|
@ -667,7 +817,7 @@ void R_AddSkins(UINT16 wadnum)
|
|||
pos++;
|
||||
}
|
||||
}
|
||||
else if (!R_ProcessPatchableFields(skin, stoken, value))
|
||||
else if (!R_ProcessPatchableFields(skin, stoken, value, wadfiles[wadnum]->compatmode))
|
||||
CONS_Debug(DBG_SETUP, "R_AddSkins: Unknown keyword '%s' in S_SKIN lump #%d (WAD %s)\n", stoken, lump, wadfiles[wadnum]->filename);
|
||||
|
||||
next_token:
|
||||
|
|
@ -822,7 +972,7 @@ void R_PatchSkins(UINT16 wadnum)
|
|||
pos++;
|
||||
}
|
||||
}
|
||||
else if (!R_ProcessPatchableFields(skin, stoken, value))
|
||||
else if (!R_ProcessPatchableFields(skin, stoken, value, wadfiles[wadnum]->compatmode))
|
||||
CONS_Debug(DBG_SETUP, "R_PatchSkins: Unknown keyword '%s' in P_SKIN lump #%d (WAD %s)\n", stoken, lump, wadfiles[wadnum]->filename);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ struct skin_t
|
|||
skinflags_t flags;
|
||||
|
||||
char realname[SKINNAMESIZE+1]; // Display name for level completion.
|
||||
char facerank[9], facewant[9], facemmap[9]; // Arbitrarily named patch lumps
|
||||
|
||||
// SRB2kart
|
||||
UINT8 kartspeed;
|
||||
|
|
|
|||
|
|
@ -249,6 +249,30 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch
|
|||
sprtemp[frame].flip &= ~(1<<rotation);
|
||||
}
|
||||
|
||||
#define NUMFACES 3
|
||||
static size_t KART_FACES[NUMFACES] = {
|
||||
offsetof(skin_t, facerank),
|
||||
offsetof(skin_t, facewant),
|
||||
offsetof(skin_t, facemmap),
|
||||
};
|
||||
|
||||
void R_AddKartFaces(skin_t *skin)
|
||||
{
|
||||
memset(sprtemp, 0xff, sizeof(sprtemp));
|
||||
spritedef_t *sd = &skin->sprites[SPR2_XTRA];
|
||||
for (size_t f = 0; f < NUMFACES; f++)
|
||||
{
|
||||
lumpnum_t lumpnum = W_CheckNumForName(reinterpret_cast<char *>(skin) + KART_FACES[f]); // how do you do, fellow C++ers?
|
||||
if (lumpnum == LUMPERROR)
|
||||
I_Error("R_AddKartFaces: missing patch %s for skin %s", reinterpret_cast<char *>(skin) + KART_FACES[f], skin->name);
|
||||
R_InstallSpriteLump(WADFILENUM(lumpnum), LUMPNUM(lumpnum), numspritelumps++, f, 0, 0);
|
||||
}
|
||||
sd->numframes = NUMFACES;
|
||||
sd->spriteframes = static_cast<spriteframe_t*>(Z_Realloc(sd->spriteframes, sizeof(spriteframe_t)*NUMFACES, PU_STATIC, NULL));
|
||||
M_Memcpy(sd->spriteframes, sprtemp, sizeof(spriteframe_t)*NUMFACES);
|
||||
}
|
||||
#undef NUMFACES
|
||||
|
||||
// Install a single sprite, given its identifying name (4 chars)
|
||||
//
|
||||
// (originally part of R_AddSpriteDefs)
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ extern "C" {
|
|||
|
||||
#define FEETADJUST (4<<FRACBITS) // R_AddSingleSpriteDef
|
||||
|
||||
void R_AddKartFaces(skin_t *skin);
|
||||
boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump);
|
||||
|
||||
//faB: find sprites in wadfile, replace existing, add new ones
|
||||
|
|
|
|||
34
src/w_wad.c
34
src/w_wad.c
|
|
@ -298,10 +298,40 @@ static inline boolean CheckCompatFilename(char *filename)
|
|||
return toupper(basename ? basename[1] : filename[0]) == 'K';
|
||||
}
|
||||
|
||||
static inline boolean CheckCompatSkins(UINT16 wadnum)
|
||||
{
|
||||
#if 0
|
||||
UINT16 skin = W_CheckNumForNamePwad("S_SKIN", wadnum, 0);
|
||||
if (skin == INT16_MAX)
|
||||
return false;
|
||||
|
||||
// valid kart skins can only have one sprname for all frames
|
||||
const char *firstsprname = W_CheckNameForNumPwad(wadnum, ++skin);
|
||||
int maxframe = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
const char *sprname = W_CheckNameForNumPwad(wadnum, ++skin);
|
||||
if (!sprname)
|
||||
break;
|
||||
if (memcmp(sprname, firstsprname, 4))
|
||||
break;
|
||||
maxframe = max(maxframe, sprname[4]);
|
||||
}
|
||||
|
||||
// how many frames does this first sprite name have?
|
||||
// if there's at least 19 frames, this is a valid kart skin,
|
||||
// so we need compatmode to load skins from this file!
|
||||
return (maxframe - 'A') >= 18;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// try to figure out if a PK3 file needs compatmode enabled (palette remap)
|
||||
static inline boolean CheckCompatZip(UINT16 wadnum)
|
||||
{
|
||||
if (CheckCompatFilename(wadfiles[wadnum]->filename))
|
||||
if (CheckCompatFilename(wadfiles[wadnum]->filename) || CheckCompatSkins(wadnum))
|
||||
return true;
|
||||
|
||||
// assume RR/2.2 for PK3s so basegame assets work
|
||||
|
|
@ -311,7 +341,7 @@ static inline boolean CheckCompatZip(UINT16 wadnum)
|
|||
// ditto, but for WADs
|
||||
static inline boolean CheckCompatWad(UINT16 wadnum)
|
||||
{
|
||||
if (CheckCompatFilename(wadfiles[wadnum]->filename))
|
||||
if (CheckCompatFilename(wadfiles[wadnum]->filename) || CheckCompatSkins(wadnum))
|
||||
return true;
|
||||
|
||||
// assume Kart/2.1 for WADs so basegame assets work
|
||||
|
|
|
|||
Loading…
Reference in a new issue