mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-12-31 20:22:40 +00:00
Merge public master
This commit is contained in:
commit
131ce41657
15 changed files with 1523 additions and 66 deletions
|
|
@ -130,6 +130,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32
|
|||
lua_itemroulettelib.c
|
||||
lua_respawnvarslib.c
|
||||
lua_waypointslib.c
|
||||
lua_grandprixlib.c
|
||||
lua_profile.cpp
|
||||
k_kart.c
|
||||
k_respawn.c
|
||||
|
|
|
|||
|
|
@ -3015,9 +3015,19 @@ static void Got_Mapcmd(const UINT8 **cp, INT32 playernum)
|
|||
CON_LogMessage(M_GetText("Speeding off to level...\n"));
|
||||
}
|
||||
|
||||
|
||||
if (demo.playback && !demo.timing)
|
||||
precache = false;
|
||||
|
||||
|
||||
// Save demo in case map change happened after level finish
|
||||
// (either manually with the map command, or with a redo vote)
|
||||
// Isn't needed for time attack (and would also cause issues, as there
|
||||
// G_RecordDemo (which sets demo.recording to true) is called before this runs)
|
||||
if (demo.recording && modeattacking == ATTACKING_NONE)
|
||||
G_CheckDemoStatus();
|
||||
|
||||
|
||||
demo.willsave = (cv_recordmultiplayerdemos.value == 2);
|
||||
demo.savebutton = 0;
|
||||
|
||||
|
|
@ -5719,6 +5729,11 @@ static void Got_SetupVotecmd(const UINT8 **cp, INT32 playernum)
|
|||
|
||||
memcpy(g_voteLevels, tempVoteLevels, sizeof(g_voteLevels));
|
||||
|
||||
// admin can force vote state whenever
|
||||
// so we have to save this replay if it needs to be saved
|
||||
if (demo.recording)
|
||||
G_CheckDemoStatus();
|
||||
|
||||
G_SetGamestate(GS_VOTING);
|
||||
Y_StartVote();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4212,6 +4212,7 @@ boolean G_CheckDemoStatus(void)
|
|||
|
||||
if (modeattacking || demo.willsave)
|
||||
{
|
||||
demo.willsave = false;
|
||||
if (demobuf.p)
|
||||
{
|
||||
G_SaveDemo();
|
||||
|
|
|
|||
|
|
@ -5083,7 +5083,10 @@ void G_AfterIntermission(void)
|
|||
return;
|
||||
}
|
||||
else if (demo.recording && (modeattacking || demo.willsave))
|
||||
{
|
||||
demo.willsave = false;
|
||||
G_SaveDemo();
|
||||
}
|
||||
else if (demo.recording)
|
||||
G_ResetDemoRecording();
|
||||
|
||||
|
|
|
|||
|
|
@ -81,6 +81,8 @@ extern struct menuqueue
|
|||
UINT8 size;
|
||||
UINT8 sending;
|
||||
UINT8 anchor;
|
||||
boolean clearing;
|
||||
boolean cupqueue;
|
||||
roundentry_t entries[ROUNDQUEUE_MAX];
|
||||
} menuqueue;
|
||||
|
||||
|
|
|
|||
|
|
@ -961,6 +961,10 @@ void M_MenuToLevelPreamble(UINT8 ssplayers, boolean nowipe);
|
|||
void M_LevelSelected(INT16 add, boolean menuupdate);
|
||||
boolean M_LevelSelectCupSwitch(boolean next, boolean skipones);
|
||||
|
||||
void M_LevelConfirmHandler(void);
|
||||
void M_ClearQueueHandler(void);
|
||||
void M_CupQueueHandler(cupheader_t *cup);
|
||||
|
||||
// dummy consvars for GP & match race setup
|
||||
extern consvar_t cv_dummygpdifficulty;
|
||||
extern consvar_t cv_dummykartspeed;
|
||||
|
|
|
|||
|
|
@ -3340,6 +3340,21 @@ void M_DrawCupSelect(void)
|
|||
M_DrawCupPreview(y, &templevelsearch);
|
||||
|
||||
M_DrawCupTitle(120 - ty, &templevelsearch);
|
||||
|
||||
const char *worktext = "Undo";
|
||||
|
||||
if (menuqueue.size)
|
||||
worktext = "Undo";
|
||||
else if (roundqueue.size)
|
||||
worktext = "Clear Queue";
|
||||
|
||||
if (levellist.canqueue)
|
||||
{
|
||||
K_DrawGameControl(BASEVIDWIDTH/2, 6-ty, 0, va("%s Queue Cup<white> %s %s",
|
||||
(templevelsearch.cup && templevelsearch.cup != &dummy_lostandfound && !roundqueue.size) ? "<z_animated>" : "<z_pressed><gray>",
|
||||
(roundqueue.size || menuqueue.size) ? "<c_animated>" : "<c_pressed><gray>",
|
||||
worktext), 1, TINY_FONT, 0);
|
||||
}
|
||||
|
||||
if (templevelsearch.grandprix == false && templevelsearch.cup != NULL)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
#include "k_hitlag.h"
|
||||
#include "music.h" // music functions necessary for lua integration
|
||||
#include "k_terrain.h"
|
||||
#include "k_grandprix.h"
|
||||
|
||||
#include "lua_script.h"
|
||||
#include "lua_libs.h"
|
||||
|
|
@ -256,6 +257,12 @@ static const struct {
|
|||
{META_POWERUPVARS, "powerupvars_t"},
|
||||
{META_ICECUBEVARS, "icecubevars_t"},
|
||||
{META_SKYBOX, "skybox_t"},
|
||||
|
||||
{META_CUP, "cupheader_t"},
|
||||
{META_GPRANK, "gprank_t"},
|
||||
{META_GPRANKLEVEL, "gprank_level_t"},
|
||||
{META_GPRANKLEVELPERPLAYER, "gprank_level_perplayer_t"},
|
||||
{META_ROUNDENTRY, "roundentry_t"},
|
||||
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
|
@ -3997,6 +4004,84 @@ static int lib_kMomentumAngle(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int lib_kPvPAmpReward(lua_State *L)
|
||||
{
|
||||
UINT32 award = luaL_checkinteger(L, 1);
|
||||
player_t *attacker = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
|
||||
player_t *defender = *((player_t **)luaL_checkudata(L, 3, META_PLAYER));
|
||||
NOHUD
|
||||
INLEVEL
|
||||
if (!attacker || !defender)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
lua_pushinteger(L, K_PvPAmpReward(award, attacker, defender));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_kSpawnAmps(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
UINT8 amps = luaL_checkinteger(L, 2);
|
||||
mobj_t *impact = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
|
||||
NOHUD
|
||||
INLEVEL
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
if (!impact)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
K_SpawnAmps(player, amps, impact);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_kSpawnEXP(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
UINT8 exp = luaL_checkinteger(L, 2);
|
||||
mobj_t *impact = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
|
||||
NOHUD
|
||||
INLEVEL
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
if (!impact)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
K_SpawnEXP(player, exp, impact);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_kAwardPlayerAmps(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
UINT8 amps = luaL_checkinteger(L, 2);
|
||||
NOHUD
|
||||
INLEVEL
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
K_AwardPlayerAmps(player, amps);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_kOverdrive(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
NOHUD
|
||||
INLEVEL
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
lua_pushboolean(L, K_Overdrive(player));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_kDefensiveOverdrive(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
NOHUD
|
||||
INLEVEL
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
lua_pushboolean(L, K_DefensiveOverdrive(player));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int lib_kDoInstashield(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
|
|
@ -5276,6 +5361,48 @@ static int lib_kPlayerCanUseItem(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int lib_kGetGradingFactorAdjustment(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
UINT32 gradingpoint = luaL_checkinteger(L, 2);
|
||||
INLEVEL
|
||||
NOHUD
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
lua_pushfixed(L, K_GetGradingFactorAdjustment(player, gradingpoint));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_kGetGradingFactorMinMax(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
boolean max = luaL_checkboolean(L, 2);
|
||||
INLEVEL
|
||||
NOHUD
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
lua_pushfixed(L, K_GetGradingFactorMinMax(player, max));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_kGetEXP(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
INLEVEL
|
||||
NOHUD
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
lua_pushinteger(L, K_GetEXP(player));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_kGetNumGradingPoints(lua_State *L)
|
||||
{
|
||||
INLEVEL
|
||||
lua_pushinteger(L, K_GetNumGradingPoints());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_kEggmanTransfer(lua_State *L)
|
||||
{
|
||||
player_t *source = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
|
|
@ -5300,6 +5427,31 @@ static int lib_kSetTireGrease(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lib_kApplyStun(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
mobj_t *inflictor = NULL;
|
||||
mobj_t *source = NULL;
|
||||
INT32 damage = luaL_optinteger(L, 4, 0);
|
||||
UINT8 damagetype = luaL_optinteger(L, 5, 0);
|
||||
INLEVEL
|
||||
NOHUD
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
if (!lua_isnil(L, 2) && lua_isuserdata(L, 2)) {
|
||||
inflictor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
|
||||
if (!inflictor)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
}
|
||||
if (!lua_isnil(L, 3) && lua_isuserdata(L, 3)) {
|
||||
source = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
|
||||
if (!source)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
}
|
||||
K_ApplyStun(player, inflictor, source, damage, damagetype);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_kGetCollideAngle(lua_State *L)
|
||||
{
|
||||
mobj_t *t1 = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||
|
|
@ -6792,7 +6944,13 @@ static luaL_Reg lib[] = {
|
|||
{"K_MomentumAngleEx",lib_kMomentumAngleEx},
|
||||
{"K_MomentumAngleReal",lib_kMomentumAngleReal},
|
||||
{"K_MomentumAngle",lib_kMomentumAngle},
|
||||
{"K_PvPAmpReward",lib_kPvPAmpReward},
|
||||
{"K_SpawnAmps",lib_kSpawnAmps},
|
||||
{"K_SpawnEXP",lib_kSpawnEXP},
|
||||
{"K_AwardPlayerAmps",lib_kAwardPlayerAmps},
|
||||
{"K_AwardPlayerRings",lib_kAwardPlayerRings},
|
||||
{"K_Overdrive",lib_kOverdrive},
|
||||
{"K_DefensiveOverdrive",lib_kDefensiveOverdrive},
|
||||
{"K_DoInstashield",lib_kDoInstashield},
|
||||
{"K_DoPowerClash",lib_kDoPowerClash},
|
||||
{"K_DoGuardBreak",lib_kDoGuardBreak},
|
||||
|
|
@ -6901,10 +7059,15 @@ static luaL_Reg lib[] = {
|
|||
{"K_BumperInflate",lib_kBumperInflate},
|
||||
{"K_ThunderDome",lib_kThunderDome},
|
||||
{"K_PlayerCanUseItem",lib_kPlayerCanUseItem},
|
||||
{"K_GetGradingFactorAdjustment",lib_kGetGradingFactorAdjustment},
|
||||
{"K_GetGradingFactorMinMax",lib_kGetGradingFactorMinMax},
|
||||
{"K_GetEXP",lib_kGetEXP},
|
||||
{"K_GetNumGradingPoints",lib_kGetNumGradingPoints},
|
||||
{"K_PlayerGuard",lib_kPlayerGuard},
|
||||
{"K_FastFallBounce",lib_kFastFallBounce},
|
||||
{"K_EggmanTransfer",lib_kEggmanTransfer},
|
||||
{"K_SetTireGrease",lib_kSetTireGrease},
|
||||
{"K_ApplyStun",lib_kApplyStun},
|
||||
|
||||
{"K_GetCollideAngle",lib_kGetCollideAngle},
|
||||
|
||||
|
|
|
|||
969
src/lua_grandprixlib.c
Normal file
969
src/lua_grandprixlib.c
Normal file
|
|
@ -0,0 +1,969 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2025 by Freaky Mutant Man.
|
||||
// Copyright (C) 2025 by Kart Krew.
|
||||
// Copyright (C) 2020 by Sonic Team Junior.
|
||||
// Copyright (C) 2016 by John "JTE" Muniz.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file lua_grandprixlib.c
|
||||
/// \brief Grand Prix, cup and rank info for Lua scripting.
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "fastcmp.h"
|
||||
#include "doomstat.h"
|
||||
#include "k_grandprix.h"
|
||||
#include "k_rank.h"
|
||||
#include "g_game.h"
|
||||
|
||||
#include "lua_script.h"
|
||||
#include "lua_libs.h"
|
||||
|
||||
#define UNIMPLEMENTED luaL_error(L, LUA_QL("cupheader_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", cup_opt[field])
|
||||
#define RNOFIELDGP luaL_error(L, LUA_QL("grandprixinfo") " has no field named " LUA_QS, field)
|
||||
#define RNOFIELDCH luaL_error(L, LUA_QL("cupheader_t") " has no field named " LUA_QS, field)
|
||||
#define RNOFIELDGR luaL_error(L, LUA_QL("gprank_t") " has no field named " LUA_QS, field)
|
||||
#define RNOFIELDGRL luaL_error(L, LUA_QL("gprank_level_t") " has no field named " LUA_QS, field)
|
||||
#define RNOFIELDGRLP luaL_error(L, LUA_QL("gprank_level_perplayer_t") " has no field named " LUA_QS, field)
|
||||
#define RNOFIELDRQ luaL_error(L, LUA_QL("roundqueue") " has no field named " LUA_QS, field)
|
||||
#define RNOFIELDRE luaL_error(L, LUA_QL("roundentry_t") " has no field named " LUA_QS, field)
|
||||
#define GPERR luaL_error(L, LUA_QL("grandprixinfo") " field " LUA_QS " cannot be accessed while grandprixinfo.gp is false.", grandprix_opt[field])
|
||||
#define ROUNDCUEERR luaL_error(L, LUA_QL("roundqueue") " field " LUA_QS " cannot be accessed while roundqueue.size is 0.", grandprix_opt[field])
|
||||
|
||||
enum grandprix {
|
||||
grandprix_gp = 0,
|
||||
grandprix_cup,
|
||||
grandprix_gamespeed,
|
||||
grandprix_encore,
|
||||
grandprix_masterbots,
|
||||
grandprix_initialize,
|
||||
grandprix_initalize,
|
||||
grandprix_wonround,
|
||||
grandprix_eventmode,
|
||||
grandprix_specialdamage,
|
||||
grandprix_rank,
|
||||
};
|
||||
|
||||
enum cup {
|
||||
cup_valid = 0,
|
||||
cup_id,
|
||||
cup_monitor,
|
||||
cup_name,
|
||||
cup_namehash,
|
||||
cup_realname,
|
||||
cup_icon,
|
||||
cup_levellist,
|
||||
cup_cachedlevels,
|
||||
cup_numlevels,
|
||||
cup_numbonus,
|
||||
cup_emeraldnum,
|
||||
cup_playcredits,
|
||||
cup_hintcondition,
|
||||
cup_cache_cuplock,
|
||||
cup_windata,
|
||||
cup_next,
|
||||
};
|
||||
|
||||
enum gprank {
|
||||
gprank_valid = 0,
|
||||
gprank_numplayers,
|
||||
gprank_totalplayers,
|
||||
gprank_position,
|
||||
gprank_skin,
|
||||
gprank_winpoints,
|
||||
gprank_totalpoints,
|
||||
gprank_exp,
|
||||
gprank_totalexp,
|
||||
gprank_continuesused,
|
||||
gprank_prisons,
|
||||
gprank_totalprisons,
|
||||
gprank_rings,
|
||||
gprank_totalrings,
|
||||
gprank_specialwon,
|
||||
gprank_scoreposition,
|
||||
gprank_scoregppoints,
|
||||
gprank_scoreexp,
|
||||
gprank_scoreprisons,
|
||||
gprank_scorerings,
|
||||
gprank_scorecontinues,
|
||||
gprank_scoretotal,
|
||||
gprank_numlevels,
|
||||
gprank_levels,
|
||||
};
|
||||
|
||||
enum gprank_level {
|
||||
gprank_level_valid = 0,
|
||||
gprank_level_id,
|
||||
gprank_level_event,
|
||||
gprank_level_time,
|
||||
gprank_level_totalexp,
|
||||
gprank_level_totalprisons,
|
||||
gprank_level_continues,
|
||||
gprank_level_perplayer,
|
||||
};
|
||||
|
||||
enum gprank_level_perplayer {
|
||||
gprank_level_perplayer_valid = 0,
|
||||
gprank_level_perplayer_position,
|
||||
gprank_level_perplayer_rings,
|
||||
gprank_level_perplayer_exp,
|
||||
gprank_level_perplayer_prisons,
|
||||
gprank_level_perplayer_gotspecialprize,
|
||||
gprank_level_perplayer_grade,
|
||||
};
|
||||
|
||||
enum roundcue { // named "roundcue" to avoid overlap with actual roundqueue struct
|
||||
roundcue_size = 0, // placed first since we'll be checking this to see if the roundqueue is currently in use
|
||||
roundcue_roundnum,
|
||||
roundcue_position,
|
||||
roundcue_netcommunicate,
|
||||
roundcue_writetextmap,
|
||||
roundcue_snapshotmaps,
|
||||
roundcue_entries,
|
||||
};
|
||||
|
||||
enum roundentry {
|
||||
roundentry_valid = 0,
|
||||
roundentry_mapnum,
|
||||
roundentry_gametype,
|
||||
roundentry_encore,
|
||||
roundentry_rankrestricted,
|
||||
roundentry_overridden,
|
||||
};
|
||||
|
||||
static const char *const grandprix_opt[] = {
|
||||
"gp",
|
||||
"cup",
|
||||
"gamespeed",
|
||||
"encore",
|
||||
"masterbots",
|
||||
"initialize",
|
||||
"initalize",
|
||||
"wonround",
|
||||
"eventmode",
|
||||
"specialdamage",
|
||||
"rank",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *const cup_opt[] = {
|
||||
"valid",
|
||||
"id",
|
||||
"monitor",
|
||||
"name",
|
||||
"namehash",
|
||||
"realname",
|
||||
"icon",
|
||||
"levellist",
|
||||
"cachedlevels",
|
||||
"numlevels",
|
||||
"numbonus",
|
||||
"emeraldnum",
|
||||
"playcredits",
|
||||
"hintcondition",
|
||||
"cache_cuplock",
|
||||
"windata",
|
||||
"next",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *const gprank_opt[] = {
|
||||
"valid",
|
||||
"numplayers",
|
||||
"totalplayers",
|
||||
"position",
|
||||
"skin",
|
||||
"winpoints",
|
||||
"totalpoints",
|
||||
"exp",
|
||||
"totalexp",
|
||||
"continuesused",
|
||||
"prisons",
|
||||
"totalprisons",
|
||||
"rings",
|
||||
"totalrings",
|
||||
"specialwon",
|
||||
"scoreposition",
|
||||
"scoregppoints",
|
||||
"scoreexp",
|
||||
"scoreprisons",
|
||||
"scorerings",
|
||||
"scorecontinues",
|
||||
"scoretotal",
|
||||
"numlevels",
|
||||
"levels",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *const gprank_level_opt[] = {
|
||||
"valid",
|
||||
"id",
|
||||
"event",
|
||||
"time",
|
||||
"totalexp",
|
||||
"totalprisons",
|
||||
"continues",
|
||||
"perplayer",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *const gprank_level_perplayer_opt[] = {
|
||||
"valid",
|
||||
"position",
|
||||
"rings",
|
||||
"exp",
|
||||
"prisons",
|
||||
"gotspecialprize",
|
||||
"grade",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *const roundcue_opt[] = {
|
||||
"size",
|
||||
"roundnum",
|
||||
"position",
|
||||
"netcommunicate",
|
||||
"writetextmap",
|
||||
"snapshotmaps",
|
||||
"entries",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *const roundentry_opt[] = {
|
||||
"valid",
|
||||
"mapnum",
|
||||
"gametype",
|
||||
"encore",
|
||||
"rankrestricted",
|
||||
"overridden",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int grandprix_get(lua_State *L)
|
||||
{
|
||||
enum grandprix field = luaL_checkoption(L, 2, grandprix_opt[0], grandprix_opt);
|
||||
|
||||
// Don't return any grandprixinfo values while not in a GP.
|
||||
if (!grandprixinfo.gp)
|
||||
{
|
||||
switch (field)
|
||||
{
|
||||
case grandprix_gp:
|
||||
lua_pushboolean(L, false);
|
||||
return 1;
|
||||
default:
|
||||
return GPERR;
|
||||
}
|
||||
}
|
||||
|
||||
switch (field)
|
||||
{
|
||||
case grandprix_gp:
|
||||
lua_pushboolean(L, grandprixinfo.gp);
|
||||
break;
|
||||
case grandprix_cup:
|
||||
LUA_PushUserdata(L, grandprixinfo.cup, META_CUP);
|
||||
break;
|
||||
case grandprix_gamespeed:
|
||||
lua_pushnumber(L, grandprixinfo.gamespeed);
|
||||
break;
|
||||
case grandprix_encore:
|
||||
lua_pushboolean(L, grandprixinfo.encore);
|
||||
break;
|
||||
case grandprix_masterbots:
|
||||
lua_pushboolean(L, grandprixinfo.masterbots);
|
||||
break;
|
||||
case grandprix_initialize:
|
||||
case grandprix_initalize: // when the struct misspelled the variable...
|
||||
lua_pushboolean(L, grandprixinfo.initalize);
|
||||
break;
|
||||
case grandprix_wonround:
|
||||
lua_pushboolean(L, grandprixinfo.wonround);
|
||||
break;
|
||||
case grandprix_eventmode:
|
||||
lua_pushnumber(L, grandprixinfo.eventmode);
|
||||
break;
|
||||
case grandprix_specialdamage:
|
||||
lua_pushnumber(L, grandprixinfo.specialDamage);
|
||||
break;
|
||||
case grandprix_rank:
|
||||
LUA_PushUserdata(L, &grandprixinfo.rank, META_GPRANK);
|
||||
break;
|
||||
default:
|
||||
return RNOFIELDGP;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int grandprix_set(lua_State *L)
|
||||
{
|
||||
return luaL_error(L, LUA_QL("grandprixinfo") " struct cannot be edited by Lua.");
|
||||
}
|
||||
|
||||
static int cup_get(lua_State *L)
|
||||
{
|
||||
cupheader_t *cup = *((cupheader_t **)luaL_checkudata(L, 1, META_CUP));
|
||||
enum cup field = luaL_checkoption(L, 2, cup_opt[0], cup_opt);
|
||||
|
||||
if (!cup)
|
||||
{
|
||||
switch (field)
|
||||
{
|
||||
case cup_valid:
|
||||
lua_pushboolean(L, false);
|
||||
return 1;
|
||||
default:
|
||||
return LUA_ErrInvalid(L, "cupheader_t");
|
||||
}
|
||||
}
|
||||
|
||||
switch (field)
|
||||
{
|
||||
case cup_valid:
|
||||
lua_pushboolean(L, true);
|
||||
break;
|
||||
case cup_id:
|
||||
lua_pushnumber(L, cup->id);
|
||||
break;
|
||||
case cup_monitor:
|
||||
lua_pushnumber(L, cup->monitor);
|
||||
break;
|
||||
case cup_name:
|
||||
lua_pushstring(L, cup->name);
|
||||
break;
|
||||
case cup_namehash:
|
||||
return UNIMPLEMENTED;
|
||||
break;
|
||||
case cup_realname:
|
||||
lua_pushstring(L, cup->realname);
|
||||
break;
|
||||
case cup_icon:
|
||||
lua_pushstring(L, cup->icon);
|
||||
break;
|
||||
case cup_levellist:
|
||||
lua_createtable(L, ((cup->numlevels) + (cup->numbonus)), 0);
|
||||
for (size_t i = 0; i < ((cup->numlevels) + (cup->numbonus)); i++)
|
||||
{
|
||||
lua_pushstring(L, cup->levellist[i]);
|
||||
lua_rawseti(L, -2, 1 + i);
|
||||
}
|
||||
//return UNIMPLEMENTED;
|
||||
break;
|
||||
case cup_cachedlevels:
|
||||
lua_createtable(L, ((cup->numlevels) + (cup->numbonus)), 0);
|
||||
for (size_t i = 0; i < ((cup->numlevels) + (cup->numbonus)); i++)
|
||||
{
|
||||
lua_pushnumber(L, cup->cachedlevels[i]);
|
||||
lua_rawseti(L, -2, 1 + i);
|
||||
}
|
||||
break;
|
||||
case cup_numlevels:
|
||||
lua_pushnumber(L, cup->numlevels);
|
||||
break;
|
||||
case cup_numbonus:
|
||||
lua_pushnumber(L, cup->numbonus);
|
||||
break;
|
||||
case cup_emeraldnum:
|
||||
lua_pushnumber(L, cup->emeraldnum);
|
||||
break;
|
||||
case cup_playcredits:
|
||||
lua_pushboolean(L, cup->playcredits);
|
||||
break;
|
||||
case cup_hintcondition:
|
||||
lua_pushnumber(L, cup->hintcondition);
|
||||
break;
|
||||
case cup_cache_cuplock:
|
||||
return UNIMPLEMENTED;
|
||||
break;
|
||||
case cup_windata:
|
||||
return UNIMPLEMENTED;
|
||||
break;
|
||||
case cup_next:
|
||||
return UNIMPLEMENTED;
|
||||
break;
|
||||
default:
|
||||
return RNOFIELDCH;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cup_set(lua_State *L)
|
||||
{
|
||||
return luaL_error(L, LUA_QL("cupheader_t") " struct cannot be edited by Lua.");
|
||||
}
|
||||
|
||||
static int gprank_get(lua_State *L)
|
||||
{
|
||||
gpRank_t *gprank = *((gpRank_t **)luaL_checkudata(L, 1, META_GPRANK));
|
||||
enum gprank field = luaL_checkoption(L, 2, gprank_opt[0], gprank_opt);
|
||||
|
||||
if (!gprank)
|
||||
{
|
||||
switch (field)
|
||||
{
|
||||
case gprank_valid:
|
||||
lua_pushboolean(L, false);
|
||||
return 1;
|
||||
default:
|
||||
return LUA_ErrInvalid(L, "gprank_t");
|
||||
}
|
||||
}
|
||||
|
||||
switch (field)
|
||||
{
|
||||
case gprank_valid:
|
||||
lua_pushboolean(L, true);
|
||||
break;
|
||||
case gprank_numplayers:
|
||||
lua_pushnumber(L, gprank->numPlayers);
|
||||
break;
|
||||
case gprank_totalplayers:
|
||||
lua_pushnumber(L, gprank->totalPlayers);
|
||||
break;
|
||||
case gprank_position:
|
||||
lua_pushnumber(L, gprank->position);
|
||||
break;
|
||||
case gprank_skin:
|
||||
lua_pushnumber(L, gprank->skin);
|
||||
break;
|
||||
case gprank_winpoints:
|
||||
lua_pushnumber(L, gprank->winPoints);
|
||||
break;
|
||||
case gprank_totalpoints:
|
||||
lua_pushnumber(L, gprank->totalPoints);
|
||||
break;
|
||||
case gprank_exp:
|
||||
lua_pushnumber(L, gprank->exp);
|
||||
break;
|
||||
case gprank_totalexp:
|
||||
lua_pushnumber(L, gprank->totalExp);
|
||||
break;
|
||||
case gprank_continuesused:
|
||||
lua_pushnumber(L, gprank->continuesUsed);
|
||||
break;
|
||||
case gprank_prisons:
|
||||
lua_pushnumber(L, gprank->prisons);
|
||||
break;
|
||||
case gprank_totalprisons:
|
||||
lua_pushnumber(L, gprank->totalPrisons);
|
||||
break;
|
||||
case gprank_rings:
|
||||
lua_pushnumber(L, gprank->rings);
|
||||
break;
|
||||
case gprank_totalrings:
|
||||
lua_pushnumber(L, gprank->totalRings);
|
||||
break;
|
||||
case gprank_specialwon:
|
||||
lua_pushboolean(L, gprank->specialWon);
|
||||
break;
|
||||
case gprank_scoreposition:
|
||||
lua_pushnumber(L, gprank->scorePosition);
|
||||
break;
|
||||
case gprank_scoregppoints:
|
||||
lua_pushnumber(L, gprank->scoreGPPoints);
|
||||
break;
|
||||
case gprank_scoreexp:
|
||||
lua_pushnumber(L, gprank->scoreExp);
|
||||
break;
|
||||
case gprank_scoreprisons:
|
||||
lua_pushnumber(L, gprank->scorePrisons);
|
||||
break;
|
||||
case gprank_scorerings:
|
||||
lua_pushnumber(L, gprank->scoreRings);
|
||||
break;
|
||||
case gprank_scorecontinues:
|
||||
lua_pushnumber(L, gprank->scoreContinues);
|
||||
break;
|
||||
case gprank_scoretotal:
|
||||
lua_pushnumber(L, gprank->scoreTotal);
|
||||
break;
|
||||
case gprank_numlevels:
|
||||
lua_pushnumber(L, gprank->numLevels);
|
||||
break;
|
||||
case gprank_levels:
|
||||
lua_createtable(L, ((grandprixinfo.cup->numlevels) + (grandprixinfo.cup->numbonus)), 0);
|
||||
for (size_t i = 0; i < ((grandprixinfo.cup->numlevels) + (grandprixinfo.cup->numbonus)); i++)
|
||||
{
|
||||
LUA_PushUserdata(L, &gprank->levels[i], META_GPRANKLEVEL);
|
||||
lua_rawseti(L, -2, 1 + i);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return RNOFIELDGR;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int gprank_set(lua_State *L)
|
||||
{
|
||||
return luaL_error(L, LUA_QL("gprank_t") " struct cannot be edited by Lua.");
|
||||
}
|
||||
|
||||
static int gprank_level_get(lua_State *L)
|
||||
{
|
||||
gpRank_level_t *gprank_level = *((gpRank_level_t **)luaL_checkudata(L, 1, META_GPRANKLEVEL));
|
||||
enum gprank_level field = luaL_checkoption(L, 2, gprank_level_opt[0], gprank_level_opt);
|
||||
|
||||
if (!gprank_level)
|
||||
{
|
||||
switch (field)
|
||||
{
|
||||
case gprank_level_valid:
|
||||
lua_pushboolean(L, false);
|
||||
return 1;
|
||||
default:
|
||||
return LUA_ErrInvalid(L, "gprank_level_t");
|
||||
}
|
||||
}
|
||||
|
||||
switch (field)
|
||||
{
|
||||
case gprank_level_valid:
|
||||
lua_pushboolean(L, true);
|
||||
break;
|
||||
case gprank_level_id:
|
||||
lua_pushnumber(L, gprank_level->id);
|
||||
break;
|
||||
case gprank_level_event:
|
||||
lua_pushnumber(L, gprank_level->event);
|
||||
break;
|
||||
case gprank_level_time:
|
||||
lua_pushnumber(L, gprank_level->time);
|
||||
break;
|
||||
case gprank_level_totalexp:
|
||||
lua_pushnumber(L, gprank_level->totalExp);
|
||||
break;
|
||||
case gprank_level_totalprisons:
|
||||
lua_pushnumber(L, gprank_level->totalPrisons);
|
||||
break;
|
||||
case gprank_level_continues:
|
||||
lua_pushnumber(L, gprank_level->continues);
|
||||
break;
|
||||
case gprank_level_perplayer:
|
||||
lua_createtable(L, grandprixinfo.rank.numPlayers, 0);
|
||||
for (size_t i = 0; i < grandprixinfo.rank.numPlayers; i++)
|
||||
{
|
||||
LUA_PushUserdata(L, &gprank_level->perPlayer[i], META_GPRANKLEVELPERPLAYER);
|
||||
lua_rawseti(L, -2, 1 + i);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return RNOFIELDGRL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int gprank_level_set(lua_State *L)
|
||||
{
|
||||
return luaL_error(L, LUA_QL("gprank_level_t") " struct cannot be edited by Lua.");
|
||||
}
|
||||
|
||||
static int gprank_level_perplayer_get(lua_State *L)
|
||||
{
|
||||
// "perplaya" to avoid shadowed declaration
|
||||
gpRank_level_perplayer_t *gprank_level_perplaya = *((gpRank_level_perplayer_t **)luaL_checkudata(L, 1, META_GPRANKLEVELPERPLAYER));
|
||||
enum gprank_level_perplayer field = luaL_checkoption(L, 2, gprank_level_perplayer_opt[0], gprank_level_perplayer_opt);
|
||||
|
||||
if (!gprank_level_perplaya)
|
||||
{
|
||||
switch (field)
|
||||
{
|
||||
case gprank_level_perplayer_valid:
|
||||
lua_pushboolean(L, false);
|
||||
return 1;
|
||||
default:
|
||||
return LUA_ErrInvalid(L, "gprank_level_perplayer_t");
|
||||
}
|
||||
}
|
||||
|
||||
switch (field)
|
||||
{
|
||||
case gprank_level_perplayer_valid:
|
||||
lua_pushboolean(L, true);
|
||||
break;
|
||||
case gprank_level_perplayer_position:
|
||||
lua_pushnumber(L, gprank_level_perplaya->position);
|
||||
break;
|
||||
case gprank_level_perplayer_rings:
|
||||
lua_pushnumber(L, gprank_level_perplaya->rings);
|
||||
break;
|
||||
case gprank_level_perplayer_exp:
|
||||
lua_pushnumber(L, gprank_level_perplaya->exp);
|
||||
break;
|
||||
case gprank_level_perplayer_prisons:
|
||||
lua_pushnumber(L, gprank_level_perplaya->prisons);
|
||||
break;
|
||||
case gprank_level_perplayer_gotspecialprize:
|
||||
lua_pushboolean(L, gprank_level_perplaya->gotSpecialPrize);
|
||||
break;
|
||||
case gprank_level_perplayer_grade:
|
||||
lua_pushnumber(L, gprank_level_perplaya->grade);
|
||||
break;
|
||||
default:
|
||||
return RNOFIELDGRLP;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int gprank_level_perplayer_set(lua_State *L)
|
||||
{
|
||||
return luaL_error(L, LUA_QL("gprank_level_perplayer") " struct cannot be edited by Lua.");
|
||||
}
|
||||
|
||||
static int roundcue_get(lua_State *L)
|
||||
{
|
||||
enum roundcue field = luaL_checkoption(L, 2, roundcue_opt[0], roundcue_opt);
|
||||
|
||||
// Don't return any grandprixinfo values while not in a GP.
|
||||
if (!roundqueue.size)
|
||||
{
|
||||
switch (field)
|
||||
{
|
||||
case roundcue_size:
|
||||
lua_pushboolean(L, false);
|
||||
return 1;
|
||||
default:
|
||||
return ROUNDCUEERR;
|
||||
}
|
||||
}
|
||||
|
||||
switch (field)
|
||||
{
|
||||
case roundcue_size:
|
||||
lua_pushnumber(L, roundqueue.size);
|
||||
break;
|
||||
case roundcue_roundnum:
|
||||
lua_pushnumber(L, roundqueue.roundnum);
|
||||
break;
|
||||
case roundcue_position:
|
||||
lua_pushnumber(L, roundqueue.position);
|
||||
break;
|
||||
case roundcue_netcommunicate:
|
||||
return UNIMPLEMENTED;
|
||||
break;
|
||||
case roundcue_writetextmap:
|
||||
return UNIMPLEMENTED;
|
||||
break;
|
||||
case roundcue_snapshotmaps:
|
||||
lua_pushboolean(L, roundqueue.snapshotmaps);
|
||||
break;
|
||||
case roundcue_entries:
|
||||
lua_createtable(L, roundqueue.size, 0);
|
||||
for (size_t i = 0; i < roundqueue.size; i++)
|
||||
{
|
||||
LUA_PushUserdata(L, &roundqueue.entries[i], META_ROUNDENTRY);
|
||||
lua_rawseti(L, -2, 1 + i);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return RNOFIELDRQ;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int roundcue_set(lua_State *L)
|
||||
{
|
||||
return luaL_error(L, LUA_QL("roundqueue") " struct cannot be edited by Lua.");
|
||||
}
|
||||
|
||||
static int roundentry_get(lua_State *L)
|
||||
{
|
||||
roundentry_t *roundentry = *((roundentry_t **)luaL_checkudata(L, 1, META_ROUNDENTRY));
|
||||
enum roundentry field = luaL_checkoption(L, 2, roundentry_opt[0], roundentry_opt);
|
||||
|
||||
if (!roundentry)
|
||||
{
|
||||
switch (field)
|
||||
{
|
||||
case roundentry_valid:
|
||||
lua_pushboolean(L, false);
|
||||
return 1;
|
||||
default:
|
||||
return LUA_ErrInvalid(L, "roundentry_t");
|
||||
}
|
||||
}
|
||||
|
||||
switch (field)
|
||||
{
|
||||
case roundentry_valid:
|
||||
lua_pushboolean(L, true);
|
||||
break;
|
||||
case roundentry_mapnum:
|
||||
lua_pushnumber(L, roundentry->mapnum);
|
||||
break;
|
||||
case roundentry_gametype:
|
||||
lua_pushnumber(L, roundentry->gametype);
|
||||
break;
|
||||
case roundentry_encore:
|
||||
lua_pushboolean(L, roundentry->encore);
|
||||
break;
|
||||
case roundentry_rankrestricted:
|
||||
lua_pushboolean(L, roundentry->rankrestricted);
|
||||
break;
|
||||
case roundentry_overridden:
|
||||
lua_pushboolean(L, roundentry->overridden);
|
||||
break;
|
||||
default:
|
||||
return RNOFIELDRE;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int roundentry_set(lua_State *L)
|
||||
{
|
||||
return luaL_error(L, LUA_QL("roundentry_t") " struct cannot be edited by Lua.");
|
||||
}
|
||||
|
||||
#undef UNIMPLEMENTED
|
||||
#undef RNOFIELDGP
|
||||
#undef RNOFIELDCH
|
||||
#undef RNOFIELDGR
|
||||
#undef RNOFIELDGRL
|
||||
#undef RNOFIELDGRLP
|
||||
#undef RNOFIELDRQ
|
||||
#undef RNOFIELDRE
|
||||
#undef GPERR
|
||||
#undef ROUNDCUEERR
|
||||
|
||||
static int lib_numCupheaders(lua_State *L)
|
||||
{
|
||||
lua_pushinteger(L, numkartcupheaders);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// There was, in fact, a better thing to do here - thanks toaster
|
||||
#define GETCUPERR UINT16_MAX
|
||||
|
||||
// copied and edited from G_MapNumber
|
||||
static UINT16 LUA_GetCupByNum(UINT16 cupnum)
|
||||
{
|
||||
cupheader_t *checkcup;
|
||||
// find by cup id
|
||||
if (cupnum != GETCUPERR)
|
||||
{
|
||||
if (cupnum >= numkartcupheaders)
|
||||
return GETCUPERR; // id outta range
|
||||
for (checkcup = kartcupheaders; checkcup->id <= numkartcupheaders; checkcup = checkcup->next)
|
||||
{
|
||||
if (checkcup->id != cupnum)
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
return GETCUPERR; // id invalid
|
||||
}
|
||||
return checkcup->id;
|
||||
}
|
||||
|
||||
return GETCUPERR;
|
||||
}
|
||||
|
||||
// copied and edited from G_MapNumber
|
||||
static UINT16 LUA_GetCupByName(const char * name)
|
||||
{
|
||||
cupheader_t *checkcup;
|
||||
|
||||
UINT32 hash = quickncasehash(name, MAXCUPNAME);
|
||||
|
||||
// find by cup name/realname
|
||||
for (checkcup = kartcupheaders; checkcup != NULL; checkcup = checkcup->next)
|
||||
{
|
||||
if (hash != checkcup->namehash)
|
||||
continue;
|
||||
|
||||
if (strcasecmp(checkcup->name, name) != 0)
|
||||
continue;
|
||||
|
||||
return checkcup->id;
|
||||
}
|
||||
|
||||
return GETCUPERR;
|
||||
}
|
||||
|
||||
static int lib_iterateCups(lua_State *L)
|
||||
{
|
||||
INT32 i = -1;
|
||||
cupheader_t *tempcup = kartcupheaders;
|
||||
|
||||
if (lua_gettop(L) < 2)
|
||||
{
|
||||
lua_pushcfunction(L, lib_iterateCups);
|
||||
return 1;
|
||||
}
|
||||
|
||||
lua_settop(L, 2);
|
||||
lua_remove(L, 1); // state is unused.
|
||||
|
||||
if (!lua_isnil(L, 1))
|
||||
{
|
||||
i = ((*((cupheader_t **)luaL_checkudata(L, 1, META_CUP)))->id) + 1;
|
||||
}
|
||||
else
|
||||
i = 0;
|
||||
|
||||
for (tempcup = kartcupheaders; tempcup->id < numkartcupheaders; tempcup = tempcup->next)
|
||||
{
|
||||
if (tempcup->next == NULL)
|
||||
break;
|
||||
|
||||
if (tempcup->id >= i)
|
||||
break;
|
||||
}
|
||||
|
||||
// cups are always valid, only added, never removed
|
||||
if (i < numkartcupheaders)
|
||||
{
|
||||
LUA_PushUserdata(L, tempcup, META_CUP);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Shamelessly copied and edited from lua_waypointslib.c (with thanks to JugadorXEI)
|
||||
static int lib_getCupheader(lua_State *L)
|
||||
{
|
||||
const char *field;
|
||||
size_t i;
|
||||
cupheader_t *checkcup;
|
||||
UINT16 getResult = GETCUPERR;
|
||||
|
||||
// find cup by id number
|
||||
if (lua_type(L, 2) == LUA_TNUMBER)
|
||||
{
|
||||
i = luaL_checkinteger(L, 2);
|
||||
if (i > numkartcupheaders)
|
||||
return luaL_error(L, "cupheader_t id %d out of loaded range (0 - %d)", i, numkartcupheaders);
|
||||
getResult = LUA_GetCupByNum(i);
|
||||
if (getResult == GETCUPERR)
|
||||
return luaL_error(L, "cupheader_t id %d invalid", i);
|
||||
for (checkcup = kartcupheaders; checkcup->id < numkartcupheaders; checkcup = checkcup->next)
|
||||
{
|
||||
if (checkcup->id != getResult)
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
|
||||
return luaL_error(L, "cupheader_t id %d invalid (LUA_GetCupByNum failed?)", i);
|
||||
}
|
||||
LUA_PushUserdata(L, checkcup, META_CUP);
|
||||
return 1;
|
||||
}
|
||||
|
||||
field = luaL_checkstring(L, 2);
|
||||
|
||||
// special function iterate
|
||||
if (fastcmp(field,"iterate"))
|
||||
{
|
||||
lua_pushcfunction(L, lib_iterateCups);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (lua_type(L, 2) == LUA_TSTRING)
|
||||
{
|
||||
getResult = LUA_GetCupByName(field);
|
||||
if (getResult == GETCUPERR)
|
||||
return luaL_error(L, "no cupheader_t with name %s", field);
|
||||
}
|
||||
|
||||
// If, after all this...
|
||||
if (getResult == GETCUPERR)
|
||||
return luaL_error(L, "internal failure in lua_grandprixlib.c???");
|
||||
|
||||
for (checkcup = kartcupheaders; checkcup->id < numkartcupheaders; checkcup = checkcup->next)
|
||||
{
|
||||
if (checkcup->id != getResult)
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
|
||||
return luaL_error(L, "cupheader_t id %d invalid (LUA_GetCupByName failed?)", i);
|
||||
}
|
||||
|
||||
LUA_PushUserdata(L, checkcup, META_CUP);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LUA_GrandPrixLib(lua_State *L)
|
||||
{
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, grandprix_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, grandprix_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "grandprixinfo");
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, roundcue_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, roundcue_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "roundqueue");
|
||||
|
||||
luaL_newmetatable(L, META_CUP);
|
||||
lua_pushcfunction(L, cup_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, cup_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_pop(L,1);
|
||||
|
||||
luaL_newmetatable(L, META_GPRANK);
|
||||
lua_pushcfunction(L, gprank_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, gprank_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_pop(L,1);
|
||||
|
||||
luaL_newmetatable(L, META_GPRANKLEVEL);
|
||||
lua_pushcfunction(L, gprank_level_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, gprank_level_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_pop(L,1);
|
||||
|
||||
luaL_newmetatable(L, META_GPRANKLEVELPERPLAYER);
|
||||
lua_pushcfunction(L, gprank_level_perplayer_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, gprank_level_perplayer_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_pop(L,1);
|
||||
|
||||
luaL_newmetatable(L, META_ROUNDENTRY);
|
||||
lua_pushcfunction(L, roundentry_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, roundentry_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_pop(L,1);
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, lib_getCupheader);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, lib_numCupheaders);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "cups");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -122,6 +122,12 @@ extern lua_State *gL;
|
|||
#define META_ICECUBEVARS "ICECUBEVARS_T*"
|
||||
#define META_SKYBOX "SKYBOX_T*"
|
||||
|
||||
#define META_CUP "CUPHEADER_T*"
|
||||
#define META_GPRANK "GPRANK_T*"
|
||||
#define META_GPRANKLEVEL "GPRANK_LEVEL_T*"
|
||||
#define META_GPRANKLEVELPERPLAYER "GPRANK_LEVEL_PERPLAYER_T*"
|
||||
#define META_ROUNDENTRY "ROUNDENTRY_T*"
|
||||
|
||||
boolean luaL_checkboolean(lua_State *L, int narg);
|
||||
|
||||
int LUA_EnumLib(lua_State *L);
|
||||
|
|
@ -146,6 +152,7 @@ int LUA_BotVarsLib(lua_State *L);
|
|||
int LUA_TerrainLib(lua_State *L);
|
||||
int LUA_RespawnVarsLib(lua_State *L);
|
||||
int LUA_WaypointLib(lua_State *L);
|
||||
int LUA_GrandPrixLib(lua_State *L);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ static lua_CFunction liblist[] = {
|
|||
LUA_TerrainLib, // t_splash_t, t_footstep_t, t_overlay_t, terrain_t
|
||||
LUA_RespawnVarsLib, // respawnvars_t
|
||||
LUA_WaypointLib, // waypoint_t
|
||||
LUA_GrandPrixLib, // grandprixinfo, cupheader_t, gprank_t, skinrecord_t, etc.
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1019,7 +1019,10 @@ static void M_HandleColorRotate(setup_player_t *p, UINT8 num)
|
|||
{
|
||||
if (p->skin >= 0)
|
||||
{
|
||||
p->color = SKINCOLOR_NONE;
|
||||
if (p->color == SKINCOLOR_NONE)
|
||||
p->color = PR_GetProfile(p->profilen)->color;
|
||||
else
|
||||
p->color = SKINCOLOR_NONE;
|
||||
p->rotate = CSROTATETICS;
|
||||
p->hitlag = true;
|
||||
S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s
|
||||
|
|
@ -1252,8 +1255,11 @@ static void M_HandleFollowerColorRotate(setup_player_t *p, UINT8 num)
|
|||
}
|
||||
else if (M_MenuExtraPressed(num))
|
||||
{
|
||||
UINT16 profile_followercolor = PR_GetProfile(p->profilen)->followercolor;
|
||||
if (p->followercolor == FOLLOWERCOLOR_MATCH)
|
||||
p->followercolor = FOLLOWERCOLOR_OPPOSITE;
|
||||
else if (p->followercolor == FOLLOWERCOLOR_OPPOSITE && profile_followercolor != FOLLOWERCOLOR_OPPOSITE && profile_followercolor != FOLLOWERCOLOR_MATCH)
|
||||
p->followercolor = profile_followercolor;
|
||||
else if (p->followercolor == SKINCOLOR_NONE)
|
||||
p->followercolor = FOLLOWERCOLOR_MATCH;
|
||||
else
|
||||
|
|
|
|||
|
|
@ -287,6 +287,97 @@ static void M_GPBackup(INT32 choice)
|
|||
M_StartCup(UINT8_MAX);
|
||||
}
|
||||
|
||||
static boolean M_IsCupQueueable(cupheader_t *cup)
|
||||
{
|
||||
levelsearch_t templevelsearch = levellist.levelsearch; // copy levellist so we don't mess with stuff I think
|
||||
UINT16 ShownCount = 0;
|
||||
UINT16 CupCount = 0;
|
||||
UINT32 CheckGametype[2] = {TOL_RACE,TOL_BATTLE};
|
||||
|
||||
templevelsearch.cup = cup;
|
||||
|
||||
UINT8 e, i = 0;
|
||||
for (e = 0; e < 2; e++)
|
||||
{
|
||||
templevelsearch.typeoflevel = CheckGametype[e];
|
||||
ShownCount += M_CountLevelsToShowInList(&templevelsearch);
|
||||
}
|
||||
//CONS_Printf(M_GetText("ShownCount: %d\n"), ShownCount);
|
||||
UINT16 checkmap = NEXTMAP_INVALID;
|
||||
for (i = 0; i < CUPCACHE_SPECIAL; i++)
|
||||
{
|
||||
checkmap = templevelsearch.cup->cachedlevels[i];
|
||||
if (checkmap == NEXTMAP_INVALID)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
CupCount++;
|
||||
}
|
||||
//CONS_Printf(M_GetText("CupCount: %d\n"), CupCount);
|
||||
if (ShownCount >= CupCount) // greater than is used to ensure multi-gametype maps don't accidentally cause this to return false.
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void M_CupStartResponse(INT32 ch)
|
||||
{
|
||||
if (ch != MA_YES)
|
||||
return;
|
||||
|
||||
if (!(server || (IsPlayerAdmin(consoleplayer))))
|
||||
return;
|
||||
|
||||
M_LevelConfirmHandler();
|
||||
}
|
||||
|
||||
static void M_CupQueueResponse(INT32 ch)
|
||||
{
|
||||
if (ch != MA_YES)
|
||||
return;
|
||||
|
||||
if (!(server || (IsPlayerAdmin(consoleplayer))))
|
||||
return;
|
||||
|
||||
cupheader_t *queuedcup = cupgrid.builtgrid[CUPMENU_CURSORID];
|
||||
|
||||
M_CupQueueHandler(queuedcup);
|
||||
|
||||
S_StartSound(NULL, sfx_gshe2);
|
||||
|
||||
while ((menuqueue.size + roundqueue.size) > ROUNDQUEUE_MAX)
|
||||
menuqueue.size--;
|
||||
|
||||
if (!netgame)
|
||||
{
|
||||
M_StartMessage("Cup Queue",
|
||||
va(M_GetText(
|
||||
"You just queued %s CUP.\n"
|
||||
"\n"
|
||||
"Do you want to start the\n"
|
||||
"cup immediately?\n"
|
||||
), queuedcup->realname
|
||||
), &M_CupStartResponse, MM_YESNO,
|
||||
"Here we go!",
|
||||
"On second thought..."
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
M_StartMessage("Cup Queue",
|
||||
va(M_GetText(
|
||||
"You just queued %s CUP.\n"
|
||||
"\n"
|
||||
"Do you want to queue it\n"
|
||||
"for everyone?\n"
|
||||
), queuedcup->realname
|
||||
), &M_CupStartResponse, MM_YESNO,
|
||||
"Queue em up!",
|
||||
"Not yet"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void M_CupSelectHandler(INT32 choice)
|
||||
{
|
||||
const UINT8 pid = 0;
|
||||
|
|
@ -429,6 +520,63 @@ void M_CupSelectHandler(INT32 choice)
|
|||
S_StartSound(NULL, sfx_s3k63);
|
||||
}
|
||||
}
|
||||
// Queue a cup for match race and netgames. See levelselect.c for most of how this actually works.
|
||||
else if (levellist.canqueue && M_MenuButtonPressed(pid, MBT_Z))
|
||||
{
|
||||
M_SetMenuDelay(pid);
|
||||
|
||||
if (cupgrid.builtgrid[CUPMENU_CURSORID] == &dummy_lostandfound)
|
||||
S_StartSound(NULL, sfx_gshe7);
|
||||
|
||||
else if (!M_IsCupQueueable(cupgrid.builtgrid[CUPMENU_CURSORID]))
|
||||
{
|
||||
S_StartSound(NULL, sfx_s3kb2);
|
||||
M_StartMessage("Back to the Grand Prix!", "Can't queue a cup you haven't fully unlocked!", NULL, MM_NOTHING, NULL, NULL);
|
||||
}
|
||||
|
||||
// Better to avoid any headaches here - pass the buck to the Extra button.
|
||||
else if (roundqueue.size)
|
||||
{
|
||||
S_StartSound(NULL, sfx_s3kb2);
|
||||
M_StartMessage("Queue is not empty!", "Clear the queue before trying to queue a cup!", NULL, MM_NOTHING, NULL, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// We're not queueing Battle maps if we're in single-player Match Race.
|
||||
if (!levellist.netgame && (cv_splitplayers.value == 1) && !netgame)
|
||||
{
|
||||
M_StartMessage("Cup Queue",
|
||||
va(M_GetText(
|
||||
"This will queue all Race courses in this cup.\n"
|
||||
"\n"
|
||||
"Any rounds already in the queue will be cleared out.\n"
|
||||
"\n"
|
||||
"Do you want to queue the cup?\n"
|
||||
)), &M_CupQueueResponse, MM_YESNO,
|
||||
"Let's do it!",
|
||||
"Nah.");
|
||||
}
|
||||
else
|
||||
{
|
||||
M_StartMessage("Cup Queue",
|
||||
va(M_GetText(
|
||||
"This will queue the entire cup, including both Race and Battle courses.\n"
|
||||
"\n"
|
||||
"Any rounds already in the queue will be cleared out.\n"
|
||||
"\n"
|
||||
"Do you want to queue the cup?\n"
|
||||
)), &M_CupQueueResponse, MM_YESNO,
|
||||
"Let's do it!",
|
||||
"Nah.");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (levellist.canqueue && M_MenuExtraPressed(pid))
|
||||
{
|
||||
M_ClearQueueHandler();
|
||||
}
|
||||
else if (M_MenuBackPressed(pid))
|
||||
{
|
||||
M_SetMenuDelay(pid);
|
||||
|
|
@ -443,4 +591,6 @@ void M_CupSelectHandler(INT32 choice)
|
|||
void M_CupSelectTick(void)
|
||||
{
|
||||
cupgrid.previewanim++;
|
||||
// Shoving this here for cup queue purposes.
|
||||
M_LevelSelectTick();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -832,8 +832,10 @@ void M_LevelSelected(INT16 add, boolean menuupdate)
|
|||
static void M_MenuQueueStopSend(INT32 ch)
|
||||
{
|
||||
(void)ch;
|
||||
|
||||
|
||||
memset(&menuqueue, 0, sizeof(struct menuqueue));
|
||||
|
||||
menuqueue.clearing = false;
|
||||
}
|
||||
|
||||
static void M_MenuQueueSelectedLocal(void)
|
||||
|
|
@ -905,6 +907,92 @@ static void M_MenuQueueSelectedLocal(void)
|
|||
}
|
||||
}
|
||||
|
||||
// Copy-pasted and edited from G_GPCupIntoRoundQueue
|
||||
void M_CupQueueHandler(cupheader_t *cup)
|
||||
{
|
||||
UINT8 i, levelindex = 0, bonusindex = 0;
|
||||
UINT8 bonusmodulo = max(1, (cup->numlevels+1)/(cup->numbonus+1));
|
||||
UINT16 cupLevelNum;
|
||||
INT32 gtcheck;
|
||||
|
||||
// We shouldn't get to this point while there's rounds queued, but if we do, get outta there.
|
||||
if (roundqueue.size)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
menuqueue.size = 0;
|
||||
|
||||
// Levels are added to the queue in the following pattern.
|
||||
// For 5 Race rounds and 2 Bonus rounds, the most common case:
|
||||
// race - race - BONUS - race - race - BONUS - race
|
||||
// The system is flexible enough to permit other arrangements.
|
||||
// However, we just want to keep the pacing even & consistent.
|
||||
while (levelindex < cup->numlevels)
|
||||
{
|
||||
memset(menuqueue.entries+menuqueue.size, 0, sizeof(roundentry_t));
|
||||
|
||||
// Fill like two or three Race maps.
|
||||
for (i = 0; i < bonusmodulo; i++)
|
||||
{
|
||||
cupLevelNum = cup->cachedlevels[levelindex];
|
||||
|
||||
if (cupLevelNum >= nummapheaders)
|
||||
{
|
||||
// Just skip the map if it's invalid.
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((mapheaderinfo[cupLevelNum]->typeoflevel & TOL_RACE) == TOL_RACE)
|
||||
{
|
||||
gtcheck = GT_RACE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtcheck = mapheaderinfo[cupLevelNum]->typeoflevel;
|
||||
}
|
||||
|
||||
menuqueue.entries[menuqueue.size].mapnum = cupLevelNum;
|
||||
menuqueue.entries[menuqueue.size].gametype = gtcheck;
|
||||
menuqueue.entries[menuqueue.size].encore = (cv_kartencore.value == 1);
|
||||
|
||||
menuqueue.size++;
|
||||
|
||||
levelindex++;
|
||||
if (levelindex >= cup->numlevels)
|
||||
break;
|
||||
}
|
||||
|
||||
// Attempt to add an interstitial Battle round.
|
||||
// If we're in singleplayer Match Race, just skip this.
|
||||
if ((levelindex < cup->numlevels
|
||||
&& bonusindex < cup->numbonus) && (levellist.netgame || (cv_splitplayers.value > 1) || netgame))
|
||||
{
|
||||
cupLevelNum = cup->cachedlevels[CUPCACHE_BONUS + bonusindex];
|
||||
|
||||
if (cupLevelNum < nummapheaders)
|
||||
{
|
||||
if ((mapheaderinfo[cupLevelNum]->typeoflevel & TOL_BATTLE) == TOL_BATTLE)
|
||||
{
|
||||
gtcheck = GT_BATTLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtcheck = mapheaderinfo[cupLevelNum]->typeoflevel;
|
||||
}
|
||||
// In the case of Bonus rounds, we simply skip invalid maps.
|
||||
menuqueue.entries[menuqueue.size].mapnum = cupLevelNum;
|
||||
menuqueue.entries[menuqueue.size].gametype = gtcheck;
|
||||
menuqueue.entries[menuqueue.size].encore = (cv_kartencore.value == 1);
|
||||
|
||||
menuqueue.size++;
|
||||
}
|
||||
|
||||
bonusindex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean M_LevelSelectCupSwitch(boolean next, boolean skipones)
|
||||
{
|
||||
levelsearch_t templevelsearch = levellist.levelsearch;
|
||||
|
|
@ -1002,6 +1090,40 @@ static void M_MenuQueueResponse(INT32 ch)
|
|||
SendNetXCmd(XD_EXITLEVEL, NULL, 0);
|
||||
}
|
||||
|
||||
// Ripped out of LevelSelectHandler for use in cup queueing from cupselect.c
|
||||
void M_LevelConfirmHandler(void)
|
||||
{
|
||||
// Starting immediately OR importing queue
|
||||
|
||||
while ((menuqueue.size + roundqueue.size) > ROUNDQUEUE_MAX)
|
||||
menuqueue.size--;
|
||||
|
||||
if (!levellist.canqueue || !menuqueue.size)
|
||||
{
|
||||
M_LevelSelected(levellist.cursor, true);
|
||||
}
|
||||
else if (netgame)
|
||||
{
|
||||
menuqueue.anchor = roundqueue.size;
|
||||
menuqueue.sending = 1;
|
||||
|
||||
M_StartMessage("Queueing Rounds",
|
||||
va(M_GetText(
|
||||
"Attempting to send %d Round%s...\n"
|
||||
"\n"
|
||||
"If this is taking longer than you\n"
|
||||
"expect, exit out of this message.\n"
|
||||
), menuqueue.size, (menuqueue.size == 1 ? "" : "s")
|
||||
), &M_MenuQueueStopSend, MM_NOTHING,
|
||||
NULL,
|
||||
"This is taking too long..."
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
M_MenuQueueSelectedLocal();
|
||||
}
|
||||
}
|
||||
|
||||
static void M_ClearQueueResponse(INT32 ch)
|
||||
{
|
||||
|
|
@ -1012,18 +1134,56 @@ static void M_ClearQueueResponse(INT32 ch)
|
|||
return;
|
||||
|
||||
S_StartSound(NULL, sfx_slip);
|
||||
|
||||
if (netgame)
|
||||
|
||||
if (!netgame)
|
||||
memset(&roundqueue, 0, sizeof(struct roundqueue));
|
||||
if (netgame && (roundqueue.size != 0))
|
||||
{
|
||||
if (roundqueue.size)
|
||||
{
|
||||
Handle_MapQueueSend(0, ROUNDQUEUE_CMD_CLEAR, false);
|
||||
}
|
||||
return;
|
||||
menuqueue.clearing = true;
|
||||
Handle_MapQueueSend(0, ROUNDQUEUE_CMD_CLEAR, false);
|
||||
M_StartMessage("Clearing Rounds",
|
||||
va(M_GetText(
|
||||
"Attempting to clear %d Round%s...\n"
|
||||
"\n"
|
||||
"If this is taking longer than you\n"
|
||||
"expect, exit out of this message.\n"
|
||||
), roundqueue.size, (roundqueue.size == 1 ? "" : "s")
|
||||
), &M_MenuQueueStopSend, MM_NOTHING,
|
||||
NULL,
|
||||
"This is taking too long..."
|
||||
);
|
||||
}
|
||||
|
||||
memset(&roundqueue, 0, sizeof(struct roundqueue));
|
||||
}
|
||||
|
||||
// Ripped out of LevelSelectHandler for use in queue clearing from cupselect.c
|
||||
void M_ClearQueueHandler(void)
|
||||
{
|
||||
while ((menuqueue.size + roundqueue.size) > ROUNDQUEUE_MAX)
|
||||
menuqueue.size--;
|
||||
|
||||
if (menuqueue.size)
|
||||
{
|
||||
S_StartSound(NULL, sfx_shldls);
|
||||
menuqueue.size--;
|
||||
}
|
||||
else if (roundqueue.size)
|
||||
{
|
||||
M_StartMessage("Queue Clearing",
|
||||
va(M_GetText(
|
||||
"There %s %d Round%s of play queued.\n"
|
||||
"\n"
|
||||
"Do you want to empty the queue?\n"
|
||||
),
|
||||
(roundqueue.size == 1 ? "is" : "are"),
|
||||
roundqueue.size,
|
||||
(roundqueue.size == 1 ? "" : "s")
|
||||
), &M_ClearQueueResponse, MM_YESNO,
|
||||
"Time to start fresh",
|
||||
"Not right now"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void M_LevelSelectHandler(INT32 choice)
|
||||
{
|
||||
const UINT8 pid = 0;
|
||||
|
|
@ -1074,38 +1234,9 @@ void M_LevelSelectHandler(INT32 choice)
|
|||
|
||||
if (M_MenuConfirmPressed(pid))
|
||||
{
|
||||
// Starting immediately OR importing queue
|
||||
|
||||
M_SetMenuDelay(pid);
|
||||
|
||||
while ((menuqueue.size + roundqueue.size) > ROUNDQUEUE_MAX)
|
||||
menuqueue.size--;
|
||||
|
||||
if (!levellist.canqueue || !menuqueue.size)
|
||||
{
|
||||
M_LevelSelected(levellist.cursor, true);
|
||||
}
|
||||
else if (netgame)
|
||||
{
|
||||
menuqueue.anchor = roundqueue.size;
|
||||
menuqueue.sending = 1;
|
||||
|
||||
M_StartMessage("Queueing Rounds",
|
||||
va(M_GetText(
|
||||
"Attempting to send %d Round%s...\n"
|
||||
"\n"
|
||||
"If this is taking longer than you\n"
|
||||
"expect, exit out of this message.\n"
|
||||
), menuqueue.size, (menuqueue.size == 1 ? "" : "s")
|
||||
), &M_MenuQueueStopSend, MM_NOTHING,
|
||||
NULL,
|
||||
"This is taking too long..."
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
M_MenuQueueSelectedLocal();
|
||||
}
|
||||
M_LevelConfirmHandler();
|
||||
}
|
||||
else if (levellist.canqueue && M_MenuButtonPressed(pid, MBT_Z))
|
||||
{
|
||||
|
|
@ -1138,30 +1269,7 @@ void M_LevelSelectHandler(INT32 choice)
|
|||
}
|
||||
else if (levellist.canqueue && M_MenuExtraPressed(pid))
|
||||
{
|
||||
while ((menuqueue.size + roundqueue.size) > ROUNDQUEUE_MAX)
|
||||
menuqueue.size--;
|
||||
|
||||
if (menuqueue.size)
|
||||
{
|
||||
S_StartSound(NULL, sfx_shldls);
|
||||
menuqueue.size--;
|
||||
}
|
||||
else if (roundqueue.size)
|
||||
{
|
||||
M_StartMessage("Queue Clearing",
|
||||
va(M_GetText(
|
||||
"There %s %d Round%s of play queued.\n"
|
||||
"\n"
|
||||
"Do you want to empty the queue?\n"
|
||||
),
|
||||
(roundqueue.size == 1 ? "is" : "are"),
|
||||
roundqueue.size,
|
||||
(roundqueue.size == 1 ? "" : "s")
|
||||
), &M_ClearQueueResponse, MM_YESNO,
|
||||
"Time to start fresh",
|
||||
"Not right now"
|
||||
);
|
||||
}
|
||||
M_ClearQueueHandler();
|
||||
}
|
||||
else if (M_MenuBackPressed(pid))
|
||||
{
|
||||
|
|
@ -1176,9 +1284,20 @@ void M_LevelSelectHandler(INT32 choice)
|
|||
|
||||
void M_LevelSelectTick(void)
|
||||
{
|
||||
if (menuqueue.clearing)
|
||||
{
|
||||
if (roundqueue.size != 0)
|
||||
return;
|
||||
menuqueue.clearing = false;
|
||||
if (!menuqueue.cupqueue)
|
||||
M_StopMessage(MA_NONE);
|
||||
else
|
||||
menuqueue.cupqueue = false;
|
||||
}
|
||||
|
||||
if (!menuqueue.sending)
|
||||
return;
|
||||
|
||||
|
||||
if ((menuqueue.sending <= menuqueue.size) // Sending
|
||||
&& (roundqueue.size >= menuqueue.anchor)) // Didn't get it wiped
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2796,6 +2796,7 @@ void V_DrawStringScaled(
|
|||
if (nodanceoverride)
|
||||
{
|
||||
dance = false;
|
||||
cyoff = 0;
|
||||
}
|
||||
}
|
||||
else if (c == V_STRINGDANCE)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue