Merge branch 'master' into duel

This commit is contained in:
Sally Coolatta 2024-09-08 08:46:16 -04:00
commit ef627afcf3
9 changed files with 180 additions and 104 deletions

View file

@ -176,6 +176,7 @@ char srb2home[256] = ".";
char srb2path[256] = ".";
boolean usehome = true;
const char *pandf = "%s" PATHSEP "%s";
const char *spandf = "%s" PATHSEP "%s" PATHSEP "%s"; // subdirs wooo
char addonsdir[MAX_WADPATH];
char downloaddir[sizeof addonsdir + sizeof DOWNLOADDIR_PART] = "DOWNLOAD";
@ -1388,24 +1389,24 @@ static void IdentifyVersion(void)
// if you change the ordering of this or add/remove a file, be sure to update the md5
// checking in D_SRB2Main
D_AddFile(startupiwads, va(pandf,srb2waddir,"scripts.pk3"));
D_AddFile(startupiwads, va(pandf,srb2waddir,"gfx.pk3"));
D_AddFile(startupiwads, va(pandf,srb2waddir,"textures_general.pk3"));
D_AddFile(startupiwads, va(pandf,srb2waddir,"textures_segazones.pk3"));
D_AddFile(startupiwads, va(pandf,srb2waddir,"textures_originalzones.pk3"));
D_AddFile(startupiwads, va(pandf,srb2waddir,"chars.pk3"));
D_AddFile(startupiwads, va(pandf,srb2waddir,"followers.pk3"));
D_AddFile(startupiwads, va(pandf,srb2waddir,"maps.pk3"));
D_AddFile(startupiwads, va(pandf,srb2waddir,"unlocks.pk3"));
D_AddFile(startupiwads, va(pandf,srb2waddir,"staffghosts.pk3"));
D_AddFile(startupiwads, va(pandf,srb2waddir,"shaders.pk3"));
D_AddFile(startupiwads, va(spandf,srb2waddir,"data","scripts.pk3"));
D_AddFile(startupiwads, va(spandf,srb2waddir,"data","gfx.pk3"));
D_AddFile(startupiwads, va(spandf,srb2waddir,"data","textures_general.pk3"));
D_AddFile(startupiwads, va(spandf,srb2waddir,"data","textures_segazones.pk3"));
D_AddFile(startupiwads, va(spandf,srb2waddir,"data","textures_originalzones.pk3"));
D_AddFile(startupiwads, va(spandf,srb2waddir,"data","chars.pk3"));
D_AddFile(startupiwads, va(spandf,srb2waddir,"data","followers.pk3"));
D_AddFile(startupiwads, va(spandf,srb2waddir,"data","maps.pk3"));
D_AddFile(startupiwads, va(spandf,srb2waddir,"data","unlocks.pk3"));
D_AddFile(startupiwads, va(spandf,srb2waddir,"data","staffghosts.pk3"));
D_AddFile(startupiwads, va(spandf,srb2waddir,"data","shaders.pk3"));
#ifdef USE_PATCH_FILE
D_AddFile(startupiwads, va(pandf,srb2waddir,"patch.pk3"));
#endif
#define MUSICTEST(str) \
{\
const char *musicpath = va(pandf,srb2waddir,str);\
const char *musicpath = va(spandf,srb2waddir,"data",str);\
int ms = W_VerifyNMUSlumps(musicpath, false); \
if (ms == 1) \
{ \

View file

@ -1049,6 +1049,7 @@ struct player_t
UINT16 overshield;
fixed_t overdrivepower;
UINT8 overdriveready;
boolean overdrivelenient;
UINT8 itemflags; // holds IF_ flags (see itemflags_t)

View file

@ -172,7 +172,7 @@ demoghost *ghosts = NULL;
// - 0x000C (Ring Racers v2.2)
// - 0x000D (Ring Racers v2.3)
#define DEMOVERSION 0x000D
#define DEMOVERSION 0x000E
boolean G_CompatLevel(UINT16 level)
{

View file

@ -115,76 +115,73 @@ void srb2::save_ng_gamedata()
}
}
ng.timesBeaten = gamedata->timesBeaten;
for (int i = 0; i < numskins; i++)
auto skintojson = [](skinrecord_t *records)
{
srb2::GamedataSkinJson skin {};
skin.records.wins = records->wins;
skin.records.rounds = records->rounds;
skin.records.time.total = records->timeplayed;
skin.records.time.race = records->modetimeplayed[GDGT_RACE];
skin.records.time.battle = records->modetimeplayed[GDGT_BATTLE];
skin.records.time.prisons = records->modetimeplayed[GDGT_PRISONS];
skin.records.time.special = records->modetimeplayed[GDGT_SPECIAL];
skin.records.time.custom = records->modetimeplayed[GDGT_CUSTOM];
skin.records.time.tumble = records->tumbletime;
return skin;
};
for (int i = 0; i < numskins; i++)
{
skin_t& memskin = skins[i];
auto skin = skintojson(&memskin.records);
std::string name = std::string(memskin.name);
skin.records.wins = memskin.records.wins;
skin.records.rounds = memskin.records.rounds;
skin.records.time.total = memskin.records.timeplayed;
skin.records.time.race = memskin.records.modetimeplayed[GDGT_RACE];
skin.records.time.battle = memskin.records.modetimeplayed[GDGT_BATTLE];
skin.records.time.prisons = memskin.records.modetimeplayed[GDGT_PRISONS];
skin.records.time.special = memskin.records.modetimeplayed[GDGT_SPECIAL];
skin.records.time.custom = memskin.records.modetimeplayed[GDGT_CUSTOM];
skin.records.time.tumble = memskin.records.tumbletime;
ng.skins[name] = std::move(skin);
}
for (auto unloadedskin = unloadedskins; unloadedskin; unloadedskin = unloadedskin->next)
{
srb2::GamedataSkinJson skin {};
auto skin = skintojson(&unloadedskin->records);
std::string name = std::string(unloadedskin->name);
skin.records.wins = unloadedskin->records.wins;
ng.skins[name] = std::move(skin);
}
for (int i = 0; i < nummapheaders; i++)
auto maptojson = [](recorddata_t *records)
{
srb2::GamedataMapJson map {};
map.visited.visited = records->mapvisited & MV_VISITED;
map.visited.beaten = records->mapvisited & MV_BEATEN;
map.visited.encore = records->mapvisited & MV_ENCORE;
map.visited.spbattack = records->mapvisited & MV_SPBATTACK;
map.visited.mysticmelody = records->mapvisited & MV_MYSTICMELODY;
map.stats.timeattack.besttime = records->timeattack.time;
map.stats.timeattack.bestlap = records->timeattack.lap;
map.stats.spbattack.besttime = records->spbattack.time;
map.stats.spbattack.bestlap = records->spbattack.lap;
map.stats.time.total = records->timeplayed;
map.stats.time.netgame = records->netgametimeplayed;
map.stats.time.race = records->modetimeplayed[GDGT_RACE];
map.stats.time.battle = records->modetimeplayed[GDGT_BATTLE];
map.stats.time.prisons = records->modetimeplayed[GDGT_PRISONS];
map.stats.time.special = records->modetimeplayed[GDGT_SPECIAL];
map.stats.time.custom = records->modetimeplayed[GDGT_CUSTOM];
map.stats.time.timeattack = records->timeattacktimeplayed;
map.stats.time.spbattack = records->spbattacktimeplayed;
return map;
};
for (int i = 0; i < nummapheaders; i++)
{
auto map = maptojson(&mapheaderinfo[i]->records);
std::string lumpname = std::string(mapheaderinfo[i]->lumpname);
map.visited.visited = mapheaderinfo[i]->records.mapvisited & MV_VISITED;
map.visited.beaten = mapheaderinfo[i]->records.mapvisited & MV_BEATEN;
map.visited.encore = mapheaderinfo[i]->records.mapvisited & MV_ENCORE;
map.visited.spbattack = mapheaderinfo[i]->records.mapvisited & MV_SPBATTACK;
map.visited.mysticmelody = mapheaderinfo[i]->records.mapvisited & MV_MYSTICMELODY;
map.stats.timeattack.besttime = mapheaderinfo[i]->records.timeattack.time;
map.stats.timeattack.bestlap = mapheaderinfo[i]->records.timeattack.lap;
map.stats.spbattack.besttime = mapheaderinfo[i]->records.spbattack.time;
map.stats.spbattack.bestlap = mapheaderinfo[i]->records.spbattack.lap;
map.stats.time.total = mapheaderinfo[i]->records.timeplayed;
map.stats.time.netgame = mapheaderinfo[i]->records.netgametimeplayed;
map.stats.time.race = mapheaderinfo[i]->records.modetimeplayed[GDGT_RACE];
map.stats.time.battle = mapheaderinfo[i]->records.modetimeplayed[GDGT_BATTLE];
map.stats.time.prisons = mapheaderinfo[i]->records.modetimeplayed[GDGT_PRISONS];
map.stats.time.special = mapheaderinfo[i]->records.modetimeplayed[GDGT_SPECIAL];
map.stats.time.custom = mapheaderinfo[i]->records.modetimeplayed[GDGT_CUSTOM];
map.stats.time.timeattack = mapheaderinfo[i]->records.timeattacktimeplayed;
map.stats.time.spbattack = mapheaderinfo[i]->records.spbattacktimeplayed;
ng.maps[lumpname] = std::move(map);
}
for (auto unloadedmap = unloadedmapheaders; unloadedmap; unloadedmap = unloadedmap->next)
{
srb2::GamedataMapJson map {};
auto map = maptojson(&unloadedmap->records);
std::string lumpname = std::string(unloadedmap->lumpname);
map.visited.visited = unloadedmap->records.mapvisited & MV_VISITED;
map.visited.beaten = unloadedmap->records.mapvisited & MV_BEATEN;
map.visited.encore = unloadedmap->records.mapvisited & MV_ENCORE;
map.visited.spbattack = unloadedmap->records.mapvisited & MV_SPBATTACK;
map.visited.mysticmelody = unloadedmap->records.mapvisited & MV_MYSTICMELODY;
map.stats.timeattack.besttime = unloadedmap->records.timeattack.time;
map.stats.timeattack.bestlap = unloadedmap->records.timeattack.lap;
map.stats.spbattack.besttime = unloadedmap->records.spbattack.time;
map.stats.spbattack.bestlap = unloadedmap->records.spbattack.lap;
map.stats.time.total = unloadedmap->records.timeplayed;
map.stats.time.netgame = unloadedmap->records.netgametimeplayed;
map.stats.time.race = unloadedmap->records.modetimeplayed[GDGT_RACE];
map.stats.time.battle = unloadedmap->records.modetimeplayed[GDGT_BATTLE];
map.stats.time.prisons = unloadedmap->records.modetimeplayed[GDGT_PRISONS];
map.stats.time.special = unloadedmap->records.modetimeplayed[GDGT_SPECIAL];
map.stats.time.custom = unloadedmap->records.modetimeplayed[GDGT_CUSTOM];
map.stats.time.timeattack = unloadedmap->records.timeattacktimeplayed;
map.stats.time.spbattack = unloadedmap->records.spbattacktimeplayed;
ng.maps[lumpname] = std::move(map);
}
for (int i = 0; i < gamedata->numspraycans; i++)
@ -219,20 +216,18 @@ void srb2::save_ng_gamedata()
spraycan.map = std::string(mapheader->lumpname);
ng.spraycans.emplace_back(std::move(spraycan));
}
for (auto cup = kartcupheaders; cup; cup = cup->next)
auto cuptojson = [](cupwindata_t *windata)
{
if (cup->windata[0].best_placement == 0 && cup->windata[1].got_emerald == false)
{
continue;
}
srb2::GamedataCupJson cupdata {};
cupdata.name = std::string(cup->name);
for (size_t i = 0; i < KARTGP_MAX; i++)
{
srb2::GamedataCupRecordsJson newrecords {};
newrecords.bestgrade = cup->windata[i].best_grade;
newrecords.bestplacement = cup->windata[i].best_placement;
skinreference_t& skinref = cup->windata[i].best_skin;
newrecords.bestgrade = windata[i].best_grade;
newrecords.bestplacement = windata[i].best_placement;
skinreference_t& skinref = windata[i].best_skin;
if (skinref.unloaded)
{
newrecords.bestskin = std::string(skinref.unloaded->name);
@ -241,9 +236,23 @@ void srb2::save_ng_gamedata()
{
newrecords.bestskin = std::string(skins[skinref.id].name);
}
newrecords.gotemerald = cup->windata[i].got_emerald;
newrecords.gotemerald = windata[i].got_emerald;
cupdata.records.emplace_back(std::move(newrecords));
}
return cupdata;
};
for (auto cup = kartcupheaders; cup; cup = cup->next)
{
if (cup->windata[0].best_placement == 0 && cup->windata[1].got_emerald == false)
{
continue;
}
auto cupdata = cuptojson(cup->windata);
cupdata.name = std::string(cup->name);
ng.cups[cupdata.name] = std::move(cupdata);
}
for (auto unloadedcup = unloadedcupheaders; unloadedcup; unloadedcup = unloadedcup->next)
@ -252,25 +261,9 @@ void srb2::save_ng_gamedata()
{
continue;
}
srb2::GamedataCupJson cupdata {};
auto cupdata = cuptojson(unloadedcup->windata);
cupdata.name = std::string(unloadedcup->name);
for (int i = 0; i < KARTGP_MAX; i++)
{
srb2::GamedataCupRecordsJson newrecords {};
newrecords.bestgrade = unloadedcup->windata[i].best_grade;
newrecords.bestplacement = unloadedcup->windata[i].best_placement;
skinreference_t& skinref = unloadedcup->windata[i].best_skin;
if (skinref.unloaded)
{
newrecords.bestskin = std::string(skinref.unloaded->name);
}
else
{
newrecords.bestskin = std::string(skins[skinref.id].name);
}
newrecords.gotemerald = unloadedcup->windata[i].got_emerald;
cupdata.records.emplace_back(std::move(newrecords));
}
ng.cups[cupdata.name] = std::move(cupdata);
}

View file

@ -4130,7 +4130,7 @@ void K_AwardPlayerAmps(player_t *player, UINT8 amps)
{
// Auto Overdrive!
// If this is a fresh OD, give 'em some extra juice to make up for lack of flexibility.
if (!player->overdrive && player->mo && !P_MobjWasRemoved(player->mo))
if (!player->overdrive && player->mo && !P_MobjWasRemoved(player->mo) && player->overdriveready == 0)
{
S_StartSound(player->mo, sfx_gshac);
player->amps *= 2;
@ -4263,6 +4263,7 @@ boolean K_Overdrive(player_t *player)
player->amps = 0;
player->overdriveready = 0;
player->overdrivelenient = false;
return true;
}
@ -4284,6 +4285,8 @@ boolean K_DefensiveOverdrive(player_t *player)
player->overdrivepower = FRACUNIT;
player->amps = 0;
player->overdrivelenient = true;
player->overdriveready = false;
return true;
}
@ -9405,15 +9408,25 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
}
}
if (player->overdrive > 0 && onground == true)
if (player->overdrivelenient)
{
player->overdrive--;
// This is a Defensive Overdrive and shouldn't start deducting time until we recover
if (!P_PlayerInPain(player))
player->overdrivelenient = false;
}
else
{
if (player->overdrive > 0 && onground == true)
{
player->overdrive--;
}
if (player->overshield > 0 && onground == true)
{
player->overshield--;
}
}
if (player->overshield > 0 && onground == true)
{
player->overshield--;
}
if (player->wavedashboost == 0 || player->wavedashpower > FRACUNIT)
{

View file

@ -376,6 +376,8 @@ static int player_get(lua_State *L)
lua_pushinteger(L, plr->overdrivepower);
else if (fastcmp(field,"overdriveready"))
lua_pushinteger(L, plr->overdriveready);
else if (fastcmp(field,"overdrivelenient"))
lua_pushinteger(L, plr->overdrivelenient);
else if (fastcmp(field,"speedpunt"))
lua_pushinteger(L, plr->speedpunt);
else if (fastcmp(field,"trickcharge"))
@ -962,6 +964,8 @@ static int player_set(lua_State *L)
plr->overdrivepower = luaL_checkinteger(L, 3);
else if (fastcmp(field,"overdriveready"))
plr->overdriveready = luaL_checkinteger(L, 3);
else if (fastcmp(field,"overdrivelenient"))
plr->overdrivelenient = luaL_checkinteger(L, 3);
else if (fastcmp(field,"speedpunt"))
plr->speedpunt = luaL_checkinteger(L, 3);
else if (fastcmp(field,"trickcharge"))

View file

@ -45,6 +45,8 @@
#define UFO_NUMARMS (3)
#define UFO_ARMDELTA (ANGLE_MAX / UFO_NUMARMS)
#define UFO_START_GLASSFRAMES (1)
#define UFO_NUM_GLASSFRAMES (10)
#define ufo_emeraldnum(o) ((o)->cvmem)
#define ufo_waypoint(o) ((o)->extravalue1)
@ -56,6 +58,8 @@
#define ufo_piece_type(o) ((o)->extravalue1)
#define ufo_piece_glass_flickerframe(o) ((o)->cusval)
#define ufo_piece_owner(o) ((o)->target)
#define ufo_piece_next(o) ((o)->hnext)
#define ufo_piece_prev(o) ((o)->hprev)
@ -676,6 +680,40 @@ spawn_shard
}
}
static void
set_flickerframe (mobj_t *ufo, mobj_t *piece)
{
INT32 healthcalc = (UFO_NUM_GLASSFRAMES - 1);
if (ufo && !P_MobjWasRemoved(ufo))
{
INT32 maxhealth = mobjinfo[MT_SPECIAL_UFO].spawnhealth;
healthcalc = (maxhealth - ufo->health);
if (healthcalc > 0)
{
maxhealth /= UFO_NUM_GLASSFRAMES;
if (maxhealth <= 0)
maxhealth = 1;
healthcalc /= maxhealth;
if (healthcalc >= UFO_NUM_GLASSFRAMES)
healthcalc = (UFO_NUM_GLASSFRAMES - 1);
if (healthcalc < 0)
healthcalc = 0;
}
else
{
healthcalc = 0;
}
}
healthcalc = (healthcalc|FF_FULLBRIGHT) + UFO_START_GLASSFRAMES;
ufo_piece_glass_flickerframe(piece) = healthcalc;
piece->frame = healthcalc;
}
static void
spawn_debris (mobj_t *part)
{
@ -704,6 +742,7 @@ static void UFOCopyHitlagToPieces(mobj_t *ufo)
if (ufo_piece_type(piece) == UFO_PIECE_TYPE_GLASS)
{
set_flickerframe (ufo, piece);
spawn_debris (piece);
}
@ -728,6 +767,11 @@ static void UFOKillPiece(mobj_t *piece)
switch (ufo_piece_type(piece))
{
case UFO_PIECE_TYPE_GLASS:
{
set_flickerframe(NULL, piece);
piece->tics = 1;
return;
}
case UFO_PIECE_TYPE_GLASS_UNDER:
case UFO_PIECE_TYPE_STEM:
{
@ -1115,6 +1159,21 @@ void Obj_UFOPieceThink(mobj_t *piece)
break;
}
case UFO_PIECE_TYPE_GLASS:
{
// Flicker glass cracks for visibility
if (piece->frame == FF_SEMIBRIGHT)
{
piece->frame = ufo_piece_glass_flickerframe(piece);
}
else
{
piece->frame = FF_SEMIBRIGHT;
}
piece->destscale = 5 * ufo->destscale / 3;
UFOMoveTo(piece, ufo->x, ufo->y, ufo->z);
break;
}
case UFO_PIECE_TYPE_GLASS_UNDER:
{
piece->destscale = 5 * ufo->destscale / 3;
@ -1222,6 +1281,12 @@ static mobj_t *InitSpecialUFO(waypoint_t *start)
specialstageinfo.maxDist = ufo_distancetofinish(ufo);
}
// Set specialDamage as early as possible, for glass ball's sake
if (grandprixinfo.gp && grandprixinfo.specialDamage)
{
ufo->health -= min(4*(UINT32)mobjinfo[MT_SPECIAL_UFO].spawnhealth/10, grandprixinfo.specialDamage/6);
}
ufo_speed(ufo) = FixedMul(UFO_START_SPEED, K_GetKartGameSpeedScalar(gamespeed));
// Adjustable Special Stage emerald color/shape
@ -1295,6 +1360,8 @@ static mobj_t *InitSpecialUFO(waypoint_t *start)
P_SetMobjState(piece, S_SPECIAL_UFO_GLASS);
ufo_piece_type(piece) = UFO_PIECE_TYPE_GLASS;
set_flickerframe(ufo, piece);
/*overlay = P_SpawnMobjFromMobj(piece, 0, 0, 0, MT_OVERLAY);
P_SetTarget(&overlay->target, piece);
P_SetMobjState(overlay, S_SPECIAL_UFO_GLASS_UNDER);
@ -1347,11 +1414,6 @@ static mobj_t *InitSpecialUFO(waypoint_t *start)
P_SetTarget(&ufo_piece_prev(piece), prevPiece);
prevPiece = piece;
if (grandprixinfo.gp && grandprixinfo.specialDamage)
{
ufo->health -= min(4*(UINT32)mobjinfo[MT_SPECIAL_UFO].spawnhealth/10, grandprixinfo.specialDamage/6);
}
return ufo;
}

View file

@ -451,7 +451,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (special->fuse) // This box is respawning, but was broken very recently (see P_FuseThink)
{
// What was this box broken as?
if (special->cvmem)
if (special->cvmem && !(special->flags2 & MF2_BOSSDEAD))
K_StartItemRoulette(player, false);
else
K_StartItemRoulette(player, true);

View file

@ -602,6 +602,7 @@ static void P_NetArchivePlayers(savebuffer_t *save)
WRITEFIXED(save->p, players[i].wavedashpower);
WRITEFIXED(save->p, players[i].overdrivepower);
WRITEUINT8(save->p, players[i].overdriveready);
WRITEUINT8(save->p, players[i].overdrivelenient);
WRITEUINT16(save->p, players[i].speedpunt);
WRITEUINT16(save->p, players[i].trickcharge);
@ -1226,6 +1227,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
players[i].wavedashpower = READFIXED(save->p);
players[i].overdrivepower = READFIXED(save->p);
players[i].overdriveready = READUINT8(save->p);
players[i].overdrivelenient = READUINT8(save->p);
players[i].speedpunt = READUINT16(save->p);
players[i].trickcharge = READUINT16(save->p);