Compare commits
280 commits
692390feb7
...
8f198aeff8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f198aeff8 | ||
|
|
97b34e3e7c | ||
|
|
46bb9e41ee | ||
|
|
0d2f2e106c | ||
|
|
1e01b387df | ||
|
|
d3b8f9f3a6 | ||
|
|
1e1404162e | ||
|
|
df819b303d | ||
|
|
671b4e1f3d | ||
|
|
169ddc1533 | ||
|
|
93e679298e | ||
|
|
ee9579b950 | ||
|
|
75d232e9b3 | ||
|
|
d56031e657 | ||
|
|
62fab4b7b2 | ||
|
|
d75402b37e | ||
|
|
3cfca7dbf8 | ||
|
|
b749cc117d | ||
|
|
35bbf39f47 | ||
|
|
2430bc7e50 | ||
|
|
e266fb723a | ||
|
|
95d032889f | ||
|
|
0cffa16a45 | ||
|
|
28c4ebd968 | ||
|
|
b2d3da4aa2 | ||
|
|
44ec1d9ef5 | ||
|
|
e4a9561261 | ||
|
|
99a6d1aefa | ||
|
|
6c26d96910 | ||
|
|
37012cfc60 | ||
|
|
f551718fd2 | ||
|
|
74973764e2 | ||
|
|
0c2d8eefc2 | ||
|
|
a08c097a20 | ||
|
|
f60e499f91 | ||
|
|
db315f72ac | ||
|
|
e098598a3d | ||
|
|
eade241d3b | ||
|
|
003bef11ae | ||
|
|
31ac81fe93 | ||
|
|
3778520ee6 | ||
|
|
1f2cc02db4 | ||
|
|
179db51639 | ||
|
|
8340be41a1 | ||
|
|
602a6d5e3f | ||
|
|
10671fff5a | ||
|
|
29ca3d2ecd | ||
|
|
318ae2ef6b | ||
|
|
023f75097f | ||
|
|
eab3a88d2a | ||
|
|
aaf91e38cb | ||
|
|
87300944fa | ||
|
|
dcc5b41075 | ||
|
|
2780d33436 | ||
|
|
5ea5b11902 | ||
|
|
87337da97c | ||
|
|
83bc2dc9fb | ||
|
|
5babac8249 | ||
|
|
35292fca34 | ||
|
|
61bb7c8013 | ||
|
|
f46382f902 | ||
|
|
797c708262 | ||
|
|
a437e70376 | ||
|
|
922db84289 | ||
|
|
c3bf7e643d | ||
|
|
c5a2ae1431 | ||
|
|
bc4fb8a9c6 | ||
|
|
eea55ee9a1 | ||
|
|
c427ef90fa | ||
|
|
1cc556ade9 | ||
|
|
88f275879d | ||
|
|
4efb810721 | ||
|
|
f523c2f069 | ||
|
|
855d25ae13 | ||
|
|
e5d866eb6f | ||
|
|
3d8d167cf4 | ||
|
|
85817c57d3 | ||
|
|
f68f5dd7fd | ||
|
|
2cbfd46ddd | ||
|
|
01d2c486d1 | ||
|
|
6bc4e4f63a | ||
|
|
321f6c9e1b | ||
|
|
3f39e18456 | ||
|
|
41188a66e4 | ||
|
|
093b17987f | ||
|
|
474e613354 | ||
|
|
9dc0bdc31e | ||
|
|
5d419b48bb | ||
|
|
9df538fe32 | ||
|
|
5beb1619d5 | ||
|
|
fb5b72a600 | ||
|
|
17e92d25f1 | ||
|
|
0a74900e19 | ||
|
|
6d20c8fcbf | ||
|
|
7a86b59fc8 | ||
|
|
76c17ec7b9 | ||
|
|
5f9406cca0 | ||
|
|
5c6da29657 | ||
|
|
0b1f458fb9 | ||
|
|
eff9283bef | ||
|
|
4553420b71 | ||
|
|
9acbd66a9e | ||
|
|
0d87f8a662 | ||
|
|
91f71a3cf5 | ||
|
|
b769bcd295 | ||
|
|
eb4d4717e5 | ||
|
|
01b2f9d5b0 | ||
|
|
4495ae6b4c | ||
|
|
703afe7992 | ||
|
|
4cebf26be3 | ||
|
|
fbe224bce3 | ||
|
|
31aea3cd97 | ||
|
|
78a9947662 | ||
|
|
3b489df3db | ||
|
|
e2fba0195c | ||
|
|
de3a843974 | ||
|
|
fba66c4084 | ||
|
|
e5c97ca233 | ||
|
|
49c0b2c00e | ||
|
|
de5a8594b9 | ||
|
|
aba9e23a0d | ||
|
|
ca3d533771 | ||
|
|
7de3cc3b25 | ||
|
|
ffa7850bb6 | ||
|
|
dbabd84715 | ||
|
|
044e8c6ec1 | ||
|
|
4a1618829b | ||
|
|
b36b327a00 | ||
|
|
b6c34067bb | ||
|
|
6512d71e4e | ||
|
|
fd65151d50 | ||
|
|
2e588d3516 | ||
|
|
2f337ee3d6 | ||
|
|
0362a0dff4 | ||
|
|
bb1f65fcc1 | ||
|
|
7c7368fe93 | ||
|
|
d0ab031a71 | ||
|
|
bfc55ed016 | ||
|
|
2f69f46a0a | ||
|
|
96c1fc4bd1 | ||
|
|
7ee04cdaaa | ||
|
|
e180d7720e | ||
|
|
18d54fc07b | ||
|
|
8b2626165b | ||
|
|
9c30e7a422 | ||
|
|
d3bad05bf9 | ||
|
|
869f0f8256 | ||
|
|
7871bab697 | ||
|
|
b2595045fc | ||
|
|
1c33caa84e | ||
|
|
858162f333 | ||
|
|
c8c2d828de | ||
|
|
ea54e3f08a | ||
|
|
9568ff843b | ||
|
|
a0cd60b9a2 | ||
|
|
693374c5c1 | ||
|
|
3be59c8100 | ||
|
|
43732fe21d | ||
|
|
bb3e543fb7 | ||
|
|
8a6a2b5bf3 | ||
|
|
77e1e3fe38 | ||
|
|
33348e7c92 | ||
|
|
6b6594e430 | ||
|
|
4dc40f0256 | ||
|
|
12dc3798a7 | ||
|
|
3f611cf6d2 | ||
|
|
c204314ae9 | ||
|
|
9109ce58cc | ||
|
|
24bceed8f1 | ||
|
|
93896b5e68 | ||
|
|
14fb1048fe | ||
|
|
f517163a77 | ||
|
|
0e0964dd18 | ||
|
|
3ab2e769c5 | ||
|
|
990390fd5c | ||
|
|
7197c2e3de | ||
|
|
e39d1ecfaf | ||
|
|
f359a53756 | ||
|
|
4917fcde50 | ||
|
|
7c7f5ac1d0 | ||
|
|
8b9bead8ba | ||
|
|
9541e4fb52 | ||
|
|
a4d89f3083 | ||
|
|
4a79ad337b | ||
|
|
ef481b936f | ||
|
|
5f97577561 | ||
|
|
95eea4d1af | ||
|
|
72596e8d03 | ||
|
|
2a669a665e | ||
|
|
c906ccc7a1 | ||
|
|
ab5ded6ae9 | ||
|
|
d00e674088 | ||
|
|
8348ed1c05 | ||
|
|
ecefb06069 | ||
|
|
ea1426b947 | ||
|
|
30fbf1c4c8 | ||
|
|
dd1790749e | ||
|
|
14052daede | ||
|
|
1aed9067bb | ||
|
|
7cdb502874 | ||
|
|
2acf3725e3 | ||
|
|
3aa7217155 | ||
|
|
c3eeffc95c | ||
|
|
02212a9974 | ||
|
|
fa1b3b9431 | ||
|
|
93a4824549 | ||
|
|
462d18186c | ||
|
|
50c7019f44 | ||
|
|
51ccb74a12 | ||
|
|
4cd813575c | ||
|
|
12be394af2 | ||
|
|
9136d1da75 | ||
|
|
04dd587ef4 | ||
|
|
b702e17547 | ||
|
|
dc99014d2a | ||
|
|
a77f95dabc | ||
|
|
a02fbacf01 | ||
|
|
b87868d07e | ||
|
|
0911633728 | ||
|
|
d98dd3e2dd | ||
|
|
4a5c7fcae2 | ||
|
|
9352d77c92 | ||
|
|
659777a974 | ||
|
|
59872a8181 | ||
|
|
6461678967 | ||
|
|
7a27d853f9 | ||
|
|
2686503602 | ||
|
|
2baf834265 | ||
|
|
e1f6fb1b68 | ||
|
|
0bbc485f3e | ||
|
|
3b475919d8 | ||
|
|
da3fe6f48a | ||
|
|
c8d3a223d8 | ||
|
|
d210c8b6bd | ||
|
|
bba37cf709 | ||
|
|
6acd057189 | ||
|
|
77d3e020cd | ||
|
|
aa71181c5a | ||
|
|
1c52947194 | ||
|
|
9ab3987e0d | ||
|
|
7b58b8b488 | ||
|
|
54bb823b31 | ||
|
|
12b56701aa | ||
|
|
9c361fe3ff | ||
|
|
0ce6a91b6d | ||
|
|
d8a9f516f4 | ||
|
|
1edc6b736d | ||
|
|
ce19f740f8 | ||
|
|
e4ef793be4 | ||
|
|
1a9dfea86d | ||
|
|
51a4be0a3f | ||
|
|
af2bc96101 | ||
|
|
a8dc5774e2 | ||
|
|
5082c343c8 | ||
|
|
9874a36f91 | ||
|
|
8340e170a8 | ||
|
|
7c4d9f7dc8 | ||
|
|
e92362f36c | ||
|
|
31cca408a2 | ||
|
|
c82557529e | ||
|
|
1ef672ab9c | ||
|
|
15b83e9fc3 | ||
|
|
89f0ef836b | ||
|
|
874687e9c7 | ||
|
|
5b18297c68 | ||
|
|
7f12437c76 | ||
|
|
4192ca3da6 | ||
|
|
be8e46506a | ||
|
|
779fcde3f4 | ||
|
|
306f66e09c | ||
|
|
7b5a4c5529 | ||
|
|
8c480f9606 | ||
|
|
e1db6d59cd | ||
|
|
35483ccd84 | ||
|
|
b0e25dcc9c | ||
|
|
9986f9aaef | ||
|
|
41c584638e | ||
|
|
9ee41124c1 | ||
|
|
1eabec187a | ||
|
|
a2ecd5dbdd |
134 changed files with 8441 additions and 3940 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -19,6 +19,7 @@ Win32_LIB_ASM_Release
|
|||
*.opendb
|
||||
*.kate-swp
|
||||
/.vs
|
||||
/.vscode
|
||||
/debian
|
||||
/assets/debian
|
||||
/make
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ option(SRB2_CONFIG_TRACY "Compile with Tracy profiling enabled" OFF)
|
|||
option(SRB2_CONFIG_ASAN "Compile with AddressSanitizer (libasan)." OFF)
|
||||
set(SRB2_CONFIG_ASSET_DIRECTORY "" CACHE PATH "Path to directory that contains all asset files for the installer. If set, assets will be part of installation and cpack.")
|
||||
option(SRB2_CONFIG_LTO "Enable link time optimizations, improves performance at the cost of longer link times." ON)
|
||||
option(SRB2_CONFIG_TIDY "Enable clang tiny, checks compiled code for issues at the cost of longer compile times." OFF)
|
||||
|
||||
if(SRB2_CONFIG_ENABLE_TESTS)
|
||||
# https://github.com/catchorg/Catch2
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
BlanKart is a modification of SRB2Kart v2 Indev to make it closer to SRB2Kart gameplay while adding new features, and techincal improvements.
|
||||
|
||||
If you're interested in helping out, theres a matrix room located [here](https://matrix.to/#/#blankart:matrix.org)!
|
||||
|
||||
# Notice
|
||||
|
||||
This is still in active development and things are going to change. If you find any bugs besure to report to the [issue tracker](https://codeberg.org/NepDisk/blankart/issues)!
|
||||
|
|
@ -9,6 +11,7 @@ This is still in active development and things are going to change. If you find
|
|||
## Techincal Features
|
||||
- Full Support for UDMF, Terrain, Bots, ACS, New Waypoints and many other technical features backported from Ring Racers. Also includes some extensions to these features such as bot drifting, new terrain effects and map header toggles.
|
||||
- Ring Racers' software renderer and its multithreading.
|
||||
- Native support for both SRB2Kart and Ring Racers custom skins.
|
||||
- Backwards compatiblity with most SRB2Kart maps, assets* and scripts\*.
|
||||
- A map patching system to allow custom map things to be patched onto maps. Useful for adding rings, waypoints and other objects to existing maps.
|
||||
- Support for many SRB2Kart v1 custom client extensions from Saturn and other clients such as vote themes.
|
||||
|
|
@ -54,7 +57,7 @@ git clone https://codeberg.org/NepDisk/blankart.git
|
|||
cd blankart
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G "MSYS Makefiles" ..
|
||||
cmake -G "MSYS Makefiles" .. -DCMAKE_POLICY_VERSION_MINIMUM=3.5
|
||||
make -j$(nproc)
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,10 @@ if(SRB2_CONFIG_ASAN)
|
|||
target_link_options(SRB2SDL2 PRIVATE -fsanitize=address)
|
||||
endif()
|
||||
|
||||
if(SRB2_CONFIG_TIDY)
|
||||
set(CMAKE_CXX_CLANG_TIDY "clang-tidy;-checks=*")
|
||||
endif()
|
||||
|
||||
add_subdirectory(blua)
|
||||
add_subdirectory(blan)
|
||||
add_subdirectory(sdl)
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ p_user.c
|
|||
p_slopes.c
|
||||
p_sweep.cpp
|
||||
p_test.cpp
|
||||
p_deepcopy.cpp
|
||||
tables.c
|
||||
r_bsp.cpp
|
||||
r_data.c
|
||||
|
|
@ -116,6 +117,9 @@ lua_hudlib_drawlist.c
|
|||
lua_followerlib.c
|
||||
lua_terrainlib.c
|
||||
lua_waypointslib.c
|
||||
lua_vectorlib.c
|
||||
lua_matrixlib.c
|
||||
lua_quaternionlib.c
|
||||
k_kart.c
|
||||
k_collide.c
|
||||
k_color.c
|
||||
|
|
@ -128,6 +132,7 @@ k_bot.cpp
|
|||
k_botitem.cpp
|
||||
k_botsearch.cpp
|
||||
k_cluster.cpp
|
||||
k_odds.c
|
||||
k_grandprix.c
|
||||
k_boss.c
|
||||
k_hud.c
|
||||
|
|
|
|||
|
|
@ -10,8 +10,10 @@
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifdef __GNUC__
|
||||
#ifndef __clang__
|
||||
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
#endif
|
||||
#include "Thread.hpp"
|
||||
|
||||
#include "Array.hpp"
|
||||
|
|
|
|||
|
|
@ -10,8 +10,10 @@
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifdef __GNUC__
|
||||
#ifndef __clang__
|
||||
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
#endif
|
||||
#include "Thread.hpp"
|
||||
|
||||
#include "Array.hpp"
|
||||
|
|
|
|||
|
|
@ -4310,6 +4310,12 @@ enum
|
|||
THING_PROP_HNEXT,
|
||||
THING_PROP_HPREV,
|
||||
THING_PROP_ITNEXT,
|
||||
THING_PROP_BAKEDXOFFSET,
|
||||
THING_PROP_BAKEDYOFFSET,
|
||||
THING_PROP_BAKEDZOFFSET,
|
||||
THING_PROP_BAKEDXPIVOT,
|
||||
THING_PROP_BAKEDYPIVOT,
|
||||
THING_PROP_BAKEDZPIVOT,
|
||||
THING_PROP__MAX
|
||||
};
|
||||
|
||||
|
|
@ -4479,6 +4485,12 @@ bool CallFunc_GetThingProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, A
|
|||
PROP_MOBJ(THING_PROP_HNEXT, hnext)
|
||||
PROP_MOBJ(THING_PROP_HPREV, hprev)
|
||||
PROP_MOBJ(THING_PROP_ITNEXT, itnext)
|
||||
PROP_INT(THING_PROP_BAKEDXOFFSET, bakexoff)
|
||||
PROP_INT(THING_PROP_BAKEDYOFFSET, bakeyoff)
|
||||
PROP_INT(THING_PROP_BAKEDZOFFSET, bakezoff)
|
||||
PROP_INT(THING_PROP_BAKEDXPIVOT, bakexpiv)
|
||||
PROP_INT(THING_PROP_BAKEDYPIVOT, bakeypiv)
|
||||
PROP_INT(THING_PROP_BAKEDZPIVOT, bakezpiv)
|
||||
default:
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "GetThingProperty type %d out of range (expected 0 - %d).\n", property, THING_PROP__MAX-1);
|
||||
|
|
|
|||
|
|
@ -260,9 +260,8 @@ ACSVM::Thread *Environment::allocThread()
|
|||
ACSVM::ModuleName Environment::getModuleName(char const *str, size_t len)
|
||||
{
|
||||
ACSVM::String *name = getString(str, len);
|
||||
lumpnum_t lump = W_CheckNumForNameInFolder(str, "ACS/");
|
||||
|
||||
return { name, nullptr, static_cast<size_t>(lump) };
|
||||
return { name, nullptr, static_cast<size_t>(false) };
|
||||
}
|
||||
|
||||
void Environment::loadModule(ACSVM::Module *module)
|
||||
|
|
@ -272,22 +271,34 @@ void Environment::loadModule(ACSVM::Module *module)
|
|||
size_t lumpLen = 0;
|
||||
std::vector<ACSVM::Byte> data;
|
||||
|
||||
if (name->i == (size_t)LUMPERROR)
|
||||
lumpnum_t lumpnum = LUMPERROR;
|
||||
|
||||
if (name->i) // this module is from a map!
|
||||
{
|
||||
// No lump given for module.
|
||||
CONS_Alert(CONS_WARNING, "Could not find ACS module \"%s\"; scripts will not function properly!\n", name->s->str);
|
||||
return; //throw ACSVM::ReadError("file open failure");
|
||||
INT32 mapnum = G_MapNumber(name->s->str);
|
||||
if (mapnum < NEXTMAP_INVALID)
|
||||
lumpnum = mapheaderinfo[mapnum]->lumpnum;
|
||||
}
|
||||
else // just a lump
|
||||
{
|
||||
lumpnum = W_CheckNumForNameInFolder(name->s->str, "ACS/");
|
||||
}
|
||||
|
||||
lumpLen = W_LumpLength(name->i);
|
||||
if (lumpnum == LUMPERROR)
|
||||
{
|
||||
// No lump given for module.
|
||||
throw ACSVM::ReadError("invalid lump");
|
||||
}
|
||||
|
||||
if (W_IsLumpWad(name->i) == true || lumpLen == 0)
|
||||
lumpLen = W_LumpLength(lumpnum);
|
||||
|
||||
if (W_IsLumpWad(lumpnum) == true || lumpLen == 0)
|
||||
{
|
||||
CONS_Debug(DBG_SETUP, "Attempting to load ACS module from the BEHAVIOR lump of map '%s'...\n", name->s->str);
|
||||
|
||||
// The lump given is a virtual resource.
|
||||
// Try to grab a BEHAVIOR lump from inside of it.
|
||||
virtres_t *vRes = vres_GetMap(name->i);
|
||||
virtres_t *vRes = vres_GetMap(lumpnum);
|
||||
auto _ = srb2::finally([vRes]() { vres_Free(vRes); });
|
||||
|
||||
virtlump_t *vLump = vres_Find(vRes, "BEHAVIOR");
|
||||
|
|
@ -309,7 +320,7 @@ void Environment::loadModule(ACSVM::Module *module)
|
|||
ACSVM::Byte *lump = static_cast<ACSVM::Byte *>(Z_Calloc(lumpLen, PU_STATIC, nullptr));
|
||||
auto _ = srb2::finally([lump]() { Z_Free(lump); });
|
||||
|
||||
W_ReadLump(name->i, lump);
|
||||
W_ReadLump(lumpnum, lump);
|
||||
data.insert(data.begin(), lump, lump + lumpLen);
|
||||
}
|
||||
|
||||
|
|
@ -327,9 +338,7 @@ void Environment::loadModule(ACSVM::Module *module)
|
|||
}
|
||||
else
|
||||
{
|
||||
// Unlike Hexen, a BEHAVIOR lump is not required.
|
||||
// Simply ignore in this instance.
|
||||
CONS_Debug(DBG_SETUP, "ACS module has no data, ignoring...\n");
|
||||
throw ACSVM::ReadError("file empty");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -143,14 +143,22 @@ void ACS_LoadLevelScripts(size_t mapID)
|
|||
map->active = true;
|
||||
|
||||
// Insert BEHAVIOR lump into the list.
|
||||
virtres_t *vRes = vres_GetMap(mapheaderinfo[mapID]->lumpnum);
|
||||
auto _ = srb2::finally([vRes]() { vres_Free(vRes); });
|
||||
|
||||
// Unlike Hexen, a BEHAVIOR lump is not required.
|
||||
// Simply ignore in this instance.
|
||||
virtlump_t *vLump = vres_Find(vRes, "BEHAVIOR");
|
||||
if (vLump != nullptr && vLump->size > 0)
|
||||
{
|
||||
ACSVM::ModuleName name = ACSVM::ModuleName(
|
||||
env->getString( mapheaderinfo[mapID]->lumpname ),
|
||||
nullptr,
|
||||
mapheaderinfo[mapID]->lumpnum
|
||||
static_cast<size_t>(true)
|
||||
);
|
||||
|
||||
modules.push_back(env->getModule(name));
|
||||
CONS_Debug(DBG_SETUP, "Found BEHAVIOR lump.\n");
|
||||
}
|
||||
|
||||
if (modules.empty() == false)
|
||||
|
|
@ -517,8 +525,10 @@ void ACS_Archive(savebuffer_t *save)
|
|||
std::ostream stream{&buffer};
|
||||
ACSVM::Serial serial{stream};
|
||||
|
||||
#if 0
|
||||
// Enable debug signatures.
|
||||
serial.signs = true;
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
|
|
|
|||
|
|
@ -89,8 +89,12 @@ int luaO_rawequalObj (const TValue *t1, const TValue *t2) {
|
|||
|
||||
int luaO_str2d (const char *s, lua_Number *result) {
|
||||
char *endptr;
|
||||
double r = lua_str2number(s, &endptr);
|
||||
*result = (lua_Number)r;
|
||||
long r = lua_str2number(s, &endptr);
|
||||
if (r > INT32_MAX)
|
||||
r = INT32_MAX;
|
||||
else if (r < INT32_MIN)
|
||||
r = INT32_MIN;
|
||||
*result = (lua_Number)r;
|
||||
if (endptr == s) return 0; /* conversion failed */
|
||||
if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */
|
||||
*result = cast_num(strtoul(s, &endptr, 16));
|
||||
|
|
|
|||
|
|
@ -677,6 +677,9 @@ static void CON_MoveConsole(void)
|
|||
|
||||
INT32 CON_ShiftChar(INT32 ch)
|
||||
{
|
||||
if (I_UseNativeKeyboard())
|
||||
return ch;
|
||||
|
||||
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
|
||||
{
|
||||
if (shiftdown ^ capslock)
|
||||
|
|
@ -838,7 +841,7 @@ boolean CON_Responder(event_t *ev)
|
|||
// check for console toggle key
|
||||
if (ev->type != ev_console)
|
||||
{
|
||||
if (modeattacking || metalrecording || marathonmode)
|
||||
if ((modeattacking && !demo.playback) || metalrecording || marathonmode)
|
||||
return false;
|
||||
|
||||
if (ev->data1 >= NUMKEYS) // See also: HUD_Responder
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ UINT32 playerpacketlosstable[MAXPLAYERS];
|
|||
UINT32 playerdelaytable[MAXPLAYERS]; // mindelay values.
|
||||
|
||||
static tic_t lowest_lag;
|
||||
boolean server_lagless;
|
||||
SINT8 server_lagless;
|
||||
|
||||
SINT8 nodetoplayer[MAXNETNODES];
|
||||
SINT8 nodetoplayer2[MAXNETNODES]; // say the numplayer for this node if any (splitscreen)
|
||||
|
|
@ -1424,6 +1424,10 @@ static void SendAskInfo(INT32 node)
|
|||
|
||||
serverelem_t serverlist[MAXSERVERLIST];
|
||||
UINT32 serverlistcount = 0;
|
||||
UINT32 serverlistultimatecount = 0;
|
||||
|
||||
static boolean resendserverlistnode[MAXNETNODES];
|
||||
static tic_t serverlistepoch;
|
||||
|
||||
static void SL_ClearServerList(INT32 connectedserver)
|
||||
{
|
||||
|
|
@ -1436,6 +1440,7 @@ static void SL_ClearServerList(INT32 connectedserver)
|
|||
serverlist[i].node = 0;
|
||||
}
|
||||
serverlistcount = 0;
|
||||
memset(resendserverlistnode, 0, sizeof resendserverlistnode);
|
||||
M_UpdateNumServerPages();
|
||||
}
|
||||
|
||||
|
|
@ -1453,6 +1458,8 @@ static void SL_InsertServer(serverinfo_pak* info, SINT8 node)
|
|||
{
|
||||
UINT32 i;
|
||||
|
||||
resendserverlistnode[node] = false;
|
||||
|
||||
// search if not already on it
|
||||
i = SL_SearchServer(node);
|
||||
if (i == UINT32_MAX)
|
||||
|
|
@ -1493,6 +1500,8 @@ void CL_QueryServerList (msg_server_t *server_list)
|
|||
|
||||
CL_UpdateServerList();
|
||||
|
||||
serverlistepoch = I_GetTime();
|
||||
|
||||
for (i = 0; server_list[i].header.buffer[0]; i++)
|
||||
{
|
||||
// Make sure MS version matches our own, to
|
||||
|
|
@ -1505,19 +1514,42 @@ void CL_QueryServerList (msg_server_t *server_list)
|
|||
if (node == -1)
|
||||
break; // no more node free
|
||||
SendAskInfo(node);
|
||||
// Force close the connection so that servers can't eat
|
||||
// up nodes forever if we never get a reply back from them
|
||||
// (usually when they've not forwarded their ports).
|
||||
//
|
||||
// Don't worry, we'll get in contact with the working
|
||||
// servers again when they send SERVERINFO to us later!
|
||||
//
|
||||
// (Note: as a side effect this probably means every
|
||||
// server in the list will probably be using the same node (e.g. node 1),
|
||||
// not that it matters which nodes they use when
|
||||
// the connections are closed afterwards anyway)
|
||||
// -- Monster Iestyn 12/11/18
|
||||
Net_CloseConnection(node|FORCECLOSE);
|
||||
resendserverlistnode[node] = true;
|
||||
// Leave this node open. It'll be closed if the
|
||||
// request times out (CL_TimeoutServerList).
|
||||
}
|
||||
}
|
||||
|
||||
serverlistultimatecount = i;
|
||||
}
|
||||
|
||||
#define SERVERLISTRESENDRATE NEWTICRATE
|
||||
|
||||
void CL_TimeoutServerList(void)
|
||||
{
|
||||
if (netgame && serverlistultimatecount > serverlistcount)
|
||||
{
|
||||
const tic_t timediff = I_GetTime() - serverlistepoch;
|
||||
const tic_t timetoresend = timediff % SERVERLISTRESENDRATE;
|
||||
const boolean timedout = timediff > connectiontimeout;
|
||||
|
||||
if (timedout || (timediff > 0 && timetoresend == 0))
|
||||
{
|
||||
INT32 node;
|
||||
|
||||
for (node = 1; node < MAXNETNODES; ++node)
|
||||
{
|
||||
if (resendserverlistnode[node])
|
||||
{
|
||||
if (timedout)
|
||||
Net_CloseConnection(node|FORCECLOSE);
|
||||
else
|
||||
SendAskInfo(node);
|
||||
}
|
||||
}
|
||||
|
||||
if (timedout)
|
||||
serverlistultimatecount = serverlistcount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1887,8 +1919,10 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
|
|||
break;
|
||||
}
|
||||
|
||||
#ifndef HAVE_THREADS
|
||||
if (curl_running)
|
||||
CURLGetFile();
|
||||
#endif
|
||||
|
||||
if (waitmore)
|
||||
break; // exit the case
|
||||
|
|
@ -3387,8 +3421,8 @@ consvar_t cv_resynchattempts = CVAR_INIT ("resynchattempts", "2", CV_SAVE, resyn
|
|||
consvar_t cv_blamecfail = CVAR_INIT ("blamecfail", "Off", CV_SAVE, CV_OnOff, NULL);
|
||||
|
||||
// max file size to send to a player (in kilobytes)
|
||||
static CV_PossibleValue_t maxsend_cons_t[] = {{0, "MIN"}, {51200, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_maxsend = CVAR_INIT ("maxsend", "51200", CV_SAVE, maxsend_cons_t, NULL);
|
||||
static CV_PossibleValue_t maxsend_cons_t[] = {{-1, "MIN"}, {999999999, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_maxsend = CVAR_INIT ("maxsend", "204800", CV_SAVE, maxsend_cons_t, NULL);
|
||||
consvar_t cv_noticedownload = CVAR_INIT ("noticedownload", "Off", CV_SAVE, CV_OnOff, NULL);
|
||||
|
||||
// Speed of file downloading (in packets per tic)
|
||||
|
|
@ -5741,6 +5775,17 @@ boolean TryRunTics(tic_t realtics)
|
|||
COM_BufTicker();
|
||||
if (mapchangepending)
|
||||
D_MapChange(-1, 0, encoremode, false, 2, false, fromlevelselect); // finish the map change
|
||||
|
||||
// fun fact: this used to be located in NetUpdate!
|
||||
// as it turns out, reloading the level in rendering code is a very bad idea!
|
||||
if (client)
|
||||
{
|
||||
// If the client just finished redownloading the game state, load it
|
||||
if (cl_redownloadinggamestate && fileneeded[0].status == FS_FOUND)
|
||||
CL_ReloadReceivedSavegame();
|
||||
|
||||
hu_redownloadinggamestate = cl_redownloadinggamestate;
|
||||
}
|
||||
}
|
||||
|
||||
NetUpdate();
|
||||
|
|
@ -5944,6 +5989,7 @@ static tic_t gametime = 0;
|
|||
static void UpdatePingTable(void)
|
||||
{
|
||||
tic_t fastest;
|
||||
tic_t slowest;
|
||||
tic_t lag;
|
||||
|
||||
INT32 i;
|
||||
|
|
@ -5954,6 +6000,7 @@ static void UpdatePingTable(void)
|
|||
PingUpdate();
|
||||
|
||||
fastest = 0;
|
||||
slowest = 0;
|
||||
|
||||
// update node latency values so we can take an average later.
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
@ -5968,14 +6015,19 @@ static void UpdatePingTable(void)
|
|||
lag = playerpingtable[i];
|
||||
if (! fastest || lag < fastest)
|
||||
fastest = lag;
|
||||
|
||||
if (! slowest || lag > slowest)
|
||||
slowest = lag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (server_lagless)
|
||||
if (server_lagless == 1)
|
||||
lowest_lag = 0;
|
||||
else
|
||||
else if (server_lagless == 0)
|
||||
lowest_lag = fastest;
|
||||
else if (server_lagless == -1)
|
||||
lowest_lag = slowest;
|
||||
|
||||
// Don't gentleman below your mindelay
|
||||
if (lowest_lag < (tic_t)cv_mindelay.value)
|
||||
|
|
@ -6184,12 +6236,7 @@ void NetUpdate(void)
|
|||
|
||||
if (client)
|
||||
{
|
||||
// If the client just finished redownloading the game state, load it
|
||||
if (cl_redownloadinggamestate && fileneeded[0].status == FS_FOUND)
|
||||
CL_ReloadReceivedSavegame();
|
||||
|
||||
CL_SendClientCmd(); // Send tic cmd
|
||||
hu_redownloadinggamestate = cl_redownloadinggamestate;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -425,6 +425,7 @@ struct serverelem_t
|
|||
|
||||
extern serverelem_t serverlist[MAXSERVERLIST];
|
||||
extern UINT32 serverlistcount;
|
||||
extern UINT32 serverlistultimatecount;
|
||||
extern INT32 mapchangepending;
|
||||
|
||||
// Points inside doomcom
|
||||
|
|
@ -488,7 +489,7 @@ extern UINT32 playerpacketlosstable[MAXPLAYERS];
|
|||
extern UINT32 playerdelaytable[MAXPLAYERS];
|
||||
extern tic_t servermaxping;
|
||||
|
||||
extern boolean server_lagless;
|
||||
extern SINT8 server_lagless;
|
||||
extern consvar_t cv_mindelay;
|
||||
|
||||
extern consvar_t cv_netticbuffer, cv_allownewplayer, cv_maxplayers, cv_joindelay;
|
||||
|
|
@ -569,6 +570,7 @@ void CL_ClearPlayer(INT32 playernum);
|
|||
void CL_RemovePlayer(INT32 playernum, kickreason_t reason);
|
||||
void CL_QueryServerList(msg_server_t *list);
|
||||
void CL_UpdateServerList(void);
|
||||
void CL_TimeoutServerList(void);
|
||||
// Is there a game running
|
||||
boolean Playing(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "am_map.h"
|
||||
#include "console.h"
|
||||
#include "d_net.h"
|
||||
#include "d_netfil.h"
|
||||
#include "f_finale.h"
|
||||
#include "f_dscredits.hpp"
|
||||
#include "g_game.h"
|
||||
|
|
@ -89,8 +90,8 @@
|
|||
#define ASSET_HASH_TEXTURES_KART 0xb4211b2f32b6a291
|
||||
#define ASSET_HASH_CHARS_KART 0x1e68a3e01aa5c68b
|
||||
#define ASSET_HASH_MAPS_KART 0x38558ed00da41ce9
|
||||
#define ASSET_HASH_MAIN_PK3 0xd9cf115699dc58c4
|
||||
#define ASSET_HASH_MAPPATCH_PK3 0xf1c7678ded3a2d1b
|
||||
#define ASSET_HASH_MAIN_PK3 0xd0bf225260f749ed
|
||||
#define ASSET_HASH_MAPPATCH_PK3 0xefe28bb9de73a31c
|
||||
#define ASSET_HASH_BONUSCHARS_KART 0x60e6f13d822a7461
|
||||
#ifdef USE_PATCH_FILE
|
||||
#define ASSET_HASH_PATCH_PK3 0x0000000000000000
|
||||
|
|
@ -1187,6 +1188,7 @@ void D_StartTitle(void)
|
|||
|
||||
// okay, stop now
|
||||
// (otherwise the game still thinks we're playing!)
|
||||
CURLAbortFile();
|
||||
SV_StopServer();
|
||||
SV_ResetServer();
|
||||
|
||||
|
|
@ -1704,8 +1706,6 @@ void D_SRB2Main(void)
|
|||
memset(timelimits, 0, sizeof(timelimits));
|
||||
memset(pointlimits, 0, sizeof(pointlimits));
|
||||
|
||||
timelimits[GT_BATTLE] = 2;
|
||||
|
||||
CON_SetLoadingProgress(LOADED_HUINIT);
|
||||
|
||||
if (modifiedgame)
|
||||
|
|
|
|||
|
|
@ -1006,7 +1006,7 @@ static boolean ShouldDropPacket(void)
|
|||
{
|
||||
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
|
||||
return (packetdropquantity[netbuffer->packettype])
|
||||
|| (packetdroprate != 0 && rand() < (RAND_MAX * (packetdroprate / 100.f))) || packetdroprate == 100;
|
||||
|| (packetdroprate != 0 && rand() < (RAND_MAX * (packetdroprate / 100))) || packetdroprate == 100;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
182
src/d_netcmd.c
182
src/d_netcmd.c
|
|
@ -160,8 +160,10 @@ static void KartChaining_OnChange(void);
|
|||
static void KartSlipdash_OnChange(void);
|
||||
static void KartSlopeBoost_OnChange(void);
|
||||
static void KartDrafting_OnChange(void);
|
||||
static void KartAirDrop_OnChange(void);
|
||||
static void KartItemBreaker_OnChange(void);
|
||||
static void KartInvinType_OnChange(void);
|
||||
static void KartBumpSpark_OnChange(void);
|
||||
|
||||
static void Schedule_OnChange(void);
|
||||
|
||||
|
|
@ -184,6 +186,7 @@ static void Command_AcceptInvite_f(void);
|
|||
static void Command_RejectInvite_f(void);
|
||||
static void Command_LeaveParty_f(void);
|
||||
|
||||
static void Command_Addfilelocal(void);
|
||||
static void Command_Addfile(void);
|
||||
static void Command_ListWADS_f(void);
|
||||
static void Command_ListDoomednums_f(void);
|
||||
|
|
@ -444,7 +447,9 @@ static CV_PossibleValue_t kartbot_cons_t[] = {
|
|||
{13,"Lv.MAX"},
|
||||
{0, NULL}
|
||||
};
|
||||
static CV_PossibleValue_t kartbot_cap_cons_t[] = {{0, "MIN"}, {MAXPLAYERS, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_kartbot = CVAR_INIT ("kartbot", "0", CV_NETVAR, kartbot_cons_t, NULL);
|
||||
consvar_t cv_kartbot_cap = CVAR_INIT ("kartbot_cap", "0", CV_NETVAR, kartbot_cap_cons_t, NULL);
|
||||
consvar_t cv_kartbot_modifiermax = CVAR_INIT ("kartbot_modifiermax", "1.0", CV_NETVAR|CV_FLOAT, CV_Unsigned, NULL);
|
||||
consvar_t cv_kartbot_basetrackcomplexity = CVAR_INIT ("kartbot_basetrackcomplexity", "-7000", CV_NETVAR, CV_Signed, NULL);
|
||||
|
||||
|
|
@ -455,9 +460,13 @@ consvar_t cv_kartrings = CVAR_INIT ("kartrings", "No", CV_NETVAR|CV_CALL|CV_NOIN
|
|||
|
||||
static CV_PossibleValue_t ringsmin_cons_t[] = {{INT8_MIN, "MIN"}, {0, "MAX"}, {0, NULL}};
|
||||
static CV_PossibleValue_t ringsmax_cons_t[] = {{0, "MIN"}, {INT8_MAX, "MAX"}, {0, NULL}};
|
||||
|
||||
consvar_t cv_kartringsmin = CVAR_INIT ("kartringsmin", "-20", CV_NETVAR, ringsmin_cons_t, NULL);
|
||||
consvar_t cv_kartringsmax = CVAR_INIT ("kartringsmax", "20", CV_NETVAR, ringsmax_cons_t, NULL);
|
||||
|
||||
static CV_PossibleValue_t ringsstart_cons_t[] = {{INT8_MIN, "MIN"}, {INT8_MAX, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_kartringsstart = CVAR_INIT ("kartringsstart", "5", CV_NETVAR, ringsstart_cons_t, NULL);
|
||||
|
||||
// Stacking related
|
||||
consvar_t cv_kartstacking = CVAR_INIT ("kartstacking", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, KartStacking_OnChange);
|
||||
consvar_t cv_kartstacking_diminishparam = CVAR_INIT ("kartstacking_diminishparam", "0.32", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
|
||||
|
|
@ -494,6 +503,10 @@ consvar_t cv_kartstacking_start_speedboost = CVAR_INIT ("vanillaboost_start_spee
|
|||
consvar_t cv_kartstacking_start_accelboost = CVAR_INIT ("vanillaboost_start_accelboost", "6.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
|
||||
consvar_t cv_kartstacking_start_stackable = CVAR_INIT ("vanillaboost_start_stackable", "On", CV_NETVAR, CV_OnOff, NULL);
|
||||
|
||||
consvar_t cv_kartstacking_walltransfer_speedboost = CVAR_INIT ("vanillaboost_walltransfer_speedboost", "0.10", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
|
||||
consvar_t cv_kartstacking_walltransfer_accelboost = CVAR_INIT ("vanillaboost_walltransfer_accelboost", "5.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
|
||||
consvar_t cv_kartstacking_walltransfer_stackable = CVAR_INIT ("vanillaboost_walltransfer_stackable", "On", CV_NETVAR, CV_OnOff, NULL);
|
||||
|
||||
consvar_t cv_kartstacking_drift_speedboost = CVAR_INIT ("vanillaboost_drift_speedboost", "0.25", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
|
||||
consvar_t cv_kartstacking_drift_accelboost = CVAR_INIT ("vanillaboost_drift_accelboost", "4.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
|
||||
consvar_t cv_kartstacking_drift_stackable = CVAR_INIT ("vanillaboost_drift_stackable", "On", CV_NETVAR, CV_OnOff, NULL);
|
||||
|
|
@ -510,10 +523,10 @@ consvar_t cv_kartstacking_slope_accelboost = CVAR_INIT ("vanillaboost_slope_acce
|
|||
consvar_t cv_kartstacking_slope_stackable = CVAR_INIT ("vanillaboost_slope_stackable", "On", CV_NETVAR, CV_OnOff, NULL);
|
||||
|
||||
// Max speed for high speeds
|
||||
consvar_t cv_kartstacking_drafting_minspeed = CVAR_INIT ("vanillaboost_draft_minspeed", "0.22", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
|
||||
consvar_t cv_kartstacking_drafting_minspeed = CVAR_INIT ("vanillaboost_draft_minspeed", "0.16", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
|
||||
|
||||
// Max speed for low speeds
|
||||
consvar_t cv_kartstacking_drafting_maxspeed = CVAR_INIT ("vanillaboost_draft_maxspeed", "0.32", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
|
||||
consvar_t cv_kartstacking_drafting_maxspeed = CVAR_INIT ("vanillaboost_draft_maxspeed", "0.26", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
|
||||
|
||||
consvar_t cv_kartchaining = CVAR_INIT ("kartchaining", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, KartChaining_OnChange);
|
||||
consvar_t cv_kartchainingoffroad = CVAR_INIT ("kartchaining_chainoffroad", "No", CV_NETVAR, CV_YesNo, NULL);
|
||||
|
|
@ -526,9 +539,19 @@ consvar_t cv_kartusepwrlv = CVAR_INIT ("kartusepwrlv", "Yes", CV_NETVAR, CV_YesN
|
|||
|
||||
consvar_t cv_kartpurpledrift = CVAR_INIT ("kartpurpledrift", "No", CV_NETVAR, CV_YesNo, KartPurpleDrift_OnChange);
|
||||
|
||||
consvar_t cv_kartbumpspark = CVAR_INIT ("kartbumpspark", "No", CV_NETVAR, CV_YesNo, NULL);
|
||||
static CV_PossibleValue_t bumpspark_cons_t[] = {{BUMPSPARK_NONE, "Off"},
|
||||
{BUMPSPARK_NOCHARGE, "Remove Charge Only"},
|
||||
{BUMPSPARK_RESET100, "Reset to Blue"},
|
||||
{BUMPSPARK_ALL, "On"},
|
||||
{0, NULL}};
|
||||
|
||||
consvar_t cv_kartbumpspring = CVAR_INIT ("kartbumpspring", "No", CV_NETVAR, CV_YesNo, NULL);
|
||||
consvar_t cv_kartbumpspark = CVAR_INIT("kartbumpspark",
|
||||
"Remove Charge Only",
|
||||
CV_NETVAR | CV_CALL,
|
||||
bumpspark_cons_t,
|
||||
KartBumpSpark_OnChange);
|
||||
|
||||
consvar_t cv_kartbumpspring = CVAR_INIT ("kartbumpspring", "Yes", CV_NETVAR, CV_YesNo, NULL);
|
||||
|
||||
consvar_t cv_kartslipdash = CVAR_INIT ("kartslipdash", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, KartSlipdash_OnChange);
|
||||
|
||||
|
|
@ -539,6 +562,19 @@ consvar_t cv_kartdrafting_closedraft = CVAR_INIT ("kartdrafting_closedraft", "Of
|
|||
consvar_t cv_kartdrafting_closedeadzone = CVAR_INIT ("kartdrafting_closedeadzone", "640", CV_NETVAR|CV_CHEAT, CV_Unsigned, NULL);
|
||||
consvar_t cv_kartdrafting_basedistance = CVAR_INIT ("kartdrafting_basedistance", "2560", CV_NETVAR|CV_CHEAT, CV_Unsigned, NULL);
|
||||
|
||||
consvar_t cv_kartairdrop = CVAR_INIT ("kartairdrop", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, KartAirDrop_OnChange);
|
||||
|
||||
// Odds distancing
|
||||
#define MAXODDSDIST ((INT32_MAX / FRACUNIT) / 2)
|
||||
static CV_PossibleValue_t distvar_cons_t[] = {{1, "MIN"}, {MAXODDSDIST, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_kartoddsdist = CVAR_INIT ("kartoddsdist", "2048", CV_NETVAR|CV_CHEAT, distvar_cons_t, NULL);
|
||||
consvar_t cv_kartlegacyoddsdist = CVAR_INIT ("kartlegacyoddsdist", "2048", CV_NETVAR|CV_CHEAT, distvar_cons_t, NULL);
|
||||
|
||||
// SPB distance; no legacy modifiers currently (lazy)
|
||||
static CV_PossibleValue_t spbdist_cons_t[] = {{1, "MIN"}, {32000, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_kartspbdist = CVAR_INIT ("kartspbdist", "8192", CV_NETVAR|CV_CHEAT, spbdist_cons_t, NULL);
|
||||
#undef MAXODDSDIST
|
||||
|
||||
// Invincibility modifiers
|
||||
static CV_PossibleValue_t invintype_cons_t[] = {{0, "Legacy"}, {1, "Alternative"}, {0, NULL}};
|
||||
consvar_t cv_kartinvintype = CVAR_INIT ("kartinvintype", "Legacy", CV_NETVAR|CV_CALL, invintype_cons_t, KartInvinType_OnChange);
|
||||
|
|
@ -609,7 +645,7 @@ consvar_t cv_rollingdemos = CVAR_INIT ("rollingdemos", "On", CV_SAVE, CV_OnOff,
|
|||
|
||||
static CV_PossibleValue_t pointlimit_cons_t[] = {{1, "MIN"}, {MAXSCORE, "MAX"}, {0, "None"}, {0, NULL}};
|
||||
consvar_t cv_pointlimit = CVAR_INIT ("pointlimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, pointlimit_cons_t, PointLimit_OnChange);
|
||||
static CV_PossibleValue_t timelimit_cons_t[] = {{1, "MIN"}, {30, "MAX"}, {0, "None"}, {0, NULL}};
|
||||
static CV_PossibleValue_t timelimit_cons_t[] = {{1, "MIN"}, {99999, "MAX"}, {0, "None"}, {0, NULL}};
|
||||
consvar_t cv_timelimit = CVAR_INIT ("timelimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, timelimit_cons_t, TimeLimit_OnChange);
|
||||
|
||||
static CV_PossibleValue_t numlaps_cons_t[] = {{0, "MIN"}, {MAX_LAPS, "MAX"}, {-1, "Map default"}, {0, NULL}};
|
||||
|
|
@ -634,7 +670,8 @@ consvar_t cv_nettimeout = CVAR_INIT ("nettimeout", "210", CV_CALL|CV_SAVE, netti
|
|||
consvar_t cv_jointimeout = CVAR_INIT ("jointimeout", "210", CV_CALL|CV_SAVE, nettimeout_cons_t, JoinTimeout_OnChange);
|
||||
consvar_t cv_maxping = CVAR_INIT ("maxdelay", "20", CV_SAVE, CV_Unsigned, NULL);
|
||||
|
||||
consvar_t cv_lagless = CVAR_INIT ("lagless", "On", CV_SAVE|CV_NETVAR|CV_CALL, CV_OnOff, Lagless_OnChange);
|
||||
static CV_PossibleValue_t lagless_cons_t[] = {{-1, "Worst"}, {0, "Best"}, {1, "Lagless"}, {0, NULL}};
|
||||
consvar_t cv_lagless = CVAR_INIT ("lagless", "Lagless", CV_SAVE|CV_NETVAR|CV_CALL, lagless_cons_t, Lagless_OnChange);
|
||||
|
||||
static CV_PossibleValue_t pingtimeout_cons_t[] = {{8, "MIN"}, {120, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_pingtimeout = CVAR_INIT ("maxdelaytimeout", "10", CV_SAVE, pingtimeout_cons_t, NULL);
|
||||
|
|
@ -646,13 +683,24 @@ consvar_t cv_showping = CVAR_INIT ("showping", "Always", CV_SAVE, showping_cons_
|
|||
static CV_PossibleValue_t pingmeasurement_cons_t[] = {{0, "Frames"}, {1, "Milliseconds"}, {0, NULL}};
|
||||
consvar_t cv_pingmeasurement = CVAR_INIT ("pingmeasurement", "Frames", CV_SAVE, pingmeasurement_cons_t, NULL);
|
||||
|
||||
consvar_t cv_showlapemblem = CVAR_INIT ("showlapemblem", "On", CV_SAVE, CV_OnOff, NULL);
|
||||
static CV_PossibleValue_t showlapemblem_cons_t[] = {{0, "Off"}, {1, "Emblem Only"}, {2, "Splits Only"}, {3, "All"}, {0, NULL}};
|
||||
consvar_t cv_showlapemblem = CVAR_INIT ("showlapemblem", "All", CV_SAVE, showlapemblem_cons_t, NULL);
|
||||
|
||||
static CV_PossibleValue_t lapemblemmode_cons_t[] = {{0, "Centre"}, {1, "Race Timer"}, {0, NULL}};
|
||||
consvar_t cv_lapemblemmode = CVAR_INIT ("lapemblemmode", "Centre", CV_SAVE, lapemblemmode_cons_t, NULL);
|
||||
|
||||
// Race splits rely on showlapemblem, so toggling them off isn't really necessary.
|
||||
static CV_PossibleValue_t racesplits_cons_t[] = {{1, "Next"}, {2, "Leader"}, {0, NULL}};
|
||||
consvar_t cv_racesplits = CVAR_INIT ("racesplits", "Leader", CV_SAVE, racesplits_cons_t, NULL);
|
||||
|
||||
consvar_t cv_showminimapnames = CVAR_INIT ("showminimapnames", "Off", CV_SAVE, CV_OnOff, NULL);
|
||||
static CV_PossibleValue_t minimapdot_cons_t[] = {{0, "Off"}, {1, "Dot"}, {2, "Headlight"}, {0, NULL}};
|
||||
consvar_t cv_showminimapangle = CVAR_INIT ("showminimapangle", "Dot", CV_SAVE, minimapdot_cons_t, NULL);
|
||||
consvar_t cv_minihead = CVAR_INIT ("smallminimapplayers", "Off", CV_SAVE, CV_OnOff, NULL);
|
||||
|
||||
static CV_PossibleValue_t spinoutroll_cons_t[] = {{0, "Off"}, {1, "Minimap Only"}, {2, "Rankings Only"}, {3, "Minimap+Rankings"}, {0, NULL}};
|
||||
consvar_t cv_spinoutroll = CVAR_INIT ("spinoutroll", "Minimap+Rankings", CV_SAVE, spinoutroll_cons_t, NULL);
|
||||
|
||||
consvar_t cv_showviewpointtext = CVAR_INIT ("showviewpointtext", "On", CV_SAVE, CV_OnOff, NULL);
|
||||
|
||||
// Intermission time Tails 04-19-2002
|
||||
|
|
@ -688,6 +736,8 @@ consvar_t cv_schedule = CVAR_INIT ("schedule", "On", CV_NETVAR|CV_CALL, CV_OnOff
|
|||
|
||||
consvar_t cv_automate = CVAR_INIT ("automate", "On", CV_NETVAR, CV_OnOff, NULL);
|
||||
|
||||
consvar_t cv_debugmappatch = CVAR_INIT ("debugmappatch", "", 0, NULL, NULL);
|
||||
|
||||
char timedemo_name[256];
|
||||
boolean timedemo_csv;
|
||||
char timedemo_csv_id[256];
|
||||
|
|
@ -851,6 +901,7 @@ void D_RegisterServerCommands(void)
|
|||
COM_AddCommand("showmap", Command_Showmap_f);
|
||||
COM_AddCommand("maphash", Command_Maphash_f);
|
||||
|
||||
COM_AddCommand("addfilelocal", Command_Addfilelocal);
|
||||
COM_AddCommand("addfile", Command_Addfile);
|
||||
COM_AddCommand("listwad", Command_ListWADS_f);
|
||||
COM_AddCommand("listmapthings", Command_ListDoomednums_f);
|
||||
|
|
@ -964,7 +1015,10 @@ void D_RegisterServerCommands(void)
|
|||
CV_RegisterVar(&cv_showminimapnames);
|
||||
CV_RegisterVar(&cv_showminimapangle);
|
||||
CV_RegisterVar(&cv_minihead);
|
||||
CV_RegisterVar(&cv_spinoutroll);
|
||||
CV_RegisterVar(&cv_showlapemblem);
|
||||
CV_RegisterVar(&cv_lapemblemmode);
|
||||
CV_RegisterVar(&cv_racesplits);
|
||||
CV_RegisterVar(&cv_showviewpointtext);
|
||||
|
||||
CV_RegisterVar(&cv_schedule);
|
||||
|
|
@ -997,6 +1051,8 @@ void D_RegisterServerCommands(void)
|
|||
#ifdef LUA_ALLOW_BYTECODE
|
||||
COM_AddCommand("dumplua", Command_Dumplua_f);
|
||||
#endif
|
||||
|
||||
CV_RegisterVar(&cv_debugmappatch);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
|
|
@ -1113,6 +1169,7 @@ void D_RegisterClientCommands(void)
|
|||
CV_RegisterVar(&cv_skin[i]);
|
||||
CV_RegisterVar(&cv_follower[i]);
|
||||
CV_RegisterVar(&cv_followercolor[i]);
|
||||
CV_RegisterVar(&cv_jitterlegacy[i]);
|
||||
}
|
||||
|
||||
// preferred number of players
|
||||
|
|
@ -1288,7 +1345,6 @@ void D_RegisterClientCommands(void)
|
|||
|
||||
CV_RegisterVar(&cv_connectawaittime);
|
||||
CV_RegisterVar(&cv_serverinfoscreen);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1930,6 +1986,7 @@ enum {
|
|||
WP_KICKSTARTACCEL = 1<<0,
|
||||
WP_SHRINKME = 1<<1,
|
||||
WP_FLIPCAM = 1<<2,
|
||||
WP_LEGACYJITTER = 1<<3
|
||||
};
|
||||
|
||||
void WeaponPref_Send(UINT8 ssplayer)
|
||||
|
|
@ -1945,6 +2002,9 @@ void WeaponPref_Send(UINT8 ssplayer)
|
|||
if (cv_flipcam[ssplayer].value)
|
||||
prefs |= WP_FLIPCAM;
|
||||
|
||||
if (!(cv_jitterlegacy[ssplayer].value))
|
||||
prefs |= WP_LEGACYJITTER;
|
||||
|
||||
UINT8 buf[2];
|
||||
buf[0] = prefs;
|
||||
buf[1] = cv_mindelay.value;
|
||||
|
|
@ -1967,6 +2027,9 @@ void WeaponPref_Save(UINT8 **cp, INT32 playernum)
|
|||
if (player->pflags & PF_FLIPCAM)
|
||||
prefs |= WP_FLIPCAM;
|
||||
|
||||
if (player->jitterlegacy)
|
||||
prefs |= WP_LEGACYJITTER;
|
||||
|
||||
WRITEUINT8(*cp, prefs);
|
||||
}
|
||||
|
||||
|
|
@ -1977,6 +2040,7 @@ void WeaponPref_Parse(UINT8 **cp, INT32 playernum)
|
|||
UINT8 prefs = READUINT8(*cp);
|
||||
|
||||
player->pflags &= ~(PF_KICKSTARTACCEL|PF_SHRINKME|PF_FLIPCAM);
|
||||
player->jitterlegacy = false;
|
||||
|
||||
if (prefs & WP_KICKSTARTACCEL)
|
||||
player->pflags |= PF_KICKSTARTACCEL;
|
||||
|
|
@ -1987,6 +2051,9 @@ void WeaponPref_Parse(UINT8 **cp, INT32 playernum)
|
|||
if (prefs & WP_FLIPCAM)
|
||||
player->pflags |= PF_FLIPCAM;
|
||||
|
||||
if (prefs & WP_LEGACYJITTER)
|
||||
player->jitterlegacy = true;
|
||||
|
||||
if (leveltime < 2)
|
||||
{
|
||||
// BAD HACK: No other place I tried to slot this in
|
||||
|
|
@ -4743,6 +4810,44 @@ static void Got_RunSOCcmd(UINT8 **cp, INT32 playernum)
|
|||
G_SetGameModified(true, false);
|
||||
}
|
||||
|
||||
static void Command_Addfilelocal(void)
|
||||
{
|
||||
const char *fn;
|
||||
INT32 i;
|
||||
size_t docompat = COM_CheckPartialParm("-c");
|
||||
size_t nocompat = COM_CheckPartialParm("-n");
|
||||
wadcompat_t compat = WC_AUTO;
|
||||
|
||||
if (docompat && nocompat)
|
||||
{
|
||||
CONS_Printf(M_GetText("Please specify only one of -c or -n\n"));
|
||||
return;
|
||||
}
|
||||
else if (docompat)
|
||||
compat = WC_ON;
|
||||
else if (nocompat)
|
||||
compat = WC_OFF;
|
||||
|
||||
if (COM_Argc() != 2 + (docompat || nocompat))
|
||||
{
|
||||
CONS_Printf(M_GetText("addfilelocal [-c|-n] <filename.pk3/wad/lua/soc>: Load local add-on\n"
|
||||
"-c forces compatmode, -n disables it.\n"));
|
||||
return;
|
||||
}
|
||||
else
|
||||
fn = COM_Argv(1);
|
||||
|
||||
// Disallow non-printing characters and semicolons.
|
||||
for (i = 0; fn[i] != '\0'; i++)
|
||||
if (!isprint(fn[i]) || fn[i] == ';')
|
||||
return;
|
||||
|
||||
// Add any wad file, ignoring checks for if it contains complex things like
|
||||
// lua. Great for complex but client-side customizations, like different
|
||||
// level cards or anything like that.
|
||||
P_AddWadFile(fn, compat, true);
|
||||
}
|
||||
|
||||
/** Adds a pwad at runtime.
|
||||
* Searches for sounds, maps, music, new images.
|
||||
*/
|
||||
|
|
@ -4836,7 +4941,7 @@ static void Command_Addfile(void)
|
|||
// Add file on your client directly if it is trivial, or you aren't in a netgame.
|
||||
if (!(netgame || multiplayer) || musiconly)
|
||||
{
|
||||
P_AddWadFile(fn, compat);
|
||||
P_AddWadFile(fn, compat, false);
|
||||
addedfiles[numfilesadded++] = fn;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -4976,7 +5081,7 @@ static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
|
|||
|
||||
ncs = findfile(filename, filehash, true);
|
||||
|
||||
if (ncs != FS_FOUND || !P_AddWadFile(filename, compat))
|
||||
if (ncs != FS_FOUND || !P_AddWadFile(filename, compat, false))
|
||||
{
|
||||
Command_ExitGame_f();
|
||||
if (ncs == FS_FOUND)
|
||||
|
|
@ -5319,9 +5424,8 @@ static void JoinTimeout_OnChange(void)
|
|||
static void
|
||||
Lagless_OnChange (void)
|
||||
{
|
||||
/* don't back out of dishonesty, or go lagless after playing honestly */
|
||||
if (cv_lagless.value && gamestate == GS_LEVEL)
|
||||
server_lagless = true;
|
||||
if (gamestate == GS_LEVEL)
|
||||
server_lagless = cv_lagless.value;
|
||||
}
|
||||
|
||||
UINT32 timelimitintics = 0;
|
||||
|
|
@ -7518,6 +7622,40 @@ static void KartDrafting_OnChange(void)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void KartAirDrop_OnChange(void)
|
||||
{
|
||||
if (K_CanChangeRules() == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!K_AirDropActive() && cv_kartairdrop.value)
|
||||
{
|
||||
if (leveltime < starttime)
|
||||
{
|
||||
airdropactive = true;
|
||||
CONS_Printf(M_GetText("Air Drop has been turned \"On\".\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Printf(M_GetText("Air Drop will be turned \"On\" Next Round.\n"));
|
||||
}
|
||||
}
|
||||
else if (K_AirDropActive() && !cv_kartairdrop.value)
|
||||
{
|
||||
if (leveltime < starttime)
|
||||
{
|
||||
airdropactive = false;
|
||||
CONS_Printf(M_GetText("Drafting has been turned \"Off\".\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Printf(M_GetText("Drafting will be turned \"Off\" next round.\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void KartItemBreaker_OnChange(void)
|
||||
{
|
||||
if (K_CanChangeRules() == false)
|
||||
|
|
@ -7558,6 +7696,24 @@ static void KartInvinType_OnChange(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void KartBumpSpark_OnChange(void)
|
||||
{
|
||||
if (K_CanChangeRules() == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (leveltime < starttime)
|
||||
{
|
||||
CONS_Printf(M_GetText("Bump spark type has been changed to \"%s\".\n"), cv_kartbumpspark.string);
|
||||
bumpsparkactive = (UINT8)cv_kartbumpspark.value;
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Printf(M_GetText("Bump spark type will be changed to \"%s\" next round.\n"), cv_kartbumpspark.string);
|
||||
}
|
||||
}
|
||||
|
||||
static void Schedule_OnChange(void)
|
||||
{
|
||||
size_t i;
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@ extern consvar_t cv_kartgametypepreference;
|
|||
extern consvar_t cv_kartspeedometer;
|
||||
extern consvar_t cv_kartvoices;
|
||||
extern consvar_t cv_kartbot;
|
||||
extern consvar_t cv_kartbot_cap;
|
||||
extern consvar_t cv_kartbot_modifiermax;
|
||||
extern consvar_t cv_kartbot_basetrackcomplexity;
|
||||
extern consvar_t cv_karteliminatelast;
|
||||
|
|
@ -124,6 +125,7 @@ extern consvar_t cv_kartusepwrlv;
|
|||
extern consvar_t cv_kartrings;
|
||||
extern consvar_t cv_kartringsmin;
|
||||
extern consvar_t cv_kartringsmax;
|
||||
extern consvar_t cv_kartringsstart;
|
||||
|
||||
extern consvar_t cv_kartstacking;
|
||||
extern consvar_t cv_kartstacking_diminishparam;
|
||||
|
|
@ -158,6 +160,10 @@ extern consvar_t cv_kartstacking_start_speedboost;
|
|||
extern consvar_t cv_kartstacking_start_accelboost;
|
||||
extern consvar_t cv_kartstacking_start_stackable;
|
||||
|
||||
extern consvar_t cv_kartstacking_walltransfer_speedboost;
|
||||
extern consvar_t cv_kartstacking_walltransfer_accelboost;
|
||||
extern consvar_t cv_kartstacking_walltransfer_stackable;
|
||||
|
||||
extern consvar_t cv_kartstacking_drift_speedboost;
|
||||
extern consvar_t cv_kartstacking_drift_accelboost;
|
||||
extern consvar_t cv_kartstacking_drift_stackable;
|
||||
|
|
@ -196,6 +202,12 @@ extern consvar_t cv_kartinvindistmul;
|
|||
extern consvar_t cv_kartinvin_maxtime;
|
||||
extern consvar_t cv_kartinvin_midtime;
|
||||
|
||||
extern consvar_t cv_kartairdrop;
|
||||
|
||||
extern consvar_t cv_kartoddsdist;
|
||||
extern consvar_t cv_kartlegacyoddsdist;
|
||||
extern consvar_t cv_kartspbdist;
|
||||
|
||||
extern consvar_t cv_encorevotes;
|
||||
|
||||
extern consvar_t cv_votetime;
|
||||
|
|
@ -225,8 +237,11 @@ extern consvar_t cv_pingmeasurement;
|
|||
extern consvar_t cv_showminimapnames;
|
||||
extern consvar_t cv_showminimapangle;
|
||||
extern consvar_t cv_minihead;
|
||||
extern consvar_t cv_spinoutroll;
|
||||
|
||||
extern consvar_t cv_showlapemblem;
|
||||
extern consvar_t cv_lapemblemmode;
|
||||
extern consvar_t cv_racesplits;
|
||||
extern consvar_t cv_showviewpointtext;
|
||||
|
||||
extern consvar_t cv_skipmapcheck;
|
||||
|
|
@ -239,6 +254,8 @@ extern consvar_t cv_director;
|
|||
|
||||
extern consvar_t cv_schedule;
|
||||
|
||||
extern consvar_t cv_debugmappatch;
|
||||
|
||||
extern char timedemo_name[256];
|
||||
extern boolean timedemo_csv;
|
||||
extern char timedemo_csv_id[256];
|
||||
|
|
|
|||
178
src/d_netfil.c
178
src/d_netfil.c
|
|
@ -98,6 +98,9 @@ static filetran_t transfer[MAXNETNODES];
|
|||
INT32 fileneedednum; // Number of files needed to join the server
|
||||
fileneeded_t fileneeded[MAX_WADFILES]; // List of needed files
|
||||
static tic_t lasttimeackpacketsent = 0;
|
||||
#ifdef HAVE_THREADS
|
||||
static I_mutex downloadmutex;
|
||||
#endif
|
||||
|
||||
// For resuming failed downloads
|
||||
typedef struct
|
||||
|
|
@ -164,7 +167,7 @@ UINT8 *PutFileNeeded(UINT16 firstfile)
|
|||
for (; i < numwadfiles; i++) //mainwads+1, otherwise we start on the first mainwad
|
||||
{
|
||||
// If it has only music/sound lumps, don't put it in the list
|
||||
if (i >= NUMMAINWADS && !wadfiles[i]->important)
|
||||
if (!wadfiles[i]->important)
|
||||
continue;
|
||||
|
||||
if (firstfile)
|
||||
|
|
@ -173,6 +176,8 @@ UINT8 *PutFileNeeded(UINT16 firstfile)
|
|||
continue;
|
||||
}
|
||||
|
||||
// CONS_Printf("putting %d (%s) - mw %d\n", i, wadfiles[i]->filename, mainwads);
|
||||
|
||||
nameonly(strcpy(wadfilename, wadfiles[i]->filename));
|
||||
|
||||
// Look below at the WRITE macros to understand what these numbers mean.
|
||||
|
|
@ -197,7 +202,7 @@ UINT8 *PutFileNeeded(UINT16 firstfile)
|
|||
// Store in the upper four bits
|
||||
if (!cv_downloading.value)
|
||||
filestatus += (2 << 4); // Won't send
|
||||
else if ((wadfiles[i]->filesize <= (UINT32)cv_maxsend.value * 1024))
|
||||
else if (cv_maxsend.value == -1 || (wadfiles[i]->filesize <= (UINT32)cv_maxsend.value * 1024))
|
||||
filestatus += (1 << 4); // Will send if requested
|
||||
// else
|
||||
// filestatus += (0 << 4); -- Won't send, too big
|
||||
|
|
@ -555,7 +560,10 @@ INT32 CL_CheckFiles(void)
|
|||
#endif
|
||||
for (i = 0; i < fileneedednum || j < numwadfiles;)
|
||||
{
|
||||
if (j < numwadfiles && !wadfiles[j]->important)
|
||||
// CONS_Printf("checking %d of %d / %d of %d?\n", i, fileneedednum, j, numwadfiles);
|
||||
// CONS_Printf("i: %s / j: %s \n", fileneeded[i].filename, wadfiles[j]->filename);
|
||||
|
||||
if (j < numwadfiles && !wadfiles[j]->important && !wadfiles[j]->localfile)
|
||||
{
|
||||
// Unimportant on our side.
|
||||
++j;
|
||||
|
|
@ -565,7 +573,9 @@ INT32 CL_CheckFiles(void)
|
|||
// If this test is true, we've reached the end of one file list
|
||||
// and the other still has a file that's important
|
||||
if (i >= fileneedednum || j >= numwadfiles)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
// For the sake of speed, only bother with a hash check
|
||||
if (wadfiles[j]->hash != fileneeded[i].hash)
|
||||
|
|
@ -646,7 +656,7 @@ boolean CL_LoadServerFiles(void)
|
|||
continue; // Already loaded
|
||||
else if (fileneeded[i].status == FS_FOUND)
|
||||
{
|
||||
P_PartialAddWadFile(fileneeded[i].filename, fileneeded[i].compatmode ? WC_ON : WC_OFF);
|
||||
P_PartialAddWadFile(fileneeded[i].filename, fileneeded[i].compatmode ? WC_ON : WC_OFF, false);
|
||||
G_SetGameModified(true, false);
|
||||
fileneeded[i].status = FS_OPEN;
|
||||
return false;
|
||||
|
|
@ -947,7 +957,7 @@ static boolean AddFileToSendQueue(INT32 node, const char *filename, UINT8 fileid
|
|||
}
|
||||
|
||||
// Handle huge file requests (i.e. bigger than cv_maxsend.value KB)
|
||||
if (wadfiles[i]->filesize > (UINT32)cv_maxsend.value * 1024)
|
||||
if (cv_maxsend.value != -1 && wadfiles[i]->filesize > (UINT32)cv_maxsend.value * 1024)
|
||||
{
|
||||
// Too big
|
||||
// Don't inform client (client sucks, man)
|
||||
|
|
@ -1793,10 +1803,13 @@ void CURLPrepareFile(const char* url, int dfilenum)
|
|||
I_Error("Attempted to download files in -nodownload mode");
|
||||
#endif
|
||||
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
if (!multi_handle)
|
||||
{
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
multi_handle = curl_multi_init();
|
||||
}
|
||||
|
||||
http_handle = curl_easy_init();
|
||||
multi_handle = curl_multi_init();
|
||||
|
||||
if (http_handle && multi_handle)
|
||||
{
|
||||
|
|
@ -1847,99 +1860,134 @@ void CURLPrepareFile(const char* url, int dfilenum)
|
|||
curl_multi_add_handle(multi_handle, http_handle);
|
||||
|
||||
curl_multi_perform(multi_handle, &curl_runninghandles);
|
||||
|
||||
curl_starttime = time(NULL);
|
||||
curl_running = true;
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
I_spawn_thread("http-download", (I_thread_fn)CURLGetFile, NULL);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void CURLAbortFile(void)
|
||||
{
|
||||
curl_running = false;
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
// lock and unlock to wait for the download thread to exit
|
||||
I_lock_mutex(&downloadmutex);
|
||||
I_unlock_mutex(downloadmutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CURLGetFile(void)
|
||||
{
|
||||
CURLMcode mc; /* return code used by curl_multi_wait() */
|
||||
CURLcode easyres; /* Return from easy interface */
|
||||
int numfds;
|
||||
CURLMsg *m; /* for picking up messages with the transfer status */
|
||||
CURL *e;
|
||||
int msgs_left; /* how many messages are left */
|
||||
const char *easy_handle_error;
|
||||
long response_code = 0;
|
||||
static char *filename;
|
||||
|
||||
if (curl_runninghandles)
|
||||
{
|
||||
curl_multi_perform(multi_handle, &curl_runninghandles);
|
||||
#ifdef HAVE_THREADS
|
||||
boolean running = true;
|
||||
|
||||
/* wait for activity, timeout or "nothing" */
|
||||
mc = curl_multi_wait(multi_handle, NULL, 0, 1000, &numfds);
|
||||
|
||||
if (mc != CURLM_OK)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "curl_multi_wait() failed, code %d.\n", mc);
|
||||
return;
|
||||
}
|
||||
curl_curfile->currentsize = curl_dlnow;
|
||||
curl_curfile->totalsize = curl_dltotal;
|
||||
}
|
||||
|
||||
/* See how the transfers went */
|
||||
while ((m = curl_multi_info_read(multi_handle, &msgs_left)))
|
||||
I_lock_mutex(&downloadmutex);
|
||||
while (running && curl_running)
|
||||
#endif
|
||||
{
|
||||
if (m && (m->msg == CURLMSG_DONE))
|
||||
if (curl_runninghandles)
|
||||
{
|
||||
e = m->easy_handle;
|
||||
easyres = m->data.result;
|
||||
filename = Z_StrDup(curl_realname);
|
||||
nameonly(filename);
|
||||
if (easyres != CURLE_OK)
|
||||
{
|
||||
if (easyres == CURLE_HTTP_RETURNED_ERROR)
|
||||
curl_easy_getinfo(e, CURLINFO_RESPONSE_CODE, &response_code);
|
||||
curl_multi_perform(multi_handle, &curl_runninghandles);
|
||||
|
||||
easy_handle_error = (response_code) ? va("HTTP reponse code %ld", response_code) : curl_easy_strerror(easyres);
|
||||
curl_curfile->status = FS_FALLBACK;
|
||||
curl_curfile->currentsize = curl_origfilesize;
|
||||
curl_curfile->totalsize = curl_origtotalfilesize;
|
||||
curl_failedwebdownload = true;
|
||||
fclose(curl_curfile->file);
|
||||
remove(curl_curfile->filename);
|
||||
CONS_Printf(M_GetText("Failed to download %s (%s)\n"), filename, easy_handle_error);
|
||||
/* wait for activity, timeout or "nothing" */
|
||||
mc = curl_multi_wait(multi_handle, NULL, 0, 1000, NULL);
|
||||
|
||||
if (mc != CURLM_OK)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "curl_multi_wait() failed, code %d.\n", mc);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
fclose(curl_curfile->file);
|
||||
curl_curfile->currentsize = curl_dlnow;
|
||||
curl_curfile->totalsize = curl_dltotal;
|
||||
}
|
||||
|
||||
if (checkfilehash(curl_curfile->filename, curl_curfile->hash) == FS_BADHASH)
|
||||
/* See how the transfers went */
|
||||
while ((m = curl_multi_info_read(multi_handle, &msgs_left)))
|
||||
{
|
||||
if (m && (m->msg == CURLMSG_DONE))
|
||||
{
|
||||
#ifdef HAVE_THREADS
|
||||
running = false;
|
||||
#endif
|
||||
e = m->easy_handle;
|
||||
easyres = m->data.result;
|
||||
|
||||
char *filename = Z_StrDup(curl_realname);
|
||||
nameonly(filename);
|
||||
|
||||
if (easyres != CURLE_OK)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("HTTP Download of %s finished but is corrupt or has been modified\n"), filename);
|
||||
long response_code = 0;
|
||||
|
||||
if (easyres == CURLE_HTTP_RETURNED_ERROR)
|
||||
curl_easy_getinfo(e, CURLINFO_RESPONSE_CODE, &response_code);
|
||||
|
||||
easy_handle_error = (response_code) ? va("HTTP response code %ld", response_code) : curl_easy_strerror(easyres);
|
||||
curl_curfile->status = FS_FALLBACK;
|
||||
curl_curfile->currentsize = curl_origfilesize;
|
||||
curl_curfile->totalsize = curl_origtotalfilesize;
|
||||
curl_failedwebdownload = true;
|
||||
fclose(curl_curfile->file);
|
||||
remove(curl_curfile->filename);
|
||||
CONS_Printf(M_GetText("Failed to download %s (%s)\n"), filename, easy_handle_error);
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Printf(M_GetText("Finished HTTP download of %s\n"), filename);
|
||||
downloadcompletednum++;
|
||||
downloadcompletedsize += curl_curfile->totalsize;
|
||||
curl_curfile->status = FS_FOUND;
|
||||
fclose(curl_curfile->file);
|
||||
|
||||
if (checkfilehash(curl_curfile->filename, curl_curfile->hash) == FS_BADHASH)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("HTTP Download of %s finished but is corrupt or has been modified\n"), filename);
|
||||
curl_curfile->status = FS_FALLBACK;
|
||||
curl_failedwebdownload = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Printf(M_GetText("Finished HTTP download of %s\n"), filename);
|
||||
downloadcompletednum++;
|
||||
downloadcompletedsize += curl_curfile->totalsize;
|
||||
curl_curfile->status = FS_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
Z_Free(filename);
|
||||
curl_curfile->file = NULL;
|
||||
#ifndef HAVE_THREADS
|
||||
curl_running = false;
|
||||
#endif
|
||||
curl_transfers--;
|
||||
curl_multi_remove_handle(multi_handle, e);
|
||||
curl_easy_cleanup(e);
|
||||
|
||||
if (!curl_transfers)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
Z_Free(filename);
|
||||
curl_curfile->file = NULL;
|
||||
curl_running = false;
|
||||
curl_transfers--;
|
||||
curl_multi_remove_handle(multi_handle, e);
|
||||
curl_easy_cleanup(e);
|
||||
|
||||
if (!curl_transfers)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!curl_transfers)
|
||||
if (!curl_transfers || !curl_running)
|
||||
{
|
||||
curl_multi_cleanup(multi_handle);
|
||||
curl_global_cleanup();
|
||||
multi_handle = NULL;
|
||||
}
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
curl_running = false;
|
||||
I_unlock_mutex(downloadmutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
HTTP_login *
|
||||
|
|
|
|||
|
|
@ -164,6 +164,7 @@ size_t nameonlylength(const char *s);
|
|||
|
||||
#ifdef HAVE_CURL
|
||||
void CURLPrepareFile(const char* url, int dfilenum);
|
||||
void CURLAbortFile(void);
|
||||
void CURLGetFile(void);
|
||||
HTTP_login * CURLGetLogin (const char *url, HTTP_login ***return_prev_next);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -40,11 +40,14 @@ extern "C" {
|
|||
typedef enum
|
||||
{
|
||||
SF_MACHINE = 1, // Beep boop. Are you a robot?
|
||||
SF_NOGIBS = 1<<1, // Does this kart smash into pieces?
|
||||
SF_OLDDEATH = 1<<2, // Kart V1 styled death animation
|
||||
SF_OLDDEATH = 1<<1, // Kart V1 styled death animation
|
||||
// free up to and including 1<<31
|
||||
} skinflags_t;
|
||||
|
||||
// Splits are per-lap in Blankart, but let's keep this as-is.
|
||||
// mine: pedantic; isn't MAX_LAPS = 99 here?
|
||||
#define MAXRACESPLITS 32
|
||||
|
||||
//
|
||||
// Player states.
|
||||
//
|
||||
|
|
@ -269,6 +272,18 @@ typedef enum
|
|||
khud_cardanimation, // Used to determine the position of some full-screen Battle Mode graphics
|
||||
khud_yougotem, // "You Got Em" gfx when hitting someone as a karma player via a method that gets you back in the game instantly
|
||||
|
||||
// Splits
|
||||
khud_splittime, // Delta between you and highest split
|
||||
khud_splitwin, // How to color/flag the split based on gaining/losing | ahead/behind
|
||||
khud_splittimer, // How long to show splits HUD
|
||||
khud_splitskin, // Skin index of the leading player
|
||||
khud_splitcolor, // Skincolor of the leading player
|
||||
khud_splitposition, // Who are we comparing to?
|
||||
|
||||
// Drifting
|
||||
khud_afterimagetime, // tics left for displaying afterimage
|
||||
khud_afterimagevalue, // what value the drift ended at
|
||||
|
||||
NUMKARTHUD
|
||||
} karthudtype_t;
|
||||
|
||||
|
|
@ -481,6 +496,15 @@ struct saltyhop_t
|
|||
fixed_t momz, zoffset; // erm... the mechanism....
|
||||
};
|
||||
|
||||
// enum for saved lap times
|
||||
typedef enum
|
||||
{
|
||||
LAP_CUR,
|
||||
LAP_BEST,
|
||||
LAP_LAST,
|
||||
LAP__MAX
|
||||
} laptime_e;
|
||||
|
||||
// ========================================================================
|
||||
// PLAYER STRUCTURE
|
||||
// ========================================================================
|
||||
|
|
@ -566,6 +590,9 @@ struct player_t
|
|||
// SRB2kart stuff
|
||||
INT32 kartstuff[NUMKARTSTUFF];
|
||||
INT32 karthud[NUMKARTHUD];
|
||||
boolean jitterlegacy; // If true, makes Ring Racers characters jitter during drifts like
|
||||
// SRB2Kart.
|
||||
|
||||
|
||||
// Basic gameplay things
|
||||
UINT8 position; // Used for Kart positions, mostly for deterministic stuff
|
||||
|
|
@ -601,6 +628,9 @@ struct player_t
|
|||
fixed_t driftcharge; // Charge your drift so you can release a burst of speed
|
||||
UINT8 driftboost; // (0 to 125) - Boost you get from drifting
|
||||
tic_t driftsparkGrowTimer;
|
||||
tic_t driftelapsed; // Elapsed time spent during a drift.
|
||||
|
||||
fixed_t spinoutrot; // When a player spins out, this value increments modulus 360.
|
||||
|
||||
SINT8 aizdriftstrat; // (-1 to 1) - Let go of your drift while boosting? Helper for the SICK STRATZ (sliptiding!) you have just unlocked
|
||||
INT32 aizdrifttilt;
|
||||
|
|
@ -653,12 +683,16 @@ struct player_t
|
|||
SINT8 ringmax; // maximum rings
|
||||
UINT8 pickuprings; // Number of rings being picked up before added to the counter (prevents rings from being deleted forever over 20)
|
||||
UINT8 ringdelay; // (0 to 3) - 3 tic delay between every ring usage
|
||||
UINT8 ringlock; // Timer for automatic handeling of ringlock
|
||||
UINT16 ringboost; // Ring boost timer
|
||||
UINT16 ringtime; // The current Ring boost timer if it wasn't capped. Used for spam prevention measures.
|
||||
UINT16 superring; // Spawn rings on top of you every tic!
|
||||
UINT8 nextringaward; // When should we spawn our next superring ring?
|
||||
UINT8 ringvolume; // When consuming lots of rings, lower the sound a little.
|
||||
UINT8 ringtransparency; // When consuming lots of rings, fade out the rings again.
|
||||
UINT8 ringtransparency; // When consuming lots of rings, fade out the rings again.
|
||||
|
||||
UINT8 airdroptime; // Tracks how long airdrop has been active, used for delay before airdrop kicks in.
|
||||
boolean ringdrop; // Set when having ringdrop applied.
|
||||
|
||||
UINT8 curshield; // see kartshields_t
|
||||
UINT8 bubblecool; // Bubble Shield use cooldown
|
||||
|
|
@ -721,6 +755,9 @@ struct player_t
|
|||
UINT8 lastsafelap;
|
||||
UINT8 lastsafestarpost;
|
||||
|
||||
tic_t splits[MAXRACESPLITS]; // Times we crossed checkpoint
|
||||
INT32 pace; // Last split delta, used for checking whether gaining or losing time
|
||||
|
||||
//
|
||||
|
||||
SINT8 lives;
|
||||
|
|
@ -743,6 +780,7 @@ struct player_t
|
|||
|
||||
INT16 totalring; // Total number of rings obtained for GP
|
||||
tic_t realtime; // integer replacement for leveltime
|
||||
tic_t laptime[LAP__MAX];
|
||||
UINT8 laps; // Number of laps (optional)
|
||||
UINT8 latestlap;
|
||||
|
||||
|
|
@ -808,6 +846,9 @@ struct player_t
|
|||
|
||||
boolean prevonground;
|
||||
|
||||
boolean walltransfered;
|
||||
UINT8 walltransferboost;
|
||||
|
||||
#ifdef HWRENDER
|
||||
fixed_t fovadd; // adjust FOV for hw rendering
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1859,6 +1859,8 @@ static struct { const char *name; consvar_t *var; } HIDDENVARS[] = {
|
|||
{ "DUMMYATTACKINGSLIPDASH", &cv_dummyattackingslipdash },
|
||||
{ "DUMMYATTACKINGPURPLEDRIFT", &cv_dummyattackingpurpledrift },
|
||||
{ "DUMMYATTACKINGSLOPEBOOST", &cv_dummyattackingslopeboost },
|
||||
{ "DUMMYATTACKINGAIRDROP", &cv_dummyattackingairdrop },
|
||||
{ "DUMMYATTACKINGBUMPSPARK", &cv_dummyattackingbumpspark },
|
||||
{ "DUMMYSTAFF", &cv_dummystaff },
|
||||
{ "DUMMYMULTIPLAYER", &cv_dummymultiplayer },
|
||||
{ "DUMMYIP", &cv_dummyip },
|
||||
|
|
@ -3711,10 +3713,11 @@ void readfollower(MYFILE *f)
|
|||
followers[numfollowers].horzlag = 3*FRACUNIT;
|
||||
followers[numfollowers].vertlag = 6*FRACUNIT;
|
||||
followers[numfollowers].anglelag = 8*FRACUNIT;
|
||||
followers[numfollowers].bobspeed = (TICRATE*2)*FRACUNIT;
|
||||
followers[numfollowers].bobspeed = TICRATE*2;
|
||||
followers[numfollowers].bobamp = 4*FRACUNIT;
|
||||
followers[numfollowers].hitconfirmtime = TICRATE;
|
||||
followers[numfollowers].defaultcolor = SKINCOLOR_GREEN;
|
||||
followers[numfollowers].defaultcolor = FOLLOWERCOLOR_MATCH;
|
||||
strcpy(followers[numfollowers].icon, "MISSING");
|
||||
|
||||
do
|
||||
{
|
||||
|
|
@ -3748,6 +3751,11 @@ void readfollower(MYFILE *f)
|
|||
strcpy(followers[numfollowers].name, word2);
|
||||
nameset = true;
|
||||
}
|
||||
else if (fastcmp(word, "ICON"))
|
||||
{
|
||||
strlcpy(followers[numfollowers].icon, word2, 8+1);
|
||||
nameset = true;
|
||||
}
|
||||
else if (fastcmp(word, "MODE"))
|
||||
{
|
||||
if (word2)
|
||||
|
|
|
|||
|
|
@ -379,13 +379,18 @@ const char *const GAMETYPERULE_LIST[] = {
|
|||
"BOTS",
|
||||
"RINGS",
|
||||
"BUMPERS",
|
||||
"POINTS",
|
||||
"BATTLEODDS",
|
||||
"PAPERITEMS",
|
||||
"WANTED",
|
||||
"WANTEDSPB",
|
||||
"KARMA",
|
||||
"ITEMARROWS",
|
||||
"ITEMBREAKER",
|
||||
"BATTLESTARTS",
|
||||
"CLOSERPLAYERS",
|
||||
"BATTLEBOXES",
|
||||
"BATTLESPEED",
|
||||
"POINTLIMIT",
|
||||
"TIMELIMIT",
|
||||
"OVERTIME",
|
||||
|
|
@ -755,6 +760,8 @@ struct menu_routine_s const MENU_ROUTINES[] = {
|
|||
{ "QUITVIEWSERVER", &MR_QuitViewServer },
|
||||
{ "HANDLEVIEWSERVER", &MR_HandleViewServer },
|
||||
{ "CAMERASETUP", &MR_CameraSetup },
|
||||
// { "BARCSS", &MR_HandleBarCss },
|
||||
{ "HANDLESETUPMULTIPLAYERMENU", &MR_HandleSetupMultiPlayerMenu },
|
||||
#ifdef HAVE_DISCORDRPC
|
||||
{ "HANDLEDISCORDREQUESTS", &MR_HandleDiscordRequests },
|
||||
#endif
|
||||
|
|
@ -769,6 +776,9 @@ struct menu_drawer_s const MENU_DRAWERS[] = {
|
|||
{ "DRAWTIMEATTACKMENU", &MD_DrawTimeAttackMenu },
|
||||
{ "DRAWMPMAINMENU", &MD_DrawMPMainMenu },
|
||||
{ "DRAWSETUPMULTIPLAYERMENU", &MD_DrawSetupMultiPlayerMenu },
|
||||
// { "DRAWCSSCHARACTER", &MD_DrawCssCharacter },
|
||||
// { "DRAWBARCSSSELECTOR", &MD_DrawBarCssSelector },
|
||||
// { "DRAWGRIDCSSSELECTOR", &MD_DrawGridCssSelector },
|
||||
{ "DRAWVIDEOMODE", &MD_DrawVideoMode },
|
||||
{ "DRAWADDONS", &MD_DrawAddons },
|
||||
{ "DRAWREPLAYSTARTMENU", &MD_DrawReplayStartMenu },
|
||||
|
|
@ -1000,7 +1010,6 @@ struct int_const_s const INT_CONST[] = {
|
|||
// Character flags (skinflags_t)
|
||||
{"SF_HIRES",0},
|
||||
{"SF_MACHINE",SF_MACHINE},
|
||||
{"SF_NOGIBS",SF_NOGIBS},
|
||||
{"SF_OLDDEATH",SF_OLDDEATH},
|
||||
|
||||
// Sound flags
|
||||
|
|
@ -1083,6 +1092,7 @@ struct int_const_s const INT_CONST[] = {
|
|||
{"OV_DONT3DOFFSET", OV_DONT3DOFFSET},
|
||||
{"OV_DONTXYSCALE", OV_DONTXYSCALE},
|
||||
{"OV_DONTROLL", OV_DONTROLL},
|
||||
{"OV_DONTBAKEOFFSET", OV_DONTBAKEOFFSET},
|
||||
|
||||
// Player state (playerstate_t)
|
||||
{"PST_LIVE",PST_LIVE}, // Playing or camping.
|
||||
|
|
@ -1592,7 +1602,8 @@ struct int_const_s const INT_CONST[] = {
|
|||
{"TMBOT_NORUBBERBAND",TMBOT_NORUBBERBAND},
|
||||
{"TMBOT_NOCONTROL",TMBOT_NOCONTROL},
|
||||
{"TMBOT_FORCEDIR",TMBOT_FORCEDIR},
|
||||
//{"TMBOT_FASTFALL",TMBOT_FASTFALL},
|
||||
{"TMBOT_AIRDROP",TMBOT_AIRDROP},
|
||||
{"TMBOT_FASTFALL",TMBOT_AIRDROP},
|
||||
|
||||
// textmapbottrick_t
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -475,6 +475,12 @@ UINT32 quickncasehash (const char *p, size_t n)
|
|||
#endif
|
||||
#endif
|
||||
|
||||
// the GNU cleanup attribute: plugging memory leaks since 2003!
|
||||
// on scope exit, the cleanup function is called with a pointer to the declared variable,
|
||||
// essentially behaving like a C++ destructor
|
||||
// NOTE: you WILL have nasal troubles if the variable is not initialized
|
||||
#define CLEANUP(f) __attribute__((__cleanup__(f)))
|
||||
|
||||
// An assert-type mechanism.
|
||||
// NOTE: USE SRB2_ASSERT FOR C++ CODE INSTEAD
|
||||
#ifdef PARANOIA
|
||||
|
|
|
|||
|
|
@ -479,37 +479,42 @@ enum GameTypeRules
|
|||
{
|
||||
// Race rules
|
||||
GTR_CIRCUIT = 1, // Enables the finish line, laps, and the waypoint system.
|
||||
GTR_RACEODDS = 1<<2, // ItemOdds used in this mode are for racing.
|
||||
GTR_BOTS = 1<<3, // Allows bots in this gametype. Combine with BotTiccmd hooks to make bots support your gametype.
|
||||
GTR_RINGS = 1<<4, // Allow Rings in this gametype.
|
||||
GTR_RACEODDS = 1<<1, // ItemOdds used in this mode are for racing.
|
||||
GTR_BOTS = 1<<2, // Allows bots in this gametype. Combine with BotTiccmd hooks to make bots support your gametype.
|
||||
GTR_RINGS = 1<<3, // Allow Rings in this gametype.
|
||||
|
||||
// Battle gametype rules
|
||||
GTR_BUMPERS = 1<<5, // Enables the bumper health system
|
||||
GTR_BATTLEODDS = 1<<6, // ItemOdds used in this mode are for battling.
|
||||
GTR_PAPERITEMS = 1<<7, // Replaces item boxes with paper item spawners
|
||||
GTR_WANTED = 1<<8, // Enables the wanted anti-camping system
|
||||
GTR_KARMA = 1<<9, // Enables the Karma system if you're out of bumpers
|
||||
GTR_ITEMARROWS = 1<<10, // Show item box arrows above players
|
||||
GTR_ITEMBREAKER = 1<<11, // Enables the use of Item Breaker in this Gamemode
|
||||
GTR_BATTLESTARTS = 1<<12, // Use Battle Mode start positions.
|
||||
GTR_BUMPERS = 1<<4, // Enables the bumper health system.
|
||||
GTR_POINTS = 1<<5, // Get awarded score when hitting people.
|
||||
GTR_BATTLEODDS = 1<<6, // ItemOdds used in this mode are for battling.
|
||||
GTR_PAPERITEMS = 1<<7, // Replaces item boxes with paper item spawners.
|
||||
GTR_WANTED = 1<<8, // Enables the wanted anti-camping system.
|
||||
GTR_WANTEDSPB = 1<<9, // Unleash Self-Propelled Bombs on Wanted players.
|
||||
GTR_KARMA = 1<<10, // Enables the Karma system if you're out of bumpers.
|
||||
GTR_ITEMARROWS = 1<<11, // Show item box arrows above players.
|
||||
GTR_ITEMBREAKER = 1<<12, // Enables the use of Item Breaker in this Gamemode.
|
||||
GTR_BATTLESTARTS = 1<<13, // Use Battle Mode start positions.
|
||||
GTR_CLOSERPLAYERS = 1<<14, // Enables specfic gameplay tweaks with closer players.
|
||||
GTR_BATTLEBOXES = 1<<15, // Itemboxes respawn differently.
|
||||
GTR_BATTLESPEED = 1<<16, // Use battle gamespeed cvar.
|
||||
|
||||
GTR_POINTLIMIT = 1<<13, // Reaching point limit ends the round
|
||||
GTR_TIMELIMIT = 1<<14, // Reaching time limit ends the round
|
||||
GTR_OVERTIME = 1<<15, // Allow overtime behavior
|
||||
GTR_POINTLIMIT = 1<<17, // Reaching point limit ends the round.
|
||||
GTR_TIMELIMIT = 1<<18, // Reaching time limit ends the round.
|
||||
GTR_OVERTIME = 1<<19, // Allow overtime behavior.
|
||||
|
||||
// Custom gametype rules
|
||||
GTR_TEAMS = 1<<16, // Teams are forced on
|
||||
GTR_NOTEAMS = 1<<17, // Teams are forced off
|
||||
GTR_TEAMSTARTS = 1<<18, // Use team-based start positions
|
||||
GTR_TEAMS = 1<<20, // Teams are forced on.
|
||||
GTR_NOTEAMS = 1<<21, // Teams are forced off.
|
||||
GTR_TEAMSTARTS = 1<<22, // Use team-based start positions.
|
||||
|
||||
// Grand Prix rules
|
||||
//Free = 1<<19,
|
||||
GTR_LIVES = 1<<20, // Lives system, players are forced to spectate during Game Over.
|
||||
GTR_SPECIALBOTS = 1<<21, // Bot difficulty gets stronger between rounds, and the rival system is enabled.
|
||||
//Free = 1<<23,
|
||||
GTR_LIVES = 1<<24, // Lives system, players are forced to spectate during Game Over.
|
||||
GTR_SPECIALBOTS = 1<<25, // Bot difficulty gets stronger between rounds, and the rival system is enabled.
|
||||
|
||||
// Misc
|
||||
GTR_NOCOUNTDOWN = 1<<22, // Disables Countdown timer and control lock at the start of levels.
|
||||
GTR_ENCORE = 1<<23, // Enable Encore mode.
|
||||
GTR_NOCOUNTDOWN = 1<<26, // Disables Countdown timer and control lock at the start of levels.
|
||||
GTR_ENCORE = 1<<27, // Enable Encore mode.
|
||||
|
||||
// free: to and including 1<<31
|
||||
};
|
||||
|
|
@ -667,6 +672,7 @@ extern boolean franticitems;
|
|||
extern boolean encoremode, prevencoremode;
|
||||
extern boolean comeback;
|
||||
|
||||
extern SINT8 mostwanted;
|
||||
extern SINT8 battlewanted[4];
|
||||
extern tic_t wantedcalcdelay;
|
||||
extern tic_t indirectitemcooldown;
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ void I_WaitVBL(INT32 count)
|
|||
(void)count;
|
||||
}
|
||||
|
||||
void I_ReadScreen(UINT8 *scr)
|
||||
void I_ReadScreen(UINT8 * restrict scr, INT32 scale)
|
||||
{
|
||||
(void)scr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -972,7 +972,7 @@ void F_SecretCreditsTicker(void)
|
|||
finalescene = elapsed;
|
||||
}
|
||||
|
||||
if ((((elapsed - finalescene) / FINALESECDELAY) != finalesecs))
|
||||
if ((((elapsed - finalescene) / FINALESECDELAY) != (longtic_t)finalesecs))
|
||||
{
|
||||
finalesecs = ((elapsed - finalescene) / FINALESECDELAY);
|
||||
|
||||
|
|
|
|||
|
|
@ -911,17 +911,16 @@ const char *blancredits[] = {
|
|||
"Kart Krew Dev",
|
||||
"\"JugadorXEI\"",
|
||||
"\"Kimberly\"",
|
||||
"\"Chearii\"",
|
||||
"",
|
||||
"\1Item Design",
|
||||
"\"NepDisk\"",
|
||||
"\"Anonimus\"",
|
||||
"\"Denny\" aka \"shephoron\"",
|
||||
"",
|
||||
"\1Design Support",
|
||||
"\"Rim Jobless\"",
|
||||
"\"JonUD\"",
|
||||
"\"luna\"",
|
||||
"\"Denny\" aka \"shephoron\"",
|
||||
"\"White Mage (guy who picked up controller)\"",
|
||||
"",
|
||||
"\1New Item Art",
|
||||
|
|
@ -948,6 +947,16 @@ const char *blancredits[] = {
|
|||
"\"Mayo\"",
|
||||
"\"ArcadeStriker\"",
|
||||
"",
|
||||
// Anyone who's been directly involved with getting rid of SIGSEGV
|
||||
// culprits gets credited here.
|
||||
"\1Super Special SIGSEGV Search and Smash Squad",
|
||||
"\"NepDisk\"",
|
||||
"\"GenericHeroGuy\"",
|
||||
"\"Anonimus\"",
|
||||
"\"MotoBugger\"",
|
||||
"\"Rim Jobless\"",
|
||||
"\"Toad The Fungus\"",
|
||||
"",
|
||||
"\1Testing",
|
||||
"\"NepDisk\"",
|
||||
"\"Alug\"",
|
||||
|
|
@ -960,8 +969,6 @@ const char *blancredits[] = {
|
|||
"\"Anonimus\"",
|
||||
"\"luna\"",
|
||||
"\"swift\"",
|
||||
"\"Astronight\"",
|
||||
"\"Denny\" aka \"shephoron\"",
|
||||
"\"Rim Jobless\"",
|
||||
"\"White Mage (guy who picked up controller)\"",
|
||||
"\"Mayo\"",
|
||||
|
|
|
|||
|
|
@ -316,7 +316,7 @@ void F_WipeStartScreen(void)
|
|||
}
|
||||
#endif
|
||||
wipe_scr_start = screens[3];
|
||||
I_ReadScreen(wipe_scr_start);
|
||||
I_ReadScreen(wipe_scr_start, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -333,7 +333,7 @@ void F_WipeEndScreen(void)
|
|||
}
|
||||
#endif
|
||||
wipe_scr_end = screens[4];
|
||||
I_ReadScreen(wipe_scr_end);
|
||||
I_ReadScreen(wipe_scr_end, 1);
|
||||
V_DrawBlock(0, 0, 0, vid.width, vid.height, wipe_scr_start);
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
258
src/g_demo.c
258
src/g_demo.c
|
|
@ -112,7 +112,7 @@ demoghost *ghosts = NULL;
|
|||
// DEMO RECORDING
|
||||
//
|
||||
|
||||
#define DEMOVERSION 0x000A
|
||||
#define DEMOVERSION 0x000C
|
||||
#define DEMOHEADER "\xF0" "BlanReplay" "\x0F"
|
||||
|
||||
#define DF_GHOST 0x01 // This demo contains ghost data too!
|
||||
|
|
@ -399,9 +399,9 @@ static UINT8 *G_ReadZipTic(ticcmd_t *cmd, UINT8 *dp, UINT16 version)
|
|||
if (version < 0x000a && ziptic & 0x8000) // ZT_BOT
|
||||
{
|
||||
UINT16 botziptic = READUINT16(dp);
|
||||
if (botziptic & 1) READSINT8(dp);
|
||||
if (botziptic & 2) READSINT8(dp);
|
||||
if (botziptic & 4) READSINT8(dp);
|
||||
if (botziptic & 1) (void)READSINT8(dp);
|
||||
if (botziptic & 2) (void)READSINT8(dp);
|
||||
if (botziptic & 4) (void)READSINT8(dp);
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
|
@ -649,7 +649,7 @@ static UINT8 *G_ReadRawExtraData(extradata_t *extra, UINT8 *dp, UINT16 version)
|
|||
}
|
||||
|
||||
// parses a demo header from the given byte pointer
|
||||
// remember to call G_FreeDemoHeader! (unless an error occurs)
|
||||
// remember to call G_FreeDemoHeader!
|
||||
static headerstatus_e G_ReadDemoHeader(UINT8 *dp, demoheader_t *header)
|
||||
{
|
||||
UINT8 *startdp = dp;
|
||||
|
|
@ -683,6 +683,11 @@ static headerstatus_e G_ReadDemoHeader(UINT8 *dp, demoheader_t *header)
|
|||
case DEMOVERSION: // latest always supported
|
||||
break;
|
||||
|
||||
case 0x000B:
|
||||
break;
|
||||
case 0x000A:
|
||||
break;
|
||||
|
||||
case 0x0009:
|
||||
serverinfo = false;
|
||||
break;
|
||||
|
|
@ -1463,7 +1468,7 @@ void G_GhostAddHit(INT32 playernum, mobj_t *victim)
|
|||
return;
|
||||
ghostext[playernum].flags |= EZT_HIT;
|
||||
ghostext[playernum].hits++;
|
||||
ghostext[playernum].hitlist = Z_Realloc(ghostext[playernum].hitlist, ghostext[playernum].hits * sizeof(mobj_t *), PU_LEVEL, &ghostext[playernum].hitlist);
|
||||
Z_Realloc(ghostext[playernum].hitlist, ghostext[playernum].hits * sizeof(mobj_t *), PU_STATIC, &ghostext[playernum].hitlist);
|
||||
P_SetTarget(ghostext[playernum].hitlist + (ghostext[playernum].hits-1), victim);
|
||||
}
|
||||
|
||||
|
|
@ -1645,6 +1650,7 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum)
|
|||
WRITEANGLE(demobuf.p,mo->angle);
|
||||
P_SetTarget(ghostext[playernum].hitlist+i, NULL);
|
||||
}
|
||||
Z_Free(ghostext[playernum].hitlist);
|
||||
ghostext[playernum].hits = 0;
|
||||
}
|
||||
if (ghostext[playernum].flags & EZT_SPRITE)
|
||||
|
|
@ -1818,7 +1824,7 @@ void G_ConsGhostTic(INT32 playernum)
|
|||
gy = oldghost[playernum].y;
|
||||
gz = oldghost[playernum].z;
|
||||
|
||||
if (abs(px-gx) > syncleeway || abs(py-gy) > syncleeway || abs(pz-gz) > syncleeway)
|
||||
if ((UINT32)abs(px-gx) > syncleeway || (UINT32)abs(py-gy) > syncleeway || (UINT32)abs(pz-gz) > syncleeway)
|
||||
{
|
||||
ghostext[playernum].desyncframes++;
|
||||
|
||||
|
|
@ -2001,8 +2007,8 @@ void G_GhostTicker(void)
|
|||
for (UINT16 i = 0; i < zt.damagecount; i++)
|
||||
{
|
||||
zipticdamage_t *damage = &zt.damage[i];
|
||||
if (!(mobjinfo[damage->type].flags & MF_SHOOTABLE)
|
||||
|| !(mobjinfo[damage->type].flags & (MF_ENEMY|MF_MONITOR))
|
||||
// MAP15S03 has a broken EZT_HIT at leveltime 3455 which is all 0xff... so bounds check damage->type
|
||||
if ((damage->type < nummobjtypes && !(mobjinfo[damage->type].flags & (MF_SHOOTABLE|MF_ENEMY|MF_MONITOR)))
|
||||
|| damage->health != 0 || i >= 4) // only spawn for the first 4 hits per frame, to prevent ghosts from splode-spamming too bad.
|
||||
continue;
|
||||
mobj_t *poof = P_SpawnMobj(damage->x, damage->y, damage->z, MT_GHOST);
|
||||
|
|
@ -2736,6 +2742,20 @@ void G_BeginRecording(void)
|
|||
raflags |= RAF_PURPLEDRIFT;
|
||||
if (cv_dummyattackingslopeboost.value)
|
||||
raflags |= RAF_SLOPEBOOST;
|
||||
if (cv_dummyattackingairdrop.value)
|
||||
raflags |= RAF_AIRDROP;
|
||||
switch (cv_dummyattackingbumpspark.value)
|
||||
{
|
||||
case BUMPSPARK_ALL:
|
||||
raflags |= RAF_BUMPSPARK;
|
||||
break;
|
||||
case BUMPSPARK_RESET100:
|
||||
raflags |= RAF_BS_RESET100;
|
||||
break;
|
||||
case BUMPSPARK_NOCHARGE:
|
||||
raflags |= RAF_BUMPDRIFT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -3082,7 +3102,7 @@ static void G_LoadDemoExtraFiles(demoheader_t *header)
|
|||
}
|
||||
else
|
||||
{
|
||||
P_PartialAddWadFile(file->filename, file->compatmode ? WC_ON : WC_OFF);
|
||||
P_PartialAddWadFile(file->filename, file->compatmode ? WC_ON : WC_OFF, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3178,13 +3198,11 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
|
|||
I_Assert(bufsize != 0);
|
||||
|
||||
// read demo header
|
||||
demoheader_t header;
|
||||
CLEANUP(G_FreeDemoHeader) demoheader_t header;
|
||||
headerstatus_e status = G_ReadDemoHeader(buffer, &header);
|
||||
(void)status;
|
||||
I_Assert(status == HEADER_OK);
|
||||
I_Assert(header.version == VERSION);
|
||||
I_Assert(header.subversion == SUBVERSION);
|
||||
I_Assert(header.demoversion == DEMOVERSION);
|
||||
I_Assert(status == HEADER_OK && header.version == VERSION
|
||||
&& header.subversion == SUBVERSION && header.demoversion == DEMOVERSION);
|
||||
|
||||
Z_Free(buffer);
|
||||
|
||||
|
|
@ -3200,8 +3218,6 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
|
|||
else
|
||||
newlap = UINT32_MAX;
|
||||
|
||||
G_FreeDemoHeader(&header);
|
||||
|
||||
// load old file
|
||||
FIL_DefaultExtension(oldname, ".lmp");
|
||||
if (!FIL_ReadFile(oldname, &buffer))
|
||||
|
|
@ -3211,7 +3227,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
|
|||
}
|
||||
|
||||
// read demo header
|
||||
demoheader_t oldheader;
|
||||
CLEANUP(G_FreeDemoHeader) demoheader_t oldheader;
|
||||
if (G_ReadDemoHeader(buffer, &oldheader) != HEADER_OK)
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("File '%s' invalid format. It will be overwritten.\n"), oldname);
|
||||
|
|
@ -3224,7 +3240,6 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
|
|||
if (!(oldheader.demoflags & aflags))
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("File '%s' not from same game mode. It will be overwritten.\n"), oldname);
|
||||
G_FreeDemoHeader(&oldheader);
|
||||
return UINT8_MAX;
|
||||
}
|
||||
|
||||
|
|
@ -3234,8 +3249,6 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
|
|||
else
|
||||
oldlap = 0;
|
||||
|
||||
G_FreeDemoHeader(&oldheader);
|
||||
|
||||
c = 0;
|
||||
|
||||
if (uselaps)
|
||||
|
|
@ -3258,20 +3271,20 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
|
|||
|
||||
void G_LoadDemoInfo(menudemo_t *pdemo)
|
||||
{
|
||||
UINT8 *infobuffer, *extrainfo_p;
|
||||
CLEANUP(Z_Pfree) UINT8 *infobuffer = NULL;
|
||||
const UINT8 *extrainfo_p;
|
||||
|
||||
if (!FIL_ReadFile(pdemo->filepath, &infobuffer))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Failed to read file '%s'.\n"), pdemo->filepath);
|
||||
pdemo->type = MD_INVALID;
|
||||
sprintf(pdemo->title, "INVALID REPLAY");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
pdemo->type = MD_LOADED;
|
||||
|
||||
demoheader_t header;
|
||||
CLEANUP(G_FreeDemoHeader) demoheader_t header;
|
||||
switch (G_ReadDemoHeader(infobuffer, &header))
|
||||
{
|
||||
case HEADER_OK:
|
||||
|
|
@ -3281,21 +3294,18 @@ void G_LoadDemoInfo(menudemo_t *pdemo)
|
|||
CONS_Alert(CONS_ERROR, M_GetText("%s is not a SRB2Kart replay file.\n"), pdemo->filepath);
|
||||
pdemo->type = MD_INVALID;
|
||||
sprintf(pdemo->title, "INVALID REPLAY");
|
||||
Z_Free(infobuffer);
|
||||
return;
|
||||
|
||||
case HEADER_BADVERSION:
|
||||
CONS_Alert(CONS_ERROR, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemo->filepath);
|
||||
pdemo->type = MD_INVALID;
|
||||
sprintf(pdemo->title, "INVALID REPLAY");
|
||||
Z_Free(infobuffer);
|
||||
return;
|
||||
|
||||
case HEADER_BADFORMAT:
|
||||
CONS_Alert(CONS_ERROR, M_GetText("%s is the wrong type of recording and cannot be played.\n"), pdemo->filepath);
|
||||
pdemo->type = MD_INVALID;
|
||||
sprintf(pdemo->title, "INVALID REPLAY");
|
||||
Z_Free(infobuffer);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -3310,7 +3320,6 @@ void G_LoadDemoInfo(menudemo_t *pdemo)
|
|||
if (!(header.demoflags & DF_MULTIPLAYER))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("%s is not a multiplayer replay and can't be listed on this menu fully yet.\n"), pdemo->filepath);
|
||||
Z_Free(infobuffer);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -3383,10 +3392,6 @@ void G_LoadDemoInfo(menudemo_t *pdemo)
|
|||
if (count >= MAXPLAYERS)
|
||||
break; //@TODO still cycle through the rest of these if extra demo data is ever used
|
||||
}
|
||||
|
||||
// I think that's everything we need?
|
||||
Z_Free(infobuffer);
|
||||
G_FreeDemoHeader(&header);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -3405,18 +3410,38 @@ void G_DeferedPlayDemo(const char *name)
|
|||
|
||||
#define SKIPERRORS
|
||||
|
||||
static void PrintDemoError(const char (*msg)[1024])
|
||||
{
|
||||
if (*msg[0] == '\0')
|
||||
return;
|
||||
|
||||
CONS_Alert(CONS_ERROR, "%s", *msg);
|
||||
demo.playback = false;
|
||||
demo.title = false;
|
||||
if (!CON_Ready()) // In the console they'll just see the notice there! No point pulling them out.
|
||||
M_StartMessage(*msg, NULL, MM_NOTHING);
|
||||
}
|
||||
|
||||
static void FreeDemoBuffer(savebuffer_t **freebuffer)
|
||||
{
|
||||
if (*freebuffer != NULL)
|
||||
P_SaveBufferFree(*freebuffer);
|
||||
}
|
||||
|
||||
void G_DoPlayDemo(char *defdemoname)
|
||||
{
|
||||
UINT16 i, j;
|
||||
lumpnum_t l;
|
||||
char *n,*pdemoname;
|
||||
char msg[1024];
|
||||
UINT8 pnum;
|
||||
CLEANUP(Z_Pfree) char *pdemoname = NULL;
|
||||
const char *n;
|
||||
CLEANUP(PrintDemoError) char msg[1024];
|
||||
CLEANUP(FreeDemoBuffer) savebuffer_t *freebuffer = NULL;
|
||||
|
||||
#if defined(SKIPERRORS) && !defined(DEVELOP)
|
||||
boolean skiperrors = false;
|
||||
#endif
|
||||
|
||||
msg[0] = '\0';
|
||||
M_ClearMenus(true);
|
||||
G_InitDemoRewind();
|
||||
gameaction = ga_nothing;
|
||||
|
|
@ -3446,7 +3471,7 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
if (P_SaveBufferFromFile(&demobuf, defdemoname) == false)
|
||||
{
|
||||
snprintf(msg, 1024, M_GetText("Failed to read file '%s'.\n"), defdemoname);
|
||||
goto lumperror;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// load demo resource from WAD
|
||||
|
|
@ -3458,7 +3483,7 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
if ((l = W_CheckNumForName(defdemoname)) == LUMPERROR)
|
||||
{
|
||||
snprintf(msg, 1024, M_GetText("Failed to read lump '%s'.\n"), defdemoname);
|
||||
goto lumperror;
|
||||
return;
|
||||
}
|
||||
|
||||
P_SaveBufferFromLump(&demobuf, l);
|
||||
|
|
@ -3484,7 +3509,7 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
if (mapnum >= nummapheaders || mapheaderinfo[mapnum]->lumpnum == LUMPERROR)
|
||||
{
|
||||
snprintf(msg, 1024, M_GetText("Failed to read lump '%s (couldn't find map %s)'.\n"), defdemoname, mapname);
|
||||
goto lumperror;
|
||||
return;
|
||||
}
|
||||
|
||||
vRes = vres_GetMap(mapheaderinfo[mapnum]->lumpnum);
|
||||
|
|
@ -3493,7 +3518,7 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
if (vLump == NULL)
|
||||
{
|
||||
snprintf(msg, 1024, M_GetText("Failed to read lump '%s (couldn't find lump %s in %s)'.\n"), defdemoname, pdemoname, mapname);
|
||||
goto lumperror;
|
||||
return;
|
||||
}
|
||||
|
||||
P_SaveBufferAlloc(&demobuf, vLump->size);
|
||||
|
|
@ -3509,10 +3534,9 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
|
||||
// read demo header
|
||||
demo.playback = true;
|
||||
demo.buffer = &demobuf;
|
||||
|
||||
demoheader_t header;
|
||||
demo.buffer = freebuffer = &demobuf;
|
||||
|
||||
CLEANUP(G_FreeDemoHeader) demoheader_t header;
|
||||
switch (G_ReadDemoHeader(demobuf.p, &header))
|
||||
{
|
||||
case HEADER_OK:
|
||||
|
|
@ -3521,15 +3545,15 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
|
||||
case HEADER_BADMAGIC:
|
||||
snprintf(msg, 1024, M_GetText("%s is not a SRB2Kart replay file.\n"), pdemoname);
|
||||
goto headererror;
|
||||
return;
|
||||
|
||||
case HEADER_BADVERSION:
|
||||
snprintf(msg, 1024, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemoname);
|
||||
goto headererror;
|
||||
return;
|
||||
|
||||
case HEADER_BADFORMAT:
|
||||
snprintf(msg, 1024, M_GetText("%s is the wrong type of recording and cannot be played.\n"), pdemoname);
|
||||
goto headererror;
|
||||
return;
|
||||
}
|
||||
|
||||
demo.version = header.demoversion;
|
||||
|
|
@ -3561,31 +3585,31 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
snprintf(msg, 1024,
|
||||
M_GetText("Required files for this demo are not loaded.\n\nUse\n\"playdemo %s -addfiles\"\nto load them and play the demo.\n"),
|
||||
pdemoname);
|
||||
goto error;
|
||||
return;
|
||||
|
||||
case DFILE_ERROR_OUTOFORDER:
|
||||
snprintf(msg, 1024,
|
||||
M_GetText("Required files for this demo are loaded out of order.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"),
|
||||
pdemoname);
|
||||
goto error;
|
||||
return;
|
||||
|
||||
case DFILE_ERROR_INCOMPLETEOUTOFORDER:
|
||||
snprintf(msg, 1024,
|
||||
M_GetText("Required files for this demo are not loaded, and some are out of order.\n\nUse\n\"playdemo %s -addfiles\"\nto load needed files and play the demo.\n"),
|
||||
pdemoname);
|
||||
goto error;
|
||||
return;
|
||||
|
||||
case DFILE_ERROR_CANNOTLOAD:
|
||||
snprintf(msg, 1024,
|
||||
M_GetText("Required files for this demo cannot be loaded.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"),
|
||||
pdemoname);
|
||||
goto error;
|
||||
return;
|
||||
|
||||
case DFILE_ERROR_EXTRAFILES:
|
||||
snprintf(msg, 1024,
|
||||
M_GetText("You have additional files loaded beyond the demo's file list.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"),
|
||||
pdemoname);
|
||||
goto error;
|
||||
return;
|
||||
}
|
||||
|
||||
// Moved here so these init properly.
|
||||
|
|
@ -3601,14 +3625,14 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
if (!gamemap || (gamemap > nummapheaders) || !mapheaderinfo[gamemap-1] || mapheaderinfo[gamemap-1]->lumpnum == LUMPERROR)
|
||||
{
|
||||
snprintf(msg, 1024, M_GetText("%s features a course that is not currently loaded.\n"), pdemoname);
|
||||
goto error;
|
||||
return;
|
||||
}
|
||||
|
||||
// Sigh ... it's an empty demo.
|
||||
if (header.empty)
|
||||
{
|
||||
snprintf(msg, 1024, M_GetText("%s contains no data to be played.\n"), pdemoname);
|
||||
goto error;
|
||||
return;
|
||||
}
|
||||
|
||||
// extra checks for RA replays
|
||||
|
|
@ -3625,10 +3649,13 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
if (reason)
|
||||
{
|
||||
snprintf(msg, 1024, M_GetText("%s is a Record Attack replay with %s, and is thus invalid.\n"), pdemoname, reason);
|
||||
goto error;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// no more error checks at this point, don't free demobuf
|
||||
freebuffer = NULL;
|
||||
|
||||
modeattacking = (demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT;
|
||||
multiplayer = !!(demoflags & DF_MULTIPLAYER);
|
||||
|
||||
|
|
@ -3656,8 +3683,6 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
// Load "mapmusrng" used for altmusic selection
|
||||
mapmusrng = header.mapmusrng;
|
||||
|
||||
Z_Free(pdemoname);
|
||||
|
||||
memset(&oldcmd,0,sizeof(oldcmd));
|
||||
memset(&oldghost,0,sizeof(oldghost));
|
||||
memset(&ghostext,0,sizeof(ghostext));
|
||||
|
|
@ -3685,7 +3710,7 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
memset(camera,0,sizeof(camera)); // reset freecam
|
||||
|
||||
// Load players that were in-game when the map started
|
||||
for (pnum = 0; pnum < header.numplayers; pnum++)
|
||||
for (UINT8 pnum = 0; pnum < header.numplayers; pnum++)
|
||||
{
|
||||
demoplayer_t *plr = &header.playerdata[pnum];
|
||||
UINT8 p = plr->playernum;
|
||||
|
|
@ -3792,33 +3817,19 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
CopyCaretColors(connectedservercontact, header.servercontact, MAXSERVERCONTACT);
|
||||
strncpy(connectedserverdescription, header.serverdescription, MAXSERVERDESCRIPTION);
|
||||
|
||||
for (pnum = 0; pnum < header.numplayers; pnum++)
|
||||
for (i = 0; i < header.numplayers; i++)
|
||||
{
|
||||
// oldghost init doesn't work here, players aren't immediately spawned anymore
|
||||
|
||||
// Set saved attribute values
|
||||
// No cheat checking here, because even if they ARE wrong...
|
||||
// it would only break the replay if we clipped them.
|
||||
demoplayer_t *plr = &header.playerdata[pnum];
|
||||
demoplayer_t *plr = &header.playerdata[i];
|
||||
players[plr->playernum].kartspeed = plr->kartspeed;
|
||||
players[plr->playernum].kartweight = plr->kartweight;
|
||||
}
|
||||
|
||||
demo.deferstart = true;
|
||||
G_FreeDemoHeader(&header);
|
||||
return;
|
||||
|
||||
error:
|
||||
G_FreeDemoHeader(&header);
|
||||
headererror:
|
||||
P_SaveBufferFree(&demobuf);
|
||||
lumperror:
|
||||
CONS_Alert(CONS_ERROR, "%s", msg);
|
||||
Z_Free(pdemoname);
|
||||
demo.playback = false;
|
||||
demo.title = false;
|
||||
if (!CON_Ready()) // In the console they'll just see the notice there! No point pulling them out.
|
||||
M_StartMessage(msg, NULL, MM_NOTHING);
|
||||
}
|
||||
|
||||
void G_SetupDemoPlayer(INT32 i)
|
||||
|
|
@ -3833,11 +3844,13 @@ void G_AddGhost(char *defdemoname)
|
|||
{
|
||||
INT32 i;
|
||||
lumpnum_t l;
|
||||
char *n,*pdemoname;
|
||||
CLEANUP(Z_Pfree) char *pdemoname = NULL;
|
||||
const char *n;
|
||||
UINT64 demohash;
|
||||
UINT32 raflags;
|
||||
demoghost *gh;
|
||||
UINT8 flags;
|
||||
UINT8 *buffer;
|
||||
CLEANUP(Z_Pfree) UINT8 *buffer = NULL;
|
||||
mapthing_t *mthing;
|
||||
skin_t *ghskin = &skins[0];
|
||||
|
||||
|
|
@ -3856,7 +3869,6 @@ void G_AddGhost(char *defdemoname)
|
|||
if (!FIL_ReadFileTag(defdemoname, &buffer, PU_LEVEL))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Failed to read file '%s'.\n"), defdemoname);
|
||||
Z_Free(pdemoname);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -3864,13 +3876,12 @@ void G_AddGhost(char *defdemoname)
|
|||
else if ((l = W_CheckNumForName(defdemoname)) == LUMPERROR)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Failed to read lump '%s'.\n"), defdemoname);
|
||||
Z_Free(pdemoname);
|
||||
return;
|
||||
}
|
||||
else // it's an internal demo
|
||||
buffer = W_CacheLumpNum(l, PU_LEVEL);
|
||||
|
||||
demoheader_t header;
|
||||
CLEANUP(G_FreeDemoHeader) demoheader_t header;
|
||||
switch (G_ReadDemoHeader(buffer, &header))
|
||||
{
|
||||
case HEADER_OK:
|
||||
|
|
@ -3878,20 +3889,14 @@ void G_AddGhost(char *defdemoname)
|
|||
|
||||
case HEADER_BADMAGIC:
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Not a SRB2 replay.\n"), pdemoname);
|
||||
Z_Free(pdemoname);
|
||||
Z_Free(buffer);
|
||||
return;
|
||||
|
||||
case HEADER_BADVERSION:
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Demo version incompatible.\n"), pdemoname);
|
||||
Z_Free(pdemoname);
|
||||
Z_Free(buffer);
|
||||
return;
|
||||
|
||||
case HEADER_BADFORMAT:
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Demo format unacceptable.\n"), pdemoname);
|
||||
Z_Free(pdemoname);
|
||||
Z_Free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -3901,50 +3906,82 @@ void G_AddGhost(char *defdemoname)
|
|||
if (demohash == gh->checksum) // another ghost in the game already has this checksum?
|
||||
{ // Don't add another one, then!
|
||||
CONS_Debug(DBG_SETUP, "Rejecting duplicate ghost %s (hash was matched)\n", pdemoname);
|
||||
Z_Free(pdemoname);
|
||||
Z_Free(buffer);
|
||||
G_FreeDemoHeader(&header);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
flags = header.demoflags;
|
||||
raflags = header.raflags;
|
||||
if (!(flags & DF_GHOST))
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: No ghost data in this demo.\n"), pdemoname);
|
||||
Z_Free(pdemoname);
|
||||
Z_Free(buffer);
|
||||
G_FreeDemoHeader(&header);
|
||||
return;
|
||||
}
|
||||
|
||||
if (flags & DF_LUAVARS) // can't be arsed to add support for grinding away ported lua material
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Replay data contains luavars, cannot continue.\n"), pdemoname);
|
||||
Z_Free(pdemoname);
|
||||
Z_Free(buffer);
|
||||
G_FreeDemoHeader(&header);
|
||||
return;
|
||||
}
|
||||
|
||||
if (header.empty)
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Replay is empty.\n"), pdemoname);
|
||||
Z_Free(pdemoname);
|
||||
Z_Free(buffer);
|
||||
G_FreeDemoHeader(&header);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check RA flags.
|
||||
{
|
||||
UINT32 ourraflags = 0;
|
||||
UINT16 demoversion = header.demoversion;
|
||||
|
||||
if (cv_dummyattackingrings.value)
|
||||
ourraflags |= RAF_RINGS;
|
||||
if (cv_dummyattackingstacking.value)
|
||||
ourraflags |= RAF_STACKING;
|
||||
if (cv_dummyattackingchaining.value)
|
||||
ourraflags |= RAF_CHAINING;
|
||||
if (cv_dummyattackingslipdash.value)
|
||||
ourraflags |= RAF_SLIPDASH;
|
||||
if (cv_dummyattackingpurpledrift.value)
|
||||
ourraflags |= RAF_PURPLEDRIFT;
|
||||
if (cv_dummyattackingslopeboost.value)
|
||||
ourraflags |= RAF_SLOPEBOOST;
|
||||
if (cv_dummyattackingairdrop.value)
|
||||
ourraflags |= RAF_AIRDROP;
|
||||
|
||||
switch (cv_dummyattackingbumpspark.value)
|
||||
{
|
||||
case BUMPSPARK_ALL:
|
||||
raflags |= RAF_BUMPSPARK;
|
||||
break;
|
||||
case BUMPSPARK_RESET100:
|
||||
raflags |= RAF_BS_RESET100;
|
||||
break;
|
||||
case BUMPSPARK_NOCHARGE:
|
||||
raflags |= RAF_BUMPDRIFT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (demoversion <= 0x000B)
|
||||
{
|
||||
ourraflags &= ~RAF_AIRDROP;
|
||||
ourraflags &= ~RAF_BUMPSPARKMASK;
|
||||
}
|
||||
|
||||
if (ourraflags != raflags)
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Replay doesn't match current RA mode.\n"), pdemoname);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
demoplayer_t *plr = &header.playerdata[0];
|
||||
|
||||
// any invalidating flags?
|
||||
if ((plr->flags & (DEMO_SPECTATOR|DEMO_BOT)) != 0)
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid player slot (spectator/bot)\n"), defdemoname);
|
||||
Z_Free(pdemoname);
|
||||
Z_Free(buffer);
|
||||
G_FreeDemoHeader(&header);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -3968,6 +4005,7 @@ void G_AddGhost(char *defdemoname)
|
|||
gh->buffer = buffer;
|
||||
gh->checksum = demohash;
|
||||
gh->p = buffer + header.endofs;
|
||||
buffer = NULL; // buffer can't be freed now!
|
||||
|
||||
ghosts = gh;
|
||||
|
||||
|
|
@ -4022,8 +4060,6 @@ void G_AddGhost(char *defdemoname)
|
|||
gh->oldmo.color = gh->mo->color;
|
||||
|
||||
CONS_Printf(M_GetText("Added ghost %s from %s\n"), plr->name, pdemoname);
|
||||
G_FreeDemoHeader(&header);
|
||||
Z_Free(pdemoname);
|
||||
}
|
||||
|
||||
// Clean up all ghosts
|
||||
|
|
@ -4041,26 +4077,21 @@ void G_FreeGhosts(void)
|
|||
// A simplified version of G_AddGhost...
|
||||
void G_UpdateStaffGhostName(lumpnum_t l)
|
||||
{
|
||||
UINT8 *buffer = W_CacheLumpNum(l, PU_CACHE);
|
||||
CLEANUP(Z_Pfree) UINT8 *buffer = W_CacheLumpNum(l, PU_CACHE);
|
||||
|
||||
demoheader_t header;
|
||||
CLEANUP(G_FreeDemoHeader) demoheader_t header;
|
||||
if (G_ReadDemoHeader(buffer, &header) != HEADER_OK)
|
||||
goto fail;
|
||||
return;
|
||||
|
||||
if (!(header.demoflags & DF_GHOST))
|
||||
goto fail; // we don't NEED to do it here, but whatever
|
||||
return; // we don't NEED to do it here, but whatever
|
||||
|
||||
if (header.numplayers == 0 || header.playerdata[0].playernum != 0)
|
||||
goto fail;
|
||||
return;
|
||||
if (header.playerdata[0].flags & (DEMO_SPECTATOR|DEMO_BOT))
|
||||
goto fail;
|
||||
strcpy(dummystaffname, header.playerdata[0].name);
|
||||
return;
|
||||
|
||||
// Ok, no longer any reason to care, bye
|
||||
fail:
|
||||
G_FreeDemoHeader(&header);
|
||||
Z_Free(buffer);
|
||||
return;
|
||||
strcpy(dummystaffname, header.playerdata[0].name);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -4454,7 +4485,8 @@ void G_SyncDemoParty(INT32 rem, INT32 newsplitscreen)
|
|||
// viewports.
|
||||
|
||||
// Remove this player
|
||||
G_LeaveParty(rem);
|
||||
if (playeringame[rem])
|
||||
G_LeaveParty(rem);
|
||||
|
||||
// And reset the rest of the party
|
||||
for (int i = 0; i <= r_splitscreen_copy; ++i)
|
||||
|
|
|
|||
|
|
@ -41,6 +41,12 @@ typedef enum
|
|||
RAF_SLIPDASH = 1<<3,
|
||||
RAF_PURPLEDRIFT = 1<<4,
|
||||
RAF_SLOPEBOOST = 1<<5,
|
||||
RAF_AIRDROP = 1<<6,
|
||||
RAF_BUMPDRIFT = 1<<7,
|
||||
RAF_BUMPSPARK = 2<<7,
|
||||
RAF_BS_RESET100 = 3<<7,
|
||||
RAF_BUMPSPARKMASK = 0x3<<7,
|
||||
|
||||
// up to 1<<31 is free
|
||||
} raflags_t;
|
||||
|
||||
|
|
|
|||
51
src/g_game.c
51
src/g_game.c
|
|
@ -296,6 +296,7 @@ SINT8 pickedvote; // What vote the host rolls
|
|||
|
||||
// Server-sided, synched variables
|
||||
SINT8 battlewanted[4]; // WANTED players in battle, worth x2 points
|
||||
SINT8 mostwanted; // The "most wanted" (first in line) player.
|
||||
tic_t wantedcalcdelay; // Time before it recalculates WANTED
|
||||
tic_t indirectitemcooldown; // Cooldown before any more Shrink, SPB, or any other item that works indirectly is awarded
|
||||
tic_t hyubgone; // Cooldown before hyudoro is allowed to be rerolled
|
||||
|
|
@ -442,6 +443,17 @@ consvar_t cv_shrinkme[MAXSPLITSCREENPLAYERS] = {
|
|||
CVAR_INIT ("shrinkme4", "Off", CV_CALL, CV_OnOff, weaponPrefChange4)
|
||||
};
|
||||
|
||||
// Jon's lament
|
||||
static CV_PossibleValue_t driftjitter_cons_t[] = {{0, "SRB2Kart"}, {1, "Ring Racers"}, {0, NULL}};
|
||||
|
||||
// Drift jitter settings.
|
||||
consvar_t cv_jitterlegacy[MAXSPLITSCREENPLAYERS] = {
|
||||
CVAR_INIT ("driftjitter", "Ring Racers", CV_SAVE|CV_CALL|CV_NOINIT, driftjitter_cons_t, weaponPrefChange),
|
||||
CVAR_INIT ("driftjitter2", "Ring Racers", CV_SAVE|CV_CALL|CV_NOINIT, driftjitter_cons_t, weaponPrefChange),
|
||||
CVAR_INIT ("driftjitter3", "Ring Racers", CV_SAVE|CV_CALL|CV_NOINIT, driftjitter_cons_t, weaponPrefChange),
|
||||
CVAR_INIT ("driftjitter4", "Ring Racers", CV_SAVE|CV_CALL|CV_NOINIT, driftjitter_cons_t, weaponPrefChange)
|
||||
};
|
||||
|
||||
static CV_PossibleValue_t zerotoone_cons_t[] = {{0, "MIN"}, {FRACUNIT, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_deadzone[MAXSPLITSCREENPLAYERS] = {
|
||||
CVAR_INIT ("deadzone", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL),
|
||||
|
|
@ -472,14 +484,16 @@ SINT8 G_RecordPresetIndex(void)
|
|||
boolean slipdash = cv_dummyattackingslipdash.value;
|
||||
boolean purpledrift = cv_dummyattackingpurpledrift.value;
|
||||
boolean slopeboost = cv_dummyattackingslopeboost.value;
|
||||
boolean airdrop = cv_dummyattackingairdrop.value;
|
||||
UINT8 bumpspark = cv_dummyattackingbumpspark.value;
|
||||
|
||||
if (!rings && !stacking && !chaining && !slipdash && !purpledrift && !slopeboost)
|
||||
if (!rings && !stacking && !chaining && !slipdash && !purpledrift && !slopeboost && !airdrop && (bumpspark == BUMPSPARK_NONE))
|
||||
return RP_KART;
|
||||
|
||||
if (stacking && chaining && slopeboost && !rings && !slipdash && !purpledrift)
|
||||
if (stacking && chaining && slopeboost && airdrop && !rings && !slipdash && !purpledrift && (bumpspark == BUMPSPARK_ALL))
|
||||
return RP_TECH;
|
||||
|
||||
if (rings && stacking && chaining && slipdash && purpledrift && slopeboost)
|
||||
if (rings && stacking && chaining && slipdash && purpledrift && slopeboost && (bumpspark == BUMPSPARK_NOCHARGE))
|
||||
return RP_BLAN;
|
||||
|
||||
return RP_CUST;
|
||||
|
|
@ -2391,6 +2405,8 @@ static inline void G_PlayerFinishLevel(INT32 player)
|
|||
void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
||||
{
|
||||
player_t *p;
|
||||
|
||||
UINT8 i;
|
||||
INT32 score, roundscore;
|
||||
INT32 lives;
|
||||
|
||||
|
|
@ -2467,6 +2483,9 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
UINT8 lastsafelap;
|
||||
UINT8 lastsafestarpost;
|
||||
UINT16 bigwaypointgap;
|
||||
boolean jitterlegacy = false;
|
||||
|
||||
tic_t laptime[LAP__MAX];
|
||||
|
||||
score = players[player].score;
|
||||
lives = players[player].lives;
|
||||
|
|
@ -2490,6 +2509,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
followercolor = players[player].followercolor;
|
||||
followerskin = players[player].followerskin;
|
||||
|
||||
jitterlegacy = players[player].jitterlegacy;
|
||||
|
||||
availabilities = players[player].availabilities;
|
||||
|
||||
charflags = players[player].charflags;
|
||||
|
|
@ -2520,7 +2541,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
bumper = ((gametyperules & GTR_BUMPERS) ? K_StartingBumperCount() : 0);
|
||||
karmapoints = 0;
|
||||
wanted = 0;
|
||||
rings = 5;
|
||||
rings = cv_kartringsstart.value;
|
||||
minrings = cv_kartringsmin.value;
|
||||
maxrings = cv_kartringsmax.value;
|
||||
kickstartaccel = 0;
|
||||
|
|
@ -2544,6 +2565,10 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
nextcheck = 0;
|
||||
xtralife = 0;
|
||||
|
||||
for (i = 0; i < LAP__MAX; i++)
|
||||
{
|
||||
laptime[i] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -2600,6 +2625,11 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
lastsafelap = players[player].lastsafelap;
|
||||
lastsafestarpost = players[player].lastsafestarpost;
|
||||
bigwaypointgap = players[player].bigwaypointgap;
|
||||
|
||||
for (i = 0; i < LAP__MAX; i++)
|
||||
{
|
||||
laptime[i] = players[player].laptime[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (!betweenmaps)
|
||||
|
|
@ -2615,7 +2645,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
follower = NULL;
|
||||
}
|
||||
|
||||
spectatorreentry = players[player].spectatorreentry;
|
||||
spectatorreentry = (betweenmaps ? 0 : players[player].spectatorreentry);
|
||||
|
||||
grieftime = players[player].grieftime;
|
||||
griefstrikes = players[player].griefstrikes;
|
||||
|
|
@ -2665,6 +2695,11 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
p->latestlap = latestlap;
|
||||
p->totalring = totalring;
|
||||
|
||||
for (i = 0; i < LAP__MAX; i++)
|
||||
{
|
||||
p->laptime[i] = laptime[i];
|
||||
}
|
||||
|
||||
p->bot = bot;
|
||||
p->botvars.style = style;
|
||||
p->botvars.difficulty = botdifficulty;
|
||||
|
|
@ -2689,9 +2724,11 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
p->eggmanblame = -1;
|
||||
p->nocontrol = nocontrol;
|
||||
p->kickstartaccel = kickstartaccel;
|
||||
p->jitterlegacy = jitterlegacy;
|
||||
|
||||
p->ringvolume = 255;
|
||||
p->ringtransparency = 255;
|
||||
p->spinoutrot = 0;
|
||||
|
||||
p->spectatorreentry = spectatorreentry;
|
||||
p->grieftime = grieftime;
|
||||
|
|
@ -2718,8 +2755,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
// Check to make sure their color didn't change somehow...
|
||||
if (G_GametypeHasTeams())
|
||||
{
|
||||
UINT8 i;
|
||||
|
||||
if (p->ctfteam == 1 && p->skincolor != skincolor_redteam)
|
||||
{
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
|
|
@ -3339,7 +3374,7 @@ UINT32 gametypedefaultrules[NUMGAMETYPES] =
|
|||
// Race
|
||||
GTR_CIRCUIT|GTR_BOTS|GTR_RINGS|GTR_ENCORE|GTR_RACEODDS,
|
||||
// Battle
|
||||
GTR_BUMPERS|GTR_RINGS|GTR_KARMA|GTR_WANTED|GTR_ITEMARROWS|GTR_ITEMBREAKER|GTR_BATTLESTARTS|GTR_TIMELIMIT|GTR_BATTLEODDS
|
||||
GTR_BUMPERS|GTR_POINTS|GTR_RINGS|GTR_KARMA|GTR_WANTED|GTR_WANTEDSPB|GTR_ITEMARROWS|GTR_ITEMBREAKER|GTR_BATTLESTARTS|GTR_TIMELIMIT|GTR_POINTLIMIT|GTR_BATTLEODDS|GTR_CLOSERPLAYERS|GTR_BATTLEBOXES|GTR_BATTLESPEED
|
||||
};
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -78,6 +78,8 @@ extern consvar_t cv_invertmouse;
|
|||
|
||||
extern consvar_t cv_kickstartaccel[MAXSPLITSCREENPLAYERS];
|
||||
extern consvar_t cv_shrinkme[MAXSPLITSCREENPLAYERS];
|
||||
extern consvar_t cv_jitterlegacy[MAXSPLITSCREENPLAYERS];
|
||||
|
||||
extern consvar_t cv_deadzone[MAXSPLITSCREENPLAYERS];
|
||||
extern consvar_t cv_deadzonestyle[MAXSPLITSCREENPLAYERS];
|
||||
|
||||
|
|
|
|||
194
src/h_timers.cpp
194
src/h_timers.cpp
|
|
@ -42,10 +42,10 @@ typedef struct itimer_s
|
|||
{
|
||||
const char* name; // name of timer
|
||||
INT32 timer; // current time
|
||||
std::vector<patch_t*> patches; // timer graphics (big/freeplay)
|
||||
//std::vector<patch_t*> patches; // timer graphics (big/freeplay)
|
||||
std::vector<patch_t*> patches_small; // timer graphics (small)
|
||||
INT32 anim_frames; // tic duration for each graphic
|
||||
INT32 xoffs = 0, yoffs = 0; // offsets for freeplay mode
|
||||
//INT32 xoffs = 0, yoffs = 0; // offsets for freeplay mode
|
||||
INT32 xoffs_small = 0, yoffs_small = 0; // offsets for normal mode
|
||||
boolean counter; // not a timer, show a counter instead
|
||||
boolean badtimer; // timer is colored red
|
||||
|
|
@ -143,8 +143,8 @@ static std::vector<itimer_t> addTimers_unsorted;
|
|||
void K_AddItemTimerEx(
|
||||
const char *name,
|
||||
INT32 *timer,
|
||||
char **patches, char **patches_small,
|
||||
INT32 patches_size, INT32 patches_small_size,
|
||||
/*char **patches,*/ char **patches_small,
|
||||
/*INT32 patches_size,*/ INT32 patches_small_size,
|
||||
INT32 anim_duration,
|
||||
INT32 xoffs, INT32 yoffs,
|
||||
INT32 xoffs_small, INT32 yoffs_small,
|
||||
|
|
@ -156,13 +156,13 @@ void K_AddItemTimerEx(
|
|||
t.timer_p = timer;
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < patches_size; i++)
|
||||
t.patches.push_back(qche(patches[i]));
|
||||
//for (i = 0; i < patches_size; i++)
|
||||
//t.patches.push_back(qche(patches[i]));
|
||||
for (i = 0; i < patches_small_size; i++)
|
||||
t.patches_small.push_back(qche(patches[i]));
|
||||
t.patches_small.push_back(qche(patches_small[i]));
|
||||
|
||||
t.anim_frames = anim_duration;
|
||||
t.xoffs = xoffs; t.yoffs = yoffs;
|
||||
//t.xoffs = xoffs; t.yoffs = yoffs;
|
||||
t.xoffs_small = xoffs_small; t.yoffs_small = yoffs_small;
|
||||
t.counter = counter;
|
||||
|
||||
|
|
@ -173,6 +173,37 @@ void K_AddItemTimerEx(
|
|||
addTimers.push_back(t);
|
||||
}
|
||||
|
||||
void K_getTimersDrawinfo(drawinfo_t *out)
|
||||
{
|
||||
INT32 fx, fy, flags = V_HUDTRANS|V_SNAPTOBOTTOM|V_SPLITSCREEN;
|
||||
|
||||
fx = 160 + cv_timers_xoffset.value;
|
||||
fy = 170 + cv_timers_yoffset.value;
|
||||
|
||||
if (r_splitscreen == 1)
|
||||
{
|
||||
flags &= ~V_SNAPTOBOTTOM;
|
||||
fx = 160;
|
||||
fy = 75;
|
||||
}
|
||||
else if (r_splitscreen > 1)
|
||||
{
|
||||
flags &= ~V_SNAPTOBOTTOM;
|
||||
fy = 75;
|
||||
fx = 80;
|
||||
}
|
||||
|
||||
if (r_splitscreen > 0)
|
||||
{
|
||||
flags &= ~V_HUDTRANS;
|
||||
flags |= V_30TRANS;
|
||||
}
|
||||
|
||||
out->x = fx;
|
||||
out->y = fy;
|
||||
out->flags = flags;
|
||||
}
|
||||
|
||||
void K_DisplayItemTimers(void)
|
||||
{
|
||||
if (!cv_itemtimers.value) return;
|
||||
|
|
@ -184,58 +215,65 @@ void K_DisplayItemTimers(void)
|
|||
{ // sneaker
|
||||
"shoe",
|
||||
stplyr->sneakertimer,
|
||||
{qche("K_ISSHOE")},
|
||||
{qche("HL_SNKR")},
|
||||
1, -15, -15, -4, -2,
|
||||
//{qche("K_ISSHOE")},
|
||||
{qche("K_TISHOE")},
|
||||
1, /*-15, -15,*/ -4, -2,
|
||||
},
|
||||
{ // invinc
|
||||
"invincible",
|
||||
stplyr->invincibilitytimer,
|
||||
{qche("K_ISINV1"), qche("K_ISINV2"), qche("K_ISINV3"), qche("K_ISINV4"), qche("K_ISINV5"), qche("K_ISINV6")},
|
||||
{qche("HL_INVNC")},
|
||||
3, -15, -15, -4, -2,
|
||||
//{qche("K_ISINV1"), qche("K_ISINV2"), qche("K_ISINV3"), qche("K_ISINV4"), qche("K_ISINV5"), qche("K_ISINV6")},
|
||||
{qche("K_TIINV1"), qche("K_TIINV2"), qche("K_TIINV3"), qche("K_TIINV4"), qche("K_TIINV5"), qche("K_TIINV6")},
|
||||
3, /*-15, -15,*/ -4, -2,
|
||||
},
|
||||
{ // grow
|
||||
"grow",
|
||||
std::max<INT16>(0, stplyr->growshrinktimer),
|
||||
{qche("K_ISGROW")},
|
||||
{qche("HL_GROW")},
|
||||
1, -15, -15, -4, -2,
|
||||
//{qche("K_ISGROW")},
|
||||
{qche("K_TIGROW")},
|
||||
1, /*-15, -15,*/ -4, -2,
|
||||
},
|
||||
{ // rocket sneakers
|
||||
"rocketsneakers",
|
||||
stplyr->rocketsneakertimer,
|
||||
{qche("K_ISRSHE")},
|
||||
{qche("ISPYRSHE")},
|
||||
1, -15, -15, -4, -2,
|
||||
//{qche("K_ISRSHE")},
|
||||
{qche("K_TIRSHE")},
|
||||
1, /*-15, -15,*/ -4, -2,
|
||||
},
|
||||
{ // hyudoro
|
||||
"hyudoro",
|
||||
stplyr->hyudorotimer,
|
||||
{qche("K_ISHYUD")},
|
||||
{qche("HL_HYU")},
|
||||
1, -15, -15, -4, -2,
|
||||
//{qche("K_ISHYUD")},
|
||||
{qche("K_TIHYUD")},
|
||||
1, /*-15, -15,*/ -4, -2,
|
||||
},
|
||||
{ // drift boost
|
||||
"driftsparkboost",
|
||||
stplyr->driftboost,
|
||||
{qche("IT_ORB0"), qche("IT_ORB1"), qche("IT_ORB2"), qche("IT_ORB3"), qche("IT_ORB4"), qche("IT_ORB3"), qche("IT_ORB2"), qche("IT_ORB1")},
|
||||
{qche("MSO_SPH1"), qche("MSO_SPH2"), qche("MSO_SPH3"), qche("MSO_SPH4")},
|
||||
3,
|
||||
//{qche("K_DRSP1"), qche("K_DRSP2")},
|
||||
{qche("K_TISRK1"), qche("K_TISRK2")},
|
||||
2, /*-15, -15,*/ -4, -2,
|
||||
},
|
||||
{ // start boost
|
||||
"startboost",
|
||||
stplyr->startboost,
|
||||
{qche("K_ISSTB")},
|
||||
{qche("K_SSSTB")},
|
||||
1,
|
||||
//{qche("K_ISSTB")},
|
||||
{qche("K_TISTB")},
|
||||
1, /*-15, -15,*/ -4, -2,
|
||||
},
|
||||
{ // ring boost
|
||||
"ringboost",
|
||||
stplyr->ringboost,
|
||||
{qche("IT_RING")},
|
||||
{qche("MSO_RNG")},
|
||||
1,
|
||||
//{qche("K_ISRING")},
|
||||
{qche("K_TIRING")},
|
||||
1, /*-15, -15,*/ -4, -2,
|
||||
},
|
||||
{ // flameshield
|
||||
"flameshield",
|
||||
stplyr->flametimer,
|
||||
//{qche("K_ISFLMS")},
|
||||
{qche("K_TIFLMS")},
|
||||
1, /*-15, -15,*/ -4, -2,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -250,27 +288,41 @@ void K_DisplayItemTimers(void)
|
|||
{ // spinout
|
||||
"spinout",
|
||||
std::max<UINT16>(stplyr->spinouttimer, stplyr->wipeoutslow),
|
||||
{qche("K_DIZZ1"), qche("K_DIZZ2"), qche("K_DIZZ3"), qche("K_DIZZ4")},
|
||||
{qche("MSO_HRT1"), qche("MSO_HRT2"), qche("MSO_HRT3"), qche("MSO_HRT4")},
|
||||
3, .badtimer = true,
|
||||
//{qche("K_DIZZ1"), qche("K_DIZZ2"), qche("K_DIZZ3"), qche("K_DIZZ4")},
|
||||
{qche("K_TISPN1"), qche("K_TISPN2"), qche("K_TISPN3"), qche("K_TISPN4")},
|
||||
3, /*-15, -15,*/ -4, -2,
|
||||
false,
|
||||
true,
|
||||
}
|
||||
);
|
||||
timers.push_back(
|
||||
{ // shrink
|
||||
"shrink",
|
||||
std::max<INT16>(0, -stplyr->growshrinktimer),
|
||||
{qche("K_ISSHRK")},
|
||||
{qche("HL_SHRNK")},
|
||||
3, -15, -15, -4, -3, .badtimer = true,
|
||||
//{qche("K_ISSHRK")},
|
||||
{qche("K_TISHRK")},
|
||||
1,
|
||||
//-15,
|
||||
//-15,
|
||||
-4,
|
||||
-2,
|
||||
false,
|
||||
true,
|
||||
}
|
||||
);
|
||||
timers.push_back(
|
||||
{ // spb
|
||||
"blueshell",
|
||||
"spb",
|
||||
(INT32)spbTimers[stplyr-players],
|
||||
{qche("IT_SPB1"), qche("IT_SPB2")},
|
||||
{qche("IT_SPBS1"), qche("IT_SPBS2")},
|
||||
1, .badtimer = (stplyr->position == K_GetBestRank()),
|
||||
//{qche("K_ISSPB")},
|
||||
{qche("K_TISPB")},
|
||||
1,
|
||||
//-15,
|
||||
//-15,
|
||||
-4,
|
||||
-2,
|
||||
false,
|
||||
(stplyr->position == K_GetBestRank())
|
||||
}
|
||||
);
|
||||
// Same with boost stacks
|
||||
|
|
@ -278,46 +330,44 @@ void K_DisplayItemTimers(void)
|
|||
{ // boosts
|
||||
"boosts",
|
||||
K_StackingActive() ? stplyr->numboosts : 0,
|
||||
{qche("IT_BOOST0"), qche("IT_BOOST1"), qche("IT_BOOST2"), qche("IT_BOOST3"), qche("IT_BOOST4"), qche("IT_BOOST3"), qche("IT_BOOST2"), qche("IT_BOOST1")},
|
||||
{qche("MSO_SPD1"), qche("MSO_SPD2"), qche("MSO_SPD3"), qche("MSO_SPD4"), qche("MSO_SPD3"), qche("MSO_SPD2")},
|
||||
3, .counter = true,
|
||||
//{qche("K_DRSP1"), qche("K_DRSP2")},
|
||||
{qche("K_TISRK1"), qche("K_TISRK2")},
|
||||
2, /*-15, -15,*/ -3, -2,
|
||||
true,
|
||||
}
|
||||
);
|
||||
|
||||
timers.push_back(
|
||||
/*timers.push_back(
|
||||
{ // dead
|
||||
"spr_realisticexplosion",
|
||||
stplyr->deadtimer ? std::max<INT32>(0, TICRATE - stplyr->deadtimer) : 0,
|
||||
{qche("IT_DED1"), qche("IT_DED2"), qche("IT_DED3"), qche("IT_DED4"), qche("IT_DED5"), qche("IT_DED6"), qche("IT_DED7"), qche("IT_DED8")},
|
||||
//{qche("IT_DED1"), qche("IT_DED2"), qche("IT_DED3"), qche("IT_DED4"), qche("IT_DED5"), qche("IT_DED6"), qche("IT_DED7"), qche("IT_DED8")},
|
||||
{qche("IT_DEAD1"), qche("IT_DEAD2"), qche("IT_DEAD3"), qche("IT_DEAD4"), qche("IT_DEAD5"), qche("IT_DEAD6"), qche("IT_DEAD7"), qche("IT_DEAD8")},
|
||||
1, .yoffs = -4, .badtimer = true,
|
||||
1,
|
||||
//0,
|
||||
//-4,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
true,
|
||||
}
|
||||
);
|
||||
);*/
|
||||
|
||||
// insert unsortable timers
|
||||
timers.insert(timers.end(), addTimers_unsorted.begin(), addTimers_unsorted.end());
|
||||
|
||||
if ((K_NotFreePlay() && !modeattacking) || r_splitscreen > 0) // "HOME" style, with icons at the bottom
|
||||
if (!modeattacking) // "HOME" style, with icons at the bottom
|
||||
{
|
||||
INT32 itemx = 160, itemy = 160;
|
||||
INT32 flags = V_SNAPTOBOTTOM|V_SLIDEIN|V_SPLITSCREEN;
|
||||
INT32 itemx = 0, itemy = 0;
|
||||
INT32 flags = 0;
|
||||
INT32 stepx = 25;
|
||||
INT32 viewnum = R_GetViewNumber();
|
||||
|
||||
if (r_splitscreen == 1)
|
||||
{
|
||||
flags &= ~V_SNAPTOBOTTOM;
|
||||
itemy = 75;
|
||||
}
|
||||
else if (r_splitscreen > 1)
|
||||
{
|
||||
flags &= ~V_SNAPTOBOTTOM;
|
||||
itemy = 75;
|
||||
itemx = 80;
|
||||
}
|
||||
|
||||
if (r_splitscreen > 0)
|
||||
flags |= V_30TRANS;
|
||||
drawinfo_t info;
|
||||
K_getTimersDrawinfo(&info);
|
||||
itemx = info.x;
|
||||
itemy = info.y;
|
||||
flags = info.flags;
|
||||
|
||||
// Move it up to account for viewpoint text
|
||||
if (cv_showviewpointtext.value && !demo.title && !P_IsLocalPlayer(stplyr) && !camera[viewnum].freecam && !r_splitscreen)
|
||||
|
|
@ -368,9 +418,9 @@ void K_DisplayItemTimers(void)
|
|||
textcmap = cmap;
|
||||
}
|
||||
|
||||
if (fastcmp(t.name, "invincibilitytimer"))
|
||||
if (fastcmp(t.name, "boosts"))
|
||||
{
|
||||
cmap = R_GetTranslationColormap(TC_RAINBOW, (skincolornum_t)K_RainbowColor(leveltime), GTC_CACHE);
|
||||
flags |= V_GREENMAP;
|
||||
}
|
||||
|
||||
if (t.counter) // don't show up as time
|
||||
|
|
@ -382,7 +432,10 @@ void K_DisplayItemTimers(void)
|
|||
|
||||
// very bad!
|
||||
if (t.badtimer)
|
||||
textcmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_CRIMSON, GTC_CACHE);
|
||||
{
|
||||
flags |= V_REDMAP;
|
||||
//textcmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_CRIMSON, GTC_CACHE);
|
||||
}
|
||||
|
||||
patch_t *item = t.patches_small[patchnum];
|
||||
V_DrawFixedPatch((itemx - (item->width/2))<<FRACBITS, (itemy + t.yoffs_small)<<FRACBITS, FRACUNIT, flags, t.patches_small[patchnum], cmap);
|
||||
|
|
@ -402,7 +455,7 @@ void K_DisplayItemTimers(void)
|
|||
itemx += stepx;
|
||||
}
|
||||
}
|
||||
else // FREEPLAY - Move these to the left side, where the rankings usually are
|
||||
/*else // FREEPLAY - Move these to the left side, where the rankings usually are
|
||||
{
|
||||
if (r_splitscreen) // How?
|
||||
return;
|
||||
|
|
@ -483,4 +536,5 @@ void K_DisplayItemTimers(void)
|
|||
fy += step;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ extern "C" {
|
|||
|
||||
#include "command.h"
|
||||
#include "d_player.h"
|
||||
#include "k_hud.h"
|
||||
|
||||
extern consvar_t cv_itemtimers;
|
||||
extern tic_t spbTimers[MAXPLAYERS];
|
||||
|
|
@ -34,6 +35,7 @@ void K_AddItemTimerEx(
|
|||
INT32 xoffs_small, INT32 yoffs_small,
|
||||
boolean counter, boolean unsorted);
|
||||
void K_DisplayItemTimers(void);
|
||||
void K_getTimersDrawinfo(drawinfo_t *out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@
|
|||
#include "hw_glob.h"
|
||||
#include "hw_drv.h"
|
||||
|
||||
#include "../m_misc.h" //FIL_WriteFile()
|
||||
#include "../r_draw.h" //viewborderlump
|
||||
#include "../r_main.h"
|
||||
#include "../w_wad.h"
|
||||
|
|
@ -1252,41 +1251,18 @@ static inline boolean saveTGA(const char *file_name, void *buffer,
|
|||
// screen shot
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
UINT8 *HWR_GetScreenshot(void)
|
||||
UINT8 *HWR_GetScreenshot(INT32 scale)
|
||||
{
|
||||
static UINT8 *buf = NULL;
|
||||
|
||||
buf = realloc(buf, vid.width * vid.height * 3);
|
||||
buf = realloc(buf, (vid.width/scale)*(vid.height/scale)*3);
|
||||
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
// returns 24bit 888 RGB
|
||||
HWD.pfnReadRect(0, 0, vid.width, vid.height, vid.width * 3, (void *)buf);
|
||||
HWD.pfnReadScreenFinalTexture(buf, scale);
|
||||
return buf;
|
||||
}
|
||||
|
||||
boolean HWR_Screenshot(const char *pathname)
|
||||
{
|
||||
boolean ret;
|
||||
UINT8 *buf = malloc(vid.width * vid.height * 3 * sizeof (*buf));
|
||||
|
||||
if (!buf)
|
||||
{
|
||||
CONS_Debug(DBG_RENDER, "HWR_Screenshot: Failed to allocate memory\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// returns 24bit 888 RGB
|
||||
HWD.pfnReadRect(0, 0, vid.width, vid.height, vid.width * 3, (void *)buf);
|
||||
|
||||
#ifdef USE_PNG
|
||||
ret = M_SavePNG(pathname, buf, vid.width, vid.height, NULL);
|
||||
#else
|
||||
ret = saveTGA(pathname, buf, vid.width, vid.height);
|
||||
#endif
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif //HWRENDER
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFl
|
|||
EXPORT void HWRAPI(SetTexture) (GLMipmap_t *TexInfo);
|
||||
EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *TexInfo);
|
||||
EXPORT void HWRAPI(DeleteTexture) (GLMipmap_t *TexInfo);
|
||||
EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 *dst_data);
|
||||
EXPORT void HWRAPI(ReadScreenFinalTexture) (UINT8 * restrict dest, INT32 scale);
|
||||
EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip);
|
||||
EXPORT void HWRAPI(ClearMipMapCache) (void);
|
||||
|
||||
|
|
@ -99,7 +99,7 @@ struct hwdriver_s
|
|||
SetTexture pfnSetTexture;
|
||||
UpdateTexture pfnUpdateTexture;
|
||||
DeleteTexture pfnDeleteTexture;
|
||||
ReadRect pfnReadRect;
|
||||
ReadScreenFinalTexture pfnReadScreenFinalTexture;
|
||||
GClipRect pfnGClipRect;
|
||||
ClearMipMapCache pfnClearMipMapCache;
|
||||
SetSpecialState pfnSetSpecialState;//Hurdler: added for backward compatibility
|
||||
|
|
|
|||
|
|
@ -4712,15 +4712,25 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
patch_t *rotsprite = NULL;
|
||||
INT32 rollangle = 0;
|
||||
angle_t spriterotangle = 0;
|
||||
vector2_t visoffs, rotoffset;
|
||||
#endif
|
||||
|
||||
// uncapped/interpolation
|
||||
interpmobjstate_t interp = {0};
|
||||
mobj_t *interptarg;
|
||||
|
||||
if (!thing)
|
||||
return;
|
||||
|
||||
R_InterpolateMobjState(thing, R_GetTimeFrac(RTF_LEVEL), &interp);
|
||||
interptarg = thing;
|
||||
|
||||
if (R_IsOverlayingInvinciblePlayer(thing))
|
||||
{
|
||||
// Kill overlay misalignment
|
||||
interptarg = thing->target;
|
||||
}
|
||||
|
||||
R_InterpolateMobjState(interptarg, R_GetTimeFrac(RTF_LEVEL), &interp);
|
||||
|
||||
dispoffset = thing->dispoffset;
|
||||
|
||||
|
|
@ -4877,12 +4887,36 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
flip = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// initialize and rotate pitch/roll vectors
|
||||
visoffs.x = 0;
|
||||
visoffs.y = 0;
|
||||
rotoffset.x = 0;
|
||||
rotoffset.y = 0;
|
||||
|
||||
const fixed_t visoffymul = (vflip ? -FRACUNIT : FRACUNIT);
|
||||
|
||||
if (R_ThingIsUsingBakedOffsets(thing))
|
||||
{
|
||||
R_RotateSpriteOffsetsByPitchRoll(thing,
|
||||
vflip,
|
||||
hflip,
|
||||
&interp,
|
||||
&visoffs,
|
||||
&rotoffset);
|
||||
|
||||
rotoffset.x *= FRACUNIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (thing->renderflags & RF_ABSOLUTEOFFSETS)
|
||||
{
|
||||
spr_offset = interp.spritexoffset;
|
||||
#ifdef ROTSPRITE
|
||||
spr_topoffset = (interp.spriteyoffset + FixedDiv((visoffs.y * visoffymul), mapobjectscale) + (rotoffset.y * visoffymul));
|
||||
#else
|
||||
spr_topoffset = interp.spriteyoffset;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -4892,7 +4926,12 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
flipoffset = -1;
|
||||
|
||||
spr_offset += interp.spritexoffset * flipoffset;
|
||||
#ifdef ROTSPRITE
|
||||
spr_topoffset += (interp.spriteyoffset + FixedDiv((visoffs.y * visoffymul),
|
||||
mapobjectscale) + (rotoffset.y * visoffymul)) * flipoffset;
|
||||
#else
|
||||
spr_topoffset += interp.spriteyoffset * flipoffset;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (papersprite)
|
||||
|
|
@ -4943,17 +4982,30 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
}
|
||||
else
|
||||
{
|
||||
#ifdef ROTSPRITE
|
||||
if (visoffs.x)
|
||||
{
|
||||
visoffs.x = (FixedDiv((visoffs.x * FRACUNIT), mapobjectscale));
|
||||
}
|
||||
#endif
|
||||
if (flip)
|
||||
{
|
||||
x1 = (FIXED_TO_FLOAT(spr_width - spr_offset) * this_xscale);
|
||||
#ifdef ROTSPRITE
|
||||
spr_offset -= visoffs.x;
|
||||
spr_offset -= rotoffset.x;
|
||||
#endif
|
||||
x1 = (FIXED_TO_FLOAT((spr_width - spr_offset)) * this_xscale);
|
||||
x2 = (FIXED_TO_FLOAT(spr_offset) * this_xscale);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef ROTSPRITE
|
||||
spr_offset += visoffs.x;
|
||||
spr_offset += rotoffset.x;
|
||||
#endif
|
||||
x1 = (FIXED_TO_FLOAT(spr_offset) * this_xscale);
|
||||
x2 = (FIXED_TO_FLOAT(spr_width - spr_offset) * this_xscale);
|
||||
}
|
||||
|
||||
// test if too close
|
||||
/*
|
||||
if (papersprite)
|
||||
|
|
@ -5095,7 +5147,10 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
// New colormap stuff for skins Tails 06-07-2002
|
||||
if (thing->colorized)
|
||||
{
|
||||
vis->colormap = R_GetTranslationColormap(TC_RAINBOW, thing->color, GTC_CACHE);
|
||||
vis->colormap = R_GetTranslationColormap(
|
||||
R_IsOverlayingInvinciblePlayer(thing) ? TC_BLINK : TC_RAINBOW,
|
||||
thing->color,
|
||||
GTC_CACHE);
|
||||
}
|
||||
else if (thing->skin && thing->sprite == SPR_PLAY) // This thing is a player!
|
||||
{
|
||||
|
|
@ -5538,7 +5593,7 @@ static void HWR_DrawSkyBackground(player_t *player)
|
|||
|
||||
dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f);
|
||||
|
||||
v[0].s = v[3].s = (-1.0f * angle) / ((ANGLE_90-1)*dimensionmultiply); // left
|
||||
v[0].s = v[3].s = (-1.0f * angle) / (((float)ANGLE_90-1.0f)*dimensionmultiply); // left
|
||||
v[2].s = v[1].s = v[0].s + (1.0f/dimensionmultiply); // right (or left + 1.0f)
|
||||
// use +angle and -1.0f above instead if you wanted old backwards behavior
|
||||
|
||||
|
|
|
|||
|
|
@ -54,8 +54,7 @@ void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT32
|
|||
void HWR_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 color);
|
||||
void HWR_DrawPic(INT32 x,INT32 y,lumpnum_t lumpnum);
|
||||
|
||||
UINT8 *HWR_GetScreenshot(void);
|
||||
boolean HWR_Screenshot(const char *pathname);
|
||||
UINT8 *HWR_GetScreenshot(INT32 scale);
|
||||
|
||||
void HWR_AddCommands(void);
|
||||
void HWR_AddSessionCommands(void);
|
||||
|
|
|
|||
|
|
@ -1685,18 +1685,27 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
|
|||
p.angley = FIXED_TO_FLOAT(anglef);
|
||||
}
|
||||
|
||||
angle_t pitchR, rollR, fixedAngY;
|
||||
|
||||
// drift frame unrotation hack...
|
||||
if (modeltype == MODELTYPE_OLDPLAYER && (spr2 == SPR2_DRRN || spr2 == SPR2_DRLN))
|
||||
p.angley += spr2 == SPR2_DRRN ? 45.0f : -45.0f;
|
||||
|
||||
pitchR = 0;
|
||||
rollR = 0;
|
||||
fixedAngY = 0;
|
||||
|
||||
{
|
||||
fixed_t anglef = AngleFixed(R_SpriteRotationAngle(spr->mobj, NULL, &interp));
|
||||
|
||||
p.rollangle = 0.0f;
|
||||
|
||||
// make fixedAngY a disguised fixed_t first
|
||||
fixedAngY = FLOAT_TO_FIXED(p.angley);
|
||||
|
||||
if (anglef)
|
||||
{
|
||||
fixed_t camAngleDiff = AngleFixed(viewangle) - FLOAT_TO_FIXED(p.angley); // dumb reconversion back, I know
|
||||
fixed_t camAngleDiff = AngleFixed(viewangle) - (fixed_t)(fixedAngY); // dumb reconversion back, I know
|
||||
|
||||
anglef *= flip ? -1 : 1; // Adjust for flipping
|
||||
|
||||
|
|
@ -1708,9 +1717,19 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
|
|||
p.centery = FIXED_TO_FLOAT(spr->mobj->height / 2);
|
||||
|
||||
// rotation axes relative to camera
|
||||
p.rollx = FIXED_TO_FLOAT(FINECOSINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT));
|
||||
p.rollz = FIXED_TO_FLOAT(FINESINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT));
|
||||
pitchR = FINESINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT);
|
||||
rollR = FINECOSINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT);
|
||||
|
||||
p.rollx = FIXED_TO_FLOAT((fixed_t)rollR);
|
||||
p.rollz = FIXED_TO_FLOAT((fixed_t)pitchR);
|
||||
|
||||
// convert to angles
|
||||
pitchR = FixedAngle((fixed_t)pitchR);
|
||||
rollR = FixedAngle((fixed_t)rollR);
|
||||
}
|
||||
|
||||
// make this a proper angle now
|
||||
fixedAngY = FixedAngle(fixedAngY);
|
||||
}
|
||||
|
||||
p.anglez = FIXED_TO_FLOAT(AngleFixed(R_InterpolateAngle(spr->mobj->old_pitch, spr->mobj->pitch)));
|
||||
|
|
@ -1722,6 +1741,8 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
|
|||
HWD.pfnSetShader(SHADER_MODEL); // model shader
|
||||
{
|
||||
float this_scale = FIXED_TO_FLOAT(interp.scale);
|
||||
fixed_t floorClip = spr->mobj->terrain ? spr->mobj->terrain->floorClip : 0;
|
||||
float finalfloorClip = FIXED_TO_FLOAT(FixedMul(floorClip, mapobjectscale)*P_MobjFlip(spr->mobj));
|
||||
|
||||
float xs = this_scale * FIXED_TO_FLOAT(interp.spritexscale);
|
||||
float ys = this_scale * FIXED_TO_FLOAT(interp.spriteyscale);
|
||||
|
|
@ -1742,7 +1763,89 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
|
|||
// offset perpendicular to the camera angle
|
||||
p.x -= ox * gl_viewsin;
|
||||
p.y += ox * gl_viewcos;
|
||||
p.z += oy;
|
||||
p.z += oy - finalfloorClip;
|
||||
|
||||
if (R_ThingIsUsingBakedOffsets(spr->mobj))
|
||||
{
|
||||
// visoffset stuff
|
||||
float xx, xy, yx, yy;
|
||||
float zx, zy, zz;
|
||||
float xpiv, ypiv, zpiv;
|
||||
fixed_t zh;
|
||||
fixed_t xoffs, yoffs;
|
||||
|
||||
// xoffs = (cos(xoff) + sin(yoff))
|
||||
xoffs =
|
||||
FixedMul(spr->mobj->bakeyoff, -FINECOSINE(fixedAngY >> ANGLETOFINESHIFT)) +
|
||||
FixedMul(spr->mobj->bakexoff, FINESINE(fixedAngY >> ANGLETOFINESHIFT));
|
||||
|
||||
// yoffs = (-sin(xoff) + cos(yoff))
|
||||
yoffs =
|
||||
FixedMul(spr->mobj->bakeyoff, -FINESINE(fixedAngY >> ANGLETOFINESHIFT)) +
|
||||
FixedMul(spr->mobj->bakexoff, FINECOSINE(fixedAngY >> ANGLETOFINESHIFT));
|
||||
|
||||
const fixed_t hflipmul = hflip ? -FRACUNIT : FRACUNIT;
|
||||
|
||||
xpiv = FIXED_TO_FLOAT(
|
||||
FixedMul(
|
||||
FixedMul(spr->mobj->bakeypiv,
|
||||
-FINECOSINE(fixedAngY >> ANGLETOFINESHIFT)) +
|
||||
FixedMul(spr->mobj->bakexpiv,
|
||||
FINESINE(fixedAngY >> ANGLETOFINESHIFT)),
|
||||
hflipmul));
|
||||
ypiv = FIXED_TO_FLOAT(
|
||||
FixedMul(
|
||||
FixedMul(spr->mobj->bakeypiv,
|
||||
-FINESINE(fixedAngY >> ANGLETOFINESHIFT)) +
|
||||
FixedMul(spr->mobj->bakexpiv,
|
||||
FINECOSINE(fixedAngY >> ANGLETOFINESHIFT)),
|
||||
hflipmul));
|
||||
zpiv = FIXED_TO_FLOAT(spr->mobj->bakezpiv * ((flip) ? -1 : 1));
|
||||
|
||||
pitchR = ((pitchR + spr->mobj->pitch) * ((flip) ? -1 : 1));
|
||||
rollR = ((rollR + spr->mobj->roll) * ((flip) ? -1 : 1));
|
||||
|
||||
// x offset
|
||||
xx = FIXED_TO_FLOAT(FixedMul(FixedMul(
|
||||
FixedMul(xoffs,spr->mobj->spritexscale),
|
||||
hflipmul),
|
||||
FINECOSINE(pitchR >> ANGLETOFINESHIFT)
|
||||
));
|
||||
xy = FIXED_TO_FLOAT(FixedMul(FixedMul(
|
||||
FixedMul(xoffs,spr->mobj->spritexscale),
|
||||
hflipmul),
|
||||
-FINESINE(pitchR >> ANGLETOFINESHIFT)
|
||||
));
|
||||
|
||||
// y offset
|
||||
yx = FIXED_TO_FLOAT(FixedMul(FixedMul(
|
||||
FixedMul(yoffs,spr->mobj->spritexscale),
|
||||
hflipmul),
|
||||
FINECOSINE(rollR >> ANGLETOFINESHIFT)
|
||||
));
|
||||
|
||||
yy = FIXED_TO_FLOAT(FixedMul(FixedMul(
|
||||
FixedMul(yoffs,spr->mobj->spritexscale),
|
||||
hflipmul),
|
||||
-FINESINE(rollR >> ANGLETOFINESHIFT)
|
||||
));
|
||||
|
||||
// z offset
|
||||
zh = FixedMul(FixedMul(spr->mobj->bakezoff,spr->mobj->spriteyscale),
|
||||
FINECOSINE(rollR >> ANGLETOFINESHIFT));
|
||||
|
||||
zz = FIXED_TO_FLOAT(FixedMul(zh,
|
||||
FINECOSINE(pitchR >> ANGLETOFINESHIFT)));
|
||||
zx = FIXED_TO_FLOAT(FixedMul(zh,
|
||||
FINESINE(pitchR >> ANGLETOFINESHIFT)));
|
||||
zy = FIXED_TO_FLOAT(FixedMul(zh,
|
||||
FINESINE(rollR >> ANGLETOFINESHIFT)));
|
||||
|
||||
// do these namings even make sense at this point?
|
||||
p.x += xx + zx + xpiv;
|
||||
p.z += (xy + yy + zz * (flip ? -1 : 1)) + zpiv;
|
||||
p.y += yx + zy + ypiv;
|
||||
}
|
||||
|
||||
HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, md2->scale * xs, md2->scale * ys, flip, hflip, &Surf);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,9 @@
|
|||
#include "r_opengl.h"
|
||||
#include "r_vbo.h"
|
||||
|
||||
// requires GL 4.3
|
||||
//#define GLDEBUGMESSAGE
|
||||
|
||||
#if defined (HWRENDER) && !defined (NOROPENGL)
|
||||
|
||||
struct GLRGBAFloat
|
||||
|
|
@ -281,6 +284,10 @@ static void GL_MSG_Error(const char *format, ...)
|
|||
#define pglCopyTexImage2D glCopyTexImage2D
|
||||
#define pglCopyTexSubImage2D glCopyTexSubImage2D
|
||||
|
||||
#ifdef GLDEBUGMESSAGE
|
||||
#define pglDebugMessageCallback glDebugMessageCallback
|
||||
#endif
|
||||
|
||||
#else //!STATIC_OPENGL
|
||||
|
||||
/* 1.0 functions */
|
||||
|
|
@ -423,6 +430,11 @@ static PFNglDeleteBuffers pglDeleteBuffers;
|
|||
typedef void (APIENTRY * PFNglBlendEquation) (GLenum mode);
|
||||
static PFNglBlendEquation pglBlendEquation;
|
||||
|
||||
#ifdef GLDEBUGMESSAGE
|
||||
typedef void (APIENTRY * PFNglDebugMessageCallback) (void (APIENTRY *DEBUGPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam), const void *userParam);
|
||||
static PFNglDebugMessageCallback pglDebugMessageCallback;
|
||||
#endif
|
||||
|
||||
|
||||
/* 1.2 Parms */
|
||||
/* GL_CLAMP_TO_EDGE_EXT */
|
||||
|
|
@ -983,6 +995,10 @@ void SetupGLFunc4(void)
|
|||
*(void**)&pglUniform3fv = GetGLFunc("glUniform3fv");
|
||||
*(void**)&pglGetUniformLocation = GetGLFunc("glGetUniformLocation");
|
||||
#endif
|
||||
|
||||
#ifdef GLDEBUGMESSAGE
|
||||
*(void**)&pglDebugMessageCallback = GetGLFunc("glDebugMessageCallback");
|
||||
#endif
|
||||
}
|
||||
|
||||
EXPORT boolean HWRAPI(CompileShaders) (void)
|
||||
|
|
@ -1335,6 +1351,50 @@ void SetModelView(GLint w, GLint h)
|
|||
pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix);
|
||||
}
|
||||
|
||||
#ifdef GLDEBUGMESSAGE
|
||||
static void APIENTRY DebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam)
|
||||
{
|
||||
const char *debugsource, *debugtype;
|
||||
|
||||
switch (source)
|
||||
{
|
||||
#define S(s) case GL_DEBUG_SOURCE_##s: debugsource = #s; break
|
||||
S(API);
|
||||
S(WINDOW_SYSTEM);
|
||||
S(SHADER_COMPILER);
|
||||
S(THIRD_PARTY);
|
||||
S(APPLICATION);
|
||||
S(OTHER);
|
||||
#undef S
|
||||
default:
|
||||
debugsource = "unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
#define S(s) case GL_DEBUG_TYPE_##s: debugtype = #s; break
|
||||
S(ERROR);
|
||||
S(DEPRECATED_BEHAVIOR);
|
||||
S(UNDEFINED_BEHAVIOR);
|
||||
S(PORTABILITY);
|
||||
S(PERFORMANCE);
|
||||
S(MARKER);
|
||||
S(PUSH_GROUP);
|
||||
S(POP_GROUP);
|
||||
S(OTHER);
|
||||
#undef S
|
||||
default:
|
||||
debugtype = "unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
alerttype_t level = severity == GL_DEBUG_SEVERITY_HIGH ? CONS_ERROR
|
||||
: severity == GL_DEBUG_SEVERITY_MEDIUM ? CONS_WARNING
|
||||
: CONS_NOTICE;
|
||||
CONS_Alert(level, "OpenGL (%s) (%s): %s\n", debugsource, debugtype, message);
|
||||
}
|
||||
#endif
|
||||
|
||||
// -----------------+
|
||||
// SetStates : Set permanent states
|
||||
|
|
@ -1395,6 +1455,12 @@ void SetStates(void)
|
|||
pglLoadIdentity();
|
||||
pglScalef(1.0f, 1.0f, -1.0f);
|
||||
pglGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix); // added for new coronas' code (without depth buffer)
|
||||
|
||||
#ifdef GLDEBUGMESSAGE
|
||||
pglEnable(GL_DEBUG_OUTPUT);
|
||||
pglEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
||||
pglDebugMessageCallback(&DebugMessage, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1514,58 +1580,37 @@ EXPORT void HWRAPI(ClearMipMapCache) (void)
|
|||
Flush();
|
||||
}
|
||||
|
||||
|
||||
// -----------------+
|
||||
// ReadRect : Read a rectangle region of the truecolor framebuffer
|
||||
// : store pixels as 16bit 565 RGB
|
||||
// Returns : 16bit 565 RGB pixel array stored in dst_data
|
||||
// -----------------+
|
||||
EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height,
|
||||
INT32 dst_stride, UINT16 * dst_data)
|
||||
// -----------------------+
|
||||
// ReadScreenFinalTexture : Reads out the final screen texture
|
||||
// Returns : 24bit RGB pixel array stored in dest
|
||||
// -----------------------+
|
||||
EXPORT void HWRAPI(ReadScreenFinalTexture) (UINT8 * restrict dest, INT32 scale)
|
||||
{
|
||||
INT32 i;
|
||||
// GL_DBG_Printf ("ReadRect()\n");
|
||||
if (dst_stride == width*3)
|
||||
{
|
||||
GLubyte*top = (GLvoid*)dst_data, *bottom = top + dst_stride * (height - 1);
|
||||
GLubyte *row = malloc(dst_stride);
|
||||
if (!row) return;
|
||||
pglPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
pglReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, dst_data);
|
||||
pglPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
for(i = 0; i < height/2; i++)
|
||||
{
|
||||
memcpy(row, top, dst_stride);
|
||||
memcpy(top, bottom, dst_stride);
|
||||
memcpy(bottom, row, dst_stride);
|
||||
top += dst_stride;
|
||||
bottom -= dst_stride;
|
||||
}
|
||||
free(row);
|
||||
}
|
||||
else
|
||||
{
|
||||
INT32 j;
|
||||
GLubyte *image = malloc(width*height*3*sizeof (*image));
|
||||
if (!image) return;
|
||||
pglPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
pglReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
pglPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
for (i = height-1; i >= 0; i--)
|
||||
{
|
||||
for (j = 0; j < width; j++)
|
||||
{
|
||||
dst_data[(height-1-i)*width+j] =
|
||||
(UINT16)(
|
||||
((image[(i*width+j)*3]>>3)<<11) |
|
||||
((image[(i*width+j)*3+1]>>2)<<5) |
|
||||
((image[(i*width+j)*3+2]>>3)));
|
||||
}
|
||||
}
|
||||
free(image);
|
||||
}
|
||||
}
|
||||
const INT32 stride = (screen_width/scale)*3;
|
||||
INT32 scanlines = screen_height;
|
||||
GLubyte * restrict image;
|
||||
|
||||
image = malloc(screen_width*screen_height*3);
|
||||
pglPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
pglReadPixels(0, 0, screen_width, screen_height, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
|
||||
// TODO the downscaling happens in the screen capture code now,
|
||||
// yet we're still doing this on the CPU? sheesh...
|
||||
// this is where actual knowledge of OpenGL would've come in handy
|
||||
image += scanlines*screen_width*3;
|
||||
while ((scanlines -= scale) >= 0)
|
||||
{
|
||||
image -= screen_width*scale*3;
|
||||
if (scale == 1)
|
||||
memcpy(dest, image, stride);
|
||||
else for (INT32 i = 0; i < stride; i += 3)
|
||||
memcpy(dest + i, image + i*scale, 3);
|
||||
dest += stride;
|
||||
}
|
||||
|
||||
// ...yet still, restrict doesn't make the inner loop any faster
|
||||
free(image - ((screen_height % scale) * screen_width*3));
|
||||
}
|
||||
|
||||
// -----------------+
|
||||
// GClipRect : Defines the 2D hardware clipping window
|
||||
|
|
|
|||
|
|
@ -2058,7 +2058,7 @@ static void HU_DrawDemoInfo(void)
|
|||
void HU_DrawSongCredits(void)
|
||||
{
|
||||
fixed_t x;
|
||||
fixed_t y = (r_splitscreen ? (BASEVIDHEIGHT/2)-4 : 32) * FRACUNIT;
|
||||
fixed_t y = ((r_splitscreen && G_GamestateUsesLevel()) ? (BASEVIDHEIGHT/2)-4 : 32) * FRACUNIT;
|
||||
INT32 snapflags = cursongcredit.snapflags;
|
||||
INT32 bgt;
|
||||
|
||||
|
|
@ -2592,7 +2592,7 @@ static void HU_DrawRankings(void)
|
|||
|
||||
tab[scorelines].name = player_names[i];
|
||||
|
||||
if ((gametyperules & GTR_CIRCUIT))
|
||||
if (gametyperules & GTR_CIRCUIT)
|
||||
{
|
||||
if (!players[i].exiting)
|
||||
sprintf(tab[scorelines].string, "Lap %d", players[i].laps);
|
||||
|
|
@ -2605,7 +2605,7 @@ static void HU_DrawRankings(void)
|
|||
sprintf(tab[scorelines].string, "%i'%02i\"%02i", min, sec, cen);
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (gametyperules & GTR_POINTS)
|
||||
sprintf(tab[scorelines].string, "%d", players[i].roundscore);
|
||||
|
||||
scorelines++;
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ void I_WaitVBL(INT32 count);
|
|||
|
||||
\return void
|
||||
*/
|
||||
void I_ReadScreen(UINT8 *scr);
|
||||
void I_ReadScreen(UINT8 * restrict scr, INT32 scale);
|
||||
|
||||
/** \brief Start disk icon
|
||||
*/
|
||||
|
|
@ -153,6 +153,10 @@ void I_EndRead(void);
|
|||
|
||||
UINT32 I_GetRefreshRate(void);
|
||||
|
||||
boolean I_UseNativeKeyboard(void);
|
||||
|
||||
extern consvar_t cv_keyboardlayout;
|
||||
|
||||
void I_SetBorderlessWindow(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ void P_ResetData(INT32 flags)
|
|||
|
||||
if (!init)
|
||||
{
|
||||
lumpnum = W_CheckNumForLongNamePwadNoUpper("states", MAINWAD_MAIN, 0);
|
||||
lumpnum = W_CheckNumForLongNamePwad("states", MAINWAD_MAIN, 0);
|
||||
DEH_LoadDehackedLumpPwad(MAINWAD_MAIN, lumpnum, true);
|
||||
}
|
||||
}
|
||||
|
|
@ -183,7 +183,7 @@ void P_ResetData(INT32 flags)
|
|||
|
||||
if (!init)
|
||||
{
|
||||
lumpnum = W_CheckNumForLongNamePwadNoUpper("mobjs", MAINWAD_MAIN, 0);
|
||||
lumpnum = W_CheckNumForLongNamePwad("mobjs", MAINWAD_MAIN, 0);
|
||||
DEH_LoadDehackedLumpPwad(MAINWAD_MAIN, lumpnum, true);
|
||||
}
|
||||
}
|
||||
|
|
@ -211,7 +211,7 @@ void P_ResetData(INT32 flags)
|
|||
|
||||
if (!init)
|
||||
{
|
||||
lumpnum = W_CheckNumForLongNamePwadNoUpper("skincolors", MAINWAD_MAIN, 0);
|
||||
lumpnum = W_CheckNumForLongNamePwad("skincolors", MAINWAD_MAIN, 0);
|
||||
DEH_LoadDehackedLumpPwad(MAINWAD_MAIN, lumpnum, true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -222,4 +222,3 @@ _(A_RoamingShadowThinker, ROAMINGSHADOWTHINKER)
|
|||
_(A_MayonakaArrow, MAYONAKAARROW)
|
||||
_(A_MementosTPParticles, MEMENTOSTPPARTICLES)
|
||||
_(A_ReaperThinker, REAPERTHINKER)
|
||||
_(A_DeathSpin, DEATHSPIN)
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@ _(UNKNOWN)
|
|||
_(THOK) // Thok! mobj
|
||||
_(SHADOW) // Linkdraw Shadow (for invisible objects)
|
||||
_(PLAYER)
|
||||
_(KART_LEFTOVER)
|
||||
_(KART_TIRE)
|
||||
|
||||
// Enemies
|
||||
_(BLUECRAWLA) // Crawla (Blue)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// SRB2K colors
|
||||
_(NONE)
|
||||
|
||||
_(WHITE) // kart colors
|
||||
_(WHITE)
|
||||
_(SILVER)
|
||||
_(GREY)
|
||||
_(NICKEL)
|
||||
|
|
@ -62,7 +63,7 @@ _(ROBOHOOD)
|
|||
_(MINT)
|
||||
_(GREEN)
|
||||
_(PINETREE)
|
||||
_(EMERALD)
|
||||
_(TURTLE)
|
||||
_(SWAMP)
|
||||
_(DREAM)
|
||||
_(PLAGUE)
|
||||
|
|
@ -82,10 +83,10 @@ _(THUNDER)
|
|||
_(RUST)
|
||||
_(WRISTWATCH)
|
||||
_(JET)
|
||||
_(SAPPHIRE) // sweet mother, i cannot weave - slender aphrodite has overcome me with longing for a girl
|
||||
_(SAPPHIRE)
|
||||
_(PERIWINKLE)
|
||||
_(BLUE)
|
||||
_(BLUEBERRY)
|
||||
_(MIDNIGHT)
|
||||
_(NOVA)
|
||||
_(PASTEL)
|
||||
_(MOONSLAM)
|
||||
|
|
@ -101,170 +102,268 @@ _(BYZANTIUM)
|
|||
_(POMEGRANATE)
|
||||
_(LILAC)
|
||||
|
||||
_(TAN) // v2 colors, i think? separated from the rest (yay compatmode!)
|
||||
// Ring Racers New Colors
|
||||
// These are listed after the Kart colors for backwards compatability
|
||||
_(SUNSLAM)
|
||||
_(TAN)
|
||||
_(BANANA)
|
||||
_(PERIDOT)
|
||||
_(TURTLE)
|
||||
_(EMERALD)
|
||||
_(AQUAMARINE)
|
||||
_(TURQUOISE)
|
||||
_(ROBIN)
|
||||
_(ULTRAMARINE)
|
||||
_(MIDNIGHT)
|
||||
_(BLUEBERRY)
|
||||
_(THISTLE)
|
||||
_(MOONSET)
|
||||
_(VIOLET)
|
||||
_(MAGENTA)
|
||||
_(BLOSSOM)
|
||||
_(TAFFY)
|
||||
|
||||
_(BONE) // vanilla colors - shoutouts to Sonic Team Jr.
|
||||
// SRB2 Vanilla 2.2 Ports
|
||||
// featuring Viv's vivid colours (toast 21/07/17)
|
||||
// Tweaks & additions (Lach, Chrispy, sphere, Alice, MotorRoach & Saneko 26/10/22)
|
||||
// Conversion to Kart/Ring Racers style (BlanKart 21/04/25)
|
||||
_(BONE)
|
||||
_(CARBON)
|
||||
_(INK)
|
||||
_(GHOST)
|
||||
_(AETHER)
|
||||
_(MARBLE)
|
||||
_(MOONSTONE)
|
||||
_(BLUEBELL)
|
||||
_(CHOCOLATE)
|
||||
_(CHESTNUT)
|
||||
_(LATTE)
|
||||
_(BOULDER)
|
||||
_(BRASS)
|
||||
_(VINTAGE)
|
||||
_(ECRU)
|
||||
_(SANDSTORM)
|
||||
_(ROSEBUSH)
|
||||
_(LEEK)
|
||||
_(EGGPLANT)
|
||||
_(CERISE)
|
||||
_(CRANBERRY)
|
||||
_(PEPPER)
|
||||
_(MAHOGANY)
|
||||
_(BLAZING)
|
||||
_(GARNET)
|
||||
_(PEACHY)
|
||||
_(QUAIL)
|
||||
_(LANTERN)
|
||||
_(FOUNDATION)
|
||||
_(BURNING)
|
||||
_(APRICOT)
|
||||
_(SANDY)
|
||||
_(SUNFLOWER)
|
||||
_(OLIVINE)
|
||||
_(APPLE)
|
||||
_(SEAFOAM)
|
||||
_(FOREST)
|
||||
_(TOPAZ)
|
||||
_(FROST)
|
||||
_(WAVE)
|
||||
_(ICY)
|
||||
_(PEACOCK)
|
||||
_(VAPOR)
|
||||
_(GEMSTONE)
|
||||
_(NEON)
|
||||
_(PLUM)
|
||||
|
||||
_(DIAMOND) // custom color expansion begins here
|
||||
_(RAVEN)
|
||||
_(MUD)
|
||||
_(EARTHWORM)
|
||||
_(YOGURT)
|
||||
_(PEARL)
|
||||
_(STRAWBERRY)
|
||||
_(SODA)
|
||||
_(BLOODCELL)
|
||||
_(MAHOGANY)
|
||||
_(FIERY)
|
||||
_(SPICE)
|
||||
_(KING)
|
||||
_(HOTDOG)
|
||||
_(CARNATION)
|
||||
_(CANDY)
|
||||
_(NEBULA)
|
||||
_(STEAMPUNK)
|
||||
_(AMBER)
|
||||
_(CARROT)
|
||||
_(CHEESE)
|
||||
_(DUNE)
|
||||
_(BRASS)
|
||||
_(CITRINE)
|
||||
_(SANDY)
|
||||
_(LEMON)
|
||||
_(CASKET)
|
||||
_(PEAR)
|
||||
_(GECKO)
|
||||
_(VENOM)
|
||||
_(APPLE)
|
||||
_(HEADLIGHT)
|
||||
_(CHARTREUSE)
|
||||
_(FOREST)
|
||||
_(JADE)
|
||||
_(MASTER)
|
||||
_(HARLEQUIN)
|
||||
_(SEAFOAM)
|
||||
_(ISLAND)
|
||||
_(BOTTLE)
|
||||
_(OCEAN)
|
||||
_(WAVE)
|
||||
_(FROST)
|
||||
_(VACATION)
|
||||
_(HYDRO)
|
||||
_(SKY)
|
||||
_(MARINE)
|
||||
_(DEPTHS)
|
||||
_(FANTASY)
|
||||
_(ICY)
|
||||
_(DAYBREAK)
|
||||
_(ARCTIC)
|
||||
_(CORNFLOWER)
|
||||
_(COBALT)
|
||||
_(NIGHTFALL)
|
||||
_(GALAXY)
|
||||
_(VAPOR)
|
||||
_(MAJESTY)
|
||||
_(NOBLE)
|
||||
_(BERRY)
|
||||
_(SIBERITE)
|
||||
_(NEON)
|
||||
_(GRAPE)
|
||||
_(ARISTOCRAT)
|
||||
_(BLOOM)
|
||||
_(MALLOW)
|
||||
_(EVENTIDE)
|
||||
_(PLUM)
|
||||
_(PUNCH)
|
||||
_(FLAMINGO)
|
||||
_(FANCY)
|
||||
_(SANGRIA)
|
||||
_(VOLCANIC)
|
||||
|
||||
// Custom Color Expansion
|
||||
// Featuring all new colors to best match Kart and Ring Racers
|
||||
_(IVORY)
|
||||
_(ABYSS)
|
||||
_(DIAMOND)
|
||||
_(RAVEN)
|
||||
_(NOIR)
|
||||
_(VANILLA)
|
||||
_(FIREFLY)
|
||||
_(COFFEE)
|
||||
_(CHOCOLATE)
|
||||
_(DUST)
|
||||
_(HICKORY)
|
||||
_(PEARL)
|
||||
_(ROSEGOLD)
|
||||
_(DRAGONFRUIT)
|
||||
_(STRAWBERRY)
|
||||
_(AMARANTH)
|
||||
_(PARROT)
|
||||
_(SODA)
|
||||
_(VERMILLION)
|
||||
_(WINE)
|
||||
_(BLOODCELL)
|
||||
_(SYRUP)
|
||||
_(SUNBURST)
|
||||
_(GRAPEFRUIT)
|
||||
_(DEEPFRY)
|
||||
_(SENTINEL)
|
||||
_(FIERY)
|
||||
_(AUTUMN)
|
||||
_(SPICE)
|
||||
_(SUMMER)
|
||||
_(HALLOWEEN)
|
||||
_(DUNE)
|
||||
_(CHEESE)
|
||||
_(CARROT)
|
||||
_(TIGER)
|
||||
_(SIENNA)
|
||||
_(AMBER)
|
||||
_(STEAMPUNK)
|
||||
_(BLONDE)
|
||||
_(DRAVITE)
|
||||
_(CANARY)
|
||||
_(HORNET)
|
||||
_(MOON)
|
||||
_(KHAKI)
|
||||
_(LIGHT)
|
||||
_(PEPPERMINT)
|
||||
_(PYRAMID)
|
||||
_(LASER)
|
||||
_(ASPARAGUS)
|
||||
_(DANDELION)
|
||||
_(SAGE)
|
||||
_(JUNGLE)
|
||||
_(PLANTATION)
|
||||
_(SCIENCE)
|
||||
_(WILD)
|
||||
_(JUNIPER)
|
||||
_(PEPPERMINT)
|
||||
_(SPRING)
|
||||
_(IGUANA)
|
||||
_(AVOCADO)
|
||||
_(ARMY)
|
||||
_(CROW)
|
||||
_(CHARTEUSE)
|
||||
_(SLIME)
|
||||
_(DIANNE)
|
||||
_(BEAN)
|
||||
_(CLOVER)
|
||||
_(LEAF)
|
||||
_(JUNGLE)
|
||||
_(EVERGREEN)
|
||||
_(TROPIC)
|
||||
_(IGUANA)
|
||||
_(SOUR)
|
||||
_(SLIME)
|
||||
_(WATERMELON)
|
||||
_(MIAMI)
|
||||
_(SPEARMINT)
|
||||
_(PATINA)
|
||||
_(LAKESIDE)
|
||||
_(CAPRI)
|
||||
_(ELECTRIC)
|
||||
_(PEGASUS)
|
||||
_(PLASMA)
|
||||
_(COMET)
|
||||
_(LIGHTNING)
|
||||
_(VACATION)
|
||||
_(DEPTHS)
|
||||
_(DIANNE)
|
||||
_(EXOTIC)
|
||||
_(SNOW)
|
||||
_(MOON)
|
||||
_(PIPEWORK)
|
||||
_(SACRAMENTO)
|
||||
_(EVERGREEN)
|
||||
_(CHILL)
|
||||
_(PEACOCK)
|
||||
_(WINTER)
|
||||
_(MECHA)
|
||||
_(POLAR)
|
||||
_(COTTONCANDY)
|
||||
_(SNOWMAN)
|
||||
_(CRYSTAL)
|
||||
_(WATERSTONE)
|
||||
_(LUNAR)
|
||||
_(ONYX)
|
||||
_(ASTRONAUT)
|
||||
_(COMET)
|
||||
_(MINSK)
|
||||
_(LAPIS)
|
||||
_(ORCA)
|
||||
_(STORM)
|
||||
_(COTTONCANDY) // this color was a pain to get right
|
||||
_(CYBER) // this one too
|
||||
_(GROWTH)
|
||||
_(NOCTURNE)
|
||||
_(ZIRCON)
|
||||
_(ORCHID)
|
||||
_(EMPERESS)
|
||||
_(NIGHTWALK)
|
||||
_(AMETHYST)
|
||||
_(IRIS)
|
||||
_(GOTHIC)
|
||||
_(GRAPE)
|
||||
_(INDIGO)
|
||||
_(CORDOVAN)
|
||||
_(SAKURA)
|
||||
_(DISCO)
|
||||
_(MULBERRY)
|
||||
_(BOYSENBERRY)
|
||||
_(MYSTIC)
|
||||
_(VELOUR)
|
||||
_(WICKED)
|
||||
_(GLAMOUR)
|
||||
_(UNICORN)
|
||||
|
||||
_(SUPER1) // Super Sonic Yellow
|
||||
// Super Colors
|
||||
// Currently not implemented, using SRB2K's as a placeholder
|
||||
_(SUPER1)
|
||||
_(SUPER2)
|
||||
_(SUPER3)
|
||||
_(SUPER4)
|
||||
_(SUPER5)
|
||||
|
||||
_(TSUPER1) // Super Tails Orange
|
||||
_(TSUPER1)
|
||||
_(TSUPER2)
|
||||
_(TSUPER3)
|
||||
_(TSUPER4)
|
||||
_(TSUPER5)
|
||||
|
||||
_(KSUPER1) // Super Knuckles Red
|
||||
_(KSUPER1)
|
||||
_(KSUPER2)
|
||||
_(KSUPER3)
|
||||
_(KSUPER4)
|
||||
_(KSUPER5)
|
||||
|
||||
_(PSUPER1) // Hyper Sonic Pink
|
||||
_(PSUPER1)
|
||||
_(PSUPER2)
|
||||
_(PSUPER3)
|
||||
_(PSUPER4)
|
||||
_(PSUPER5)
|
||||
|
||||
_(BSUPER1) // Hyper Sonic Blue
|
||||
_(BSUPER1)
|
||||
_(BSUPER2)
|
||||
_(BSUPER3)
|
||||
_(BSUPER4)
|
||||
_(BSUPER5)
|
||||
|
||||
_(ASUPER1) // Aqua Super
|
||||
_(ASUPER1)
|
||||
_(ASUPER2)
|
||||
_(ASUPER3)
|
||||
_(ASUPER4)
|
||||
_(ASUPER5)
|
||||
|
||||
_(GSUPER1) // Hyper Sonic Green
|
||||
_(GSUPER1)
|
||||
_(GSUPER2)
|
||||
_(GSUPER3)
|
||||
_(GSUPER4)
|
||||
_(GSUPER5)
|
||||
|
||||
_(WSUPER1) // Hyper Sonic White
|
||||
_(WSUPER1)
|
||||
_(WSUPER2)
|
||||
_(WSUPER3)
|
||||
_(WSUPER4)
|
||||
_(WSUPER5)
|
||||
|
||||
_(CSUPER1) // Creamy Super (Shadow?)
|
||||
_(CSUPER1)
|
||||
_(CSUPER2)
|
||||
_(CSUPER3)
|
||||
_(CSUPER4)
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@ _(UNKN)
|
|||
|
||||
_(THOK) // Thok! mobj
|
||||
_(PLAY)
|
||||
_(KART)
|
||||
_(TIRE)
|
||||
|
||||
// Enemies
|
||||
_(POSS) // Crawla (Blue)
|
||||
|
|
|
|||
|
|
@ -48,9 +48,6 @@ _(KART_SIGN)
|
|||
// technically the player goes here but it's an infinite tic state
|
||||
_(OBJPLACE_DUMMY)
|
||||
|
||||
_(KART_LEFTOVER)
|
||||
_(KART_TIRE)
|
||||
|
||||
// Blue Crawla
|
||||
_(POSS_STND)
|
||||
_(POSS_RUN1)
|
||||
|
|
|
|||
|
|
@ -55,6 +55,20 @@ boolean K_IsPlayerWanted(player_t *player)
|
|||
return false;
|
||||
}
|
||||
|
||||
boolean K_IsPlayerMostWanted(player_t *player)
|
||||
{
|
||||
if (mostwanted == -1)
|
||||
return false;
|
||||
|
||||
if (!(gametyperules & GTR_WANTEDSPB))
|
||||
return false;
|
||||
|
||||
if (player == &players[mostwanted])
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void K_CalculateBattleWanted(void)
|
||||
{
|
||||
UINT8 numingame = 0, numwanted = 0;
|
||||
|
|
@ -62,6 +76,8 @@ void K_CalculateBattleWanted(void)
|
|||
UINT8 ties = 0, nextcamppos = 0;
|
||||
UINT8 i, j;
|
||||
|
||||
mostwanted = -1;
|
||||
|
||||
if (!(gametyperules & GTR_WANTED))
|
||||
{
|
||||
memset(battlewanted, -1, sizeof (battlewanted));
|
||||
|
|
@ -162,6 +178,10 @@ void K_CalculateBattleWanted(void)
|
|||
if (ties < (numwanted-i)) // Is it still low enough after counting?
|
||||
{
|
||||
battlewanted[i] = camppos[nextcamppos];
|
||||
|
||||
if (!nextcamppos)
|
||||
mostwanted = battlewanted[i];
|
||||
|
||||
nextcamppos++;
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ extern UINT8 numtargets;
|
|||
|
||||
INT32 K_StartingBumperCount(void);
|
||||
boolean K_IsPlayerWanted(player_t *player);
|
||||
boolean K_IsPlayerMostWanted(player_t *player);
|
||||
void K_CalculateBattleWanted(void);
|
||||
void K_SpawnBattlePoints(player_t *source, player_t *victim, UINT8 amount);
|
||||
void K_CheckBumpers(void);
|
||||
|
|
|
|||
|
|
@ -394,7 +394,7 @@ boolean K_BHeapPush(bheap_t *const heap, void *const item, UINT32 value, updatei
|
|||
if (heap->count >= heap->capacity)
|
||||
{
|
||||
size_t newarraycapacity = heap->capacity * 2;
|
||||
heap->array = Z_Realloc(heap->array, newarraycapacity, PU_STATIC, NULL);
|
||||
heap->array = Z_Realloc(heap->array, newarraycapacity * sizeof(bheapitem_t), PU_STATIC, NULL);
|
||||
|
||||
if (heap->array == NULL)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -80,6 +80,8 @@ void K_DrawBotDebugger(const player_t *player)
|
|||
V_DrawThinString(x2, y+32, vflags|(bd->driftlockout ? V_ORANGEMAP : 0), va("driftlockout: %d", bd->driftlockout));
|
||||
V_DrawThinString(x1, y+40, vflags, va("driftturn: %d", bd->driftturn));
|
||||
V_DrawThinString(x2, y+40, vflags, va("drifttime: %d", bd->drifttime));
|
||||
V_DrawThinString(x1, y+48, vflags, va("preditionerror: %d", bd->predictionerror));
|
||||
V_DrawThinString(x2, y+48, vflags|(bd->griplockout ? V_ORANGEMAP : 0), va("griplockout: %d", bd->griplockout));
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
|
|
@ -257,14 +259,7 @@ void K_UpdateMatchRaceBots(void)
|
|||
else
|
||||
{
|
||||
difficulty = cv_kartbot.value;
|
||||
if (netgame)
|
||||
{
|
||||
pmax = std::min<UINT8>(pmax, static_cast<UINT8>(cv_maxplayers.value));
|
||||
}
|
||||
if (cv_ingamecap.value > 0)
|
||||
{
|
||||
pmax = std::min<UINT8>(pmax, static_cast<UINT8>(cv_ingamecap.value));
|
||||
}
|
||||
pmax = std::min<UINT8>(pmax, static_cast<UINT8>(cv_kartbot_cap.value));
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
@ -362,7 +357,7 @@ void K_UpdateMatchRaceBots(void)
|
|||
{
|
||||
UINT16 index = P_RandomKey(usableskins);
|
||||
skinnum = grabskins[index];
|
||||
if (((cv_ingamecap.value > 0) && (usableskins+1 >= cv_ingamecap.value)) || (usableskins+1 >= cv_maxplayers.value))
|
||||
if (((cv_kartbot_cap.value > 0) && (usableskins+1 >= cv_kartbot_cap.value)) || (usableskins+1 >= cv_maxplayers.value))
|
||||
{
|
||||
grabskins[index] = grabskins[--usableskins];
|
||||
}
|
||||
|
|
@ -555,6 +550,9 @@ botcontroller_t *K_GetBotController(const mobj_t *mobj)
|
|||
--------------------------------------------------*/
|
||||
fixed_t K_BotMapModifier(void)
|
||||
{
|
||||
// fuck it we ball
|
||||
return 5*FRACUNIT/10;
|
||||
|
||||
constexpr INT32 complexity_scale = 10000;
|
||||
fixed_t modifier_max = K_TrackModifierMax();
|
||||
|
||||
|
|
@ -1231,6 +1229,8 @@ static INT32 K_HandleBotTrack(botdata_t *bd, const player_t *player, angle_t des
|
|||
moveangle = player->mo->angle;
|
||||
anglediff = AngleDeltaSigned(moveangle, destangle);
|
||||
|
||||
bd->predictionerror = std::min(destangle - moveangle, moveangle - destangle);
|
||||
|
||||
// line up for an incoming drift
|
||||
if (bd->driftstate == DRIFTSTATE_STARTING)
|
||||
{
|
||||
|
|
@ -1300,6 +1300,26 @@ static INT32 K_HandleBotTrack(botdata_t *bd, const player_t *player, angle_t des
|
|||
bd->acceldown = true;
|
||||
bd->brakedown = false;
|
||||
|
||||
// Additional grip for turns.
|
||||
if ((player->speed > K_GetKartSpeed(player, false, false)/2) && !bd->griplockout)//35*FRACUNIT
|
||||
{
|
||||
const angle_t MAXERROR = ANGLE_45;
|
||||
const angle_t MIDERROR = ANGLE_22h;
|
||||
|
||||
if (bd->predictionerror > MAXERROR && bd->driftstate == DRIFTSTATE_AUTO)
|
||||
{
|
||||
bd->acceldown = false;
|
||||
bd->brakedown = true;
|
||||
}
|
||||
else if (bd->predictionerror > MIDERROR && bd->driftstate == DRIFTSTATE_AUTO)
|
||||
{
|
||||
bd->brakedown = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (bd->griplockout > 0)
|
||||
bd->griplockout--;
|
||||
|
||||
if (dirdist <= rad
|
||||
&& bd->driftstate != DRIFTSTATE_STARTING) // steer towards waypoints when starting drift
|
||||
{
|
||||
|
|
@ -1334,6 +1354,8 @@ static INT32 K_HandleBotTrack(botdata_t *bd, const player_t *player, angle_t des
|
|||
turnvalue = 541 - (turnvalue - 541); // weight 5 = 541
|
||||
|
||||
turnamt = std::clamp(FixedMul(driftpower, turnvalue), -KART_FULLTURN, KART_FULLTURN);
|
||||
|
||||
bd->griplockout = 6;
|
||||
}
|
||||
/*
|
||||
else if ((turnamt) && (bd->driftstate == DRIFTSTATE_AUTO) &&
|
||||
|
|
@ -1618,6 +1640,26 @@ void K_BotTicker(const player_t *player)
|
|||
forcedDir = true;
|
||||
}
|
||||
|
||||
if (P_IsObjectOnGround(player->mo) == false)
|
||||
{
|
||||
if (player->airdroptime == 0
|
||||
&& K_AirDropActive()
|
||||
&& !P_PlayerInPain(player)
|
||||
&& !player->loop.radius
|
||||
&& !(player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT)
|
||||
&& !player->respawn)
|
||||
{
|
||||
if (botController != nullptr && (botController->flags & TMBOT_AIRDROP) == TMBOT_AIRDROP)
|
||||
{
|
||||
// Air Drop!
|
||||
bd->brakedown = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//return; // Don't allow bots to turn in the air.
|
||||
}
|
||||
|
||||
if (forcedDir == true)
|
||||
{
|
||||
destangle = R_PointToAngle2(player->mo->x, player->mo->y, bd->predict.x, bd->predict.y);
|
||||
|
|
@ -1663,12 +1705,15 @@ void K_BotTicker(const player_t *player)
|
|||
ps_bots[player - players].item = I_GetPreciseTime() - t;
|
||||
}
|
||||
|
||||
// Update turning quicker if we're moving at high speeds.
|
||||
UINT8 turndelta = (player->speed > (7 * K_GetKartSpeed(player, false, false) / 4)) ? 2 : 1;
|
||||
|
||||
if (turnamt > 0)
|
||||
{
|
||||
// Count up
|
||||
if (bd->turnconfirm < BOTTURNCONFIRM)
|
||||
{
|
||||
bd->turnconfirm++;
|
||||
bd->turnconfirm += turndelta;
|
||||
}
|
||||
}
|
||||
else if (turnamt < 0)
|
||||
|
|
@ -1676,7 +1721,7 @@ void K_BotTicker(const player_t *player)
|
|||
// Count down
|
||||
if (bd->turnconfirm > -BOTTURNCONFIRM)
|
||||
{
|
||||
bd->turnconfirm--;
|
||||
bd->turnconfirm -= turndelta;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -1684,11 +1729,11 @@ void K_BotTicker(const player_t *player)
|
|||
// Back to neutral
|
||||
if (bd->turnconfirm < 0)
|
||||
{
|
||||
bd->turnconfirm++;
|
||||
bd->turnconfirm += turndelta;
|
||||
}
|
||||
else if (bd->turnconfirm > 0)
|
||||
{
|
||||
bd->turnconfirm--;
|
||||
bd->turnconfirm -= turndelta;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1777,7 +1822,10 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
}
|
||||
|
||||
// BOT_STYLE_NORMAL is the only other style, so...
|
||||
cmd->forwardmove = !!bd->acceldown * MAXPLMOVE - !!bd->brakedown * MAXPLMOVE/2;
|
||||
SINT8 maxacceldown = (!!bd->acceldown * MAXPLMOVE);
|
||||
SINT8 maxbrakedown = !!bd->brakedown * MAXPLMOVE/2;
|
||||
|
||||
cmd->forwardmove = maxacceldown - maxbrakedown;
|
||||
if (bd->itemthrow != 0)
|
||||
{
|
||||
cmd->throwdir = bd->itemthrow * KART_FULLTURN;
|
||||
|
|
|
|||
|
|
@ -98,6 +98,9 @@ struct botdata_t
|
|||
boolean itemwasdown; // last tic's item button
|
||||
SINT8 itemthrow; // throwdir
|
||||
INT16 turnamt; // turning
|
||||
|
||||
angle_t predictionerror; // How bad is our momentum angle relative to where we're trying to go?
|
||||
angle_t griplockout; // When you need to prevent grip braking, use this.
|
||||
};
|
||||
|
||||
// AVAILABLE FOR LUA
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "m_random.h"
|
||||
#include "r_things.h" // numskins
|
||||
#include "m_easing.h"
|
||||
#include "k_odds.h"
|
||||
|
||||
// Looks for players around the bot, and presses the item button
|
||||
// if there is one in range.
|
||||
|
|
@ -960,6 +961,11 @@ static void K_BotItemFlame(botdata_t *bd, const player_t *player)
|
|||
{
|
||||
ZoneScoped;
|
||||
|
||||
if (player->flametimer >= (itemtime*3)-5)
|
||||
{
|
||||
bd->itemdelay = 5;
|
||||
}
|
||||
|
||||
if (P_IsObjectOnGround(player->mo) == false)
|
||||
{
|
||||
// Drain itemdelay as needed so theres no delay when landing.
|
||||
|
|
|
|||
|
|
@ -233,10 +233,22 @@ void K_InitBrightmapsPwad(INT32 wadNum)
|
|||
break;
|
||||
}
|
||||
|
||||
texNum = R_CheckTextureNumForName(bms->textureName);
|
||||
texNum = R_CheckTextureNumForName(bms->textureName, TEXTURETYPE_TEXTURE);
|
||||
|
||||
if (texNum == -1)
|
||||
{
|
||||
texNum = R_CheckTextureNumForName(bms->textureName, TEXTURETYPE_FLAT);
|
||||
}
|
||||
|
||||
if (texNum != -1)
|
||||
{
|
||||
bmNum = R_CheckTextureNumForName(bms->brightmapName);
|
||||
bmNum = R_CheckTextureNumForName(bms->brightmapName, TEXTURETYPE_TEXTURE);
|
||||
|
||||
if (bmNum == -1)
|
||||
{
|
||||
bmNum = R_CheckTextureNumForName(bms->brightmapName, TEXTURETYPE_FLAT);
|
||||
}
|
||||
|
||||
R_UpdateTextureBrightmap(texNum, (bmNum == -1 ? 0 : bmNum));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "doomtype.h"
|
||||
#include "p_mobj.h"
|
||||
#include "k_kart.h"
|
||||
#include "k_odds.h"
|
||||
#include "p_local.h"
|
||||
#include "s_sound.h"
|
||||
#include "r_main.h" // R_PointToAngle2, R_PointToDist2
|
||||
|
|
@ -56,6 +57,8 @@ boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2)
|
|||
|
||||
if (t2->player)
|
||||
{
|
||||
if (t2->player->flashing && !(t1->type == MT_ORBINAUT || t1->type == MT_JAWZ))
|
||||
return true;
|
||||
|
||||
if (t2->player->hyudorotimer)
|
||||
return true; // no interaction
|
||||
|
|
@ -542,11 +545,17 @@ static void K_BubbleShieldCollideDrain(player_t *player, mobj_t *bubble)
|
|||
}
|
||||
}
|
||||
|
||||
boolean K_BubbleShieldReflect(mobj_t *t1, mobj_t *t2)
|
||||
boolean K_BubbleShieldReflect(mobj_t *t1, mobj_t *t2, boolean isplayer)
|
||||
{
|
||||
mobj_t *owner = t1->player ? t1 : t1->target;
|
||||
INT32 div = 2;
|
||||
|
||||
if (!t2->threshold)
|
||||
if (isplayer)
|
||||
{
|
||||
div = 1;
|
||||
}
|
||||
|
||||
if ((!t2->threshold)||(isplayer))
|
||||
{
|
||||
if (!t2->momx && !t2->momy)
|
||||
{
|
||||
|
|
@ -554,15 +563,23 @@ boolean K_BubbleShieldReflect(mobj_t *t1, mobj_t *t2)
|
|||
}
|
||||
else
|
||||
{
|
||||
t2->momx = (-1*t2->momx)/2;
|
||||
t2->momy = (-1*t2->momy)/2;
|
||||
t2->momz = (-1*t2->momz)/2;
|
||||
t2->angle += ANGLE_180;
|
||||
t2->momx = (-1*t2->momx)/div;
|
||||
t2->momy = (-1*t2->momy)/div;
|
||||
t2->momz = (-1*t2->momz)/div;
|
||||
|
||||
if (!isplayer)
|
||||
{
|
||||
t2->angle += ANGLE_180;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isplayer)
|
||||
{
|
||||
if (t2->type == MT_JAWZ)
|
||||
P_SetTarget(&t2->tracer, t2->target); // Back to the source!
|
||||
P_SetTarget(&t2->target, owner); // Let the source reflect it back again!
|
||||
t2->threshold = 10;
|
||||
}
|
||||
if (t2->type == MT_JAWZ)
|
||||
P_SetTarget(&t2->tracer, t2->target); // Back to the source!
|
||||
P_SetTarget(&t2->target, owner); // Let the source reflect it back again!
|
||||
t2->threshold = 10;
|
||||
S_StartSound(t1, sfx_s3k44);
|
||||
}
|
||||
|
||||
|
|
@ -574,26 +591,37 @@ boolean K_BubbleShieldCanReflect(mobj_t *t1, mobj_t *t2)
|
|||
return (t2->type == MT_ORBINAUT || t2->type == MT_JAWZ || t2->type == MT_JAWZ_DUD
|
||||
|| t2->type == MT_BANANA || t2->type == MT_EGGMANITEM || t2->type == MT_BALLHOG
|
||||
|| t2->type == MT_SSMINE || t2->type == MT_LANDMINE || t2->type == MT_SINK
|
||||
|| t2->type == MT_KART_LEFTOVER
|
||||
|| (t2->type == MT_PLAYER && t1->target != t2));
|
||||
}
|
||||
|
||||
static boolean K_PlayerCanBeBubbleBumped(player_t *player)
|
||||
{
|
||||
return (((K_GetKartInvinType() == KARTINVIN_LEGACY) && (player->invincibilitytimer))
|
||||
|| (player->growshrinktimer > 0));
|
||||
}
|
||||
|
||||
boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2)
|
||||
{
|
||||
if (t2->type == MT_PLAYER)
|
||||
{
|
||||
// Ignore players.
|
||||
return true;
|
||||
|
||||
boolean bumpme = ((t2->player) && (K_PlayerCanBeBubbleBumped(t2->player)));
|
||||
|
||||
if (!bumpme)
|
||||
{
|
||||
// Ignore non-bumpable players.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (K_BubbleShieldCanReflect(t1, t2))
|
||||
{
|
||||
if (!t2->threshold)
|
||||
if ((!t2->threshold)||(t2->player))
|
||||
{
|
||||
// Drain my stuff please.
|
||||
K_BubbleShieldCollideDrain(t1->target->player, t1);
|
||||
}
|
||||
return K_BubbleShieldReflect(t1, t2);
|
||||
return K_BubbleShieldReflect(t1, t2, (t2->player) ? true : false);
|
||||
}
|
||||
|
||||
if (t2->flags & MF_SHOOTABLE)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ boolean K_MineExplosionCollide(mobj_t *t1, mobj_t *t2);
|
|||
boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2);
|
||||
void K_ThunderShieldAttack(mobj_t *actor, fixed_t size);
|
||||
|
||||
boolean K_BubbleShieldReflect(mobj_t *t1, mobj_t *t2);
|
||||
boolean K_BubbleShieldReflect(mobj_t *t1, mobj_t *t2, boolean isplayer);
|
||||
boolean K_BubbleShieldCanReflect(mobj_t *t1, mobj_t *t2);
|
||||
|
||||
boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2);
|
||||
|
|
|
|||
|
|
@ -20,12 +20,12 @@
|
|||
UINT16 altinvinccolors[16] = {
|
||||
SKINCOLOR_BLOODCELL, // 0
|
||||
SKINCOLOR_FUCHSIA, // 1
|
||||
SKINCOLOR_LANTERN, // 2
|
||||
SKINCOLOR_MOON, // 2
|
||||
SKINCOLOR_FIERY, // 3
|
||||
SKINCOLOR_FLAME, // 4
|
||||
SKINCOLOR_APRICOT, // 5
|
||||
SKINCOLOR_GARDEN, // 6
|
||||
SKINCOLOR_OLIVINE, // 7
|
||||
SKINCOLOR_OLIVE, // 7
|
||||
SKINCOLOR_LIME, // 8
|
||||
SKINCOLOR_EMERALD, // 9
|
||||
SKINCOLOR_NAVY, // 10
|
||||
|
|
|
|||
|
|
@ -53,6 +53,8 @@ struct follower_t
|
|||
{
|
||||
char skinname[SKINNAMESIZE+1]; // Skin Name. This is what to refer to when asking the commands anything.
|
||||
char name[SKINNAMESIZE+1]; // Name. This is used for the menus. We'll just follow the same rules as skins for this.
|
||||
char icon[8+1]; // Lump names are only 8 characters. (+1 for \0)
|
||||
|
||||
|
||||
skincolornum_t defaultcolor; // default color for menus.
|
||||
followermode_t mode; // Follower behavior modifier.
|
||||
|
|
|
|||
1430
src/k_hud.c
1430
src/k_hud.c
File diff suppressed because it is too large
Load diff
|
|
@ -41,6 +41,8 @@ IMPL_HUD_OFFSET(rings); // Number of rings
|
|||
IMPL_HUD_OFFSET(dnft); // Countdown (did not finish timer)
|
||||
IMPL_HUD_OFFSET(speed); // Speedometer
|
||||
IMPL_HUD_OFFSET(acce); // Accessibility
|
||||
IMPL_HUD_OFFSET(timers); // Drafting
|
||||
IMPL_HUD_OFFSET(draft); // Drafting
|
||||
IMPL_HUD_OFFSET(posi); // Position in race
|
||||
IMPL_HUD_OFFSET(face); // Mini rankings
|
||||
IMPL_HUD_OFFSET(stcd); // Starting countdown
|
||||
|
|
@ -91,6 +93,7 @@ void K_getItemBoxDrawinfo(drawinfo_t *out);
|
|||
void K_getLapsDrawinfo(drawinfo_t *out);
|
||||
void K_getRingsDrawinfo(drawinfo_t *out);
|
||||
void K_getMinimapDrawinfo(drawinfo_t *out);
|
||||
void K_getSlipstreamDrawinfo(drawinfo_t *out);
|
||||
const char *K_GetItemPatch(UINT8 item, boolean tiny);
|
||||
void K_ReloadHUDColorCvar(void);
|
||||
boolean K_UseColorHud(void);
|
||||
|
|
@ -103,7 +106,7 @@ INT32 K_DrawNeoTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines
|
|||
void K_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer, INT32 hilicol);
|
||||
|
||||
#define MAXSERVERMODS 255
|
||||
#define MAXSERVERMODNAME 13
|
||||
#define MAXSERVERMODNAME 14
|
||||
|
||||
struct servermods_t
|
||||
{
|
||||
|
|
|
|||
2303
src/k_kart.c
2303
src/k_kart.c
File diff suppressed because it is too large
Load diff
39
src/k_kart.h
39
src/k_kart.h
|
|
@ -68,9 +68,6 @@ extern boolean clusterplayer[MAXPLAYERS];
|
|||
extern UINT32 clusterid; // ID of the "cluster player", the one closest to the cluster point.
|
||||
extern vector3_t clusterpoint, clusterdtf;
|
||||
|
||||
// :)
|
||||
#define MAXODDS 8
|
||||
|
||||
// Bubble Shield's maximum health
|
||||
#define MAXBUBBLEHEALTH 6
|
||||
|
||||
|
|
@ -125,6 +122,10 @@ extern vector3_t clusterpoint, clusterdtf;
|
|||
#define STARTACCELBOOST K_RAGuard(cv_kartstacking_start_accelboost)
|
||||
#define STARTSTACKABLE K_RAGuard(cv_kartstacking_start_stackable)
|
||||
|
||||
#define WALLTRANSFERSPEEDBOOST K_RAGuard(cv_kartstacking_walltransfer_speedboost)
|
||||
#define WALLTRANSFERACCELBOOST K_RAGuard(cv_kartstacking_walltransfer_accelboost)
|
||||
#define WALLTRANSFERSTACKABLE K_RAGuard(cv_kartstacking_walltransfer_stackable)
|
||||
|
||||
#define DRIFTSPEEDBOOST K_RAGuard(cv_kartstacking_drift_speedboost)
|
||||
#define DRIFTACCELBOOST K_RAGuard(cv_kartstacking_drift_accelboost)
|
||||
#define DRIFTSTACKABLE K_RAGuard(cv_kartstacking_drift_stackable)
|
||||
|
|
@ -189,19 +190,6 @@ UINT32 K_GetPlayerDontDrawFlag(player_t *player);
|
|||
boolean K_IsPlayerLosing(player_t *player);
|
||||
fixed_t K_GetKartGameSpeedScalar(SINT8 value);
|
||||
|
||||
extern consvar_t *KartItemCVars[NUMKARTRESULTS-1];
|
||||
|
||||
UINT8 K_FindUseodds(const player_t *player, fixed_t mashed, UINT32 pdis, UINT8 bestbumper, boolean spbrush);
|
||||
INT32 K_FindLegacyUseodds(player_t *player, fixed_t mashed, INT32 pingame, INT32 bestbumper, boolean spbrush, boolean dontforcespb);
|
||||
fixed_t K_ItemOddsScale(UINT8 numPlayers, boolean spbrush);
|
||||
UINT32 K_ScaleItemDistance(UINT32 distance, UINT8 numPlayers, boolean spbrush);
|
||||
INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, UINT32 ourDist, UINT32 clusterDist, fixed_t mashed, boolean spbrush, boolean bot, boolean rival);
|
||||
INT32 K_KartGetLegacyItemOdds(UINT8 pos, SINT8 item, fixed_t clusterDist, fixed_t mashed, boolean spbrush);
|
||||
INT32 K_GetRollingRouletteItem(player_t *player);
|
||||
INT32 K_GetShieldFromPlayer(player_t *player);
|
||||
INT32 K_GetShieldFromItem(INT32 item);
|
||||
SINT8 K_ItemResultToType(SINT8 getitem);
|
||||
UINT8 K_ItemResultToAmount(SINT8 getitem);
|
||||
fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against);
|
||||
boolean K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid);
|
||||
void K_KartPainEnergyFling(player_t *player);
|
||||
|
|
@ -209,7 +197,6 @@ void K_FlipFromObject(mobj_t *mo, mobj_t *master);
|
|||
void K_MatchGenericExtraFlags(mobj_t *mo, mobj_t *master);
|
||||
void K_GenericExtraFlagsNoZAdjust(mobj_t *mo, mobj_t *master);
|
||||
void K_SpawnDashDustRelease(player_t *player);
|
||||
void K_SpawnDriftBoostClip(player_t *player);
|
||||
void K_SpawnNormalSpeedLines(player_t *player);
|
||||
void K_SpawnDraftSpeedLines(player_t *player, fixed_t scale, skincolornum_t color, boolean translucent);
|
||||
void K_SpawnInvincibilitySpeedLines(mobj_t *mo);
|
||||
|
|
@ -222,6 +209,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd);
|
|||
void K_KartPlayerAfterThink(player_t *player);
|
||||
angle_t K_MomentumAngle(mobj_t *mo);
|
||||
void K_AwardPlayerRings(player_t *player, UINT16 rings, boolean overload);
|
||||
void K_HandleRaceSplits(player_t *player, tic_t time, UINT8 checkpoint);
|
||||
void K_DoInstashield(player_t *player);
|
||||
void K_BattleAwardHit(player_t *player, player_t *victim, mobj_t *inflictor, UINT8 bumpersRemoved);
|
||||
void K_SpinPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 type);
|
||||
|
|
@ -270,8 +258,7 @@ void K_SetRespawnAtNextWaypoint(player_t * player);
|
|||
INT16 K_GetKartTurnValue(const player_t *player, INT16 turnvalue);
|
||||
INT32 K_GetKartDriftSparkValue(const player_t *player);
|
||||
INT32 K_GetKartDriftSparkValueForStage(const player_t *player, UINT8 stage);
|
||||
void K_SpawnDriftBoostExplosion(player_t *player, int stage);
|
||||
void K_SpawnDriftElectricSparks(player_t *player);
|
||||
UINT8 K_GetKartDriftSparkStageForValue(const player_t *player, INT32 value);
|
||||
INT32 K_GetDriftAngleOffset(player_t *player);
|
||||
void K_KartUpdatePosition(player_t *player);
|
||||
void K_KartLegacyUpdatePosition(player_t *player);
|
||||
|
|
@ -324,6 +311,9 @@ void K_PlayHitEmSound(mobj_t *source, mobj_t *other);
|
|||
void K_TryHurtSoundExchange(mobj_t *victim, mobj_t *attacker);
|
||||
void K_PlayPowerGloatSound(mobj_t *source);
|
||||
|
||||
INT32 K_GetShieldFromPlayer(player_t *player);
|
||||
INT32 K_GetShieldFromItem(INT32 item);
|
||||
|
||||
void K_SetItemOut(player_t *player);
|
||||
void K_UnsetItemOut(player_t *player);
|
||||
|
||||
|
|
@ -336,7 +326,9 @@ boolean K_ChainingActive(void);
|
|||
boolean K_SlipdashActive(void);
|
||||
boolean K_SlopeBoostActive(void);
|
||||
boolean K_DraftingActive(void);
|
||||
boolean K_AirDropActive(void);
|
||||
boolean K_GetKartInvinType(void);
|
||||
INT32 K_GetBumpSpark(void);
|
||||
boolean K_BoostChain(player_t *player, INT32 timer, boolean chainsound);
|
||||
INT32 K_ChainOrDeincrementTime(player_t *player, INT32 timer, INT32 deincrement, boolean chainsound);
|
||||
boolean K_UsingLegacyCheckpoints(void);
|
||||
|
|
@ -345,6 +337,7 @@ INT32 K_CheckpointThreshold(boolean roundup);
|
|||
|
||||
void K_UpdateMobjItemOverlay(mobj_t *part, SINT8 itemType, UINT8 itemCount);
|
||||
|
||||
fixed_t K_BoostRescale(fixed_t value,fixed_t oldmin,fixed_t oldmax,fixed_t newmin,fixed_t newmax);
|
||||
void K_DoBoost(player_t *player, fixed_t speedboost, fixed_t accelboost, boolean stack, boolean visible);
|
||||
void K_ClearBoost(player_t *player);
|
||||
|
||||
|
|
@ -359,6 +352,14 @@ void K_AwardScaledPlayerRings(player_t *player, SINT8 mode);
|
|||
|
||||
void K_QuiteSaltyHop(player_t *player);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BUMPSPARK_NONE = 0,
|
||||
BUMPSPARK_NOCHARGE,
|
||||
BUMPSPARK_RESET100, // Reset to 100 (blue); the Sunflower's Garden system
|
||||
BUMPSPARK_ALL
|
||||
} bumpsparktype_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
|||
1283
src/k_odds.c
Normal file
1283
src/k_odds.c
Normal file
File diff suppressed because it is too large
Load diff
53
src/k_odds.h
Normal file
53
src/k_odds.h
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
// BLANKART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2018-2025 by Kart Krew.
|
||||
// Copyright (C) 2025 by "Anonimus".
|
||||
// Copyright (C) 2025 Blankart Team.
|
||||
//
|
||||
// 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 k_odds.hpp
|
||||
/// \brief Kart item odds systems.
|
||||
|
||||
#ifndef __K_ODDS__
|
||||
#define __K_ODDS__
|
||||
|
||||
#include "command.h" // Need for player_t
|
||||
#include "doomdef.h"
|
||||
#include "doomtype.h"
|
||||
#include "d_player.h" // Need for player_t
|
||||
#include "d_ticcmd.h"
|
||||
#include "m_fixed.h"
|
||||
#include "k_kart.h" // K_RAGuard
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Max odds count
|
||||
#define MAXODDS 16
|
||||
|
||||
// Distance variables
|
||||
#define DISTVAR K_RAGuard(cv_kartoddsdist)
|
||||
#define DISTVAR_LEGACY K_RAGuard(cv_kartlegacyoddsdist)
|
||||
#define SPBDISTVAR K_RAGuard(cv_kartspbdist)
|
||||
|
||||
extern consvar_t *KartItemCVars[NUMKARTRESULTS-1];
|
||||
|
||||
UINT32 K_CalculateInitalPDIS(const player_t *player, UINT8 pingame);
|
||||
UINT32 K_CalculatePDIS(const player_t *player, UINT8 numPlayers, boolean *spbrush);
|
||||
UINT8 K_FindUseodds(const player_t *player, fixed_t mashed, UINT32 pdis, UINT8 bestbumper, boolean spbrush);
|
||||
UINT32 K_ScaleItemDistance(UINT32 distance, UINT8 numPlayers, boolean spbrush);
|
||||
INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, UINT32 ourDist, UINT32 clusterDist, fixed_t mashed, boolean spbrush, boolean bot, boolean rival);
|
||||
INT32 K_GetRollingRouletteItem(player_t *player);
|
||||
SINT8 K_ItemResultToType(SINT8 getitem);
|
||||
UINT8 K_ItemResultToAmount(SINT8 getitem);
|
||||
void K_KartItemRoulette(player_t *player, ticcmd_t *cmd);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __K_ODDS__
|
||||
|
|
@ -956,7 +956,7 @@ static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs, tic_t timer)
|
|||
|
||||
if (mo->player != NULL)
|
||||
{
|
||||
boolean karmabomb = ((gametyperules & GTR_KARMA) && mo->player->bumper <= 0);
|
||||
boolean karmabomb = ((gametyperules & GTR_BUMPERS) && mo->player->bumper <= 0);
|
||||
tireAngle = (mo->player->drawangle + ANGLE_180);
|
||||
speedValue = K_GetKartSpeedFromStat(mo->player->kartspeed, karmabomb);
|
||||
}
|
||||
|
|
@ -2136,7 +2136,13 @@ static boolean K_TERRAINLumpParser(char *data, size_t size)
|
|||
f->terrainID = K_GetTerrainHeapIndex(t);
|
||||
CONS_Printf("Texture '%s' set to Terrain '%s'\n", f->textureName, tkn);
|
||||
|
||||
INT32 tex = R_CheckTextureNumForName(f->textureName);
|
||||
INT32 tex = R_CheckTextureNumForName(f->textureName, TEXTURETYPE_TEXTURE);
|
||||
|
||||
if (tex == -1)
|
||||
{
|
||||
R_CheckTextureNumForName(f->textureName, TEXTURETYPE_FLAT);
|
||||
}
|
||||
|
||||
if (tex != -1)
|
||||
{
|
||||
textures[tex]->terrainID = f->terrainID;
|
||||
|
|
|
|||
|
|
@ -191,8 +191,6 @@ static const struct {
|
|||
{META_NODE, "node_t"},
|
||||
#endif
|
||||
{META_SLOPE, "slope_t"},
|
||||
{META_VECTOR2, "vector2_t"},
|
||||
{META_VECTOR3, "vector3_t"},
|
||||
{META_MAPHEADER, "mapheader_t"},
|
||||
|
||||
{META_POLYOBJ, "polyobj_t"},
|
||||
|
|
@ -245,6 +243,11 @@ static const struct {
|
|||
{META_OVERLAY, "t_overlay_t"},
|
||||
{META_TERRAIN, "terrain_t"},
|
||||
|
||||
{META_VECTOR2, "vector2_t"},
|
||||
{META_VECTOR3, "vector3_t"},
|
||||
{META_MATRIX, "matrix_t"},
|
||||
{META_QUATERNION, "quaternion_t"},
|
||||
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
@ -2552,7 +2555,10 @@ static int lib_rCheckTextureNumForName(lua_State *L)
|
|||
{
|
||||
const char *name = luaL_checkstring(L, 1);
|
||||
//HUDSAFE
|
||||
lua_pushinteger(L, R_CheckTextureNumForName(name));
|
||||
INT32 num = R_CheckTextureNumForName(name, TEXTURETYPE_TEXTURE);
|
||||
if (num == -1)
|
||||
num = R_CheckTextureNumForName(name, TEXTURETYPE_FLAT);
|
||||
lua_pushinteger(L, num);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -4167,6 +4173,13 @@ static int lib_kDraftingActive(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
// Checks if Air Drop is active.
|
||||
static int lib_kAirDropActive(lua_State *L)
|
||||
{
|
||||
lua_pushboolean(L, K_AirDropActive());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Grabs the currently active invintype.
|
||||
static int lib_kGetKartInvinType(lua_State *L)
|
||||
{
|
||||
|
|
@ -4174,6 +4187,13 @@ static int lib_kGetKartInvinType(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
// Gets the currently active bumpspark type.
|
||||
static int lib_kGetBumpSpark(lua_State *L)
|
||||
{
|
||||
lua_pushinteger(L, K_GetBumpSpark());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Checks if current map is using legacy boss3 bassed checkpoints. Useful for map compat.
|
||||
static int lib_kUsingLegacyCheckpoints(lua_State *L)
|
||||
{
|
||||
|
|
@ -5263,6 +5283,8 @@ static luaL_Reg lib[] = {
|
|||
{"K_SlipdashActive",lib_kSlipdashActive},
|
||||
{"K_SlopeBoostActive",lib_kSlopeBoostActive},
|
||||
{"K_DraftingActive",lib_kDraftingActive},
|
||||
{"K_AirDropActive",lib_kAirDropActive},
|
||||
{"K_GetBumpSpark",lib_kGetBumpSpark},
|
||||
{"K_GetKartInvinType",lib_kGetKartInvinType},
|
||||
{"K_UsingLegacyCheckpoints",lib_kUsingLegacyCheckpoints},
|
||||
{"K_DoBoost",lib_kDoBoost},
|
||||
|
|
|
|||
|
|
@ -169,68 +169,70 @@ static int botdata_get(lua_State *L)
|
|||
{
|
||||
case botdata_valid:
|
||||
lua_pushboolean(L, botdata != NULL);
|
||||
return 1;
|
||||
break;
|
||||
case botdata_itemdelay:
|
||||
lua_pushinteger(L, botdata->itemdelay);
|
||||
return 1;
|
||||
break;
|
||||
case botdata_itemconfirm:
|
||||
lua_pushinteger(L, botdata->itemconfirm);
|
||||
return 1;
|
||||
break;
|
||||
case botdata_turnconfirm:
|
||||
lua_pushinteger(L, botdata->turnconfirm);
|
||||
return 1;
|
||||
break;
|
||||
case botdata_respawnconfirm:
|
||||
lua_pushinteger(L, botdata->respawnconfirm);
|
||||
return 1;
|
||||
break;
|
||||
case botdata_driftstate:
|
||||
lua_pushinteger(L, botdata->driftstate);
|
||||
return 1;
|
||||
break;
|
||||
case botdata_driftturn:
|
||||
lua_pushinteger(L, botdata->driftturn);
|
||||
return 1;
|
||||
break;
|
||||
case botdata_drifttime:
|
||||
lua_pushinteger(L, botdata->drifttime);
|
||||
return 1;
|
||||
break;
|
||||
case botdata_driftlockout:
|
||||
lua_pushinteger(L, botdata->driftlockout);
|
||||
return 1;
|
||||
break;
|
||||
case botdata_driftmaxdist:
|
||||
lua_pushinteger(L, botdata->driftmaxdist);
|
||||
return 1;
|
||||
break;
|
||||
case botdata_driftpowerdiv:
|
||||
lua_pushinteger(L, botdata->driftpowerdiv);
|
||||
return 1;
|
||||
break;
|
||||
case botdata_driftstatedelay:
|
||||
lua_pushinteger(L, botdata->driftstatedelay);
|
||||
return 1;
|
||||
break;
|
||||
case botdata_driftskill:
|
||||
lua_pushfixed(L, botdata->driftskill);
|
||||
return 1;
|
||||
break;
|
||||
case botdata_acceldown:
|
||||
lua_pushboolean(L, botdata->acceldown);
|
||||
return 1;
|
||||
break;
|
||||
case botdata_brakedown:
|
||||
lua_pushboolean(L, botdata->brakedown);
|
||||
return 1;
|
||||
break;
|
||||
case botdata_driftdown:
|
||||
lua_pushboolean(L, botdata->driftdown);
|
||||
return 1;
|
||||
break;
|
||||
case botdata_itemdown:
|
||||
lua_pushboolean(L, botdata->itemdown);
|
||||
return 1;
|
||||
break;
|
||||
case botdata_dolookback:
|
||||
lua_pushboolean(L, botdata->dolookback);
|
||||
return 1;
|
||||
break;
|
||||
case botdata_itemwasdown:
|
||||
lua_pushboolean(L, botdata->itemwasdown);
|
||||
return 1;
|
||||
break;
|
||||
case botdata_itemthrow:
|
||||
lua_pushinteger(L, botdata->itemthrow);
|
||||
return 1;
|
||||
break;
|
||||
case botdata_turnamt:
|
||||
lua_pushinteger(L, botdata->turnamt);
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define NOSET luaL_error(L, LUA_QL("botdata_t") " field " LUA_QS " should not be set directly.", botdata_opt[field])
|
||||
|
|
@ -248,65 +250,67 @@ static int botdata_set(lua_State *L)
|
|||
return NOSET;
|
||||
case botdata_itemdelay:
|
||||
botdata->itemdelay = luaL_checkinteger(L, 3);
|
||||
return 0;
|
||||
break;
|
||||
case botdata_itemconfirm:
|
||||
botdata->itemconfirm = luaL_checkinteger(L, 3);
|
||||
return 0;
|
||||
break;
|
||||
case botdata_turnconfirm:
|
||||
botdata->turnconfirm = luaL_checkinteger(L, 3);
|
||||
return 0;
|
||||
break;
|
||||
case botdata_respawnconfirm:
|
||||
botdata->respawnconfirm = luaL_checkinteger(L, 3);
|
||||
return 0;
|
||||
break;
|
||||
case botdata_driftstate:
|
||||
botdata->driftstate = luaL_checkinteger(L, 3);
|
||||
return 0;
|
||||
break;
|
||||
case botdata_driftturn:
|
||||
botdata->driftturn = luaL_checkinteger(L, 3);
|
||||
return 0;
|
||||
break;
|
||||
case botdata_drifttime:
|
||||
botdata->drifttime = luaL_checkinteger(L, 3);
|
||||
return 0;
|
||||
break;
|
||||
case botdata_driftlockout:
|
||||
botdata->driftlockout = luaL_checkinteger(L, 3);
|
||||
return 0;
|
||||
break;
|
||||
case botdata_driftmaxdist:
|
||||
botdata->driftmaxdist = luaL_checkinteger(L, 3);
|
||||
return 0;
|
||||
break;
|
||||
case botdata_driftpowerdiv:
|
||||
botdata->driftpowerdiv = luaL_checkinteger(L, 3);
|
||||
return 0;
|
||||
break;
|
||||
case botdata_driftstatedelay:
|
||||
botdata->driftstatedelay = luaL_checkinteger(L, 3);
|
||||
return 0;
|
||||
break;
|
||||
case botdata_driftskill:
|
||||
botdata->driftskill = luaL_checkfixed(L, 3);
|
||||
return 0;
|
||||
break;
|
||||
case botdata_acceldown:
|
||||
botdata->acceldown = luaL_checkboolean(L, 3);
|
||||
return 0;
|
||||
break;
|
||||
case botdata_brakedown:
|
||||
botdata->brakedown = luaL_checkboolean(L, 3);
|
||||
return 0;
|
||||
break;
|
||||
case botdata_driftdown:
|
||||
botdata->driftdown = luaL_checkboolean(L, 3);
|
||||
return 0;
|
||||
break;
|
||||
case botdata_itemdown:
|
||||
botdata->itemdown = luaL_checkboolean(L, 3);
|
||||
return 0;
|
||||
break;
|
||||
case botdata_dolookback:
|
||||
botdata->dolookback = luaL_checkboolean(L, 3);
|
||||
return 0;
|
||||
break;
|
||||
case botdata_itemwasdown:
|
||||
botdata->itemwasdown = luaL_checkboolean(L, 3);
|
||||
return 0;
|
||||
break;
|
||||
case botdata_itemthrow:
|
||||
botdata->itemthrow = luaL_checkinteger(L, 3);
|
||||
return 0;
|
||||
break;
|
||||
case botdata_turnamt:
|
||||
botdata->turnamt = luaL_checkinteger(L, 3);
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef NOSET
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "lua_hook.h"
|
||||
|
||||
#include "k_hud.h"
|
||||
#include "h_timers.h"
|
||||
|
||||
#define HUDONLY if (!hud_running) return luaL_error(L, "HUD rendering code should not be called outside of rendering hooks!");
|
||||
|
||||
|
|
@ -749,7 +750,7 @@ static int libd_drawOnMinimap(lua_State *L)
|
|||
if (gamestate != GS_LEVEL)
|
||||
return 0;
|
||||
|
||||
if (stplyr != &players[displayplayers[0]])
|
||||
if (stplyrnum != 0)
|
||||
return 0;
|
||||
|
||||
if (minimapinfo.minimap_pic == NULL)
|
||||
|
|
@ -1128,9 +1129,29 @@ static int libd_getColormap(lua_State *L)
|
|||
{
|
||||
if (skinnum >= MAXSKINS)
|
||||
return luaL_error(L, "skin number %d is out of range (>%d)", skinnum, MAXSKINS-1);
|
||||
else if (skinnum < 0 && skinnum > TC_DEFAULT)
|
||||
else if (skinnum < -6 && !(skinnum >= TC_BOSS && skinnum <= TC_DEFAULT))
|
||||
return luaL_error(L, "translation colormap index is out of range");
|
||||
|
||||
switch(skinnum)
|
||||
{
|
||||
skinnum = TC_DEFAULT;
|
||||
case -6:
|
||||
skinnum = TC_BLINK;
|
||||
break;
|
||||
case -5:
|
||||
skinnum = TC_RAINBOW;
|
||||
break;
|
||||
case -4:
|
||||
skinnum = TC_ALLWHITE;
|
||||
break;
|
||||
case -3:
|
||||
skinnum = TC_METALSONIC;
|
||||
break;
|
||||
case -2:
|
||||
skinnum = TC_BOSS;
|
||||
break;
|
||||
case -1:
|
||||
skinnum = TC_DEFAULT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -1367,7 +1388,9 @@ enum huddrawinfo {
|
|||
huddrawinfo_item = 0,
|
||||
huddrawinfo_gametypeinfo,
|
||||
huddrawinfo_rings,
|
||||
huddrawinfo_minimap
|
||||
huddrawinfo_minimap,
|
||||
huddrawinfo_timers,
|
||||
huddrawinfo_drafting,
|
||||
};
|
||||
|
||||
static const char *const hud_drawinfo_options[] = {
|
||||
|
|
@ -1375,6 +1398,8 @@ static const char *const hud_drawinfo_options[] = {
|
|||
"gametypeinfo",
|
||||
"rings",
|
||||
"minimap",
|
||||
"timers",
|
||||
"drafting",
|
||||
NULL};
|
||||
|
||||
static int libd_getDrawInfo(lua_State *L)
|
||||
|
|
@ -1384,10 +1409,12 @@ static int libd_getDrawInfo(lua_State *L)
|
|||
drawinfo_t info;
|
||||
|
||||
switch(option) {
|
||||
case huddrawinfo_item: K_getItemBoxDrawinfo(&info); break;
|
||||
case huddrawinfo_gametypeinfo: K_getLapsDrawinfo(&info); break;
|
||||
case huddrawinfo_rings: K_getRingsDrawinfo(&info); break;
|
||||
case huddrawinfo_minimap: K_getMinimapDrawinfo(&info); break;
|
||||
case huddrawinfo_item: K_getItemBoxDrawinfo(&info); break;
|
||||
case huddrawinfo_gametypeinfo: K_getLapsDrawinfo(&info); break;
|
||||
case huddrawinfo_rings: K_getRingsDrawinfo(&info); break;
|
||||
case huddrawinfo_minimap: K_getMinimapDrawinfo(&info); break;
|
||||
case huddrawinfo_timers: K_getSlipstreamDrawinfo(&info); break;
|
||||
case huddrawinfo_drafting: K_getTimersDrawinfo(&info); break;
|
||||
default:
|
||||
return 0; // unreachable
|
||||
}
|
||||
|
|
@ -1395,7 +1422,8 @@ static int libd_getDrawInfo(lua_State *L)
|
|||
lua_pushinteger(L, info.x);
|
||||
lua_pushinteger(L, info.y);
|
||||
lua_pushinteger(L, info.flags);
|
||||
return 3;
|
||||
lua_pushinteger(L, info.flipamount);
|
||||
return 4;
|
||||
}
|
||||
|
||||
// Get cv_translucenthud's value for HUD rendering as a normal V_xxTRANS int
|
||||
|
|
|
|||
|
|
@ -65,8 +65,6 @@ extern lua_State *gL;
|
|||
#define META_NODE "NODE_T*"
|
||||
#endif
|
||||
#define META_SLOPE "PSLOPE_T*"
|
||||
#define META_VECTOR2 "VECTOR2_T"
|
||||
#define META_VECTOR3 "VECTOR3_T"
|
||||
#define META_MAPHEADER "MAPHEADER_T*"
|
||||
|
||||
#define META_POLYOBJ "POLYOBJ_T*"
|
||||
|
|
@ -119,6 +117,11 @@ extern lua_State *gL;
|
|||
#define META_OVERLAY "T_OVERLAY_T*"
|
||||
#define META_TERRAIN "TERRAIN_T*"
|
||||
|
||||
#define META_VECTOR2 "VECTOR2_T"
|
||||
#define META_VECTOR3 "VECTOR3_T"
|
||||
#define META_MATRIX "MATRIX_T"
|
||||
#define META_QUATERNION "QUATERNION_T"
|
||||
|
||||
boolean luaL_checkboolean(lua_State *L, int narg);
|
||||
|
||||
int LUA_EnumLib(lua_State *L);
|
||||
|
|
@ -141,6 +144,9 @@ int LUA_FollowerLib(lua_State *L);
|
|||
int LUA_BotVarsLib(lua_State *L);
|
||||
int LUA_TerrainLib(lua_State *L);
|
||||
int LUA_WaypointLib(lua_State *L);
|
||||
int LUA_MatrixLib(lua_State *L);
|
||||
int LUA_QuaternionLib(lua_State *L);
|
||||
int LUA_VectorLib(lua_State *L);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
|
|
|||
|
|
@ -381,19 +381,6 @@ static const char *const slope_opt[] = {
|
|||
"flags",
|
||||
NULL};
|
||||
|
||||
// shared by both vector2_t and vector3_t
|
||||
enum vector_e {
|
||||
vector_x = 0,
|
||||
vector_y,
|
||||
vector_z
|
||||
};
|
||||
|
||||
static const char *const vector_opt[] = {
|
||||
"x",
|
||||
"y",
|
||||
"z",
|
||||
NULL};
|
||||
|
||||
enum activator_e {
|
||||
activator_valid = 0,
|
||||
activator_mo,
|
||||
|
|
@ -2375,17 +2362,32 @@ static int slope_get(lua_State *L)
|
|||
lua_pushboolean(L, 1);
|
||||
return 1;
|
||||
case slope_o: // o
|
||||
LUA_PushUserdata(L, &slope->o, META_VECTOR3);
|
||||
{
|
||||
vector3_t *vec = lua_newuserdata(L, sizeof(vector3_t));
|
||||
luaL_getmetatable(L, META_VECTOR3);
|
||||
lua_setmetatable(L, -2);
|
||||
FV3_Load(vec, slope->o.x, slope->o.y, slope->o.z);
|
||||
return 1;
|
||||
}
|
||||
case slope_d: // d
|
||||
LUA_PushUserdata(L, &slope->d, META_VECTOR2);
|
||||
{
|
||||
vector2_t *vec = lua_newuserdata(L, sizeof(vector2_t));
|
||||
luaL_getmetatable(L, META_VECTOR2);
|
||||
lua_setmetatable(L, -2);
|
||||
FV2_Load(vec, slope->d.x, slope->d.y);
|
||||
return 1;
|
||||
}
|
||||
case slope_zdelta: // zdelta
|
||||
lua_pushfixed(L, slope->zdelta);
|
||||
return 1;
|
||||
case slope_normal: // normal
|
||||
LUA_PushUserdata(L, &slope->normal, META_VECTOR3);
|
||||
{
|
||||
vector3_t *vec = lua_newuserdata(L, sizeof(vector3_t));
|
||||
luaL_getmetatable(L, META_VECTOR3);
|
||||
lua_setmetatable(L, -2);
|
||||
FV3_Load(vec, slope->normal.x, slope->normal.y, slope->normal.z);
|
||||
return 1;
|
||||
}
|
||||
case slope_zangle: // zangle
|
||||
lua_pushangle(L, slope->zangle);
|
||||
return 1;
|
||||
|
|
@ -2486,47 +2488,6 @@ static int slope_set(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
///////////////
|
||||
// vector*_t //
|
||||
///////////////
|
||||
|
||||
static int vector2_get(lua_State *L)
|
||||
{
|
||||
vector2_t *vec = *((vector2_t **)luaL_checkudata(L, 1, META_VECTOR2));
|
||||
enum vector_e field = luaL_checkoption(L, 2, vector_opt[0], vector_opt);
|
||||
|
||||
if (!vec)
|
||||
return luaL_error(L, "accessed vector2_t doesn't exist anymore.");
|
||||
|
||||
switch(field)
|
||||
{
|
||||
case vector_x: lua_pushfixed(L, vec->x); return 1;
|
||||
case vector_y: lua_pushfixed(L, vec->y); return 1;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vector3_get(lua_State *L)
|
||||
{
|
||||
vector3_t *vec = *((vector3_t **)luaL_checkudata(L, 1, META_VECTOR3));
|
||||
enum vector_e field = luaL_checkoption(L, 2, vector_opt[0], vector_opt);
|
||||
|
||||
if (!vec)
|
||||
return luaL_error(L, "accessed vector3_t doesn't exist anymore.");
|
||||
|
||||
switch(field)
|
||||
{
|
||||
case vector_x: lua_pushfixed(L, vec->x); return 1;
|
||||
case vector_y: lua_pushfixed(L, vec->y); return 1;
|
||||
case vector_z: lua_pushfixed(L, vec->z); return 1;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////
|
||||
// mapheaderinfo[] //
|
||||
/////////////////////
|
||||
|
|
@ -2896,16 +2857,6 @@ int LUA_MapLib(lua_State *L)
|
|||
lua_setfield(L, -2, "__newindex");
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_newmetatable(L, META_VECTOR2);
|
||||
lua_pushcfunction(L, vector2_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_newmetatable(L, META_VECTOR3);
|
||||
lua_pushcfunction(L, vector3_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_newmetatable(L, META_MAPHEADER);
|
||||
lua_pushcfunction(L, mapheaderinfo_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
|
|
|||
220
src/lua_matrixlib.c
Normal file
220
src/lua_matrixlib.c
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2025 by LJ Sonic
|
||||
//
|
||||
// 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_matrixlib.c
|
||||
/// \brief matrix library for Lua scripting
|
||||
|
||||
#include "m_fixed.h"
|
||||
#include "lua_script.h"
|
||||
#include "lua_libs.h"
|
||||
|
||||
static vector3_t *GetVector(lua_State *L, int index)
|
||||
{
|
||||
vector3_t *vec = lua_touserdata(L, index);
|
||||
|
||||
if (!vec)
|
||||
return NULL;
|
||||
|
||||
if (!lua_getmetatable(L, index))
|
||||
return NULL;
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, META_VECTOR3);
|
||||
if (!lua_rawequal(L, -1, -2))
|
||||
return NULL;
|
||||
|
||||
lua_pop(L, 2);
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
static void GetVectorOrXYZ(lua_State *L, int index, vector3_t *result)
|
||||
{
|
||||
vector3_t *vec = GetVector(L, index);
|
||||
if (vec)
|
||||
{
|
||||
*result = *vec;
|
||||
}
|
||||
else
|
||||
{
|
||||
result->x = luaL_checkfixed(L, 1);
|
||||
result->y = luaL_checkfixed(L, 2);
|
||||
result->z = luaL_checkfixed(L, 3);
|
||||
}
|
||||
}
|
||||
|
||||
static matrix_t *NewMatrix(lua_State *L)
|
||||
{
|
||||
matrix_t *mat = lua_newuserdata(L, sizeof(*mat));
|
||||
luaL_getmetatable(L, META_MATRIX);
|
||||
lua_setmetatable(L, -2);
|
||||
return mat;
|
||||
}
|
||||
|
||||
////////////////////
|
||||
// STATIC MEMBERS //
|
||||
////////////////////
|
||||
|
||||
static int matrix_new(lua_State *L)
|
||||
{
|
||||
FM_LoadIdentity(NewMatrix(L));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int matrix_translation(lua_State *L)
|
||||
{
|
||||
vector3_t translation;
|
||||
GetVectorOrXYZ(L, 1, &translation);
|
||||
|
||||
matrix_t *mat = NewMatrix(L);
|
||||
FM_LoadIdentity(mat);
|
||||
FM_Translate(mat, translation.x, translation.y, translation.z);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int matrix_scaling(lua_State *L)
|
||||
{
|
||||
vector3_t scaling;
|
||||
GetVectorOrXYZ(L, 1, &scaling);
|
||||
FM_Scale(NewMatrix(L), scaling.x, scaling.y, scaling.z);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static luaL_Reg matrix[] = {
|
||||
{"new", matrix_new},
|
||||
{"translation", matrix_translation},
|
||||
{"scaling", matrix_scaling},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/////////////
|
||||
// MEMBERS //
|
||||
/////////////
|
||||
|
||||
enum matrixfield_e {
|
||||
matrixfield_clone = 0,
|
||||
matrixfield_getvalue,
|
||||
matrixfield_setvalue,
|
||||
matrixfield_mulXYZ,
|
||||
};
|
||||
|
||||
static const char *const matrixfield_opt[] = {
|
||||
"clone",
|
||||
"get",
|
||||
"set",
|
||||
"mulXYZ",
|
||||
NULL};
|
||||
|
||||
static int matrix_clone(lua_State *L)
|
||||
{
|
||||
matrix_t *mat = luaL_checkudata(L, 1, META_MATRIX);
|
||||
memcpy(NewMatrix(L), mat, sizeof(matrix_t));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int matrix_getvalue(lua_State *L)
|
||||
{
|
||||
matrix_t *mat = luaL_checkudata(L, 1, META_MATRIX);
|
||||
INT32 row = luaL_checkinteger(L, 2);
|
||||
INT32 col = luaL_checkinteger(L, 3);
|
||||
|
||||
if (row < 1 || row > 4)
|
||||
return luaL_error(L, "matrix row %d out of range (1 - 4)", row);
|
||||
if (col < 1 || col > 4)
|
||||
return luaL_error(L, "matrix column %d out of range (1 - 4)", col);
|
||||
|
||||
lua_pushfixed(L, mat->m[(col - 1) * 4 + row - 1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int matrix_setvalue(lua_State *L)
|
||||
{
|
||||
matrix_t *mat = luaL_checkudata(L, 1, META_MATRIX);
|
||||
INT32 row = luaL_checkinteger(L, 2);
|
||||
INT32 col = luaL_checkinteger(L, 3);
|
||||
fixed_t value = luaL_checkfixed(L, 4);
|
||||
|
||||
if (row < 1 || row > 4)
|
||||
return luaL_error(L, "matrix row %d out of range (1 - 4)", row);
|
||||
if (col < 1 || col > 4)
|
||||
return luaL_error(L, "matrix column %d out of range (1 - 4)", col);
|
||||
|
||||
mat->m[(col - 1) * 4 + row - 1] = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int matrix_mulXYZ(lua_State *L)
|
||||
{
|
||||
matrix_t *mat = luaL_checkudata(L, 1, META_MATRIX);
|
||||
fixed_t x = luaL_checkfixed(L, 2);
|
||||
fixed_t y = luaL_checkfixed(L, 3);
|
||||
fixed_t z = luaL_checkfixed(L, 4);
|
||||
|
||||
vector3_t vec;
|
||||
vector3_t result;
|
||||
FV3_Load(&vec, x, y, z);
|
||||
FM_MultMatrixVec3(mat, &vec, &result);
|
||||
|
||||
lua_pushfixed(L, result.x);
|
||||
lua_pushfixed(L, result.y);
|
||||
lua_pushfixed(L, result.z);
|
||||
return 3;
|
||||
}
|
||||
|
||||
static int matrix_get(lua_State *L)
|
||||
{
|
||||
enum matrixfield_e field = luaL_checkoption(L, 2, matrixfield_opt[0], matrixfield_opt);
|
||||
|
||||
switch(field)
|
||||
{
|
||||
case matrixfield_clone: lua_pushcfunction(L, matrix_clone); return 1;
|
||||
case matrixfield_getvalue: lua_pushcfunction(L, matrix_getvalue); return 1;
|
||||
case matrixfield_setvalue: lua_pushcfunction(L, matrix_setvalue); return 1;
|
||||
case matrixfield_mulXYZ: lua_pushcfunction(L, matrix_mulXYZ); return 1;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////
|
||||
// OPERATORS //
|
||||
///////////////
|
||||
|
||||
static int matrix_mul(lua_State *L)
|
||||
{
|
||||
matrix_t *mat1 = luaL_checkudata(L, 1, META_MATRIX);
|
||||
|
||||
vector3_t *vec2 = GetVector(L, 2);
|
||||
if (vec2)
|
||||
{
|
||||
vector3_t *result = lua_newuserdata(L, sizeof(*result));
|
||||
luaL_getmetatable(L, META_VECTOR3);
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
FM_MultMatrixVec3(mat1, vec2, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
matrix_t *mat2 = luaL_checkudata(L, 2, META_MATRIX);
|
||||
FM_MultMatrixEx(mat1, mat2, NewMatrix(L));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LUA_MatrixLib(lua_State *L)
|
||||
{
|
||||
luaL_newmetatable(L, META_MATRIX);
|
||||
LUA_SetCFunctionField(L, "__index", matrix_get);
|
||||
LUA_SetCFunctionField(L, "__mul", matrix_mul);
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_register(L, "Matrix", matrix);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -103,6 +103,12 @@ enum mobj_e {
|
|||
mobj_sprxoff,
|
||||
mobj_spryoff,
|
||||
mobj_sprzoff,
|
||||
mobj_bakexoff,
|
||||
mobj_bakeyoff,
|
||||
mobj_bakezoff,
|
||||
mobj_bakexpiv,
|
||||
mobj_bakeypiv,
|
||||
mobj_bakezpiv,
|
||||
mobj_terrain,
|
||||
mobj_dispoffset,
|
||||
mobj_tid,
|
||||
|
|
@ -192,6 +198,12 @@ static const char *const mobj_opt[] = {
|
|||
"sprxoff",
|
||||
"spryoff",
|
||||
"sprzoff",
|
||||
"bakexoff",
|
||||
"bakeyoff",
|
||||
"bakezoff",
|
||||
"bakexpiv",
|
||||
"bakeypiv",
|
||||
"bakezpiv",
|
||||
"terrain",
|
||||
"dispoffset",
|
||||
"tid",
|
||||
|
|
@ -542,6 +554,24 @@ static int mobj_get(lua_State *L)
|
|||
case mobj_sprzoff:
|
||||
lua_pushfixed(L, mo->sprzoff);
|
||||
break;
|
||||
case mobj_bakexoff:
|
||||
lua_pushfixed(L, mo->bakexoff);
|
||||
break;
|
||||
case mobj_bakeyoff:
|
||||
lua_pushfixed(L, mo->bakeyoff);
|
||||
break;
|
||||
case mobj_bakezoff:
|
||||
lua_pushfixed(L, mo->bakezoff);
|
||||
break;
|
||||
case mobj_bakexpiv:
|
||||
lua_pushfixed(L, mo->bakexpiv);
|
||||
break;
|
||||
case mobj_bakeypiv:
|
||||
lua_pushfixed(L, mo->bakeypiv);
|
||||
break;
|
||||
case mobj_bakezpiv:
|
||||
lua_pushfixed(L, mo->bakezpiv);
|
||||
break;
|
||||
case mobj_terrain:
|
||||
LUA_PushUserdata(L, mo->terrain, META_TERRAIN);
|
||||
break;
|
||||
|
|
@ -982,6 +1012,24 @@ static int mobj_set(lua_State *L)
|
|||
case mobj_sprzoff:
|
||||
mo->sprzoff = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case mobj_bakexoff:
|
||||
mo->bakexoff = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case mobj_bakeyoff:
|
||||
mo->bakeyoff = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case mobj_bakezoff:
|
||||
mo->bakezoff = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case mobj_bakexpiv:
|
||||
mo->bakexpiv = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case mobj_bakeypiv:
|
||||
mo->bakeypiv = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case mobj_bakezpiv:
|
||||
mo->bakezpiv = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case mobj_terrain:
|
||||
mo->terrain = *((terrain_t **)luaL_checkudata(L, 3, META_TERRAIN));
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -256,12 +256,15 @@ enum player_e
|
|||
player_ringmax,
|
||||
player_pickuprings,
|
||||
player_ringdelay,
|
||||
player_ringlock,
|
||||
player_ringboost,
|
||||
player_ringtime,
|
||||
player_superring,
|
||||
player_nextringaward,
|
||||
player_ringvolume,
|
||||
player_ringtransparency,
|
||||
player_airdroptime,
|
||||
player_ringdrop,
|
||||
player_curshield,
|
||||
player_bubblecool,
|
||||
player_bubbleblowup,
|
||||
|
|
@ -357,6 +360,9 @@ enum player_e
|
|||
player_ping,
|
||||
player_packetloss,
|
||||
player_loop,
|
||||
player_prevonground,
|
||||
player_walltransfered,
|
||||
player_walltransferboost,
|
||||
#ifdef HWRENDER
|
||||
player_fovadd,
|
||||
#endif
|
||||
|
|
@ -453,12 +459,15 @@ static const char *const player_opt[] = {
|
|||
"ringmax",
|
||||
"pickuprings",
|
||||
"ringdelay",
|
||||
"ringlock",
|
||||
"ringboost",
|
||||
"ringtime",
|
||||
"superring",
|
||||
"nextringaward",
|
||||
"ringvolume",
|
||||
"ringtransparency",
|
||||
"airdroptime",
|
||||
"ringdrop",
|
||||
"curshield",
|
||||
"bubblecool",
|
||||
"bubbleblowup",
|
||||
|
|
@ -554,6 +563,9 @@ static const char *const player_opt[] = {
|
|||
"ping",
|
||||
"packetloss",
|
||||
"loop",
|
||||
"prevonground",
|
||||
"walltransfered",
|
||||
"walltransfeboost",
|
||||
#ifdef HWRENDER
|
||||
"fovadd",
|
||||
#endif
|
||||
|
|
@ -854,6 +866,9 @@ static int player_get(lua_State *L)
|
|||
case player_ringdelay:
|
||||
lua_pushinteger(L, plr->ringdelay);
|
||||
break;
|
||||
case player_ringlock:
|
||||
lua_pushinteger(L, plr->ringlock);
|
||||
break;
|
||||
case player_ringboost:
|
||||
lua_pushinteger(L, plr->ringboost);
|
||||
break;
|
||||
|
|
@ -872,6 +887,12 @@ static int player_get(lua_State *L)
|
|||
case player_ringtransparency:
|
||||
lua_pushinteger(L, plr->ringtransparency);
|
||||
break;
|
||||
case player_airdroptime:
|
||||
lua_pushinteger(L, plr->airdroptime);
|
||||
break;
|
||||
case player_ringdrop:
|
||||
lua_pushinteger(L, plr->ringdrop);
|
||||
break;
|
||||
case player_curshield:
|
||||
lua_pushinteger(L, plr->curshield);
|
||||
break;
|
||||
|
|
@ -1177,6 +1198,15 @@ static int player_get(lua_State *L)
|
|||
case player_loop:
|
||||
LUA_PushUserdata(L, &plr->loop, META_SONICLOOPVARS);
|
||||
break;
|
||||
case player_prevonground:
|
||||
lua_pushboolean(L, plr->prevonground);
|
||||
break;
|
||||
case player_walltransfered:
|
||||
lua_pushboolean(L, plr->walltransfered);
|
||||
break;
|
||||
case player_walltransferboost:
|
||||
lua_pushinteger(L, plr->walltransferboost);
|
||||
break;
|
||||
#ifdef HWRENDER
|
||||
case player_fovadd:
|
||||
lua_pushfixed(L, plr->fovadd);
|
||||
|
|
@ -1534,6 +1564,9 @@ static int player_set(lua_State *L)
|
|||
case player_ringdelay:
|
||||
plr->ringdelay = luaL_checkinteger(L, 3);
|
||||
break;
|
||||
case player_ringlock:
|
||||
plr->ringlock = luaL_checkinteger(L, 3);
|
||||
break;
|
||||
case player_ringboost:
|
||||
plr->ringboost = luaL_checkinteger(L, 3);
|
||||
break;
|
||||
|
|
@ -1552,6 +1585,12 @@ static int player_set(lua_State *L)
|
|||
case player_ringtransparency:
|
||||
plr->ringtransparency = luaL_checkinteger(L, 3);
|
||||
break;
|
||||
case player_airdroptime:
|
||||
plr->airdroptime = luaL_checkinteger(L, 3);
|
||||
break;
|
||||
case player_ringdrop:
|
||||
plr->ringdrop = luaL_checkinteger(L, 3);
|
||||
break;
|
||||
case player_curshield:
|
||||
plr->curshield = luaL_checkinteger(L, 3);
|
||||
break;
|
||||
|
|
@ -1839,6 +1878,12 @@ static int player_set(lua_State *L)
|
|||
return NOSET;
|
||||
case player_loop:
|
||||
return NOSET;
|
||||
case player_prevonground:
|
||||
return NOSET;
|
||||
case player_walltransfered:
|
||||
plr->walltransfered = lua_toboolean(L, 3);
|
||||
case player_walltransferboost:
|
||||
plr->walltransferboost= lua_tointeger(L, 3);
|
||||
#ifdef HWRENDER
|
||||
case player_fovadd:
|
||||
plr->fovadd = luaL_checkfixed(L, 3);
|
||||
|
|
|
|||
192
src/lua_quaternionlib.c
Normal file
192
src/lua_quaternionlib.c
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2025 by LJ Sonic
|
||||
//
|
||||
// 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_quaternionlib.c
|
||||
/// \brief quaternion library for Lua scripting
|
||||
|
||||
#include "m_fixed.h"
|
||||
#include "lua_script.h"
|
||||
#include "lua_libs.h"
|
||||
|
||||
static vector4_t *NewQuaternion(lua_State *L)
|
||||
{
|
||||
vector4_t *quat = lua_newuserdata(L, sizeof(*quat));
|
||||
luaL_getmetatable(L, META_QUATERNION);
|
||||
lua_setmetatable(L, -2);
|
||||
return quat;
|
||||
}
|
||||
|
||||
////////////////////
|
||||
// STATIC MEMBERS //
|
||||
////////////////////
|
||||
|
||||
static int quaternion_new(lua_State *L)
|
||||
{
|
||||
vector4_t *q = NewQuaternion(L);
|
||||
q->x = 0;
|
||||
q->y = 0;
|
||||
q->z = 0;
|
||||
q->a = FRACUNIT;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int quaternion_fromAxisRotation(lua_State *L)
|
||||
{
|
||||
vector3_t *axis = luaL_checkudata(L, 1, META_VECTOR3);
|
||||
fixed_t angle = luaL_checkfixed(L, 2);
|
||||
|
||||
fixed_t cosangle = FINECOSINE(((angle / 2) >> ANGLETOFINESHIFT) & FINEMASK);
|
||||
fixed_t sinangle = FINESINE(((angle / 2) >> ANGLETOFINESHIFT) & FINEMASK);
|
||||
vector3_t normaxis;
|
||||
|
||||
FV3_NormalizeEx(axis, &normaxis);
|
||||
|
||||
FV4_Load(NewQuaternion(L),
|
||||
FixedMul(normaxis.x, sinangle),
|
||||
FixedMul(normaxis.y, sinangle),
|
||||
FixedMul(normaxis.z, sinangle),
|
||||
cosangle
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static luaL_Reg quaternion[] = {
|
||||
{"new", quaternion_new},
|
||||
{"fromAxisRotation", quaternion_fromAxisRotation},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/////////////
|
||||
// MEMBERS //
|
||||
/////////////
|
||||
|
||||
static int quaternion_clone(lua_State *L)
|
||||
{
|
||||
vector4_t *quat = luaL_checkudata(L, 1, META_QUATERNION);
|
||||
FV4_Copy(NewQuaternion(L), quat);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int vector4_toMatrix(lua_State *L)
|
||||
{
|
||||
vector4_t *quat = luaL_checkudata(L, 1, META_QUATERNION);
|
||||
|
||||
matrix_t *mat = lua_newuserdata(L, sizeof(*mat));
|
||||
luaL_getmetatable(L, META_MATRIX);
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
fixed_t x = quat->x, y = quat->y, z = quat->z, w = quat->a;
|
||||
|
||||
fixed_t xx2 = 2 * FixedMul(x, x);
|
||||
fixed_t xy2 = 2 * FixedMul(x, y);
|
||||
fixed_t xz2 = 2 * FixedMul(x, z);
|
||||
fixed_t xw2 = 2 * FixedMul(x, w);
|
||||
fixed_t yy2 = 2 * FixedMul(y, y);
|
||||
fixed_t yz2 = 2 * FixedMul(y, z);
|
||||
fixed_t yw2 = 2 * FixedMul(y, w);
|
||||
fixed_t zz2 = 2 * FixedMul(z, z);
|
||||
fixed_t zw2 = 2 * FixedMul(z, w);
|
||||
|
||||
FM_LoadIdentity(mat);
|
||||
|
||||
mat->m[0 + 0*4] = FRACUNIT - yy2 - zz2;
|
||||
mat->m[0 + 1*4] = xy2 - zw2;
|
||||
mat->m[0 + 2*4] = xz2 + yw2;
|
||||
|
||||
mat->m[1 + 0*4] = xy2 + zw2;
|
||||
mat->m[1 + 1*4] = FRACUNIT - xx2 - zz2;
|
||||
mat->m[1 + 2*4] = yz2 - xw2;
|
||||
|
||||
mat->m[2 + 0*4] = xz2 - yw2;
|
||||
mat->m[2 + 1*4] = yz2 + xw2;
|
||||
mat->m[2 + 2*4] = FRACUNIT - xx2 - yy2;
|
||||
|
||||
mat->m[3 + 3*4] = FRACUNIT;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
enum quaternionfield_e {
|
||||
quaternionfield_clone = 0,
|
||||
quaternionfield_toMatrix,
|
||||
quaternionfield_x,
|
||||
quaternionfield_y,
|
||||
quaternionfield_z,
|
||||
quaternionfield_w,
|
||||
};
|
||||
|
||||
static const char *const quaternionfield_opt[] = {
|
||||
"clone",
|
||||
"toMatrix",
|
||||
"x",
|
||||
"y",
|
||||
"z",
|
||||
"w",
|
||||
NULL};
|
||||
|
||||
static int quaternion_get(lua_State *L)
|
||||
{
|
||||
vector4_t *quat = luaL_checkudata(L, 1, META_QUATERNION);
|
||||
enum quaternionfield_e field = luaL_checkoption(L, 2, quaternionfield_opt[0], quaternionfield_opt);
|
||||
|
||||
switch(field)
|
||||
{
|
||||
case quaternionfield_clone: lua_pushcfunction(L, quaternion_clone); return 1;
|
||||
case quaternionfield_toMatrix: lua_pushcfunction(L, vector4_toMatrix); return 1;
|
||||
|
||||
case quaternionfield_x: lua_pushfixed(L, quat->x); return 1;
|
||||
case quaternionfield_y: lua_pushfixed(L, quat->y); return 1;
|
||||
case quaternionfield_z: lua_pushfixed(L, quat->z); return 1;
|
||||
case quaternionfield_w: lua_pushfixed(L, quat->a); return 1;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////
|
||||
// OPERATORS //
|
||||
///////////////
|
||||
|
||||
|
||||
// FV4_Mul isn't an accurate multiplication, so let's silently use LJ Sonic's multiplication
|
||||
// function.
|
||||
static vector4_t *QuaternionMul(vector4_t *out, vector4_t *a, vector4_t *b)
|
||||
{
|
||||
fixed_t ax = a->x, ay = a->y, az = a->z, aw = a->a;
|
||||
fixed_t bx = b->x, by = b->y, bz = b->z, bw = b->a;
|
||||
|
||||
FV4_NormalizeEx(out, FV4_Load(out,
|
||||
FixedMul(aw, bx) + FixedMul(ax, bw) + FixedMul(ay, bz) - FixedMul(az, by),
|
||||
FixedMul(aw, by) - FixedMul(ax, bz) + FixedMul(ay, bw) + FixedMul(az, bx),
|
||||
FixedMul(aw, bz) + FixedMul(ax, by) - FixedMul(ay, bx) + FixedMul(az, bw),
|
||||
FixedMul(aw, bw) - FixedMul(ax, bx) - FixedMul(ay, by) - FixedMul(az, bz)
|
||||
));
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static int quaternion_mul(lua_State *L)
|
||||
{
|
||||
vector4_t *quat1 = luaL_checkudata(L, 1, META_QUATERNION);
|
||||
vector4_t *quat2 = luaL_checkudata(L, 2, META_QUATERNION);
|
||||
QuaternionMul(NewQuaternion(L), quat1, quat2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LUA_QuaternionLib(lua_State *L)
|
||||
{
|
||||
luaL_newmetatable(L, META_QUATERNION);
|
||||
LUA_SetCFunctionField(L, "__index", quaternion_get);
|
||||
LUA_SetCFunctionField(L, "__mul", quaternion_mul);
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_register(L, "Quaternion", quaternion);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -63,6 +63,9 @@ static lua_CFunction liblist[] = {
|
|||
LUA_BotVarsLib, // botvars_t
|
||||
LUA_TerrainLib, // t_splash_t, t_footstep_t, t_overlay_t, terrain_t
|
||||
LUA_WaypointLib, // waypoint_t
|
||||
LUA_VectorLib, // vectors
|
||||
LUA_MatrixLib, // matrices
|
||||
LUA_QuaternionLib, // quaternions
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
@ -397,6 +400,11 @@ int LUA_PushGlobals(lua_State *L, const char *word)
|
|||
} else if (fastcmp(word,"draftingactive")) {
|
||||
lua_pushinteger(L, draftingactive);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"airdropactive")) {
|
||||
lua_pushinteger(L, airdropactive);
|
||||
} else if (fastcmp(word,"bumpsparkactive")) {
|
||||
lua_pushinteger(L, bumpsparkactive);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"purpledriftactive")) {
|
||||
lua_pushinteger(L, purpledriftactive);
|
||||
return 1;
|
||||
|
|
@ -1919,6 +1927,40 @@ void LUA_UnArchive(savebuffer_t *save, boolean network, boolean compat)
|
|||
lua_pop(gL, 1); // pop tables
|
||||
}
|
||||
|
||||
static void SetBasicMetamethods(
|
||||
lua_State *L,
|
||||
lua_CFunction get,
|
||||
lua_CFunction set,
|
||||
lua_CFunction len
|
||||
)
|
||||
{
|
||||
if (get)
|
||||
LUA_SetCFunctionField(L, "__index", get);
|
||||
if (set)
|
||||
LUA_SetCFunctionField(L, "__newindex", set);
|
||||
if (len)
|
||||
LUA_SetCFunctionField(L, "__len", len);
|
||||
}
|
||||
|
||||
void LUA_SetCFunctionField(lua_State *L, const char *name, lua_CFunction value)
|
||||
{
|
||||
lua_pushcfunction(L, value);
|
||||
lua_setfield(L, -2, name);
|
||||
}
|
||||
|
||||
void LUA_RegisterUserdataMetatable(
|
||||
lua_State *L,
|
||||
const char *name,
|
||||
lua_CFunction get,
|
||||
lua_CFunction set,
|
||||
lua_CFunction len
|
||||
)
|
||||
{
|
||||
luaL_newmetatable(L, name);
|
||||
SetBasicMetamethods(L, get, set, len);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
// For mobj_t, player_t, etc. to take custom variables.
|
||||
int Lua_optoption(lua_State *L, int narg,
|
||||
const char *def, const char *const lst[])
|
||||
|
|
|
|||
|
|
@ -34,7 +34,9 @@ extern "C" {
|
|||
// fixed_t casting
|
||||
// TODO add some distinction between fixed numbers and integer numbers
|
||||
// for at least the purpose of printing and maybe math.
|
||||
#define lua_tofixed(L, i) lua_tointeger(L, i)
|
||||
#define luaL_checkfixed(L, i) luaL_checkinteger(L, i)
|
||||
#define luaL_optfixed(L, i, d) luaL_optinteger(L, i, d)
|
||||
#define lua_pushfixed(L, f) lua_pushinteger(L, f)
|
||||
|
||||
// angle_t casting
|
||||
|
|
@ -62,6 +64,16 @@ void LUA_Step(void);
|
|||
void LUA_Archive(savebuffer_t *save, boolean network);
|
||||
void LUA_UnArchive(savebuffer_t *save, boolean network, boolean compat);
|
||||
|
||||
void LUA_SetCFunctionField(lua_State *L, const char *name, lua_CFunction value);
|
||||
|
||||
void LUA_RegisterUserdataMetatable(
|
||||
lua_State *L,
|
||||
const char *name,
|
||||
lua_CFunction get,
|
||||
lua_CFunction set,
|
||||
lua_CFunction len
|
||||
);
|
||||
|
||||
int LUA_PushGlobals(lua_State *L, const char *word);
|
||||
int LUA_WriteGlobals(lua_State *L, const char *word);
|
||||
|
||||
|
|
|
|||
219
src/lua_vectorlib.c
Normal file
219
src/lua_vectorlib.c
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2025 by LJ Sonic
|
||||
//
|
||||
// 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_vectorlib.c
|
||||
/// \brief vector library for Lua scripting
|
||||
|
||||
#include "m_fixed.h"
|
||||
#include "lua_script.h"
|
||||
#include "lua_libs.h"
|
||||
|
||||
// shared by both Vector2D and Vector3D
|
||||
enum vectorfield_e {
|
||||
vectorfield_clone = 0,
|
||||
vectorfield_opposite,
|
||||
vectorfield_x,
|
||||
vectorfield_y,
|
||||
vectorfield_z,
|
||||
vectorfield_length,
|
||||
vectorfield_normalized,
|
||||
};
|
||||
|
||||
static const char *const vectorfield_opt[] = {
|
||||
"vector_clone",
|
||||
"vector_opposite",
|
||||
"x",
|
||||
"y",
|
||||
"z",
|
||||
"vector_length",
|
||||
"vector_normalized",
|
||||
NULL};
|
||||
|
||||
////////////////////////////
|
||||
// VECTOR2 STATIC MEMBERS //
|
||||
////////////////////////////
|
||||
|
||||
/////////////////////
|
||||
// VECTOR2 MEMBERS //
|
||||
/////////////////////
|
||||
|
||||
static int vector2d_get(lua_State *L)
|
||||
{
|
||||
vector2_t *vec = luaL_checkudata(L, 1, META_VECTOR2);
|
||||
enum vectorfield_e field = luaL_checkoption(L, 2, vectorfield_opt[0], vectorfield_opt);
|
||||
|
||||
switch(field)
|
||||
{
|
||||
case vectorfield_x: lua_pushfixed(L, vec->x); return 1;
|
||||
case vectorfield_y: lua_pushfixed(L, vec->y); return 1;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////
|
||||
// VECTOR3 //
|
||||
/////////////
|
||||
|
||||
static vector3_t *NewVector3(lua_State *L)
|
||||
{
|
||||
vector3_t *vec = lua_newuserdata(L, sizeof(*vec));
|
||||
luaL_getmetatable(L, META_VECTOR3);
|
||||
lua_setmetatable(L, -2);
|
||||
return vec;
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
// VECTOR3 STATIC MEMBERS //
|
||||
////////////////////////////
|
||||
|
||||
static int vector3d_new(lua_State *L)
|
||||
{
|
||||
fixed_t x = luaL_checkfixed(L, 1);
|
||||
fixed_t y = luaL_checkfixed(L, 2);
|
||||
fixed_t z = luaL_optfixed(L, 3, 0);
|
||||
|
||||
FV3_Load(NewVector3(L), x, y, z);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static luaL_Reg vector3d[] = {
|
||||
{"new", vector3d_new},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/////////////////////
|
||||
// VECTOR3 MEMBERS //
|
||||
/////////////////////
|
||||
|
||||
static int vector3d_clone(lua_State *L)
|
||||
{
|
||||
vector3_t *vec = luaL_checkudata(L, 1, META_VECTOR3);
|
||||
FV3_Copy(NewVector3(L), vec);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int vector3d_opposite(lua_State *L)
|
||||
{
|
||||
vector3_t *vec = luaL_checkudata(L, 1, META_VECTOR3);
|
||||
FV3_NegateEx(vec, NewVector3(L));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int vector3d_get(lua_State *L)
|
||||
{
|
||||
vector3_t *vec = luaL_checkudata(L, 1, META_VECTOR3);
|
||||
enum vectorfield_e field = luaL_checkoption(L, 2, vectorfield_opt[0], vectorfield_opt);
|
||||
|
||||
if (!vec)
|
||||
return luaL_error(L, "accessed vector3_t doesn't exist anymore.");
|
||||
|
||||
vector3_t unit = { 0, 0, 0 };
|
||||
switch(field)
|
||||
{
|
||||
case vectorfield_clone: lua_pushcfunction(L, vector3d_clone); return 1;
|
||||
case vectorfield_opposite: lua_pushcfunction(L, vector3d_opposite); return 1;
|
||||
|
||||
case vectorfield_x: lua_pushfixed(L, vec->x); return 1;
|
||||
case vectorfield_y: lua_pushfixed(L, vec->y); return 1;
|
||||
case vectorfield_z: lua_pushfixed(L, vec->z); return 1;
|
||||
case vectorfield_length: lua_pushfixed(L, FV3_Distance(&unit, vec)); return 1;
|
||||
case vectorfield_normalized: FV3_NormalizeEx(vec, NewVector3(L)); return 1;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////
|
||||
// VECTOR3 OPERATORS //
|
||||
///////////////////////
|
||||
|
||||
static int vector3d_eq(lua_State *L)
|
||||
{
|
||||
vector3_t *vec1 = luaL_checkudata(L, 1, META_VECTOR3);
|
||||
vector3_t *vec2 = luaL_checkudata(L, 2, META_VECTOR3);
|
||||
lua_pushboolean(L, FV3_Equal(vec1, vec2));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int vector3d_op(
|
||||
lua_State *L,
|
||||
vector3_t *(*opvector)(const vector3_t*, const vector3_t*, vector3_t*)
|
||||
)
|
||||
{
|
||||
if (lua_isnumber(L, 1) && (opvector == FV3_AddEx || opvector == FV3_MulEx))
|
||||
{
|
||||
fixed_t n1 = lua_tofixed(L, 1);
|
||||
vector3_t vec1 = { n1, n1, n1 };
|
||||
vector3_t *vec2 = luaL_checkudata(L, 2, META_VECTOR3);
|
||||
opvector(NewVector3(L), vec2, &vec1);
|
||||
}
|
||||
else if (lua_isnumber(L, 2))
|
||||
{
|
||||
vector3_t *vec1 = luaL_checkudata(L, 1, META_VECTOR3);
|
||||
fixed_t n2 = lua_tofixed(L, 2);
|
||||
vector3_t vec2 = { n2, n2, n2 };
|
||||
opvector(NewVector3(L), vec1, &vec2);
|
||||
}
|
||||
else
|
||||
{
|
||||
vector3_t *vec1 = luaL_checkudata(L, 1, META_VECTOR3);
|
||||
vector3_t *vec2 = luaL_checkudata(L, 2, META_VECTOR3);
|
||||
opvector(NewVector3(L), vec1, vec2);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int vector3d_add(lua_State *L)
|
||||
{
|
||||
return vector3d_op(L, FV3_AddEx);
|
||||
}
|
||||
|
||||
static int vector3d_sub(lua_State *L)
|
||||
{
|
||||
return vector3d_op(L, FV3_SubEx);
|
||||
}
|
||||
|
||||
static int vector3d_mul(lua_State *L)
|
||||
{
|
||||
return vector3d_op(L, FV3_MulEx);
|
||||
}
|
||||
|
||||
static int vector3d_div(lua_State *L)
|
||||
{
|
||||
return vector3d_op(L, FV3_DivideEx);
|
||||
}
|
||||
|
||||
static int vector3d_unm(lua_State *L)
|
||||
{
|
||||
vector3_t *vec = luaL_checkudata(L, 1, META_VECTOR3);
|
||||
FV3_NegateEx(vec, NewVector3(L));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LUA_VectorLib(lua_State *L)
|
||||
{
|
||||
LUA_RegisterUserdataMetatable(L, META_VECTOR2, vector2d_get, NULL, NULL);
|
||||
|
||||
luaL_newmetatable(L, META_VECTOR3);
|
||||
LUA_SetCFunctionField(L, "__index", vector3d_get);
|
||||
LUA_SetCFunctionField(L, "__eq", vector3d_eq);
|
||||
LUA_SetCFunctionField(L, "__add", vector3d_add);
|
||||
LUA_SetCFunctionField(L, "__sub", vector3d_sub);
|
||||
LUA_SetCFunctionField(L, "__mul", vector3d_mul);
|
||||
LUA_SetCFunctionField(L, "__div", vector3d_div);
|
||||
LUA_SetCFunctionField(L, "__unm", vector3d_unm);
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_register(L, "Vector3D", vector3d);
|
||||
return 0;
|
||||
}
|
||||
228
src/m_anigif.c
228
src/m_anigif.c
|
|
@ -57,14 +57,15 @@ static precise_t gif_prevframetime = 0;
|
|||
static UINT32 gif_delayus = 0; // "us" is microseconds
|
||||
static UINT8 gif_writeover = 0;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *pixels;
|
||||
size_t size;
|
||||
boolean owns_pixels;
|
||||
} gif_screen_t;
|
||||
static gif_screen_t gif_screens[2];
|
||||
|
||||
// SCReen BUFfer (obviously)
|
||||
// ---
|
||||
static UINT8 *scrbuf_pos;
|
||||
static UINT8 *scrbuf_linebegin;
|
||||
static UINT8 *scrbuf_lineend;
|
||||
static UINT8 *scrbuf_writeend;
|
||||
static INT16 scrbuf_downscaleamt = 1;
|
||||
static UINT16 scrbuf_width, scrbuf_height;
|
||||
static UINT8 *scrbuf_screens;
|
||||
|
||||
// OPTIMIZE gif output
|
||||
// ---
|
||||
|
|
@ -79,13 +80,13 @@ static gif_screen_t gif_screens[2];
|
|||
static UINT8 GIF_optimizecmprow(const UINT8 *dst, const UINT8 *src, INT32 row,
|
||||
INT32 *last, INT32 *left, INT32 *right)
|
||||
{
|
||||
const UINT8 *dp = dst + (vid.width * row);
|
||||
const UINT8 *sp = src + (vid.width * row);
|
||||
const UINT8 *dp = dst + (scrbuf_width * row);
|
||||
const UINT8 *sp = src + (scrbuf_width * row);
|
||||
const UINT8 *dtmp, *stmp;
|
||||
UINT8 doleft = 1, doright = 1;
|
||||
INT32 i = 0;
|
||||
|
||||
if (!memcmp(sp, dp, vid.width))
|
||||
if (!memcmp(sp, dp, scrbuf_width))
|
||||
return 0; // unchanged.
|
||||
|
||||
*last = row;
|
||||
|
|
@ -112,14 +113,14 @@ static UINT8 GIF_optimizecmprow(const UINT8 *dst, const UINT8 *src, INT32 row,
|
|||
}
|
||||
|
||||
// right side
|
||||
i = vid.width - 1;
|
||||
if (*right == vid.width - 1) // edge reached
|
||||
i = scrbuf_width - 1;
|
||||
if (*right == scrbuf_width - 1) // edge reached
|
||||
doright = 0;
|
||||
else if (*right >= 0) // right set, non-end-of-width
|
||||
{
|
||||
dtmp = dp + *right + 1;
|
||||
stmp = sp + *right + 1;
|
||||
if (!memcmp(stmp, dtmp, vid.width - (*right + 1)))
|
||||
if (!memcmp(stmp, dtmp, scrbuf_width - (*right + 1)))
|
||||
doright = 0; // right side not changed
|
||||
}
|
||||
while (doright)
|
||||
|
|
@ -149,7 +150,7 @@ static UINT8 GIF_optimizecmprow(const UINT8 *dst, const UINT8 *src, INT32 row,
|
|||
static void GIF_optimizeregion(const UINT8 *dst, const UINT8 *src,
|
||||
INT32 *x, INT32 *y, INT32 *w, INT32 *h)
|
||||
{
|
||||
INT32 st = 0, sb = vid.height - 1; // work from both directions
|
||||
INT32 st = 0, sb = scrbuf_height - 1; // work from both directions
|
||||
INT32 firstchg_t = -1, firstchg_b = -1; // store first changed row.
|
||||
INT32 lastchg_t = -1, lastchg_b = -1; // Store last row... just in case
|
||||
INT32 lmpix = -1, rmpix = -1; // store left and rightmost change
|
||||
|
|
@ -160,7 +161,7 @@ static void GIF_optimizeregion(const UINT8 *dst, const UINT8 *src,
|
|||
if (!stopt)
|
||||
{
|
||||
if (GIF_optimizecmprow(dst, src, st++, &lastchg_t, &lmpix, &rmpix)
|
||||
&& lmpix == 0 && rmpix == vid.width - 1)
|
||||
&& lmpix == 0 && rmpix == scrbuf_width - 1)
|
||||
stopt = 1;
|
||||
if (firstchg_t < 0 && lastchg_t >= 0)
|
||||
firstchg_t = lastchg_t;
|
||||
|
|
@ -168,7 +169,7 @@ static void GIF_optimizeregion(const UINT8 *dst, const UINT8 *src,
|
|||
if (!stopb)
|
||||
{
|
||||
if (GIF_optimizecmprow(dst, src, sb--, &lastchg_b, &lmpix, &rmpix)
|
||||
&& lmpix == 0 && rmpix == vid.width - 1)
|
||||
&& lmpix == 0 && rmpix == scrbuf_width - 1)
|
||||
stopb = 1;
|
||||
if (firstchg_b < 0 && lastchg_b >= 0)
|
||||
firstchg_b = lastchg_b;
|
||||
|
|
@ -238,18 +239,6 @@ static void GIF_bwrwrite(UINT32 idata)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// SCReen BUFfer (obviously)
|
||||
// ---
|
||||
static UINT8 *scrbuf_pos;
|
||||
static UINT8 *scrbuf_linebegin;
|
||||
static UINT8 *scrbuf_lineend;
|
||||
static UINT8 *scrbuf_writeend;
|
||||
static INT16 scrbuf_downscaleamt = 1;
|
||||
|
||||
|
||||
|
||||
// GIF LZW algorithm
|
||||
// ---
|
||||
#define GIFLZW_TABLECLR 0x100
|
||||
|
|
@ -375,10 +364,10 @@ static void GIF_lzw(void)
|
|||
GIF_bwrwrite(GIFLZW_TABLECLR);
|
||||
GIF_prepareLZW();
|
||||
}
|
||||
if ((scrbuf_pos += scrbuf_downscaleamt) >= scrbuf_lineend)
|
||||
if (++scrbuf_pos >= scrbuf_lineend)
|
||||
{
|
||||
scrbuf_lineend += (vid.width * scrbuf_downscaleamt);
|
||||
scrbuf_linebegin += (vid.width * scrbuf_downscaleamt);
|
||||
scrbuf_lineend += scrbuf_width;
|
||||
scrbuf_linebegin += scrbuf_width;
|
||||
scrbuf_pos = scrbuf_linebegin;
|
||||
}
|
||||
// Just a bit of overflow prevention
|
||||
|
|
@ -459,7 +448,6 @@ static void GIF_headwrite(void)
|
|||
{
|
||||
UINT8 *gifhead = Z_Malloc(800, PU_STATIC, NULL);
|
||||
UINT8 *p = gifhead;
|
||||
UINT16 rwidth, rheight;
|
||||
|
||||
if (!gif_out)
|
||||
return;
|
||||
|
|
@ -470,18 +458,18 @@ static void GIF_headwrite(void)
|
|||
if (gif_downscale)
|
||||
{
|
||||
scrbuf_downscaleamt = vid.dupx;
|
||||
rwidth = (vid.width / scrbuf_downscaleamt);
|
||||
rheight = (vid.height / scrbuf_downscaleamt);
|
||||
scrbuf_width = (vid.width / scrbuf_downscaleamt);
|
||||
scrbuf_height = (vid.height / scrbuf_downscaleamt);
|
||||
}
|
||||
else
|
||||
{
|
||||
scrbuf_downscaleamt = 1;
|
||||
rwidth = vid.width;
|
||||
rheight = vid.height;
|
||||
scrbuf_width = vid.width;
|
||||
scrbuf_height = vid.height;
|
||||
}
|
||||
|
||||
WRITEUINT16(p, rwidth);
|
||||
WRITEUINT16(p, rheight);
|
||||
WRITEUINT16(p, scrbuf_width);
|
||||
WRITEUINT16(p, scrbuf_height);
|
||||
|
||||
// colors, aspect, etc
|
||||
WRITEUINT8(p, 0xF7); // (0xF7 = 1111 0111)
|
||||
|
|
@ -515,28 +503,16 @@ static size_t gifframe_size = 8192;
|
|||
#ifdef HWRENDER
|
||||
static colorlookup_t gif_colorlookup;
|
||||
|
||||
static void GIF_rgbconvert(UINT8 *linear, UINT8 *scr)
|
||||
static void GIF_rgbconvert(UINT8 * restrict linear, UINT8 * restrict scr)
|
||||
{
|
||||
UINT8 r, g, b;
|
||||
size_t src, dest;
|
||||
int x, y;
|
||||
|
||||
InitColorLUT(&gif_colorlookup, (gif_localcolortable) ? gif_framepalette : gif_headerpalette, true);
|
||||
|
||||
for (x = 0; x < vid.width; x += scrbuf_downscaleamt)
|
||||
for (INT32 i = 0; i < scrbuf_width*scrbuf_height; i++)
|
||||
{
|
||||
for (y = 0; y < vid.height; y += scrbuf_downscaleamt)
|
||||
{
|
||||
dest = y*vid.width + x;
|
||||
src = dest*3;
|
||||
|
||||
r = (UINT8)linear[src];
|
||||
g = (UINT8)linear[src + 1];
|
||||
b = (UINT8)linear[src + 2];
|
||||
scr[dest] = GetColorLUTDirect(&gif_colorlookup, r, g, b);
|
||||
src += (3 * scrbuf_downscaleamt);
|
||||
dest += scrbuf_downscaleamt;
|
||||
}
|
||||
UINT8 r = *linear++;
|
||||
UINT8 g = *linear++;
|
||||
UINT8 b = *linear++;
|
||||
*scr++ = GetColorLUTDirect(&gif_colorlookup, r, g, b);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -548,8 +524,8 @@ static void GIF_rgbconvert(UINT8 *linear, UINT8 *scr)
|
|||
static void GIF_framewrite(void)
|
||||
{
|
||||
UINT8 *p;
|
||||
UINT8 *base_screen = gif_screens[0].pixels;
|
||||
UINT8 *movie_screen = gif_screens[1].pixels;
|
||||
UINT8 *base_screen = scrbuf_screens;
|
||||
UINT8 *movie_screen = scrbuf_screens;
|
||||
INT32 blitx, blity, blitw, blith;
|
||||
boolean palchanged;
|
||||
|
||||
|
|
@ -569,48 +545,35 @@ static void GIF_framewrite(void)
|
|||
else
|
||||
palchanged = false;
|
||||
|
||||
// select your framebuffer
|
||||
if (gif_frames & 1)
|
||||
base_screen += scrbuf_width*scrbuf_height;
|
||||
else
|
||||
movie_screen += scrbuf_width*scrbuf_height;
|
||||
|
||||
// blit to temp screen
|
||||
if (rendermode == render_soft)
|
||||
I_ReadScreen(movie_screen, scrbuf_downscaleamt);
|
||||
#ifdef HWRENDER
|
||||
else if (rendermode == render_opengl)
|
||||
{
|
||||
UINT8 *linear = HWR_GetScreenshot(scrbuf_downscaleamt);
|
||||
GIF_rgbconvert(linear, movie_screen);
|
||||
//free(linear); // Allocated 'statically', no need to free now
|
||||
}
|
||||
#endif
|
||||
|
||||
// Compare image data (for optimizing GIF)
|
||||
// If the palette has changed, the entire frame is considered to be different.
|
||||
if (gif_optimize && gif_frames > 0 && (!palchanged))
|
||||
{
|
||||
// before blit movie_screen points to last frame, cur_screen points to this frame
|
||||
UINT8 *cur_screen = base_screen;
|
||||
GIF_optimizeregion(cur_screen, movie_screen, &blitx, &blity, &blitw, &blith);
|
||||
|
||||
// blit to temp screen
|
||||
if (rendermode == render_soft)
|
||||
I_ReadScreen(movie_screen);
|
||||
#ifdef HWRENDER
|
||||
else if (rendermode == render_opengl)
|
||||
{
|
||||
UINT8 *linear = HWR_GetScreenshot();
|
||||
GIF_rgbconvert(linear, movie_screen);
|
||||
//free(linear); // Allocated 'statically', no need to free now
|
||||
}
|
||||
#endif
|
||||
GIF_optimizeregion(base_screen, movie_screen, &blitx, &blity, &blitw, &blith);
|
||||
}
|
||||
else
|
||||
{
|
||||
blitx = blity = 0;
|
||||
blitw = vid.width;
|
||||
blith = vid.height;
|
||||
|
||||
#ifdef HWRENDER
|
||||
// Copy the current OpenGL frame into the base screen
|
||||
if (rendermode == render_opengl)
|
||||
{
|
||||
UINT8 *linear = HWR_GetScreenshot();
|
||||
GIF_rgbconvert(linear, base_screen);
|
||||
//free(linear); // Allocated 'statically', no need to free now
|
||||
}
|
||||
#endif
|
||||
|
||||
// Copy the first frame into the movie screen
|
||||
// OpenGL already does the same above.
|
||||
if (gif_frames == 0 && rendermode == render_soft)
|
||||
I_ReadScreen(movie_screen);
|
||||
|
||||
movie_screen = base_screen;
|
||||
blitw = scrbuf_width;
|
||||
blith = scrbuf_height;
|
||||
}
|
||||
|
||||
// screen regions are handled in GIF_lzw
|
||||
|
|
@ -654,20 +617,11 @@ static void GIF_framewrite(void)
|
|||
WRITEUINT8(p, 0);
|
||||
WRITEUINT8(p, 0); // end of GCE
|
||||
|
||||
if (scrbuf_downscaleamt > 1)
|
||||
{
|
||||
// Ensure our downscaled blitx/y starts and ends on a pixel.
|
||||
blitx -= (blitx % scrbuf_downscaleamt);
|
||||
blity -= (blity % scrbuf_downscaleamt);
|
||||
blitw = ((blitw + (scrbuf_downscaleamt - 1)) / scrbuf_downscaleamt) * scrbuf_downscaleamt;
|
||||
blith = ((blith + (scrbuf_downscaleamt - 1)) / scrbuf_downscaleamt) * scrbuf_downscaleamt;
|
||||
}
|
||||
|
||||
WRITEUINT8(p, 0x2C);
|
||||
WRITEUINT16(p, (UINT16)(blitx / scrbuf_downscaleamt));
|
||||
WRITEUINT16(p, (UINT16)(blity / scrbuf_downscaleamt));
|
||||
WRITEUINT16(p, (UINT16)(blitw / scrbuf_downscaleamt));
|
||||
WRITEUINT16(p, (UINT16)(blith / scrbuf_downscaleamt));
|
||||
WRITEUINT16(p, (UINT16)blitx);
|
||||
WRITEUINT16(p, (UINT16)blity);
|
||||
WRITEUINT16(p, (UINT16)blitw);
|
||||
WRITEUINT16(p, (UINT16)blith);
|
||||
|
||||
if (!gif_localcolortable)
|
||||
WRITEUINT8(p, 0); // no local table of colors
|
||||
|
|
@ -683,8 +637,8 @@ static void GIF_framewrite(void)
|
|||
WRITEUINT8(p, 0); // They are equal, no Local Color Table needed.
|
||||
}
|
||||
|
||||
scrbuf_pos = movie_screen + blitx + (blity * vid.width);
|
||||
scrbuf_writeend = scrbuf_pos + (blitw - 1) + ((blith - 1) * vid.width);
|
||||
scrbuf_pos = movie_screen + blitx + (blity * scrbuf_width);
|
||||
scrbuf_writeend = scrbuf_pos + (blitw - 1) + ((blith - 1) * scrbuf_width);
|
||||
|
||||
if (!gifbwr_buf)
|
||||
gifbwr_buf = Z_Malloc(256, PU_STATIC, NULL);
|
||||
|
|
@ -694,8 +648,8 @@ static void GIF_framewrite(void)
|
|||
giflzw_workingCode = UINT16_MAX;
|
||||
WRITEUINT8(p, gifbwr_bits_min - 1);
|
||||
|
||||
startline = (scrbuf_pos - movie_screen) / vid.width;
|
||||
scrbuf_linebegin = movie_screen + (startline * vid.width) + blitx;
|
||||
startline = (scrbuf_pos - movie_screen) / scrbuf_width;
|
||||
scrbuf_linebegin = movie_screen + (startline * scrbuf_width) + blitx;
|
||||
scrbuf_lineend = scrbuf_linebegin + blitw;
|
||||
|
||||
//prewrite a table clear
|
||||
|
|
@ -760,55 +714,11 @@ INT32 GIF_open(const char *filename)
|
|||
|
||||
static void GIF_checkscreens(void)
|
||||
{
|
||||
for (size_t i = 0; i < sizeof(gif_screens) / sizeof(gif_screens[0]); i++)
|
||||
{
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
if (gif_screens[i].owns_pixels)
|
||||
{
|
||||
Z_Free(gif_screens[i].pixels);
|
||||
gif_screens[i].owns_pixels = false;
|
||||
}
|
||||
if (scrbuf_screens == NULL)
|
||||
Z_Malloc(scrbuf_width * scrbuf_height * 2, PU_STATIC, &scrbuf_screens);
|
||||
|
||||
gif_screens[i].size = 0;
|
||||
|
||||
if (i == 1)
|
||||
gif_screens[i].pixels = screens[2];
|
||||
else
|
||||
gif_screens[i].pixels = screens[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t sz = vid.width * vid.height * vid.bpp;
|
||||
|
||||
if (!gif_screens[i].owns_pixels)
|
||||
{
|
||||
gif_screens[i].size = sz;
|
||||
gif_screens[i].pixels = Z_Malloc(gif_screens[i].size, PU_STATIC, NULL);
|
||||
gif_screens[i].owns_pixels = true;
|
||||
}
|
||||
else if (gif_screens[i].size != sz)
|
||||
{
|
||||
gif_screens[i].size = sz;
|
||||
gif_screens[i].pixels = Z_Realloc(gif_screens[i].pixels, gif_screens[i].size, PU_STATIC, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void GIF_freescreens(void)
|
||||
{
|
||||
for (size_t i = 0; i < sizeof(gif_screens) / sizeof(gif_screens[0]); i++)
|
||||
{
|
||||
if (gif_screens[i].owns_pixels)
|
||||
{
|
||||
Z_Free(gif_screens[i].pixels);
|
||||
gif_screens[i].owns_pixels = false;
|
||||
}
|
||||
|
||||
gif_screens[i].size = 0;
|
||||
gif_screens[i].pixels = NULL;
|
||||
}
|
||||
I_Assert(scrbuf_width == vid.width / scrbuf_downscaleamt);
|
||||
I_Assert(scrbuf_height == vid.height / scrbuf_downscaleamt);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -847,7 +757,7 @@ INT32 GIF_close(void)
|
|||
Z_Free(giflzw_hashTable);
|
||||
giflzw_hashTable = NULL;
|
||||
|
||||
GIF_freescreens();
|
||||
Z_Free(scrbuf_screens);
|
||||
|
||||
CONS_Printf(M_GetText("Animated gif closed; wrote %d frames\n"), gif_frames);
|
||||
return 1;
|
||||
|
|
|
|||
233
src/m_fixed.c
233
src/m_fixed.c
|
|
@ -248,6 +248,15 @@ vector3_t *FV3_Load(vector3_t *vec, fixed_t x, fixed_t y, fixed_t z)
|
|||
return vec;
|
||||
}
|
||||
|
||||
vector4_t *FV4_Load(vector4_t *vec, fixed_t x, fixed_t y, fixed_t z, fixed_t a)
|
||||
{
|
||||
vec->x = x;
|
||||
vec->y = y;
|
||||
vec->z = z;
|
||||
vec->a = a;
|
||||
return vec;
|
||||
}
|
||||
|
||||
vector3_t *FV3_UnLoad(vector3_t *vec, fixed_t *x, fixed_t *y, fixed_t *z)
|
||||
{
|
||||
*x = vec->x;
|
||||
|
|
@ -256,11 +265,25 @@ vector3_t *FV3_UnLoad(vector3_t *vec, fixed_t *x, fixed_t *y, fixed_t *z)
|
|||
return vec;
|
||||
}
|
||||
|
||||
vector4_t *FV4_UnLoad(vector4_t *vec, fixed_t *x, fixed_t *y, fixed_t *z, fixed_t *a)
|
||||
{
|
||||
*x = vec->x;
|
||||
*y = vec->y;
|
||||
*z = vec->z;
|
||||
*a = vec->a;
|
||||
return vec;
|
||||
}
|
||||
|
||||
vector3_t *FV3_Copy(vector3_t *a_o, const vector3_t *a_i)
|
||||
{
|
||||
return M_Memcpy(a_o, a_i, sizeof(vector3_t));
|
||||
}
|
||||
|
||||
vector4_t *FV4_Copy(vector4_t *a_o, const vector4_t *a_i)
|
||||
{
|
||||
return M_Memcpy(a_o, a_i, sizeof(vector4_t));
|
||||
}
|
||||
|
||||
vector3_t *FV3_AddEx(const vector3_t *a_i, const vector3_t *a_c, vector3_t *a_o)
|
||||
{
|
||||
a_o->x = a_i->x + a_c->x;
|
||||
|
|
@ -269,11 +292,25 @@ vector3_t *FV3_AddEx(const vector3_t *a_i, const vector3_t *a_c, vector3_t *a_o)
|
|||
return a_o;
|
||||
}
|
||||
|
||||
vector4_t *FV4_AddEx(const vector4_t *a_i, const vector4_t *a_c, vector4_t *a_o)
|
||||
{
|
||||
a_o->x = a_i->x + a_c->x;
|
||||
a_o->y = a_i->y + a_c->y;
|
||||
a_o->z = a_i->z + a_c->z;
|
||||
a_o->a = a_i->a + a_c->a;
|
||||
return a_o;
|
||||
}
|
||||
|
||||
vector3_t *FV3_Add(vector3_t *a_i, const vector3_t *a_c)
|
||||
{
|
||||
return FV3_AddEx(a_i, a_c, a_i);
|
||||
}
|
||||
|
||||
vector4_t *FV4_Add(vector4_t *a_i, const vector4_t *a_c)
|
||||
{
|
||||
return FV4_AddEx(a_i, a_c, a_i);
|
||||
}
|
||||
|
||||
vector3_t *FV3_SubEx(const vector3_t *a_i, const vector3_t *a_c, vector3_t *a_o)
|
||||
{
|
||||
a_o->x = a_i->x - a_c->x;
|
||||
|
|
@ -282,37 +319,79 @@ vector3_t *FV3_SubEx(const vector3_t *a_i, const vector3_t *a_c, vector3_t *a_o)
|
|||
return a_o;
|
||||
}
|
||||
|
||||
vector4_t *FV4_SubEx(const vector4_t *a_i, const vector4_t *a_c, vector4_t *a_o)
|
||||
{
|
||||
a_o->x = a_i->x - a_c->x;
|
||||
a_o->y = a_i->y - a_c->y;
|
||||
a_o->z = a_i->z - a_c->z;
|
||||
a_o->a = a_i->a - a_c->a;
|
||||
return a_o;
|
||||
}
|
||||
|
||||
vector3_t *FV3_Sub(vector3_t *a_i, const vector3_t *a_c)
|
||||
{
|
||||
return FV3_SubEx(a_i, a_c, a_i);
|
||||
}
|
||||
|
||||
vector3_t *FV3_MulEx(const vector3_t *a_i, fixed_t a_c, vector3_t *a_o)
|
||||
vector4_t *FV4_Sub(vector4_t *a_i, const vector4_t *a_c)
|
||||
{
|
||||
a_o->x = FixedMul(a_i->x, a_c);
|
||||
a_o->y = FixedMul(a_i->y, a_c);
|
||||
a_o->z = FixedMul(a_i->z, a_c);
|
||||
return FV4_SubEx(a_i, a_c, a_i);
|
||||
}
|
||||
|
||||
vector3_t *FV3_MulEx(const vector3_t *a_i, const vector3_t *a_c, vector3_t *a_o)
|
||||
{
|
||||
a_o->x = FixedMul(a_i->x, a_c->x);
|
||||
a_o->y = FixedMul(a_i->y, a_c->y);
|
||||
a_o->z = FixedMul(a_i->z, a_c->z);
|
||||
return a_o;
|
||||
}
|
||||
|
||||
vector3_t *FV3_Mul(vector3_t *a_i, fixed_t a_c)
|
||||
vector4_t *FV4_MulEx(const vector4_t *a_i, const vector4_t *a_c, vector4_t *a_o)
|
||||
{
|
||||
a_o->x = FixedMul(a_i->x, a_c->x);
|
||||
a_o->y = FixedMul(a_i->y, a_c->y);
|
||||
a_o->z = FixedMul(a_i->z, a_c->z);
|
||||
a_o->a = FixedMul(a_i->a, a_c->a);
|
||||
return a_o;
|
||||
}
|
||||
|
||||
vector3_t *FV3_Mul(vector3_t *a_i, const vector3_t *a_c)
|
||||
{
|
||||
return FV3_MulEx(a_i, a_c, a_i);
|
||||
}
|
||||
|
||||
vector3_t *FV3_DivideEx(const vector3_t *a_i, fixed_t a_c, vector3_t *a_o)
|
||||
vector4_t *FV4_Mul(vector4_t *a_i, const vector4_t *a_c)
|
||||
{
|
||||
a_o->x = FixedDiv(a_i->x, a_c);
|
||||
a_o->y = FixedDiv(a_i->y, a_c);
|
||||
a_o->z = FixedDiv(a_i->z, a_c);
|
||||
return FV4_MulEx(a_i, a_c, a_i);
|
||||
}
|
||||
|
||||
vector3_t *FV3_DivideEx(const vector3_t *a_i, const vector3_t *a_c, vector3_t *a_o)
|
||||
{
|
||||
a_o->x = FixedDiv(a_i->x, a_c->x);
|
||||
a_o->y = FixedDiv(a_i->y, a_c->y);
|
||||
a_o->z = FixedDiv(a_i->z, a_c->z);
|
||||
return a_o;
|
||||
}
|
||||
|
||||
vector3_t *FV3_Divide(vector3_t *a_i, fixed_t a_c)
|
||||
vector4_t *FV4_DivideEx(const vector4_t *a_i, const vector4_t *a_c, vector4_t *a_o)
|
||||
{
|
||||
a_o->x = FixedDiv(a_i->x, a_c->x);
|
||||
a_o->y = FixedDiv(a_i->y, a_c->y);
|
||||
a_o->z = FixedDiv(a_i->z, a_c->z);
|
||||
a_o->a = FixedDiv(a_i->a, a_c->a);
|
||||
return a_o;
|
||||
}
|
||||
|
||||
vector3_t *FV3_Divide(vector3_t *a_i, const vector3_t *a_c)
|
||||
{
|
||||
return FV3_DivideEx(a_i, a_c, a_i);
|
||||
}
|
||||
|
||||
vector4_t *FV4_Divide(vector4_t *a_i, const vector4_t *a_c)
|
||||
{
|
||||
return FV4_DivideEx(a_i, a_c, a_i);
|
||||
}
|
||||
|
||||
// Vector Complex Math
|
||||
vector3_t *FV3_Midpoint(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a_o)
|
||||
{
|
||||
|
|
@ -325,6 +404,19 @@ vector3_t *FV3_Midpoint(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a
|
|||
return a_o;
|
||||
}
|
||||
|
||||
vector4_t *FV4_Midpoint(const vector4_t *a_1, const vector4_t *a_2, vector4_t *a_o)
|
||||
{
|
||||
a_o->x = FixedDiv(a_2->x - a_1->x, 2 * FRACUNIT);
|
||||
a_o->y = FixedDiv(a_2->y - a_1->y, 2 * FRACUNIT);
|
||||
a_o->z = FixedDiv(a_2->z - a_1->z, 2 * FRACUNIT);
|
||||
a_o->a = FixedDiv(a_2->a - a_1->a, 2 * FRACUNIT);
|
||||
a_o->x = a_1->x + a_o->x;
|
||||
a_o->y = a_1->y + a_o->y;
|
||||
a_o->z = a_1->z + a_o->z;
|
||||
a_o->a = a_1->z + a_o->a;
|
||||
return a_o;
|
||||
}
|
||||
|
||||
fixed_t FV3_Distance(const vector3_t *p1, const vector3_t *p2)
|
||||
{
|
||||
fixed_t xs = FixedMul(p2->x - p1->x, p2->x - p1->x);
|
||||
|
|
@ -333,6 +425,15 @@ fixed_t FV3_Distance(const vector3_t *p1, const vector3_t *p2)
|
|||
return FixedSqrt(xs + ys + zs);
|
||||
}
|
||||
|
||||
fixed_t FV4_Distance(const vector4_t *p1, const vector4_t *p2)
|
||||
{
|
||||
fixed_t xs = FixedMul(p2->x - p1->x, p2->x - p1->x);
|
||||
fixed_t ys = FixedMul(p2->y - p1->y, p2->y - p1->y);
|
||||
fixed_t zs = FixedMul(p2->z - p1->z, p2->z - p1->z);
|
||||
fixed_t za = FixedMul(p2->a - p1->a, p2->a - p1->a);
|
||||
return FixedSqrt(xs + ys + zs + za);
|
||||
}
|
||||
|
||||
fixed_t FV3_Magnitude(const vector3_t *a_normal)
|
||||
{
|
||||
fixed_t xs = FixedMul(a_normal->x, a_normal->x);
|
||||
|
|
@ -341,6 +442,15 @@ fixed_t FV3_Magnitude(const vector3_t *a_normal)
|
|||
return FixedSqrt(xs + ys + zs);
|
||||
}
|
||||
|
||||
fixed_t FV4_Magnitude(const vector4_t *a_normal)
|
||||
{
|
||||
fixed_t xs = FixedMul(a_normal->x, a_normal->x);
|
||||
fixed_t ys = FixedMul(a_normal->y, a_normal->y);
|
||||
fixed_t zs = FixedMul(a_normal->z, a_normal->z);
|
||||
fixed_t as = FixedMul(a_normal->a, a_normal->a);
|
||||
return FixedSqrt(xs + ys + zs + as);
|
||||
}
|
||||
|
||||
// Also returns the magnitude
|
||||
fixed_t FV3_NormalizeEx(const vector3_t *a_normal, vector3_t *a_o)
|
||||
{
|
||||
|
|
@ -351,11 +461,26 @@ fixed_t FV3_NormalizeEx(const vector3_t *a_normal, vector3_t *a_o)
|
|||
return magnitude;
|
||||
}
|
||||
|
||||
fixed_t FV4_NormalizeEx(const vector4_t *a_normal, vector4_t *a_o)
|
||||
{
|
||||
fixed_t magnitude = FV4_Magnitude(a_normal);
|
||||
a_o->x = FixedDiv(a_normal->x, magnitude);
|
||||
a_o->y = FixedDiv(a_normal->y, magnitude);
|
||||
a_o->z = FixedDiv(a_normal->z, magnitude);
|
||||
a_o->a = FixedDiv(a_normal->a, magnitude);
|
||||
return magnitude;
|
||||
}
|
||||
|
||||
fixed_t FV3_Normalize(vector3_t *a_normal)
|
||||
{
|
||||
return FV3_NormalizeEx(a_normal, a_normal);
|
||||
}
|
||||
|
||||
fixed_t FV4_Normalize(vector4_t *a_normal)
|
||||
{
|
||||
return FV4_NormalizeEx(a_normal, a_normal);
|
||||
}
|
||||
|
||||
vector3_t *FV3_NegateEx(const vector3_t *a_1, vector3_t *a_o)
|
||||
{
|
||||
a_o->x = -a_1->x;
|
||||
|
|
@ -364,11 +489,25 @@ vector3_t *FV3_NegateEx(const vector3_t *a_1, vector3_t *a_o)
|
|||
return a_o;
|
||||
}
|
||||
|
||||
vector4_t *FV4_NegateEx(const vector4_t *a_1, vector4_t *a_o)
|
||||
{
|
||||
a_o->x = -a_1->x;
|
||||
a_o->y = -a_1->y;
|
||||
a_o->z = -a_1->z;
|
||||
a_o->a = -a_1->a;
|
||||
return a_o;
|
||||
}
|
||||
|
||||
vector3_t *FV3_Negate(vector3_t *a_1)
|
||||
{
|
||||
return FV3_NegateEx(a_1, a_1);
|
||||
}
|
||||
|
||||
vector4_t *FV4_Negate(vector4_t *a_1)
|
||||
{
|
||||
return FV4_NegateEx(a_1, a_1);
|
||||
}
|
||||
|
||||
boolean FV3_Equal(const vector3_t *a_1, const vector3_t *a_2)
|
||||
{
|
||||
fixed_t Epsilon = FRACUNIT / FRACUNIT;
|
||||
|
|
@ -383,11 +522,31 @@ boolean FV3_Equal(const vector3_t *a_1, const vector3_t *a_2)
|
|||
return false;
|
||||
}
|
||||
|
||||
boolean FV4_Equal(const vector4_t *a_1, const vector4_t *a_2)
|
||||
{
|
||||
fixed_t Epsilon = FRACUNIT / FRACUNIT;
|
||||
|
||||
if ((abs(a_2->x - a_1->x) > Epsilon) ||
|
||||
(abs(a_2->y - a_1->y) > Epsilon) ||
|
||||
(abs(a_2->z - a_1->z) > Epsilon) ||
|
||||
(abs(a_2->a - a_1->a) > Epsilon))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
fixed_t FV3_Dot(const vector3_t *a_1, const vector3_t *a_2)
|
||||
{
|
||||
return (FixedMul(a_1->x, a_2->x) + FixedMul(a_1->y, a_2->y) + FixedMul(a_1->z, a_2->z));
|
||||
}
|
||||
|
||||
fixed_t FV4_Dot(const vector4_t *a_1, const vector4_t *a_2)
|
||||
{
|
||||
return (FixedMul(a_1->x, a_2->x) + FixedMul(a_1->y, a_2->y) + FixedMul(a_1->z, a_2->z) + FixedMul(a_1->a, a_2->a));
|
||||
}
|
||||
|
||||
vector3_t *FV3_Cross(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a_o)
|
||||
{
|
||||
a_o->x = FixedMul(a_1->y, a_2->z) - FixedMul(a_1->z, a_2->y);
|
||||
|
|
@ -424,8 +583,9 @@ vector3_t *FV3_ClosestPointOnLine(const vector3_t *Line, const vector3_t *p, vec
|
|||
return FV3_Copy(out, &Line[1]);
|
||||
}
|
||||
|
||||
// Return the point between <20>Line[0]<5D> and <20>Line[1]<5D>
|
||||
FV3_Mul(&V, t);
|
||||
// Return the point between "Line[0]" and "Line[1]"
|
||||
vector3_t T = { t, t, t };
|
||||
FV3_Mul(&V, &T);
|
||||
|
||||
return FV3_AddEx(&Line[0], &V, out);
|
||||
}
|
||||
|
|
@ -440,7 +600,8 @@ void FV3_ClosestPointOnVector(const vector3_t *dir, const vector3_t *p, vector3_
|
|||
fixed_t t = FV3_Dot(dir, p);
|
||||
|
||||
// Return the point on the line closest
|
||||
FV3_MulEx(dir, t, out);
|
||||
vector3_t T = { t, t, t };
|
||||
FV3_MulEx(dir, &T, out);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -782,7 +943,7 @@ void FM_CreateObjectMatrix(matrix_t *matrix, fixed_t x, fixed_t y, fixed_t z, fi
|
|||
//
|
||||
// Multiplies a vector by the specified matrix
|
||||
//
|
||||
void FM_MultMatrixVec3(const matrix_t *matrix, const vector3_t *vec, vector3_t *out)
|
||||
const vector3_t *FM_MultMatrixVec3(const matrix_t *matrix, const vector3_t *vec, vector3_t *out)
|
||||
{
|
||||
#define M(row,col) matrix->m[col * 4 + row]
|
||||
out->x = FixedMul(vec->x, M(0, 0))
|
||||
|
|
@ -800,6 +961,34 @@ void FM_MultMatrixVec3(const matrix_t *matrix, const vector3_t *vec, vector3_t *
|
|||
+ FixedMul(vec->z, M(2, 2))
|
||||
+ M(2, 3);
|
||||
#undef M
|
||||
return out;
|
||||
}
|
||||
|
||||
const vector4_t *FM_MultMatrixVec4(const matrix_t *matrix, const vector4_t *vec, vector4_t *out)
|
||||
{
|
||||
#define M(row,col) matrix->m[col * 4 + row]
|
||||
out->x = FixedMul(vec->x, M(0, 0))
|
||||
+ FixedMul(vec->y, M(0, 1))
|
||||
+ FixedMul(vec->z, M(0, 2))
|
||||
+ FixedMul(vec->a, M(0, 3));
|
||||
|
||||
out->y = FixedMul(vec->x, M(1, 0))
|
||||
+ FixedMul(vec->y, M(1, 1))
|
||||
+ FixedMul(vec->z, M(1, 2))
|
||||
+ FixedMul(vec->a, M(1, 3));
|
||||
|
||||
out->z = FixedMul(vec->x, M(2, 0))
|
||||
+ FixedMul(vec->y, M(2, 1))
|
||||
+ FixedMul(vec->z, M(2, 2))
|
||||
+ FixedMul(vec->a, M(2, 3));
|
||||
|
||||
|
||||
out->a = FixedMul(vec->x, M(3, 0))
|
||||
+ FixedMul(vec->y, M(3, 1))
|
||||
+ FixedMul(vec->z, M(3, 2))
|
||||
+ FixedMul(vec->a, M(3, 3));
|
||||
#undef M
|
||||
return out;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -807,13 +996,12 @@ void FM_MultMatrixVec3(const matrix_t *matrix, const vector3_t *vec, vector3_t *
|
|||
//
|
||||
// Multiples one matrix into another
|
||||
//
|
||||
void FM_MultMatrix(matrix_t *dest, const matrix_t *multme)
|
||||
void FM_MultMatrixEx(const matrix_t *m1, const matrix_t *m2, matrix_t *dest)
|
||||
{
|
||||
matrix_t result;
|
||||
UINT8 i, j;
|
||||
#define M(row,col) multme->m[col * 4 + row]
|
||||
#define D(row,col) dest->m[col * 4 + row]
|
||||
#define R(row,col) result.m[col * 4 + row]
|
||||
#define M(row,col) m1->m[col * 4 + row]
|
||||
#define D(row,col) m2->m[col * 4 + row]
|
||||
#define R(row,col) dest->m[col * 4 + row]
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
|
|
@ -821,13 +1009,16 @@ void FM_MultMatrix(matrix_t *dest, const matrix_t *multme)
|
|||
R(i, j) = FixedMul(D(i, 0), M(0, j)) + FixedMul(D(i, 1), M(1, j)) + FixedMul(D(i, 2), M(2, j)) + FixedMul(D(i, 3), M(3, j));
|
||||
}
|
||||
|
||||
M_Memcpy(dest, &result, sizeof(matrix_t));
|
||||
|
||||
#undef R
|
||||
#undef D
|
||||
#undef M
|
||||
}
|
||||
|
||||
void FM_MultMatrix(matrix_t *dest, const matrix_t *multme)
|
||||
{
|
||||
FM_MultMatrixEx(dest, multme, dest);
|
||||
}
|
||||
|
||||
//
|
||||
// Translate
|
||||
//
|
||||
|
|
|
|||
|
|
@ -299,10 +299,10 @@ vector3_t *FV3_AddEx(const vector3_t *a_i, const vector3_t *a_c, vector3_t *a_o)
|
|||
vector3_t *FV3_Add(vector3_t *a_i, const vector3_t *a_c);
|
||||
vector3_t *FV3_SubEx(const vector3_t *a_i, const vector3_t *a_c, vector3_t *a_o);
|
||||
vector3_t *FV3_Sub(vector3_t *a_i, const vector3_t *a_c);
|
||||
vector3_t *FV3_MulEx(const vector3_t *a_i, fixed_t a_c, vector3_t *a_o);
|
||||
vector3_t *FV3_Mul(vector3_t *a_i, fixed_t a_c);
|
||||
vector3_t *FV3_DivideEx(const vector3_t *a_i, fixed_t a_c, vector3_t *a_o);
|
||||
vector3_t *FV3_Divide(vector3_t *a_i, fixed_t a_c);
|
||||
vector3_t *FV3_MulEx(const vector3_t *a_i, const vector3_t *a_c, vector3_t *a_o);
|
||||
vector3_t *FV3_Mul(vector3_t *a_i, const vector3_t *a_c);
|
||||
vector3_t *FV3_DivideEx(const vector3_t *a_i, const vector3_t *a_c, vector3_t *a_o);
|
||||
vector3_t *FV3_Divide(vector3_t *a_i, const vector3_t *a_c);
|
||||
vector3_t *FV3_Midpoint(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a_o);
|
||||
fixed_t FV3_Distance(const vector3_t *p1, const vector3_t *p2);
|
||||
fixed_t FV3_Magnitude(const vector3_t *a_normal);
|
||||
|
|
@ -327,6 +327,32 @@ vector3_t *FV3_IntersectionPoint(const vector3_t *vNormal, const vector3_t *vLin
|
|||
UINT8 FV3_PointOnLineSide(const vector3_t *point, const vector3_t *line);
|
||||
boolean FV3_PointInsideBox(const vector3_t *point, const vector3_t *box);
|
||||
|
||||
struct vector4_t
|
||||
{
|
||||
fixed_t x, y, z, a;
|
||||
};
|
||||
|
||||
vector4_t *FV4_Load(vector4_t *vec, fixed_t x, fixed_t y, fixed_t z, fixed_t a);
|
||||
vector4_t *FV4_UnLoad(vector4_t *vec, fixed_t *x, fixed_t *y, fixed_t *z, fixed_t *a);
|
||||
vector4_t *FV4_Copy(vector4_t *a_o, const vector4_t *a_i);
|
||||
vector4_t *FV4_AddEx(const vector4_t *a_i, const vector4_t *a_c, vector4_t *a_o);
|
||||
vector4_t *FV4_Add(vector4_t *a_i, const vector4_t *a_c);
|
||||
vector4_t *FV4_SubEx(const vector4_t *a_i, const vector4_t *a_c, vector4_t *a_o);
|
||||
vector4_t *FV4_Sub(vector4_t *a_i, const vector4_t *a_c);
|
||||
vector4_t *FV4_MulEx(const vector4_t *a_i, const vector4_t *a_c, vector4_t *a_o);
|
||||
vector4_t *FV4_Mul(vector4_t *a_i, const vector4_t *a_c);
|
||||
vector4_t *FV4_DivideEx(const vector4_t *a_i, const vector4_t *a_c, vector4_t *a_o);
|
||||
vector4_t *FV4_Divide(vector4_t *a_i, const vector4_t *a_c);
|
||||
vector4_t *FV4_Midpoint(const vector4_t *a_1, const vector4_t *a_2, vector4_t *a_o);
|
||||
fixed_t FV4_Distance(const vector4_t *p1, const vector4_t *p2);
|
||||
fixed_t FV4_Magnitude(const vector4_t *a_normal);
|
||||
fixed_t FV4_NormalizeEx(const vector4_t *a_normal, vector4_t *a_o);
|
||||
fixed_t FV4_Normalize(vector4_t *a_normal);
|
||||
vector4_t *FV4_NegateEx(const vector4_t *a_1, vector4_t *a_o);
|
||||
vector4_t *FV4_Negate(vector4_t *a_1);
|
||||
boolean FV4_Equal(const vector4_t *a_1, const vector4_t *a_2);
|
||||
fixed_t FV4_Dot(const vector4_t *a_1, const vector4_t *a_2);
|
||||
|
||||
struct matrix_t
|
||||
{
|
||||
fixed_t m[16];
|
||||
|
|
@ -334,8 +360,10 @@ struct matrix_t
|
|||
|
||||
void FM_LoadIdentity(matrix_t* matrix);
|
||||
void FM_CreateObjectMatrix(matrix_t *matrix, fixed_t x, fixed_t y, fixed_t z, fixed_t anglex, fixed_t angley, fixed_t anglez, fixed_t upx, fixed_t upy, fixed_t upz, fixed_t radius);
|
||||
void FM_MultMatrixVec3(const matrix_t *matrix, const vector3_t *vec, vector3_t *out);
|
||||
const vector3_t *FM_MultMatrixVec3(const matrix_t *matrix, const vector3_t *vec, vector3_t *out);
|
||||
const vector4_t *FM_MultMatrixVec4(const matrix_t *matrix, const vector4_t *vec, vector4_t *out);
|
||||
void FM_MultMatrix(matrix_t *dest, const matrix_t *multme);
|
||||
void FM_MultMatrixEx(const matrix_t *m1, const matrix_t *m2, matrix_t *dest);
|
||||
void FM_Translate(matrix_t *dest, fixed_t x, fixed_t y, fixed_t z);
|
||||
void FM_Scale(matrix_t *dest, fixed_t x, fixed_t y, fixed_t z);
|
||||
|
||||
|
|
|
|||
928
src/m_menu.c
928
src/m_menu.c
File diff suppressed because it is too large
Load diff
15
src/m_menu.h
15
src/m_menu.h
|
|
@ -302,6 +302,7 @@ INT32 MR_Retry(INT32 choice);
|
|||
INT32 MR_EndGame(INT32 choice);
|
||||
INT32 MR_MapChange(INT32 choice);
|
||||
INT32 MR_SetupMultiPlayer(INT32 choice);
|
||||
INT32 MR_HandleSetupMultiPlayerMenu(INT32 choice);
|
||||
INT32 MR_ConfirmSpectate(INT32 choice);
|
||||
INT32 MR_ConfirmEnterGame(INT32 choice);
|
||||
INT32 MR_ConfirmTeamScramble(INT32 choice);
|
||||
|
|
@ -339,6 +340,12 @@ void MD_DrawReplayHut(void);
|
|||
void MD_DrawTimeAttackMenu(void);
|
||||
void MD_DrawMPMainMenu(void);
|
||||
void MD_DrawSetupMultiPlayerMenu(void);
|
||||
void MD_DrawCssStatBacker(void);
|
||||
void MD_DrawCssStatBars(void);
|
||||
void MD_DrawCssColourBar(void);
|
||||
void MD_DrawCssCharacter(void);
|
||||
void MD_DrawBarCssSelector(void);
|
||||
void MD_DrawGridCssSelector(void);
|
||||
void MD_DrawConnectMenu(void);
|
||||
void MD_DrawVideoMode(void);
|
||||
void MD_DrawAddons(void);
|
||||
|
|
@ -353,6 +360,8 @@ void MD_DrawViewServer(void);
|
|||
void MD_DrawDiscordRequests(void);
|
||||
#endif
|
||||
|
||||
INT32 MapGridSelectToSkin(INT32 column, INT32 row);
|
||||
|
||||
// Maybe this goes here????? Who knows.
|
||||
boolean M_MouseNeeded(void);
|
||||
|
||||
|
|
@ -413,6 +422,7 @@ extern consvar_t cv_dummygpdifficulty, cv_dummygpencore, cv_dummygpcup;
|
|||
extern consvar_t cv_dummymenuplayer, cv_dummyteam, cv_dummyspectate, cv_dummyscramble;
|
||||
extern consvar_t cv_dummyattackingrings, cv_dummyattackingstacking, cv_dummyattackingchaining;
|
||||
extern consvar_t cv_dummyattackingslipdash, cv_dummyattackingpurpledrift, cv_dummyattackingslopeboost;
|
||||
extern consvar_t cv_dummyattackingairdrop, cv_dummyattackingbumpspark;
|
||||
extern consvar_t cv_dummystaff;
|
||||
extern consvar_t cv_dummymultiplayer, cv_dummyip, cv_dummyname, cv_dummyfollower, cv_dummycolor;
|
||||
extern consvar_t cv_dummyserverpage;
|
||||
|
|
@ -461,6 +471,9 @@ fixed_t M_GetMapThumbnail(INT16 mapnum, patch_t **out);
|
|||
// Moviemode menu updating
|
||||
void Moviemode_option_Onchange(void);
|
||||
|
||||
void Skinsort_option_Onchange(void);
|
||||
void Skinselectstyle_option_Onchange(void);
|
||||
|
||||
// Player Setup menu colors linked list
|
||||
struct menucolor_t {
|
||||
menucolor_t *next;
|
||||
|
|
@ -478,6 +491,8 @@ UINT16 M_GetColorAfter(UINT16 color);
|
|||
void M_InitPlayerSetupColors(void);
|
||||
void M_FreePlayerSetupColors(void);
|
||||
|
||||
extern boolean menu_text_input;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1303,7 +1303,7 @@ void M_SaveFrame(void)
|
|||
{
|
||||
// munge planar buffer to linear
|
||||
linear = screens[2];
|
||||
I_ReadScreen(linear);
|
||||
I_ReadScreen(linear, 1);
|
||||
}
|
||||
#ifdef HWRENDER
|
||||
else
|
||||
|
|
@ -1576,6 +1576,7 @@ void M_DoScreenShot(void)
|
|||
char pathname[MAX_WADPATH];
|
||||
boolean ret = false;
|
||||
UINT8 *linear = NULL;
|
||||
UINT8 *palette;
|
||||
|
||||
// Don't take multiple screenshots, obviously
|
||||
takescreenshot = false;
|
||||
|
|
@ -1608,30 +1609,30 @@ void M_DoScreenShot(void)
|
|||
freename = Newsnapshotfile(pathname,"tga");
|
||||
#endif
|
||||
|
||||
if (!freename)
|
||||
goto failure;
|
||||
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
// munge planar buffer to linear
|
||||
linear = screens[2];
|
||||
I_ReadScreen(linear);
|
||||
}
|
||||
|
||||
if (!freename)
|
||||
goto failure;
|
||||
|
||||
// save the pcx file
|
||||
#ifdef HWRENDER
|
||||
if (rendermode == render_opengl)
|
||||
ret = HWR_Screenshot(va(pandf,pathname,freename));
|
||||
else
|
||||
#endif
|
||||
{
|
||||
I_ReadScreen(linear, 1);
|
||||
M_CreateScreenShotPalette();
|
||||
#ifdef USE_PNG
|
||||
ret = M_SavePNG(va(pandf,pathname,freename), linear, vid.width, vid.height, screenshot_palette);
|
||||
#else
|
||||
ret = WritePCXfile(va(pandf,pathname,freename), linear, vid.width, vid.height, screenshot_palette);
|
||||
#endif
|
||||
palette = screenshot_palette;
|
||||
}
|
||||
#ifdef HWRENDER
|
||||
else if (rendermode == render_opengl)
|
||||
{
|
||||
linear = HWR_GetScreenshot(1);
|
||||
palette = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_PNG
|
||||
ret = M_SavePNG(va(pandf,pathname,freename), linear, vid.width, vid.height, palette);
|
||||
#else
|
||||
ret = WritePCXfile(va(pandf,pathname,freename), linear, vid.width, vid.height, palette);
|
||||
#endif
|
||||
|
||||
failure:
|
||||
if (ret)
|
||||
|
|
|
|||
|
|
@ -431,68 +431,75 @@ static void M_DrawTickStats(void)
|
|||
perfstatcol_t detailed_thinkercount_col2 = {94, 119, V_BLUEMAP, detailed_thinkercount_row2};
|
||||
perfstatcol_t misc_calls_col = {170, 216, V_PURPLEMAP, misc_calls_row};
|
||||
|
||||
for (i = 0; i < NUM_THINKERLISTS; i++)
|
||||
if (G_GamestateUsesLevel())
|
||||
{
|
||||
for (thinker = thlist[i].next; thinker != &thlist[i]; thinker = thinker->next)
|
||||
for (i = 0; i < NUM_THINKERLISTS; i++)
|
||||
{
|
||||
thinkercount++;
|
||||
if (thinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
removecount++;
|
||||
else if (i == THINK_POLYOBJ)
|
||||
polythcount++;
|
||||
else if (i == THINK_MAIN)
|
||||
mainthcount++;
|
||||
else if (i == THINK_MOBJ)
|
||||
for (thinker = thlist[i].next; thinker != &thlist[i]; thinker = thinker->next)
|
||||
{
|
||||
if (thinker->function.acp1 == (actionf_p1)P_MobjThinker)
|
||||
thinkercount++;
|
||||
if (thinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
removecount++;
|
||||
else if (i == THINK_POLYOBJ)
|
||||
polythcount++;
|
||||
else if (i == THINK_MAIN)
|
||||
mainthcount++;
|
||||
else if (i == THINK_MOBJ)
|
||||
{
|
||||
mobj_t *mobj = (mobj_t*)thinker;
|
||||
mobjcount++;
|
||||
if (mobj->flags & MF_NOTHINK)
|
||||
nothinkcount++;
|
||||
else if (mobj->flags & MF_SCENERY)
|
||||
scenerycount++;
|
||||
else
|
||||
regularcount++;
|
||||
if (thinker->function.acp1 == (actionf_p1)P_MobjThinker)
|
||||
{
|
||||
mobj_t *mobj = (mobj_t*)thinker;
|
||||
mobjcount++;
|
||||
if (mobj->flags & MF_NOTHINK)
|
||||
nothinkcount++;
|
||||
else if (mobj->flags & MF_SCENERY)
|
||||
scenerycount++;
|
||||
else
|
||||
regularcount++;
|
||||
}
|
||||
}
|
||||
else if (i == THINK_DYNSLOPE)
|
||||
dynslopethcount++;
|
||||
else if (i == THINK_PRECIP)
|
||||
precipcount++;
|
||||
}
|
||||
else if (i == THINK_DYNSLOPE)
|
||||
dynslopethcount++;
|
||||
else if (i == THINK_PRECIP)
|
||||
precipcount++;
|
||||
}
|
||||
}
|
||||
|
||||
draw_row = 10;
|
||||
M_DrawPerfTiming(&tictime_col);
|
||||
M_DrawPerfTiming(&thinker_time_col);
|
||||
M_DrawPerfTiming(&detailed_thinker_time_col);
|
||||
if (server)
|
||||
M_DrawPerfTiming(&bot_time_col);
|
||||
M_DrawPerfTiming(&extra_thinker_time_col);
|
||||
|
||||
draw_row = 10;
|
||||
M_DrawPerfCount(&thinkercount_col);
|
||||
M_DrawPerfCount(&detailed_thinkercount_col);
|
||||
M_DrawPerfCount(&mobjthinkercount_col);
|
||||
|
||||
if (nothinkcount)
|
||||
M_DrawPerfCount(¬hinkcount_col);
|
||||
|
||||
M_DrawPerfCount(&detailed_thinkercount_col2);
|
||||
|
||||
if (M_HighResolution())
|
||||
if (G_GamestateUsesLevel())
|
||||
{
|
||||
V_DrawSmallString(212, 10, V_MONOSPACE | V_ALLOWLOWERCASE | V_PURPLEMAP, "Calls:");
|
||||
M_DrawPerfTiming(&thinker_time_col);
|
||||
M_DrawPerfTiming(&detailed_thinker_time_col);
|
||||
if (server)
|
||||
M_DrawPerfTiming(&bot_time_col);
|
||||
M_DrawPerfTiming(&extra_thinker_time_col);
|
||||
|
||||
draw_row = 15;
|
||||
}
|
||||
else
|
||||
{
|
||||
draw_row = 10;
|
||||
}
|
||||
M_DrawPerfCount(&thinkercount_col);
|
||||
M_DrawPerfCount(&detailed_thinkercount_col);
|
||||
M_DrawPerfCount(&mobjthinkercount_col);
|
||||
|
||||
M_DrawPerfCount(&misc_calls_col);
|
||||
if (nothinkcount)
|
||||
M_DrawPerfCount(¬hinkcount_col);
|
||||
|
||||
M_DrawPerfCount(&detailed_thinkercount_col2);
|
||||
|
||||
|
||||
if (M_HighResolution())
|
||||
{
|
||||
V_DrawSmallString(212, 10, V_MONOSPACE | V_ALLOWLOWERCASE | V_PURPLEMAP, "Calls:");
|
||||
|
||||
draw_row = 15;
|
||||
}
|
||||
else
|
||||
{
|
||||
draw_row = 10;
|
||||
}
|
||||
|
||||
M_DrawPerfCount(&misc_calls_col);
|
||||
}
|
||||
}
|
||||
|
||||
void M_DrawPerfStats(void)
|
||||
|
|
|
|||
|
|
@ -382,7 +382,7 @@ static boolean M_TextInputHandleBase(textinput_t *input, INT32 key, boolean emot
|
|||
key = '/';
|
||||
|
||||
// same capslock code as hu_stuff.c's HU_responder. Check there for details.
|
||||
key = /*cv_keyboardlayout.value == 3 ? CON_ShitAndAltGrChar(key) : */CON_ShiftChar(key);
|
||||
key = CON_ShiftChar(key);
|
||||
|
||||
// enter a char into the command prompt
|
||||
if (key < 32 || key > 127)
|
||||
|
|
|
|||
|
|
@ -67,7 +67,8 @@ static CV_PossibleValue_t masterserver_update_rate_cons_t[] = {
|
|||
{0, NULL}
|
||||
};
|
||||
|
||||
consvar_t cv_masterserver = CVAR_INIT ("masterserver", "https://ms.kartkrew.org/ms/api", CV_SAVE|CV_CALL, NULL, MasterServer_OnChange);
|
||||
//https://ms.kartkrew.org/ms/api
|
||||
consvar_t cv_masterserver = CVAR_INIT ("masterserver", "https://ms.srb2classic.net/MS/1", CV_SAVE|CV_CALL, NULL, MasterServer_OnChange);
|
||||
consvar_t cv_rendezvousserver = CVAR_INIT ("holepunchserver", "relay.kartkrew.org", CV_SAVE, NULL, NULL);
|
||||
consvar_t cv_servername = CVAR_INIT ("servername", "SRB2Kart server", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Update_parameters);
|
||||
consvar_t cv_server_contact = CVAR_INIT ("server_contact", "", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Update_parameters);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// BLANKART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2023 by James R.
|
||||
// Copyright (C) 2023 by Kart Krew
|
||||
// Copyright (C) 2025 by James Robert Roman
|
||||
// Copyright (C) 2025 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
|
|
@ -180,10 +180,8 @@ Obj_InitLoopEndpoint
|
|||
void
|
||||
Obj_InitLoopCenter (mobj_t *center)
|
||||
{
|
||||
const mapthing_t *mt = center->spawnpoint;
|
||||
|
||||
center_max_revolution(center) = mt->args[1] * FRACUNIT / 360;
|
||||
center_set_flip(center, mt->args[0]);
|
||||
center_max_revolution(center) = center->args[1] * FRACUNIT / 360;
|
||||
center_set_flip(center, center->args[0]);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -260,7 +258,7 @@ Obj_LoopEndpointCollide
|
|||
const fixed_t magnitude = R_PointToDist2(0, 0, px, py);
|
||||
const fixed_t newX = FixedDiv(px, magnitude);
|
||||
const fixed_t newY = FixedDiv(py, magnitude);
|
||||
|
||||
|
||||
s->origin_shift = {FixedMul(newX, FCOS(anchor->angle)),
|
||||
FixedMul(newY, FSIN(anchor->angle))};
|
||||
}
|
||||
|
|
@ -285,15 +283,15 @@ Obj_LoopEndpointCollide
|
|||
cam->enter_tic = leveltime;
|
||||
cam->exit_tic = INFTICS;
|
||||
|
||||
if (center->spawnpoint->args[4]) // is camera distance set?
|
||||
if (center->args[4]) // is camera distance set?
|
||||
{
|
||||
cam->zoom_out_speed = center->spawnpoint->args[2];
|
||||
cam->zoom_in_speed = center->spawnpoint->args[3];
|
||||
cam->dist = center->spawnpoint->args[4] * FRACUNIT;
|
||||
cam->pan = FixedAngle(center->spawnpoint->args[5] * FRACUNIT);
|
||||
cam->pan_speed = center->spawnpoint->args[6] * FRACUNIT;
|
||||
cam->pan_accel = center->spawnpoint->args[7];
|
||||
cam->pan_back = center->spawnpoint->args[8];
|
||||
cam->zoom_out_speed = center->args[2];
|
||||
cam->zoom_in_speed = center->args[3];
|
||||
cam->dist = center->args[4] * FRACUNIT;
|
||||
cam->pan = FixedAngle(center->args[5] * FRACUNIT);
|
||||
cam->pan_speed = center->args[6] * FRACUNIT;
|
||||
cam->pan_accel = center->args[7];
|
||||
cam->pan_back = center->args[8];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
229
src/p_deepcopy.cpp
Normal file
229
src/p_deepcopy.cpp
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2024 by Sally "TehRealSalt" Cochenour
|
||||
// Copyright (C) 2024 by Kart Krew
|
||||
//
|
||||
// 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 p_deepcopy.cpp
|
||||
/// \brief Methods for deep copying
|
||||
|
||||
#include "p_deepcopy.h"
|
||||
|
||||
#include "typedef.h"
|
||||
#include "z_zone.h"
|
||||
#include "taglist.h"
|
||||
#include "r_defs.h"
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void P_DeepCopy(Type *target, Type *source, void (*callback)(Type *, Type *))
|
||||
|
||||
Make a deep copy of a struct, by using memcpy
|
||||
for an initial shallow copy, and a callback
|
||||
function to handle any memory addresses.
|
||||
|
||||
Input Arguments:-
|
||||
Type: The type of the structs.
|
||||
target: The struct to copy into.
|
||||
source: The struct to copy from.
|
||||
callback: A callback function, intended to replace
|
||||
pointers after the initial shallow copy.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
|
||||
template <typename Type>
|
||||
static void P_DeepCopy(Type *target, Type *source, void (*callback)(Type *, Type *))
|
||||
{
|
||||
memcpy(target, source, sizeof(Type));
|
||||
|
||||
if (callback != nullptr)
|
||||
{
|
||||
callback(target, source);
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void P_DeepCopyArray(Type **target_array, Type **source_array, size_t source_len, void (*callback)(Type *, Type *))
|
||||
|
||||
Make a deep copy of an array of structs, by using
|
||||
memcpy for an initial shallow copy, and a callback
|
||||
function to handle any memory addresses for each
|
||||
individual struct.
|
||||
|
||||
Input Arguments:-
|
||||
Type: The type of the structs.
|
||||
target_array: The start of the array to copy into.
|
||||
This will be allocated by this function, so
|
||||
it should be freed beforehand.
|
||||
source_array: The start of the array to copy from.
|
||||
source_len: The length of the array to copy from.
|
||||
callback: A callback function, intended to replace
|
||||
pointers after the initial shallow copy.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
|
||||
template <typename Type>
|
||||
static void P_DeepCopyArray(Type **target_array, Type **source_array, size_t source_len, void (*callback)(Type *, Type *))
|
||||
{
|
||||
const size_t source_total = source_len * sizeof(Type);
|
||||
|
||||
*target_array = static_cast<Type *>(Z_Calloc(source_total, PU_LEVEL, nullptr));
|
||||
memcpy(*target_array, *source_array, source_total);
|
||||
|
||||
if (callback != nullptr)
|
||||
{
|
||||
for (size_t i = 0; i < source_len; i++)
|
||||
{
|
||||
Type *target = &(*target_array)[i];
|
||||
Type *source = &(*source_array)[i];
|
||||
|
||||
callback(target, source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void copy_taglist_tags(taglist_t *target, taglist_t *source)
|
||||
|
||||
Make a deep copy of taglist's tags fields.
|
||||
Used as a helper function for other callbacks,
|
||||
does not work as a full deep copy of taglist_t
|
||||
on its own.
|
||||
|
||||
Input Arguments:-
|
||||
target: The struct to copy into.
|
||||
source: The struct to copy from.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
|
||||
static void copy_taglist_tags(taglist_t *target, taglist_t *source)
|
||||
{
|
||||
if (source->count)
|
||||
{
|
||||
target->tags = static_cast<mtag_t *>(
|
||||
memcpy(
|
||||
Z_Malloc(
|
||||
source->count * sizeof(mtag_t),
|
||||
PU_LEVEL,
|
||||
nullptr
|
||||
),
|
||||
source->tags,
|
||||
source->count * sizeof(mtag_t)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void copy_sector_callback(sector_t *target, sector_t *source)
|
||||
|
||||
Handles memory addresses after creating a shallow copy
|
||||
of a sector_t, to turn it into a deep copy.
|
||||
|
||||
Input Arguments:-
|
||||
target: The struct to copy into.
|
||||
source: The struct to copy from.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
|
||||
static void copy_sector_callback(sector_t *target, sector_t *source)
|
||||
{
|
||||
// (Not a true deep copy until all of the memory addresses are accounted for.)
|
||||
copy_taglist_tags(&target->tags, &source->tags);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void P_DeepCopySector(sector_t *target, sector_t *source)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
|
||||
void P_DeepCopySector(sector_t *target, sector_t *source)
|
||||
{
|
||||
P_DeepCopy<sector_t>(target, source, copy_sector_callback);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void P_DeepCopySectors(sector_t **target_array, sector_t **source_array, size_t source_len)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
|
||||
void P_DeepCopySectors(sector_t **target_array, sector_t **source_array, size_t source_len)
|
||||
{
|
||||
P_DeepCopyArray<sector_t>(target_array, source_array, source_len, copy_sector_callback);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void copy_line_callback(line_t *target, line_t *source)
|
||||
|
||||
Handles memory addresses after creating a shallow copy
|
||||
of a line_t, to turn it into a deep copy.
|
||||
|
||||
Input Arguments:-
|
||||
target: The struct to copy into.
|
||||
source: The struct to copy from.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
|
||||
static void copy_line_callback(line_t *target, line_t *source)
|
||||
{
|
||||
// (Not a true deep copy until all of the memory addresses are accounted for.)
|
||||
copy_taglist_tags(&target->tags, &source->tags);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void P_DeepCopyLine(line_t *target, line_t *source)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
|
||||
void P_DeepCopyLine(line_t *target, line_t *source)
|
||||
{
|
||||
P_DeepCopy<line_t>(target, source, copy_line_callback);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void P_DeepCopyLines(line_t **target_array, line_t **source_array, size_t source_len)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
|
||||
void P_DeepCopyLines(line_t **target_array, line_t **source_array, size_t source_len)
|
||||
{
|
||||
P_DeepCopyArray<line_t>(target_array, source_array, source_len, copy_line_callback);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void P_DeepCopySide(line_t *target, line_t *source)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
|
||||
void P_DeepCopySide(side_t *target, side_t *source)
|
||||
{
|
||||
P_DeepCopy<side_t>(target, source, nullptr); // (Not a true deep copy until all of the memory addresses are accounted for.)
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void P_DeepCopySides(side_t **target_array, side_t **source_array, size_t source_len)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
|
||||
void P_DeepCopySides(side_t **target_array, side_t **source_array, size_t source_len)
|
||||
{
|
||||
P_DeepCopyArray<side_t>(target_array, source_array, source_len, nullptr); // (Not a true deep copy until all of the memory addresses are accounted for.)
|
||||
}
|
||||
131
src/p_deepcopy.h
Normal file
131
src/p_deepcopy.h
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2024 by Sally "TehRealSalt" Cochenour
|
||||
// Copyright (C) 2024 by Kart Krew
|
||||
//
|
||||
// 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 p_deepcopy.h
|
||||
/// \brief Methods for deep copying
|
||||
|
||||
#ifndef __P_DEEPCOPY__
|
||||
#define __P_DEEPCOPY__
|
||||
|
||||
#include "doomdef.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*--------------------------------------------------
|
||||
void P_DeepCopySector(sector_t *target, sector_t *source);
|
||||
|
||||
Make a deep copy of a single sector_t.
|
||||
|
||||
Input Arguments:-
|
||||
target: The struct to copy into.
|
||||
source: The struct to copy from.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
|
||||
void P_DeepCopySector(sector_t *target, sector_t *source);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void P_DeepCopySectors(sector_t **target_array, sector_t **source_array, size_t source_len);
|
||||
|
||||
Make a deep copy of an array of sector_t.
|
||||
|
||||
Input Arguments:-
|
||||
target_array: The start of the array to copy into.
|
||||
This will be allocated by this function, so
|
||||
it should be freed beforehand.
|
||||
source_array: The start of the array to copy from.
|
||||
source_len: The length of the array to copy from.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
|
||||
void P_DeepCopySectors(sector_t **target_array, sector_t **source_array, size_t source_len);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void P_DeepCopyLine(line_t *target, line_t *source)
|
||||
|
||||
Make a deep copy of a single line_t.
|
||||
|
||||
Input Arguments:-
|
||||
target: The struct to copy into.
|
||||
source: The struct to copy from.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
|
||||
void P_DeepCopyLine(line_t *target, line_t *source);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void P_DeepCopyLines(line_t **target_array, line_t **source_array, size_t source_len)
|
||||
|
||||
Make a deep copy of an array of line_t.
|
||||
|
||||
Input Arguments:-
|
||||
target_array: The start of the array to copy into.
|
||||
This will be allocated by this function, so
|
||||
it should be freed beforehand.
|
||||
source_array: The start of the array to copy from.
|
||||
source_len: The length of the array to copy from.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
|
||||
void P_DeepCopyLines(line_t **target_array, line_t **source_array, size_t source_len);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void P_DeepCopySide(line_t *target, line_t *source)
|
||||
|
||||
Make a deep copy of a single side_t.
|
||||
|
||||
Input Arguments:-
|
||||
target: The struct to copy into.
|
||||
source: The struct to copy from.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
|
||||
void P_DeepCopySide(side_t *target, side_t *source);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void P_DeepCopySides(side_t **target_array, side_t **source_array, size_t source_len)
|
||||
|
||||
Make a deep copy of an array of side_t.
|
||||
|
||||
Input Arguments:-
|
||||
target_array: The start of the array to copy into.
|
||||
This will be allocated by this function, so
|
||||
it should be freed beforehand.
|
||||
source_array: The start of the array to copy from.
|
||||
source_len: The length of the array to copy from.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
|
||||
void P_DeepCopySides(side_t **target_array, side_t **source_array, size_t source_len);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __P_DEEPCOPY__
|
||||
160
src/p_enemy.c
160
src/p_enemy.c
|
|
@ -3170,11 +3170,27 @@ void A_AttractChase(mobj_t *actor)
|
|||
if (actor->extravalue1 >= 21)
|
||||
{
|
||||
|
||||
// Base add is 4 tics for 9,9, adds 1 tic for each point closer to the 1,1 end
|
||||
actor->target->player->ringboost += K_GetKartRingPower(actor->target->player, true);
|
||||
actor->target->player->ringtime += K_GetKartRingPower(actor->target->player, true);
|
||||
if (actor->extravalue3 && !P_IsObjectOnGround(actor->target))
|
||||
{
|
||||
actor->target->momz -= (FixedMul(gravity, mapobjectscale))*P_MobjFlip(actor->target);
|
||||
actor->target->player->ringboost += 7;
|
||||
actor->target->player->ringtime += 7;
|
||||
actor->target->player->ringdrop = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Base add is 4 tics for 9,9, adds 1 tic for each point closer to the 1,1 end
|
||||
actor->target->player->ringboost += K_GetKartRingPower(actor->target->player, true);
|
||||
actor->target->player->ringtime += K_GetKartRingPower(actor->target->player, true);
|
||||
}
|
||||
|
||||
S_StartSoundAtVolume(actor->target, sfx_s1b5, actor->target->player->ringvolume);
|
||||
|
||||
if (actor->extravalue3 && !P_IsObjectOnGround(actor->target))
|
||||
{
|
||||
actor->target->momz -= (FixedMul(gravity, mapobjectscale)/2 + FixedMul(gravity, mapobjectscale)/4)*P_MobjFlip(actor->target);
|
||||
}
|
||||
|
||||
if (actor->target->player->rings <= 10)
|
||||
{
|
||||
S_StartSoundAtVolume(actor->target, sfx_ringlw, 255 - actor->target->player->rings*10);
|
||||
|
|
@ -3199,6 +3215,7 @@ void A_AttractChase(mobj_t *actor)
|
|||
( actor->target->height + offz )* P_MobjFlip(actor));
|
||||
actor->extravalue1++;
|
||||
}
|
||||
|
||||
}
|
||||
else // Collecting
|
||||
{
|
||||
|
|
@ -3424,7 +3441,14 @@ void A_FishJump(mobj_t *actor)
|
|||
if (i < MAXPLAYERS)
|
||||
{
|
||||
fixed_t rad = actor->radius>>FRACBITS;
|
||||
P_SpawnMobjFromMobj(actor, P_RandomRange(rad, -rad)<<FRACBITS, P_RandomRange(rad, -rad)<<FRACBITS, 0, (mobjtype_t)locvar2);
|
||||
|
||||
fixed_t rand_x;
|
||||
fixed_t rand_y;
|
||||
|
||||
rand_y = P_RandomRange(rad, -rad)<<FRACBITS;
|
||||
rand_x = P_RandomRange(rad, -rad)<<FRACBITS;
|
||||
|
||||
P_SpawnMobjFromMobj(actor, rand_x, rand_y, 0, (mobjtype_t)locvar2);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3516,7 +3540,7 @@ void A_SignPlayer(mobj_t *actor)
|
|||
|
||||
if (!actor->target->player)
|
||||
return;
|
||||
|
||||
|
||||
// Set the sign to be an appropriate background color for this player's skincolor.
|
||||
actor->color = skincolors[actor->target->player->skincolor].invcolor;
|
||||
actor->frame += skincolors[actor->target->player->skincolor].invshade;
|
||||
|
|
@ -7230,7 +7254,7 @@ void A_StateRangeByParameter(mobj_t *actor)
|
|||
|
||||
if (locvar2 - locvar1 < 0)
|
||||
return; // invalid range
|
||||
|
||||
|
||||
if (udmf)
|
||||
{
|
||||
parameter = actor->args[0];
|
||||
|
|
@ -9673,7 +9697,7 @@ void A_FlickyCenter(mobj_t *actor)
|
|||
return;
|
||||
|
||||
homeRadius = locvar2 ? FixedMul(abs(locvar2), actor->scale) : 384*actor->scale;
|
||||
|
||||
|
||||
if (!actor->tracer)
|
||||
{
|
||||
mobj_t *flicky = P_InternalFlickySpawn(actor, locvar1, 1, false, 0);
|
||||
|
|
@ -10118,11 +10142,16 @@ void A_FlameParticle(mobj_t *actor)
|
|||
|
||||
rad = actor->radius>>FRACBITS;
|
||||
hei = actor->height>>FRACBITS;
|
||||
particle = P_SpawnMobjFromMobj(actor,
|
||||
P_RandomRange(rad, -rad)<<FRACBITS,
|
||||
P_RandomRange(rad, -rad)<<FRACBITS,
|
||||
P_RandomRange(hei/2, hei)<<FRACBITS,
|
||||
type);
|
||||
|
||||
fixed_t rand_x;
|
||||
fixed_t rand_y;
|
||||
fixed_t rand_z;
|
||||
|
||||
rand_z = P_RandomRange(hei/2, hei)<<FRACBITS;
|
||||
rand_y = P_RandomRange(rad, -rad)<<FRACBITS;
|
||||
rand_x = P_RandomRange(rad, -rad)<<FRACBITS;
|
||||
|
||||
particle = P_SpawnMobjFromMobj(actor, rand_x, rand_y, rand_z, type);
|
||||
P_SetObjectMomZ(particle, 2<<FRACBITS, false);
|
||||
}
|
||||
|
||||
|
|
@ -10595,16 +10624,11 @@ void A_ItemPop(mobj_t *actor)
|
|||
remains->flags2 = actor->flags2; // Transfer flags2
|
||||
remains->fuse = actor->fuse; // Transfer respawn timer
|
||||
remains->cvmem = leveltime;
|
||||
remains->threshold = actor->threshold;
|
||||
if (remains->threshold != 69 && remains->threshold != 70)
|
||||
{
|
||||
remains->threshold = 68;
|
||||
}
|
||||
remains->threshold = (actor->threshold == 69 ? 69 : 68);
|
||||
// To insure this information doesn't have to be rediscovered every time you look at this function...
|
||||
// A threshold of 0 is for a "living", ordinary random item.
|
||||
// 68 means regular popped random item debris.
|
||||
// 69 used to mean old Karma Item behaviour (now you can replicate this with MF2_DONTRESPAWN).
|
||||
// 70 is a powered up Overtime item.
|
||||
// 69 means Karmabomb dropped Item behaviour
|
||||
remains->skin = NULL;
|
||||
remains->spawnpoint = actor->spawnpoint;
|
||||
|
||||
|
|
@ -10612,7 +10636,7 @@ void A_ItemPop(mobj_t *actor)
|
|||
|
||||
//if (actor->info->deathsound)
|
||||
//S_StartSound(remains, actor->info->deathsound);
|
||||
|
||||
|
||||
if (!((gametyperules & GTR_BUMPERS) && actor->target->player->bumper <= 0) && !itembreaker)
|
||||
{
|
||||
actor->target->player->itemroulette = KROULETTE_ACTIVE;
|
||||
|
|
@ -10621,7 +10645,7 @@ void A_ItemPop(mobj_t *actor)
|
|||
{
|
||||
K_AwardScaledPlayerRings(actor->target->player, ASR_ITEMBOX);
|
||||
|
||||
if (numgotboxes < 3)
|
||||
if (numtargets < 4)
|
||||
{
|
||||
actor->target->player->itemtype = KITEM_POGOSPRING;
|
||||
actor->target->player->itemamount += 1;
|
||||
|
|
@ -10631,7 +10655,7 @@ void A_ItemPop(mobj_t *actor)
|
|||
remains->flags2 &= ~MF2_AMBUSH;
|
||||
|
||||
// Here at mapload in battle?
|
||||
if ((gametyperules & GTR_BUMPERS) && (actor->flags2 & MF2_BOSSNOTRAP))
|
||||
if (gametyperules & GTR_BUMPERS && actor->threshold != 69)
|
||||
numgotboxes++;
|
||||
|
||||
P_RemoveMobj(actor);
|
||||
|
|
@ -10695,8 +10719,15 @@ void A_JawzExplode(mobj_t *actor)
|
|||
{
|
||||
INT32 speed, speed2;
|
||||
|
||||
truc = P_SpawnMobj(actor->x + P_RandomRange(-8, 8)*FRACUNIT, actor->y + P_RandomRange(-8, 8)*FRACUNIT,
|
||||
actor->z + P_RandomRange(0, 8)*FRACUNIT, MT_BOOMPARTICLE);
|
||||
fixed_t rand_x;
|
||||
fixed_t rand_y;
|
||||
fixed_t rand_z;
|
||||
|
||||
rand_z = actor->z + P_RandomRange(0, 8)*FRACUNIT;
|
||||
rand_y = actor->y + P_RandomRange(-8, 8)*FRACUNIT;
|
||||
rand_x = actor->x + P_RandomRange(-8, 8)*FRACUNIT;
|
||||
|
||||
truc = P_SpawnMobj(rand_x, rand_y, rand_z, MT_BOOMPARTICLE);
|
||||
truc->scale = actor->scale*2;
|
||||
|
||||
speed = FixedMul(7*FRACUNIT, actor->scale)>>FRACBITS;
|
||||
|
|
@ -10739,7 +10770,8 @@ void A_SPBChase(mobj_t *actor)
|
|||
return;
|
||||
}
|
||||
|
||||
// Find the player with the best rank
|
||||
// Find the player with the best rank. In gametypes with SPB forcing on WANTED
|
||||
// players, find our most-wanted player.
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator || players[i].exiting)
|
||||
|
|
@ -10754,7 +10786,15 @@ void A_SPBChase(mobj_t *actor)
|
|||
if (players[i].kartstuff[k_respawn])
|
||||
continue;*/ // respawning
|
||||
|
||||
if (players[i].position < bestrank)
|
||||
if ((gametyperules & GTR_WANTED) && (gametyperules & GTR_WANTEDSPB))
|
||||
{
|
||||
if (K_IsPlayerMostWanted(&players[i]))
|
||||
{
|
||||
player = &players[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (players[i].position < bestrank)
|
||||
{
|
||||
bestrank = players[i].position;
|
||||
player = &players[i];
|
||||
|
|
@ -10807,7 +10847,14 @@ void A_SPBChase(mobj_t *actor)
|
|||
else if (actor->extravalue2-- <= 0)
|
||||
actor->extravalue1 = 0; // back to SEEKING
|
||||
|
||||
spbplace = actor->tracer->player->position;
|
||||
if ((gametyperules & GTR_WANTED) && (gametyperules & GTR_WANTEDSPB))
|
||||
{
|
||||
spbplace = (actor->tracer->player - players);
|
||||
}
|
||||
else
|
||||
{
|
||||
spbplace = actor->tracer->player->position;
|
||||
}
|
||||
}
|
||||
|
||||
if ((K_RingsActive() == true) ) // Spawn rings to make up for the fact first has ring grabbing
|
||||
|
|
@ -10885,10 +10932,15 @@ void A_SPBChase(mobj_t *actor)
|
|||
: (16*R_PointToDist2(0, 0, actor->tracer->momx, actor->tracer->momy))/15) // Going faster than the target
|
||||
&& xyspeed > K_GetKartSpeed(actor->tracer->player, false, false)/4) // Don't display speedup lines at pitifully low speeds
|
||||
{
|
||||
mobj_t *fast = P_SpawnMobj(actor->x + (P_RandomRange(-24,24) * actor->scale),
|
||||
actor->y + (P_RandomRange(-24,24) * actor->scale),
|
||||
actor->z + (actor->height/2) + (P_RandomRange(-24,24) * actor->scale),
|
||||
MT_FASTLINE);
|
||||
fixed_t rand_x;
|
||||
fixed_t rand_y;
|
||||
fixed_t rand_z;
|
||||
|
||||
rand_z = actor->z + (actor->height/2) + (P_RandomRange(-24,24) * actor->scale);
|
||||
rand_y = actor->y + (P_RandomRange(-24,24) * actor->scale);
|
||||
rand_x = actor->x + (P_RandomRange(-24,24) * actor->scale);
|
||||
|
||||
mobj_t *fast = P_SpawnMobj(rand_x, rand_y, rand_z, MT_FASTLINE);
|
||||
fast->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy);
|
||||
//fast->momx = (3*actor->momx)/4;
|
||||
//fast->momy = (3*actor->momy)/4;
|
||||
|
|
@ -10921,7 +10973,15 @@ void A_SPBChase(mobj_t *actor)
|
|||
&& !players[actor->lastlook].spectator
|
||||
&& !players[actor->lastlook].exiting)
|
||||
{
|
||||
spbplace = players[actor->lastlook].position;
|
||||
if ((gametyperules & GTR_WANTED) && (gametyperules & GTR_WANTEDSPB))
|
||||
{
|
||||
spbplace = actor->lastlook;
|
||||
}
|
||||
else
|
||||
{
|
||||
spbplace = players[actor->lastlook].position;
|
||||
}
|
||||
|
||||
if (actor->extravalue2-- <= 0 && players[actor->lastlook].mo)
|
||||
{
|
||||
P_SetTarget(&actor->tracer, players[actor->lastlook].mo);
|
||||
|
|
@ -11283,8 +11343,15 @@ void A_FZBoomSmoke(mobj_t *actor)
|
|||
|
||||
for (i = 0; i < 8+(4*var1); i++)
|
||||
{
|
||||
mobj_t *smoke = P_SpawnMobj(actor->x + (P_RandomRange(-rad, rad)*actor->scale), actor->y + (P_RandomRange(-rad, rad)*actor->scale),
|
||||
actor->z + (P_RandomRange(0, 72)*actor->scale), MT_THOK);
|
||||
fixed_t rand_x;
|
||||
fixed_t rand_y;
|
||||
fixed_t rand_z;
|
||||
|
||||
rand_z = actor->z + (P_RandomRange(0, 72)*actor->scale);
|
||||
rand_y = actor->y + (P_RandomRange(-rad, rad)*actor->scale);
|
||||
rand_x = actor->x + (P_RandomRange(-rad, rad)*actor->scale);
|
||||
|
||||
mobj_t *smoke = P_SpawnMobj(rand_x, rand_y, rand_z, MT_THOK);
|
||||
|
||||
P_SetMobjState(smoke, S_FZEROSMOKE1);
|
||||
smoke->tics += P_RandomRange(-3, 4);
|
||||
|
|
@ -11445,13 +11512,20 @@ void A_MementosTPParticles(mobj_t *actor)
|
|||
mobj_t *mo2;
|
||||
int i = 0;
|
||||
thinker_t *th;
|
||||
fixed_t rand_x;
|
||||
fixed_t rand_y;
|
||||
fixed_t rand_z;
|
||||
|
||||
if (LUA_CallAction(A_MEMENTOSTPPARTICLES, (actor)))
|
||||
return;
|
||||
|
||||
for (; i<4; i++)
|
||||
{
|
||||
particle = P_SpawnMobj(actor->x + (P_RandomRange(-256, 256)<<FRACBITS), actor->y + (P_RandomRange(-256, 256)<<FRACBITS), actor->z + (P_RandomRange(48, 256)<<FRACBITS), MT_MEMENTOSPARTICLE);
|
||||
rand_z = actor->z + (P_RandomRange(48, 256)<<FRACBITS);
|
||||
rand_y = actor->y + (P_RandomRange(-256, 256)<<FRACBITS);
|
||||
rand_x = actor->x + (P_RandomRange(-256, 256)<<FRACBITS);
|
||||
|
||||
particle = P_SpawnMobj(rand_x, rand_y, rand_z, MT_MEMENTOSPARTICLE);
|
||||
particle->frame = 0;
|
||||
particle->color = ((i%2) ? (SKINCOLOR_RED) : (SKINCOLOR_BLACK));
|
||||
particle->destscale = 1;
|
||||
|
|
@ -11512,9 +11586,15 @@ void A_ReaperThinker(mobj_t *actor)
|
|||
if (actor->scale < 2<<FRACBITS) // we haven't finished growing YET.
|
||||
{
|
||||
// Spawn particles as we grow out of the floor, ゴ ゴ ゴ ゴ
|
||||
for (; i<16; i++)
|
||||
for (; i < 16; i++)
|
||||
{
|
||||
particle = P_SpawnMobj(actor->x + (P_RandomRange(-60, 60)<<FRACBITS), actor->y + (P_RandomRange(-60, 60)<<FRACBITS), actor->z, MT_THOK);
|
||||
fixed_t rand_x;
|
||||
fixed_t rand_y;
|
||||
|
||||
rand_y = actor->y + (P_RandomRange(-60, 60)<<FRACBITS);
|
||||
rand_x = actor->x + (P_RandomRange(-60, 60)<<FRACBITS);
|
||||
|
||||
particle = P_SpawnMobj(rand_x, rand_y, actor->z, MT_THOK);
|
||||
particle->momz = 20<<FRACBITS;
|
||||
particle->color = ((i%2 !=0) ? (SKINCOLOR_RED) : (SKINCOLOR_BLACK));
|
||||
particle->frame = 0;
|
||||
|
|
@ -11659,9 +11739,3 @@ void A_ReaperThinker(mobj_t *actor)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void A_DeathSpin(mobj_t *actor)
|
||||
{
|
||||
INT32 locvar1 = var1;
|
||||
actor->angle += locvar1;
|
||||
}
|
||||
|
|
|
|||
126
src/p_inter.c
126
src/p_inter.c
|
|
@ -39,6 +39,7 @@
|
|||
#include "k_boss.h"
|
||||
#include "p_spec.h"
|
||||
#include "k_objects.h"
|
||||
#include "k_odds.h"
|
||||
#include "acs/interface.h"
|
||||
|
||||
// CTF player names
|
||||
|
|
@ -943,12 +944,16 @@ void P_TouchStarPost(mobj_t *post, player_t *player, boolean snaptopost)
|
|||
|
||||
(void)snaptopost;
|
||||
|
||||
// SRB2kart - 150117
|
||||
if (K_UsingLegacyCheckpoints() && player->exiting) //STOP MESSING UP MY STATS FASDFASDF
|
||||
return;
|
||||
|
||||
// Going backwards triggers sound
|
||||
if (K_CheckpointThreshold(false) == numstarposts
|
||||
? post->health - player->starpostnum > 1
|
||||
: post->health >= player->starpostnum + K_CheckpointThreshold(false))
|
||||
{
|
||||
if (!player->checkskip)
|
||||
if (!player->checkskip && !player->bot)
|
||||
{
|
||||
S_StartSound(toucher, sfx_s26d);
|
||||
if (netgame && cv_antigrief.value)
|
||||
|
|
@ -1565,88 +1570,9 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
|||
case MT_PLAYER:
|
||||
if (damagetype != DMG_SPECTATOR)
|
||||
{
|
||||
target->fuse = 2*TICRATE; // timer before mobj disappears from view (even if not an actual player)
|
||||
target->fuse = TICRATE;
|
||||
target->momx = target->momy = target->momz = 0;
|
||||
|
||||
if (target->player && !(skins[target->player->skin].flags & SF_NOGIBS))
|
||||
{
|
||||
angle_t playerFlingAngle;
|
||||
angle_t kartFlingAngle;
|
||||
|
||||
if (source && !P_MobjWasRemoved(source))
|
||||
{
|
||||
playerFlingAngle = kartFlingAngle = R_PointToAngle2(
|
||||
source->x - source->momx, source->y - source->momy,
|
||||
target->x, target->y
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
kartFlingAngle = target->angle;
|
||||
|
||||
if (P_RandomByte() & 1)
|
||||
{
|
||||
kartFlingAngle -= ANGLE_45;
|
||||
}
|
||||
else
|
||||
{
|
||||
kartFlingAngle += ANGLE_45;
|
||||
}
|
||||
|
||||
playerFlingAngle = kartFlingAngle + ANGLE_180;
|
||||
}
|
||||
|
||||
// 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 (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);
|
||||
}
|
||||
|
||||
if (target->player && (skins[target->player->skin].flags & SF_OLDDEATH))
|
||||
{
|
||||
P_SetObjectMomZ(target, 14*FRACUNIT, false);
|
||||
}
|
||||
|
||||
P_SetObjectMomZ(target, 14*FRACUNIT, false);
|
||||
P_PlayDeathSound(target);
|
||||
}
|
||||
break;
|
||||
|
|
@ -2220,15 +2146,12 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
return false;
|
||||
}
|
||||
|
||||
// Check if we should allow explosion combos.
|
||||
if ((explosioncombo == false) && (player->flashing > 0 || player->squishedtimer > 0))
|
||||
{
|
||||
|
||||
// Check if we should allow explosion combos.
|
||||
if ((explosioncombo == false) && (player->flashing > 0 || player->squishedtimer > 0))
|
||||
{
|
||||
// Post-hit invincibility
|
||||
K_DoInstashield(player);
|
||||
return false;
|
||||
}
|
||||
// Post-hit invincibility
|
||||
K_DoInstashield(player);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2243,7 +2166,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
{
|
||||
K_TakeBumpersFromPlayer(source->player, player, 1);
|
||||
}
|
||||
else if (damage & DMG_KARMA)
|
||||
else if (damage & DMG_KARMA && source->player->bumper <= 0)
|
||||
{
|
||||
source->player->karmapoints++;
|
||||
if (source->player->karmapoints >= 2)
|
||||
|
|
@ -2268,11 +2191,12 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
K_DestroyBumpers(player, 1);
|
||||
}
|
||||
|
||||
if (!(type == DMG_NORMAL || type == DMG_WIPEOUT || type == DMG_VOLTAGE || type == DMG_FLIPOVER))
|
||||
if (inflictor && (inflictor->type == MT_ORBINAUT || inflictor->type == MT_ORBINAUT_SHIELD
|
||||
|| inflictor->type == MT_JAWZ || inflictor->type == MT_JAWZ_SHIELD || inflictor->type == MT_JAWZ_DUD
|
||||
|| inflictor->type == MT_SMK_THWOMP || inflictor->player))
|
||||
{
|
||||
player->sneakertimer = 0;
|
||||
player->sneakertimer = player->numsneakers = 0;
|
||||
player->mo->flags2 &= ~MF2_WATERRUN;
|
||||
|
||||
}
|
||||
|
||||
player->driftboost = 0;
|
||||
|
|
@ -2280,6 +2204,20 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
player->glanceDir = 0;
|
||||
player->pflags &= ~PF_GAINAX;
|
||||
|
||||
if (gametyperules & GTR_BUMPERS)
|
||||
{
|
||||
if (player->bumper <= 0)
|
||||
{
|
||||
player->karmadelay = comebacktime;
|
||||
if ((gametyperules & GTR_KARMA) && player->karmamode == 2 )
|
||||
{
|
||||
mobj_t *poof = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_EXPLODE);
|
||||
S_StartSound(poof, mobjinfo[MT_KARMAHITBOX].seesound);
|
||||
player->karmamode = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INT16 ringburst = 3;
|
||||
|
||||
// Handle ringloss based on hittype.
|
||||
|
|
|
|||
|
|
@ -303,6 +303,8 @@ mobjtype_t P_GetMobjtype(UINT16 mthingtype);
|
|||
|
||||
void P_RespawnSpecials(void);
|
||||
|
||||
mobj_t *P_AllocateMobj(void);
|
||||
|
||||
mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type);
|
||||
|
||||
void P_CalculatePrecipFloor(precipmobj_t *mobj);
|
||||
|
|
@ -319,6 +321,7 @@ void P_RunOverlays(void);
|
|||
#define OV_DONT3DOFFSET 1<<1
|
||||
#define OV_DONTXYSCALE 1<<2
|
||||
#define OV_DONTROLL 1<<3
|
||||
#define OV_DONTBAKEOFFSET 1<<4
|
||||
|
||||
void P_HandleMinecartSegments(mobj_t *mobj);
|
||||
void P_MobjThinker(mobj_t *mobj);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// BLANKART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2023 by Kart Krew
|
||||
// Copyright (C) 2025 by James Robert Roman.
|
||||
// Copyright (C) 2025 by Kart Krew.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
|
|
@ -11,7 +12,6 @@
|
|||
|
||||
#include "doomdef.h"
|
||||
#include "d_player.h"
|
||||
#include "doomstat.h"
|
||||
#include "k_kart.h"
|
||||
#include "p_local.h"
|
||||
#include "p_setup.h"
|
||||
|
|
|
|||
87
src/p_map.c
87
src/p_map.c
|
|
@ -1290,21 +1290,6 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing)
|
|||
|
||||
return BMIT_CONTINUE;
|
||||
}
|
||||
else if (thing->type == MT_KART_LEFTOVER)
|
||||
{
|
||||
// see if it went over / under
|
||||
if (g_tm.thing->z > thing->z + thing->height)
|
||||
return BMIT_CONTINUE; // overhead
|
||||
if (g_tm.thing->z + g_tm.thing->height < thing->z)
|
||||
return BMIT_CONTINUE; // underneath
|
||||
|
||||
if (P_IsObjectOnGround(thing) && g_tm.thing->momz < 0)
|
||||
K_KartBouncing(g_tm.thing, thing, true, false);
|
||||
else
|
||||
K_KartBouncing(g_tm.thing, thing, false, false);
|
||||
|
||||
return BMIT_CONTINUE;
|
||||
}
|
||||
else if (thing->flags & MF_SOLID)
|
||||
{
|
||||
// see if it went over / under
|
||||
|
|
@ -1650,7 +1635,7 @@ static BlockItReturn_t PIT_CheckLine(line_t *ld)
|
|||
{
|
||||
P_TestLine(ld);
|
||||
}
|
||||
else if (g_tm.maxstep > 0)
|
||||
else
|
||||
{
|
||||
if (g_tm.thing->z < open.floor)
|
||||
{
|
||||
|
|
@ -2522,20 +2507,6 @@ fixed_t P_GetThingStepUp(mobj_t *thing, fixed_t destX, fixed_t destY)
|
|||
return maxstep;
|
||||
}
|
||||
|
||||
// Used for averging height values for step up.
|
||||
static fixed_t avgheight(fixed_t a, fixed_t b)
|
||||
{
|
||||
if (((b > 0) && (a > (INT32_MAX - b))) ||
|
||||
((b < 0) && (a < (INT32_MIN - b))))
|
||||
{
|
||||
return b + (a - b) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (a + b) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
static boolean
|
||||
increment_move
|
||||
( mobj_t * thing,
|
||||
|
|
@ -2558,7 +2529,7 @@ increment_move
|
|||
radius = max(radius, mapobjectscale);
|
||||
|
||||
// And Big Large (tm) movements can skip over slopes.
|
||||
radius = min(radius, 16*mapobjectscale);
|
||||
radius = min(radius, 8*mapobjectscale);
|
||||
|
||||
// (This whole "step" system is flawed; it was OK before, but the addition of slopes has
|
||||
// exposed the problems with doing it like this. The right thing to do would be to use
|
||||
|
|
@ -2621,8 +2592,7 @@ increment_move
|
|||
if (P_UsingStepUp(thing))
|
||||
{
|
||||
//All things are affected by their scale.
|
||||
fixed_t maxstep = P_GetThingStepUp(thing, tryx, tryy);
|
||||
fixed_t stepheight = 0;
|
||||
fixed_t maxstep = g_tm.maxstep;
|
||||
|
||||
if (thing->type == MT_SKIM)
|
||||
maxstep = 0;
|
||||
|
|
@ -2644,9 +2614,7 @@ increment_move
|
|||
// Step up
|
||||
if (thing->z < g_tm.floorz)
|
||||
{
|
||||
stepheight = avgheight(g_tm.floorz - thing->z, g_tm.floorstep);
|
||||
|
||||
if (stepheight <= maxstep)
|
||||
if (g_tm.floorz - thing->z <= maxstep)
|
||||
{
|
||||
thing->z = thing->floorz = g_tm.floorz;
|
||||
thing->floorrover = g_tm.floorrover;
|
||||
|
|
@ -2659,9 +2627,7 @@ increment_move
|
|||
}
|
||||
else if (g_tm.ceilingz < thingtop)
|
||||
{
|
||||
stepheight = avgheight(thingtop - g_tm.ceilingz, g_tm.ceilingstep);
|
||||
|
||||
if (stepheight <= maxstep)
|
||||
if (thingtop - g_tm.ceilingz <= maxstep)
|
||||
{
|
||||
thing->z = ( thing->ceilingz = g_tm.ceilingz ) - thing->height;
|
||||
thing->ceilingrover = g_tm.ceilingrover;
|
||||
|
|
@ -3513,16 +3479,31 @@ static void P_BouncePlayerMove(mobj_t *mo, TryMoveResult_t *result)
|
|||
mmomx = mo->player->rmomx;
|
||||
mmomy = mo->player->rmomy;
|
||||
|
||||
if (!cv_kartbumpspark.value || modeattacking != ATTACKING_NONE)
|
||||
UINT32 bumpspark = K_GetBumpSpark();
|
||||
|
||||
// The easy solution is to do this :^)
|
||||
UINT32 basecharge = min(mo->player->driftcharge, K_GetKartDriftSparkValue(mo->player));
|
||||
|
||||
if ((bumpspark < BUMPSPARK_ALL) ||
|
||||
(modeattacking != ATTACKING_NONE && G_CompatLevel(0x0009)))
|
||||
{
|
||||
mo->player->drift = 0;
|
||||
mo->player->driftcharge = 0;
|
||||
if (!bumpspark)
|
||||
{
|
||||
// Bumps removing spark would be less frustrating if you didn't get your drift
|
||||
// removed too. Losing sparks is a fair punishment, drifting RIGHT for
|
||||
// daring to scrape a wall for a wide LEFT turn is horrendous and leads to
|
||||
// awful gluewalling.
|
||||
// TL;DR: I hate wrongdrifts and hopefully this is an okay middle ground.
|
||||
mo->player->drift = 0;
|
||||
}
|
||||
|
||||
mo->player->driftcharge = (bumpspark == BUMPSPARK_RESET100) ? basecharge : 0;
|
||||
}
|
||||
|
||||
// Regardless of bumpspark, tell bots to stop drifting if they bonk a wall.
|
||||
K_BotSetDriftState(mo->player, DRIFTSTATE_AUTO, TICRATE);
|
||||
|
||||
if (!cv_kartbumpspring.value || modeattacking != ATTACKING_NONE)
|
||||
if ((!cv_kartbumpspring.value && modeattacking == ATTACKING_NONE) || (modeattacking != ATTACKING_NONE && G_CompatLevel(0x0009)))
|
||||
{
|
||||
mo->player->pogospring = 0;
|
||||
}
|
||||
|
|
@ -3530,24 +3511,12 @@ static void P_BouncePlayerMove(mobj_t *mo, TryMoveResult_t *result)
|
|||
slidemo = mo;
|
||||
bestslideline = result->line;
|
||||
|
||||
if (bestslideline == NULL && cv_showgremlins.value)
|
||||
/*if (mo->health <= 0)
|
||||
{
|
||||
// debug
|
||||
mobj_t*x = P_SpawnMobj(mo->x, mo->y, mo->z, MT_THOK);
|
||||
x->frame = FF_FULLBRIGHT | FF_ADD;
|
||||
x->renderflags = RF_ALWAYSONTOP;
|
||||
x->color = SKINCOLOR_RED;
|
||||
|
||||
CONS_Printf(
|
||||
"GREMLIN: leveltime=%u x=%f y=%f z=%f angle=%f\n",
|
||||
leveltime,
|
||||
FixedToFloat(mo->x),
|
||||
FixedToFloat(mo->y),
|
||||
FixedToFloat(mo->z),
|
||||
AngleToFloat(R_PointToAngle2(0, 0, oldmomx, oldmomy))
|
||||
);
|
||||
tmxmove = mo->momx;
|
||||
tmymove = mo->momy;
|
||||
}
|
||||
|
||||
else if*/
|
||||
if (mo->eflags & MFE_JUSTBOUNCEDWALL) // Stronger push-out
|
||||
{
|
||||
tmxmove = mmomx;
|
||||
|
|
|
|||
|
|
@ -78,8 +78,9 @@ void P_ClosestPointOnLine3D(const vector3_t *p, const vector3_t *Line, vector3_t
|
|||
FV3_SubEx(p, v1, &c);
|
||||
|
||||
d = R_PointToDist2(0, v2->z, R_PointToDist2(v2->x, v2->y, v1->x, v1->y), v1->z);
|
||||
vector3_t vd = { d, d, d };
|
||||
FV3_Copy(&n, &V);
|
||||
FV3_Divide(&n, d);
|
||||
FV3_Divide(&n, &vd);
|
||||
|
||||
t = FV3_Dot(&n, &c);
|
||||
|
||||
|
|
@ -95,7 +96,8 @@ void P_ClosestPointOnLine3D(const vector3_t *p, const vector3_t *Line, vector3_t
|
|||
return;
|
||||
}
|
||||
|
||||
FV3_Mul(&n, t);
|
||||
vector3_t tv = { t, t, t };
|
||||
FV3_Mul(&n, &tv);
|
||||
|
||||
FV3_AddEx(v1, &n, result);
|
||||
return;
|
||||
|
|
@ -1800,12 +1802,32 @@ boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2,
|
|||
pos_x += hity_x;
|
||||
pos_y += hity_y;
|
||||
}
|
||||
else
|
||||
else if (FixedMul(hitx_x, hitx_x) + FixedMul(hitx_y, hitx_y) < FixedMul(hity_x, hity_x) + FixedMul(hity_y, hity_y))
|
||||
{
|
||||
gridpos_x += dir_x;
|
||||
pos_x += hitx_x;
|
||||
pos_y += hitx_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we hit a corner, round down towards south-east
|
||||
if (dir_x < 0 && dir_y > 0)
|
||||
{
|
||||
gridpos_y += dir_y;
|
||||
}
|
||||
else if (dir_x > 0 && dir_y < 0)
|
||||
{
|
||||
gridpos_x += dir_x;
|
||||
}
|
||||
else
|
||||
{
|
||||
gridpos_x += dir_x;
|
||||
gridpos_y += dir_y;
|
||||
}
|
||||
|
||||
pos_x += hitx_x;
|
||||
pos_y += hitx_y;
|
||||
}
|
||||
|
||||
if (flags & PT_ADDLINES)
|
||||
if (!P_BlockLinesIterator(gridpos_x, gridpos_y, PIT_AddLineIntercepts))
|
||||
|
|
|
|||
197
src/p_mobj.c
197
src/p_mobj.c
|
|
@ -50,6 +50,7 @@
|
|||
#include "k_terrain.h"
|
||||
#include "k_collide.h"
|
||||
#include "k_objects.h"
|
||||
#include "k_odds.h"
|
||||
|
||||
// BlanKart
|
||||
#include "blan/b_soc.h"
|
||||
|
|
@ -1159,6 +1160,13 @@ fixed_t P_GetMobjGravity(mobj_t *mo)
|
|||
|
||||
if (mo->player)
|
||||
{
|
||||
// MF2_OBJECTFLIP is relative -- flips sector reverse gravity back to normal
|
||||
if (mo->flags2 & MF2_OBJECTFLIP)
|
||||
{
|
||||
gravityadd = -gravityadd;
|
||||
mo->eflags ^= MFE_VERTICALFLIP;
|
||||
}
|
||||
|
||||
if (wasflip == !(mo->eflags & MFE_VERTICALFLIP)) // note!! == ! is not equivalent to != here - turns numeric into bool this way
|
||||
P_PlayerFlip(mo);
|
||||
|
||||
|
|
@ -1732,6 +1740,12 @@ void P_XYMovement(mobj_t *mo)
|
|||
mo->momz = transfermomz;
|
||||
mo->standingslope = NULL;
|
||||
mo->terrain = NULL;
|
||||
|
||||
if (mo->player)
|
||||
{
|
||||
S_StartSound(mo, sfx_kc5e);
|
||||
mo->player->walltransfered = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2844,7 +2858,6 @@ void P_PlayerZMovement(mobj_t *mo)
|
|||
P_CheckMarioBlocks(mo);
|
||||
|
||||
mo->momz = 0;
|
||||
P_CheckGravity(mo, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -6616,17 +6629,19 @@ static boolean P_IsMiscCapObject(INT32 type)
|
|||
{
|
||||
switch (type)
|
||||
{
|
||||
|
||||
case MT_RING:
|
||||
case MT_FLINGRING:
|
||||
return true;
|
||||
if (cv_kartdebugrings.value)
|
||||
return true;
|
||||
break;
|
||||
|
||||
case MT_RANDOMITEM:
|
||||
return true;
|
||||
if (itembreaker)
|
||||
return true;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -6739,6 +6754,18 @@ void P_RunOverlays(void)
|
|||
mo->roll = mo->target->roll;
|
||||
}
|
||||
|
||||
if (!(mo->threshold & OV_DONTBAKEOFFSET))
|
||||
{
|
||||
// offsets
|
||||
mo->bakexoff = mo->target->bakexoff;
|
||||
mo->bakeyoff = mo->target->bakeyoff;
|
||||
mo->bakezoff = mo->target->bakezoff;
|
||||
// pivots
|
||||
mo->bakexpiv = mo->target->bakexpiv;
|
||||
mo->bakeypiv = mo->target->bakeypiv;
|
||||
mo->bakezpiv = mo->target->bakezpiv;
|
||||
}
|
||||
|
||||
if ((mo->flags & MF_DONTENCOREMAP) != (mo->target->flags & MF_DONTENCOREMAP))
|
||||
mo->flags ^= MF_DONTENCOREMAP;
|
||||
|
||||
|
|
@ -6834,7 +6861,7 @@ static void P_PlayerInvincibilityOverlay(mobj_t *thing)
|
|||
{
|
||||
I_Assert(thing->target != NULL);
|
||||
I_Assert(thing->target->player != NULL);
|
||||
|
||||
|
||||
if (!thing->target->player->invincibilitytimer)
|
||||
{
|
||||
P_SetTarget(&thing->target, NULL);
|
||||
|
|
@ -7521,14 +7548,13 @@ static void P_MobjSceneryThink(mobj_t *mobj)
|
|||
case MT_PLAYERARROW:
|
||||
if (mobj->target && mobj->target->health
|
||||
&& mobj->target->player && !mobj->target->player->spectator
|
||||
&& mobj->target->health && mobj->target->player->playerstate != PST_DEAD
|
||||
/*&& players[displayplayers[0]].mo && !players[displayplayers[0]].spectator*/)
|
||||
&& mobj->target->health && mobj->target->player->playerstate != PST_DEAD)
|
||||
{
|
||||
fixed_t scale = 3*mobj->target->scale;
|
||||
mobj->color = mobj->target->color;
|
||||
K_MatchGenericExtraFlags(mobj, mobj->target);
|
||||
|
||||
if ((gametype == GT_RACE || mobj->target->player->bumper <= 0)
|
||||
if ((!(gametyperules & GTR_ITEMARROWS) || (gametyperules & GTR_BUMPERS && mobj->target->player->bumper <= 0))
|
||||
#if 1 // Set to 0 to test without needing to host
|
||||
|| (P_IsDisplayPlayer(mobj->target->player))
|
||||
#endif
|
||||
|
|
@ -7633,6 +7659,17 @@ static void P_MobjSceneryThink(mobj_t *mobj)
|
|||
else
|
||||
mobj->tracer->renderflags |= RF_DONTDRAW;
|
||||
}
|
||||
else if (mobj->target->player->flametimer > 1)
|
||||
{
|
||||
//itembar = mobj->target->player->flametimer; -- not today satan
|
||||
P_SetMobjState(mobj, S_PLAYERARROW_BOX);
|
||||
mobj->tracer->sprite = SPR_ITEM;
|
||||
mobj->tracer->frame = FF_FULLBRIGHT|KITEM_FLAMESHIELD;
|
||||
if (leveltime & 1)
|
||||
mobj->tracer->renderflags &= ~RF_DONTDRAW;
|
||||
else
|
||||
mobj->tracer->renderflags |= RF_DONTDRAW;
|
||||
}
|
||||
else if (mobj->target->player->growshrinktimer > 0)
|
||||
{
|
||||
P_SetMobjState(mobj, S_PLAYERARROW_BOX);
|
||||
|
|
@ -7940,7 +7977,7 @@ static boolean P_MobjDeadThink(mobj_t *mobj)
|
|||
}
|
||||
else // Apply gravity to fall downwards.
|
||||
{
|
||||
P_SetObjectMomZ(mobj, -2*FRACUNIT/3, true);
|
||||
P_SetObjectMomZ(mobj, -3*FRACUNIT/2, true);
|
||||
|
||||
if (mobj->player && (skins[mobj->player->skin].flags & SF_OLDDEATH))
|
||||
{
|
||||
|
|
@ -7953,11 +7990,16 @@ static boolean P_MobjDeadThink(mobj_t *mobj)
|
|||
if (!(mobj->fuse % 8))
|
||||
{
|
||||
fixed_t r = mobj->radius >> FRACBITS;
|
||||
mobj_t *explosion = P_SpawnMobj(
|
||||
mobj->x + (P_RandomRange(r, -r) << FRACBITS),
|
||||
mobj->y + (P_RandomRange(r, -r) << FRACBITS),
|
||||
mobj->z + (P_RandomKey(mobj->height >> FRACBITS) << FRACBITS),
|
||||
MT_SONIC3KBOSSEXPLODE);
|
||||
|
||||
fixed_t rand_x;
|
||||
fixed_t rand_y;
|
||||
fixed_t rand_z;
|
||||
|
||||
rand_z = mobj->z + (P_RandomKey(mobj->height >> FRACBITS) << FRACBITS);
|
||||
rand_y = mobj->y + (P_RandomRange(r, -r) << FRACBITS);
|
||||
rand_x = mobj->x + (P_RandomRange(r, -r) << FRACBITS);
|
||||
|
||||
mobj_t *explosion = P_SpawnMobj(rand_x, rand_y, rand_z, MT_SONIC3KBOSSEXPLODE);
|
||||
S_StartSound(explosion, sfx_s3kb4);
|
||||
}
|
||||
P_SetObjectMomZ(mobj, -2*FRACUNIT/3, true);
|
||||
|
|
@ -8341,7 +8383,8 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
// No need to check water. Who cares?
|
||||
P_RingThinker(mobj);
|
||||
|
||||
P_AddMiscCap(mobj);
|
||||
if (cv_kartdebugrings.value)
|
||||
P_AddMiscCap(mobj);
|
||||
|
||||
A_AttractChase(mobj);
|
||||
return false;
|
||||
|
|
@ -8917,7 +8960,13 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
smoke->momy = mobj->target->momy/2;
|
||||
smoke->momz = mobj->target->momz/2;
|
||||
|
||||
P_Thrust(smoke, mobj->angle+FixedAngle(P_RandomRange(135, 225)<<FRACBITS), P_RandomRange(0, 8) * mobj->target->scale);
|
||||
fixed_t rand_angle;
|
||||
fixed_t rand_move;
|
||||
|
||||
rand_move = P_RandomRange(0, 8) * mobj->target->scale;
|
||||
rand_angle = mobj->angle+FixedAngle(P_RandomRange(135, 225)<<FRACBITS);
|
||||
|
||||
P_Thrust(smoke, rand_angle, rand_move);
|
||||
}
|
||||
break;
|
||||
case MT_SPARKLETRAIL:
|
||||
|
|
@ -9291,7 +9340,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
statenum_t state = (mobj->state-states);
|
||||
|
||||
if (!mobj->target || !mobj->target->health || !mobj->target->player || mobj->target->player->spectator
|
||||
|| (gametyperules & GTR_CIRCUIT || mobj->target->player->bumper))
|
||||
|| mobj->target->player->bumper || !(gametyperules & GTR_KARMA))
|
||||
{
|
||||
P_RemoveMobj(mobj);
|
||||
return false;
|
||||
|
|
@ -9391,11 +9440,18 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
}
|
||||
else
|
||||
{
|
||||
P_SpawnMobj(mobj->x + (P_RandomRange(-48,48)*mobj->scale),
|
||||
mobj->y + (P_RandomRange(-48,48)*mobj->scale),
|
||||
mobj->z + (24*mobj->scale) + (P_RandomRange(-8,8)*mobj->scale),
|
||||
MT_SIGNSPARKLE);
|
||||
fixed_t rand_x;
|
||||
fixed_t rand_y;
|
||||
fixed_t rand_z;
|
||||
|
||||
rand_z = mobj->z + (24*mobj->scale) + (P_RandomRange(-8,8)*mobj->scale);
|
||||
rand_y = mobj->y + (P_RandomRange(-48,48)*mobj->scale);
|
||||
rand_x = mobj->x + (P_RandomRange(-48,48)*mobj->scale);
|
||||
|
||||
P_SpawnMobj(rand_x, rand_y, rand_z, MT_SIGNSPARKLE);
|
||||
|
||||
mobj->flags &= ~MF_NOGRAVITY;
|
||||
|
||||
if (abs(mobj->z - mobj->movefactor) <= (512*mobj->scale) && !mobj->cvmem)
|
||||
{
|
||||
if (mobj->info->seesound)
|
||||
|
|
@ -9453,7 +9509,14 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
else // fire + smoke pillar
|
||||
{
|
||||
UINT8 i;
|
||||
mobj_t *fire = P_SpawnMobj(mobj->x + (P_RandomRange(-32, 32)*mobj->scale), mobj->y + (P_RandomRange(-32, 32)*mobj->scale), mobj->z, MT_THOK);
|
||||
|
||||
fixed_t rand_x;
|
||||
fixed_t rand_y;
|
||||
|
||||
rand_y = mobj->y + (P_RandomRange(-32, 32)*mobj->scale);
|
||||
rand_x = mobj->x + (P_RandomRange(-32, 32)*mobj->scale);
|
||||
|
||||
mobj_t *fire = P_SpawnMobj(rand_x, rand_y, mobj->z, MT_THOK);
|
||||
|
||||
fire->sprite = SPR_FPRT;
|
||||
fire->frame = FF_FULLBRIGHT|FF_TRANS30;
|
||||
|
|
@ -9465,7 +9528,10 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
mobj_t *smoke = P_SpawnMobj(mobj->x + (P_RandomRange(-16, 16)*mobj->scale), mobj->y + (P_RandomRange(-16, 16)*mobj->scale), mobj->z, MT_SMOKE);
|
||||
rand_y = mobj->y + (P_RandomRange(-16, 16)*mobj->scale);
|
||||
rand_x = mobj->x + (P_RandomRange(-16, 16)*mobj->scale);
|
||||
|
||||
mobj_t *smoke = P_SpawnMobj(rand_x, rand_y, mobj->z, MT_SMOKE);
|
||||
|
||||
P_SetMobjState(smoke, S_FZSLOWSMOKE1);
|
||||
smoke->scale = mobj->scale;
|
||||
|
|
@ -9689,9 +9755,15 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
|
||||
if ((mobj->tracer && !P_MobjWasRemoved(mobj->tracer)) && !(leveltime % 10))
|
||||
{
|
||||
mobj_t *dust = P_SpawnMobj(mobj->x + (P_RandomRange(-4, 4)<<FRACBITS),
|
||||
mobj->y + (P_RandomRange(-4, 4)<<FRACBITS),
|
||||
mobj->z + (P_RandomRange(0, 2)<<FRACBITS), MT_BBZDUST);
|
||||
fixed_t rand_x;
|
||||
fixed_t rand_y;
|
||||
fixed_t rand_z;
|
||||
|
||||
rand_z = mobj->z + (P_RandomRange(0, 2)<<FRACBITS);
|
||||
rand_y = mobj->y + (P_RandomRange(-4, 4)<<FRACBITS);
|
||||
rand_x = mobj->x + (P_RandomRange(-4, 4)<<FRACBITS);
|
||||
|
||||
mobj_t *dust = P_SpawnMobj(rand_x, rand_y, rand_z, MT_BBZDUST);
|
||||
P_SetScale(dust, mobj->scale/2);
|
||||
P_InstaThrust(dust, FixedAngle(P_RandomRange(0,359)<<FRACBITS), abs(mobj->tracer->momz)/2);
|
||||
|
||||
|
|
@ -10196,7 +10268,7 @@ static void P_MonitorFuseThink(mobj_t *mobj)
|
|||
|
||||
static boolean P_FuseThink(mobj_t *mobj)
|
||||
{
|
||||
if (mobj->fuse <= TICRATE && (mobj->type == MT_RANDOMITEM || mobj->type == MT_EGGMANITEM || mobj->type == MT_FALLINGROCK))
|
||||
if (mobj->fuse <= TICRATE && ((mobj->type == MT_RANDOMITEM && mobj->threshold == 69) || mobj->type == MT_EGGMANITEM || mobj->type == MT_FALLINGROCK))
|
||||
mobj->renderflags ^= RF_DONTDRAW;
|
||||
|
||||
mobj->fuse--;
|
||||
|
|
@ -10224,7 +10296,7 @@ static boolean P_FuseThink(mobj_t *mobj)
|
|||
{
|
||||
;
|
||||
}
|
||||
else if (gametype == GT_BATTLE)
|
||||
else if (gametyperules & GTR_BATTLEBOXES)
|
||||
{
|
||||
if (mobj->threshold != 69)
|
||||
break;
|
||||
|
|
@ -10243,7 +10315,7 @@ static boolean P_FuseThink(mobj_t *mobj)
|
|||
newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->type);
|
||||
|
||||
// Transfer flags2 (strongbox, objectflip, bossnotrap)
|
||||
newmobj->flags2 = mobj->flags2 & ~MF2_DONTDRAW;
|
||||
newmobj->flags2 = mobj->flags2;
|
||||
}
|
||||
|
||||
P_RemoveMobj(mobj); // make sure they disappear
|
||||
|
|
@ -10925,6 +10997,24 @@ static void P_DefaultMobjShadowScale(mobj_t *thing)
|
|||
}
|
||||
}
|
||||
|
||||
mobj_t *P_AllocateMobj(void)
|
||||
{
|
||||
mobj_t *mobj;
|
||||
|
||||
if (mobjcache != NULL)
|
||||
{
|
||||
mobj = mobjcache;
|
||||
mobjcache = mobjcache->hnext;
|
||||
memset(mobj, 0, sizeof(*mobj));
|
||||
}
|
||||
else
|
||||
{
|
||||
mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL);
|
||||
}
|
||||
|
||||
return mobj;
|
||||
}
|
||||
|
||||
//
|
||||
// P_SpawnMobj
|
||||
//
|
||||
|
|
@ -10950,16 +11040,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
|||
type = MT_RAY;
|
||||
}
|
||||
|
||||
if (mobjcache != NULL)
|
||||
{
|
||||
mobj = mobjcache;
|
||||
mobjcache = mobjcache->hnext;
|
||||
memset(mobj, 0, sizeof(*mobj));
|
||||
}
|
||||
else
|
||||
{
|
||||
mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL);
|
||||
}
|
||||
mobj = P_AllocateMobj();
|
||||
|
||||
// this is officially a mobj, declared as soon as possible.
|
||||
mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker;
|
||||
|
|
@ -11171,9 +11252,6 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
|||
mobj->color = BALLOONCOLORS[P_RandomKey(sizeof(BALLOONCOLORS))];
|
||||
}
|
||||
break;
|
||||
case MT_KART_LEFTOVER:
|
||||
mobj->color = SKINCOLOR_RED;
|
||||
break;
|
||||
case MT_REDRING: // Make MT_REDRING red by default
|
||||
mobj->color = skincolor_redring;
|
||||
break;
|
||||
|
|
@ -11713,9 +11791,9 @@ void P_FreePrecipMobj(precipmobj_t *mobj)
|
|||
// Clearing out stuff for savegames
|
||||
void P_RemoveSavegameMobj(mobj_t *mobj)
|
||||
{
|
||||
// unlink from sector and block lists
|
||||
if (((thinker_t *)mobj)->function.acp1 == (actionf_p1)P_NullPrecipThinker)
|
||||
{
|
||||
// unlink from sector and block lists
|
||||
P_UnsetPrecipThingPosition((precipmobj_t *)mobj);
|
||||
|
||||
if (precipsector_list)
|
||||
|
|
@ -11738,20 +11816,18 @@ void P_RemoveSavegameMobj(mobj_t *mobj)
|
|||
P_DelSeclist(sector_list);
|
||||
sector_list = NULL;
|
||||
}
|
||||
|
||||
P_DeleteMobjStringArgs(mobj);
|
||||
}
|
||||
|
||||
// stop any playing sound
|
||||
S_StopSound(mobj);
|
||||
R_RemoveMobjInterpolator(mobj);
|
||||
P_DeleteMobjStringArgs(mobj);
|
||||
|
||||
R_RemoveMobjInterpolator(mobj);
|
||||
|
||||
// free block
|
||||
// Here we use the same code as R_RemoveThinkerDelayed, but without reference counting (we're removing everything so it shouldn't matter) and without touching currentthinker since we aren't in P_RunThinkers
|
||||
{
|
||||
thinker_t *thinker = (thinker_t *)mobj;
|
||||
thinker_t *next = thinker->next;
|
||||
(next->prev = thinker->prev)->next = next;
|
||||
Z_Free(thinker);
|
||||
}
|
||||
P_UnlinkThinker((thinker_t*)mobj);
|
||||
}
|
||||
|
||||
static CV_PossibleValue_t respawnitemtime_cons_t[] = {{1, "MIN"}, {300, "MAX"}, {0, NULL}};
|
||||
|
|
@ -12039,8 +12115,8 @@ void P_PrecipitationEffects(void)
|
|||
*/
|
||||
mobjtype_t P_GetMobjtype(UINT16 mthingtype)
|
||||
{
|
||||
mobjtype_t i;
|
||||
for (i = 0; i < NUMMOBJTYPES; i++)
|
||||
INT32 i;
|
||||
for (i = NUMMOBJTYPES-1; i >= 0; i--)
|
||||
if (mthingtype == mobjinfo[i].doomednum)
|
||||
return i;
|
||||
return MT_UNKNOWN;
|
||||
|
|
@ -12055,7 +12131,7 @@ void P_RespawnSpecials(void)
|
|||
INT32 time = 30*TICRATE; // Respawn things in empty dedicated servers
|
||||
mapthing_t *mthing = NULL;
|
||||
|
||||
if (gametype == GT_BATTLE && numgotboxes >= (4*nummapboxes/5) && !itembreaker) // Battle Mode respawns all boxes in a different way
|
||||
if ((gametyperules & GTR_BATTLEBOXES) && !itembreaker && numgotboxes >= (4*nummapboxes/5)) // Battle Mode respawns all boxes in a different way
|
||||
{
|
||||
thinker_t *th;
|
||||
|
||||
|
|
@ -12308,14 +12384,18 @@ void P_SpawnPlayer(INT32 playernum)
|
|||
P_FlashPal(p, 0, 0); // Resets
|
||||
|
||||
p->grieftime = 0;
|
||||
p->spinoutrot = 0;
|
||||
|
||||
if (gametyperules & GTR_BUMPERS)
|
||||
if (gametyperules & GTR_ITEMARROWS)
|
||||
{
|
||||
mobj_t *overheadarrow = P_SpawnMobj(mobj->x, mobj->y, mobj->z + mobj->height + 16*FRACUNIT, MT_PLAYERARROW);
|
||||
P_SetTarget(&overheadarrow->target, mobj);
|
||||
overheadarrow->renderflags |= RF_DONTDRAW;
|
||||
P_SetScale(overheadarrow, mobj->destscale);
|
||||
}
|
||||
|
||||
if (gametyperules & GTR_BUMPERS)
|
||||
{
|
||||
if (p->spectator)
|
||||
{
|
||||
// HEY! No being cheap...
|
||||
|
|
@ -12330,7 +12410,7 @@ void P_SpawnPlayer(INT32 playernum)
|
|||
|
||||
K_SpawnPlayerBattleBumpers(p);
|
||||
}
|
||||
else if (p->bumper <= 0)
|
||||
else if (p->bumper <= 0 && (gametyperules & GTR_KARMA))
|
||||
{
|
||||
mobj_t *karmahitbox = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_KARMAHITBOX); // Player hitbox is too small!!
|
||||
P_SetTarget(&karmahitbox->target, mobj);
|
||||
|
|
@ -13510,10 +13590,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
|
|||
}
|
||||
case MT_RANDOMITEM:
|
||||
{
|
||||
if (leveltime < 3)
|
||||
{
|
||||
mobj->flags2 |= MF2_BOSSNOTRAP; // mark as here on map start
|
||||
}
|
||||
mobj->flags2 |= MF2_BOSSNOTRAP; // mark as here on map start
|
||||
nummapboxes++;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
12
src/p_mobj.h
12
src/p_mobj.h
|
|
@ -312,6 +312,9 @@ struct mobj_t
|
|||
fixed_t old_spritexscale2, old_spriteyscale2;
|
||||
fixed_t old_spritexoffset, old_spriteyoffset;
|
||||
fixed_t old_spritexoffset2, old_spriteyoffset2;
|
||||
|
||||
// X and Y offsets that rotate alongside the sprite.
|
||||
INT16 rollingxoffset, rollingyoffset;
|
||||
|
||||
pslope_t *floorspriteslope; // The slope that the floorsprite is rotated by
|
||||
INT16 lightlevel; // Add to sector lightlevel, -255 - 255
|
||||
|
|
@ -404,6 +407,7 @@ struct mobj_t
|
|||
// Extra values are for internal use for whatever you want
|
||||
INT32 extravalue1;
|
||||
INT32 extravalue2;
|
||||
INT32 extravalue3;
|
||||
|
||||
// Custom values are not to be altered by us!
|
||||
// They are for SOCs to store things in.
|
||||
|
|
@ -421,6 +425,8 @@ struct mobj_t
|
|||
UINT8 shadowcolor; // Palette index to use for rendering the shadow
|
||||
|
||||
fixed_t sprxoff, spryoff, sprzoff; // Sprite offsets in real space, does NOT affect position or collision
|
||||
fixed_t bakexoff, bakeyoff, bakezoff; // BAKED sprite offsets. Simulates visuals in real space, and rotates along the object's sprite
|
||||
fixed_t bakexpiv, bakeypiv, bakezpiv; // Pivot points for baked offsets. These are *not* rotated with a sprite
|
||||
|
||||
terrain_t *terrain; // Terrain definition of the floor this object last hit. NULL when in the air.
|
||||
mobj_t *terrainOverlay; // Overlay sprite object for terrain
|
||||
|
|
@ -485,6 +491,10 @@ struct precipmobj_t
|
|||
fixed_t old_spritexscale2, old_spriteyscale2;
|
||||
fixed_t old_spritexoffset, old_spriteyoffset;
|
||||
fixed_t old_spritexoffset2, old_spriteyoffset2;
|
||||
|
||||
// X and Y offsets that rotate alongside the sprite.
|
||||
INT16 rollingxoffset, rollingyoffset;
|
||||
|
||||
pslope_t *floorspriteslope; // The slope that the floorsprite is rotated by
|
||||
INT16 lightlevel; // Add to sector lightlevel, -255 - 255
|
||||
|
||||
|
|
@ -597,6 +607,8 @@ extern boolean slipdashactive;
|
|||
extern boolean purpledriftactive;
|
||||
extern boolean slopeboostactive;
|
||||
extern boolean draftingactive;
|
||||
extern boolean airdropactive;
|
||||
extern UINT8 bumpsparkactive;
|
||||
extern UINT16 bossdisabled;
|
||||
extern boolean stoppedclock;
|
||||
|
||||
|
|
|
|||
433
src/p_saveg.c
433
src/p_saveg.c
|
|
@ -162,6 +162,10 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
|
||||
WRITEINT16(save->p, players[i].totalring);
|
||||
WRITEUINT32(save->p, players[i].realtime);
|
||||
for (j = 0; j < LAP__MAX; j++)
|
||||
{
|
||||
WRITEUINT32(save->p, players[i].laptime[j]);
|
||||
}
|
||||
WRITEUINT8(save->p, players[i].laps);
|
||||
WRITEUINT8(save->p, players[i].latestlap);
|
||||
|
||||
|
|
@ -254,6 +258,7 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
|
||||
WRITEUINT16(save->p, players[i].flashing);
|
||||
WRITEUINT16(save->p, players[i].spinouttimer);
|
||||
WRITEINT32(save->p, players[i].spinoutrot);
|
||||
WRITEUINT8(save->p, players[i].spinouttype);
|
||||
WRITEUINT16(save->p, players[i].flipovertimer);
|
||||
WRITEANGLE(save->p, players[i].flipoverangle);
|
||||
|
|
@ -322,6 +327,7 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
WRITESINT8(save->p, players[i].ringmax);
|
||||
WRITEUINT8(save->p, players[i].pickuprings);
|
||||
WRITEUINT8(save->p, players[i].ringdelay);
|
||||
WRITEUINT8(save->p, players[i].ringlock);
|
||||
WRITEUINT16(save->p, players[i].ringboost);
|
||||
WRITEUINT16(save->p, players[i].ringtime);
|
||||
WRITEUINT16(save->p, players[i].superring);
|
||||
|
|
@ -329,6 +335,9 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
WRITEUINT8(save->p, players[i].ringvolume);
|
||||
WRITEUINT8(save->p, players[i].ringtransparency);
|
||||
|
||||
WRITEUINT8(save->p, players[i].airdroptime);
|
||||
WRITEUINT8(save->p, players[i].ringdrop);
|
||||
|
||||
WRITEUINT8(save->p, players[i].curshield);
|
||||
WRITEUINT8(save->p, players[i].bubblecool);
|
||||
WRITEUINT8(save->p, players[i].bubbleblowup);
|
||||
|
|
@ -442,6 +451,10 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
// Fix janky landing particle
|
||||
WRITEUINT8(save->p, players[i].prevonground);
|
||||
|
||||
// Wall Transfer bonus
|
||||
WRITEUINT8(save->p, players[i].walltransfered);
|
||||
WRITEUINT8(save->p, players[i].walltransferboost);
|
||||
|
||||
}
|
||||
TracyCZoneEnd(__zone);
|
||||
}
|
||||
|
|
@ -517,6 +530,10 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
|||
|
||||
players[i].totalring = READINT16(save->p); // Total number of rings obtained for GP
|
||||
players[i].realtime = READUINT32(save->p); // integer replacement for leveltime
|
||||
for (j = 0; j < LAP__MAX; j++)
|
||||
{
|
||||
players[i].laptime[j] = READUINT32(save->p);
|
||||
}
|
||||
players[i].laps = READUINT8(save->p); // Number of laps (optional)
|
||||
players[i].latestlap = READUINT8(save->p);
|
||||
|
||||
|
|
@ -602,6 +619,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
|||
|
||||
players[i].flashing = READUINT16(save->p);
|
||||
players[i].spinouttimer = READUINT16(save->p);
|
||||
players[i].spinoutrot = READINT32(save->p);
|
||||
players[i].spinouttype = READUINT8(save->p);
|
||||
players[i].flipoverangle = READUINT16(save->p);
|
||||
players[i].flipovertimer = READANGLE(save->p);
|
||||
|
|
@ -670,6 +688,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
|||
players[i].ringmax = READSINT8(save->p);
|
||||
players[i].pickuprings = READUINT8(save->p);
|
||||
players[i].ringdelay = READUINT8(save->p);
|
||||
players[i].ringlock = READUINT8(save->p);
|
||||
players[i].ringboost = READUINT16(save->p);
|
||||
players[i].ringtime = READUINT16(save->p);;
|
||||
players[i].superring = READUINT16(save->p);
|
||||
|
|
@ -677,6 +696,9 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
|||
players[i].ringvolume = READUINT8(save->p);
|
||||
players[i].ringtransparency = READUINT8(save->p);
|
||||
|
||||
players[i].airdroptime = READUINT8(save->p);
|
||||
players[i].ringdrop = READUINT8(save->p);
|
||||
|
||||
players[i].curshield = READUINT8(save->p);
|
||||
players[i].bubblecool = READUINT8(save->p);
|
||||
players[i].bubbleblowup = READUINT8(save->p);
|
||||
|
|
@ -789,7 +811,11 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
|||
players[i].maxlink = READINT32(save->p);
|
||||
|
||||
// Fix janky landing particle
|
||||
players[i].prevonground = READUINT8(save->p);
|
||||
players[i].prevonground = (boolean)READUINT8(save->p);
|
||||
|
||||
// Wall Transfer bonus
|
||||
players[i].walltransfered = (boolean)READUINT8(save->p);
|
||||
players[i].walltransferboost = READUINT8(save->p);
|
||||
|
||||
//players[i].viewheight = P_GetPlayerViewHeight(players[i]); // scale cannot be factored in at this point
|
||||
}
|
||||
|
|
@ -1123,7 +1149,7 @@ static void P_NetUnArchiveColormaps(savebuffer_t *save)
|
|||
#define SD_DIFF3 0x80
|
||||
|
||||
// diff3 flags
|
||||
#define SD_TAGLIST 0x01
|
||||
#define SD__UNUSED 0x01
|
||||
#define SD_COLORMAP 0x02
|
||||
#define SD_CRUMBLESTATE 0x04
|
||||
#define SD_FLOORLIGHT 0x08
|
||||
|
|
@ -1173,7 +1199,7 @@ static boolean P_SectorStringArgsEqual(const sector_t *sc, const sector_t *spawn
|
|||
|
||||
#define LD_FLAG 0x01
|
||||
#define LD_SPECIAL 0x02
|
||||
#define LD_CLLCOUNT 0x04
|
||||
#define LD_TAG 0x04
|
||||
#define LD_S1TEXOFF 0x08
|
||||
#define LD_S1TOPTEX 0x10
|
||||
#define LD_S1BOTTEX 0x20
|
||||
|
|
@ -1187,7 +1213,7 @@ static boolean P_SectorStringArgsEqual(const sector_t *sc, const sector_t *spawn
|
|||
#define LD_S2MIDTEX 0x08
|
||||
#define LD_ARGS 0x10
|
||||
#define LD_STRINGARGS 0x20
|
||||
#define LD_EXECUTORDELAY 0x40
|
||||
#define LD__UNUSED 0x40
|
||||
#define LD_DIFF3 0x80
|
||||
|
||||
// diff3 flags
|
||||
|
|
@ -1600,7 +1626,7 @@ static void UnArchiveSectors(savebuffer_t *save)
|
|||
|
||||
// Add new entries.
|
||||
for (j = 0; j < sectors[i].tags.count; j++)
|
||||
Taggroup_Remove(tags_sectors, sectors[i].tags.tags[j], i);
|
||||
Taggroup_Add(tags_sectors, sectors[i].tags.tags[j], i);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1678,7 +1704,7 @@ static void UnArchiveSectors(savebuffer_t *save)
|
|||
|
||||
static void ArchiveLines(savebuffer_t *save)
|
||||
{
|
||||
size_t i;
|
||||
size_t i, j;
|
||||
const line_t *li = lines;
|
||||
const line_t *spawnli = spawnlines;
|
||||
const side_t *si;
|
||||
|
|
@ -1695,8 +1721,8 @@ static void ArchiveLines(savebuffer_t *save)
|
|||
if (li->special != spawnli->special)
|
||||
diff |= LD_SPECIAL;
|
||||
|
||||
if (spawnli->special == 321 || spawnli->special == 322) // only reason li->callcount would be non-zero is if either of these are involved
|
||||
diff |= LD_CLLCOUNT;
|
||||
if (!Tag_Compare(&li->tags, &spawnli->tags))
|
||||
diff |= LD_TAG;
|
||||
|
||||
if (!P_LineArgsEqual(li, spawnli))
|
||||
diff2 |= LD_ARGS;
|
||||
|
|
@ -1704,9 +1730,6 @@ static void ArchiveLines(savebuffer_t *save)
|
|||
if (!P_LineStringArgsEqual(li, spawnli))
|
||||
diff2 |= LD_STRINGARGS;
|
||||
|
||||
if (li->executordelay != spawnli->executordelay)
|
||||
diff2 |= LD_EXECUTORDELAY;
|
||||
|
||||
if (li->activation != spawnli->activation)
|
||||
diff3 |= LD_ACTIVATION;
|
||||
|
||||
|
|
@ -1756,8 +1779,12 @@ static void ArchiveLines(savebuffer_t *save)
|
|||
WRITEUINT32(save->p, li->flags);
|
||||
if (diff & LD_SPECIAL)
|
||||
WRITEINT16(save->p, li->special);
|
||||
if (diff & LD_CLLCOUNT)
|
||||
WRITEINT16(save->p, li->callcount);
|
||||
if (diff & LD_TAG)
|
||||
{
|
||||
WRITEUINT32(save->p, li->tags.count);
|
||||
for (j = 0; j < li->tags.count; j++)
|
||||
WRITEINT16(save->p, li->tags.tags[j]);
|
||||
}
|
||||
|
||||
si = &sides[li->sidenum[0]];
|
||||
if (diff & LD_S1TEXOFF)
|
||||
|
|
@ -1780,13 +1807,11 @@ static void ArchiveLines(savebuffer_t *save)
|
|||
WRITEINT32(save->p, si->midtexture);
|
||||
if (diff2 & LD_ARGS)
|
||||
{
|
||||
UINT8 j;
|
||||
for (j = 0; j < NUM_SCRIPT_ARGS; j++)
|
||||
WRITEINT32(save->p, li->args[j]);
|
||||
}
|
||||
if (diff2 & LD_STRINGARGS)
|
||||
{
|
||||
UINT8 j;
|
||||
for (j = 0; j < NUM_SCRIPT_STRINGARGS; j++)
|
||||
{
|
||||
size_t len, k;
|
||||
|
|
@ -1803,8 +1828,6 @@ static void ArchiveLines(savebuffer_t *save)
|
|||
WRITECHAR(save->p, li->stringargs[j][k]);
|
||||
}
|
||||
}
|
||||
if (diff2 & LD_EXECUTORDELAY)
|
||||
WRITEINT32(save->p, li->executordelay);
|
||||
if (diff3 & LD_ACTIVATION)
|
||||
WRITEUINT32(save->p, li->activation);
|
||||
}
|
||||
|
|
@ -1814,7 +1837,7 @@ static void ArchiveLines(savebuffer_t *save)
|
|||
|
||||
static void UnArchiveLines(savebuffer_t *save)
|
||||
{
|
||||
UINT16 i;
|
||||
UINT16 i, j;
|
||||
line_t *li;
|
||||
side_t *si;
|
||||
UINT8 diff, diff2, diff3;
|
||||
|
|
@ -1845,8 +1868,28 @@ static void UnArchiveLines(savebuffer_t *save)
|
|||
li->flags = READUINT32(save->p);
|
||||
if (diff & LD_SPECIAL)
|
||||
li->special = READINT16(save->p);
|
||||
if (diff & LD_CLLCOUNT)
|
||||
li->callcount = READINT16(save->p);
|
||||
if (diff & LD_TAG)
|
||||
{
|
||||
size_t ncount = READUINT32(save->p);
|
||||
|
||||
// Remove entries from global lists.
|
||||
for (j = 0; j < lines[i].tags.count; j++)
|
||||
Taggroup_Remove(tags_lines, lines[i].tags.tags[j], i);
|
||||
|
||||
// Reallocate if size differs.
|
||||
if (ncount != lines[i].tags.count)
|
||||
{
|
||||
lines[i].tags.count = ncount;
|
||||
lines[i].tags.tags = (mtag_t*)Z_Realloc(lines[i].tags.tags, ncount*sizeof(mtag_t), PU_LEVEL, NULL);
|
||||
}
|
||||
|
||||
for (j = 0; j < ncount; j++)
|
||||
lines[i].tags.tags[j] = READINT16(save->p);
|
||||
|
||||
// Add new entries.
|
||||
for (j = 0; j < lines[i].tags.count; j++)
|
||||
Taggroup_Add(tags_lines, lines[i].tags.tags[j], i);
|
||||
}
|
||||
|
||||
si = &sides[li->sidenum[0]];
|
||||
if (diff & LD_S1TEXOFF)
|
||||
|
|
@ -1869,13 +1912,11 @@ static void UnArchiveLines(savebuffer_t *save)
|
|||
si->midtexture = READINT32(save->p);
|
||||
if (diff2 & LD_ARGS)
|
||||
{
|
||||
UINT8 j;
|
||||
for (j = 0; j < NUM_SCRIPT_ARGS; j++)
|
||||
li->args[j] = READINT32(save->p);
|
||||
}
|
||||
if (diff2 & LD_STRINGARGS)
|
||||
{
|
||||
UINT8 j;
|
||||
for (j = 0; j < NUM_SCRIPT_STRINGARGS; j++)
|
||||
{
|
||||
size_t len = READINT32(save->p);
|
||||
|
|
@ -1894,8 +1935,6 @@ static void UnArchiveLines(savebuffer_t *save)
|
|||
li->stringargs[j][len] = '\0';
|
||||
}
|
||||
}
|
||||
if (diff2 & LD_EXECUTORDELAY)
|
||||
li->executordelay = READINT32(save->p);
|
||||
if (diff3 & LD_ACTIVATION)
|
||||
li->activation = READUINT32(save->p);
|
||||
|
||||
|
|
@ -2071,7 +2110,8 @@ typedef enum
|
|||
{
|
||||
MD3_GRAVITY = 1,
|
||||
MD3_MISCCAP = 1<<1,
|
||||
|
||||
MD3_BAKEDOFFSET = 1<<2,
|
||||
MD3_EXTVAL3 = 1<<3,
|
||||
} mobj_diff3_t;
|
||||
|
||||
typedef enum
|
||||
|
|
@ -2254,9 +2294,9 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
|
|||
// not the default but the most probable
|
||||
if (mobj->momx != 0 || mobj->momy != 0 || mobj->momz != 0 || mobj->pmomz != 0)
|
||||
diff |= MD_MOM;
|
||||
if (mobj->radius != mobj->info->radius)
|
||||
if (mobj->radius != FixedMul(mapobjectscale, mobj->info->radius))
|
||||
diff |= MD_RADIUS;
|
||||
if (mobj->height != mobj->info->height)
|
||||
if (mobj->height != FixedMul(mapobjectscale, mobj->info->height))
|
||||
diff |= MD_HEIGHT;
|
||||
if (mobj->flags != mobj->info->flags)
|
||||
diff |= MD_FLAGS;
|
||||
|
|
@ -2301,11 +2341,11 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
|
|||
diff |= MD_MOVEFACTOR;
|
||||
if (mobj->fuse)
|
||||
diff |= MD_FUSE;
|
||||
if (mobj->watertop)
|
||||
if (mobj->watertop != INT32_MAX)
|
||||
diff |= MD_WATERTOP;
|
||||
if (mobj->waterbottom)
|
||||
diff |= MD_WATERBOTTOM;
|
||||
if (mobj->scale != FRACUNIT)
|
||||
if (mobj->scale != mapobjectscale)
|
||||
diff |= MD_SCALE;
|
||||
if (mobj->destscale != mobj->scale)
|
||||
diff |= MD_DSCALE;
|
||||
|
|
@ -2348,7 +2388,8 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
|
|||
diff2 |= MD2_TID;
|
||||
if (mobj->spritexscale != FRACUNIT || mobj->spriteyscale != FRACUNIT)
|
||||
diff2 |= MD2_SPRITESCALE;
|
||||
if (mobj->spritexoffset || mobj->spriteyoffset)
|
||||
if (mobj->spritexoffset || mobj->spriteyoffset ||
|
||||
mobj->rollingxoffset || mobj->rollingyoffset)
|
||||
diff2 |= MD2_SPRITEOFFSET;
|
||||
if (mobj->sprxoff || mobj->spryoff || mobj->sprzoff)
|
||||
diff2 |= MD2_WORLDOFFSET;
|
||||
|
|
@ -2383,6 +2424,11 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
|
|||
diff3 |= MD3_GRAVITY;
|
||||
if (mobj == misccap)
|
||||
diff3 |= MD3_MISCCAP;
|
||||
if (mobj->bakexoff || mobj->bakeyoff || mobj->bakezoff || mobj->bakexpiv ||
|
||||
mobj->bakeypiv || mobj->bakezpiv)
|
||||
diff3 |= MD3_BAKEDOFFSET;
|
||||
if (mobj->extravalue3)
|
||||
diff3 |= MD3_EXTVAL3;
|
||||
|
||||
if (diff3 != 0)
|
||||
diff2 |= MD2_MORE;
|
||||
|
|
@ -2587,6 +2633,8 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
|
|||
{
|
||||
WRITEFIXED(save->p, mobj->spritexoffset);
|
||||
WRITEFIXED(save->p, mobj->spriteyoffset);
|
||||
WRITEINT16(save->p, mobj->rollingxoffset);
|
||||
WRITEINT16(save->p, mobj->rollingyoffset);
|
||||
}
|
||||
if (diff2 & MD2_WORLDOFFSET)
|
||||
{
|
||||
|
|
@ -2651,13 +2699,26 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
|
|||
}
|
||||
if (diff2 & MD2_TERRAIN)
|
||||
{
|
||||
WRITEUINT32(save->p, K_GetTerrainHeapIndex(mobj->terrain));
|
||||
WRITEUINT32(save->p, K_GetTerrainHeapIndex(mobj->terrain) + 1);
|
||||
WRITEUINT32(save->p, SaveMobjnum(mobj->terrainOverlay));
|
||||
}
|
||||
if (diff3 & MD3_GRAVITY)
|
||||
{
|
||||
WRITEFIXED(save->p, mobj->gravity);
|
||||
}
|
||||
if (diff3 & MD3_BAKEDOFFSET)
|
||||
{
|
||||
WRITEFIXED(save->p, mobj->bakexoff);
|
||||
WRITEFIXED(save->p, mobj->bakeyoff);
|
||||
WRITEFIXED(save->p, mobj->bakezoff);
|
||||
WRITEFIXED(save->p, mobj->bakexpiv);
|
||||
WRITEFIXED(save->p, mobj->bakeypiv);
|
||||
WRITEFIXED(save->p, mobj->bakezpiv);
|
||||
}
|
||||
if (diff3 & MD3_EXTVAL3)
|
||||
{
|
||||
WRITEINT32(save->p, mobj->extravalue3);
|
||||
}
|
||||
|
||||
WRITEUINT32(save->p, mobj->mobjnum);
|
||||
}
|
||||
|
|
@ -3540,7 +3601,22 @@ static inline pslope_t *LoadSlope(UINT32 slopeid)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
|
||||
static mobjtype_t g_doomednum_to_mobjtype[UINT16_MAX];
|
||||
|
||||
static void CalculateDoomednumToMobjtype(void)
|
||||
{
|
||||
memset(g_doomednum_to_mobjtype, MT_NULL, sizeof(g_doomednum_to_mobjtype));
|
||||
|
||||
for (size_t i = MT_NULL+1; i < NUMMOBJTYPES; i++)
|
||||
{
|
||||
if (mobjinfo[i].doomednum > 0 && mobjinfo[i].doomednum <= UINT16_MAX)
|
||||
{
|
||||
g_doomednum_to_mobjtype[ mobjinfo[i].doomednum ] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker, UINT8 tclass)
|
||||
{
|
||||
mobj_t *mobj;
|
||||
UINT32 diff;
|
||||
|
|
@ -3590,17 +3666,20 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL);
|
||||
mobj = P_AllocateMobj();
|
||||
|
||||
mobj->spawnpoint = &mapthings[spawnpointnum];
|
||||
mapthings[spawnpointnum].mobj = mobj;
|
||||
}
|
||||
else
|
||||
mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL);
|
||||
mobj = P_AllocateMobj();
|
||||
|
||||
// declare this as a valid mobj as soon as possible.
|
||||
mobj->thinker.function.acp1 = thinker;
|
||||
|
||||
// manually link to thinkerlist, since the thinker isn't returned anymore
|
||||
P_AddThinker(tclass, &mobj->thinker);
|
||||
|
||||
mobj->z = z;
|
||||
mobj->floorz = floorz;
|
||||
mobj->ceilingz = ceilingz;
|
||||
|
|
@ -3611,20 +3690,26 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
|
|||
mobj->type = READUINT32(save->p);
|
||||
else
|
||||
{
|
||||
for (i = 0; i < NUMMOBJTYPES; i++)
|
||||
if (mobj->spawnpoint && mobj->spawnpoint->type == mobjinfo[i].doomednum)
|
||||
break;
|
||||
if (i == NUMMOBJTYPES)
|
||||
mobjtype_t new_type = MT_NULL;
|
||||
if (mobj->spawnpoint)
|
||||
{
|
||||
new_type = g_doomednum_to_mobjtype[mobj->spawnpoint->type];
|
||||
}
|
||||
|
||||
if (new_type <= MT_NULL || new_type >= NUMMOBJTYPES)
|
||||
{
|
||||
if (mobj->spawnpoint)
|
||||
CONS_Alert(CONS_ERROR, "Found mobj with unknown map thing type %d\n", mobj->spawnpoint->type);
|
||||
CONS_Alert(CONS_ERROR, "Found mobj with unknown map thing doomednum %d\n", mobj->spawnpoint->type);
|
||||
else
|
||||
CONS_Alert(CONS_ERROR, "Found mobj with unknown map thing type NULL\n");
|
||||
CONS_Alert(CONS_ERROR, "Found mobj with unknown map thing doomednum NULL\n");
|
||||
|
||||
I_Error("Netsave corrupted");
|
||||
}
|
||||
mobj->type = i;
|
||||
|
||||
mobj->type = new_type;
|
||||
}
|
||||
mobj->info = &mobjinfo[mobj->type];
|
||||
|
||||
if (diff & MD_POS)
|
||||
{
|
||||
mobj->x = mobj->old_x = READFIXED(save->p);
|
||||
|
|
@ -3652,11 +3737,11 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
|
|||
if (diff & MD_RADIUS)
|
||||
mobj->radius = READFIXED(save->p);
|
||||
else
|
||||
mobj->radius = mobj->info->radius;
|
||||
mobj->radius = FixedMul(mobj->info->radius, mapobjectscale);
|
||||
if (diff & MD_HEIGHT)
|
||||
mobj->height = READFIXED(save->p);
|
||||
else
|
||||
mobj->height = mobj->info->height;
|
||||
mobj->height = FixedMul(mobj->info->height, mapobjectscale);
|
||||
if (diff & MD_FLAGS)
|
||||
mobj->flags = READUINT32(save->p);
|
||||
else
|
||||
|
|
@ -3734,12 +3819,14 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
|
|||
mobj->fuse = READINT32(save->p);
|
||||
if (diff & MD_WATERTOP)
|
||||
mobj->watertop = READFIXED(save->p);
|
||||
else
|
||||
mobj->watertop = INT32_MAX;
|
||||
if (diff & MD_WATERBOTTOM)
|
||||
mobj->waterbottom = READFIXED(save->p);
|
||||
if (diff & MD_SCALE)
|
||||
mobj->scale = READFIXED(save->p);
|
||||
else
|
||||
mobj->scale = FRACUNIT;
|
||||
mobj->scale = mapobjectscale;
|
||||
if (diff & MD_DSCALE)
|
||||
mobj->destscale = READFIXED(save->p);
|
||||
else
|
||||
|
|
@ -3822,10 +3909,13 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
|
|||
{
|
||||
mobj->spritexoffset = READFIXED(save->p);
|
||||
mobj->spriteyoffset = READFIXED(save->p);
|
||||
mobj->rollingxoffset = READINT16(save->p);
|
||||
mobj->rollingyoffset = READINT16(save->p);
|
||||
}
|
||||
else
|
||||
{
|
||||
mobj->spritexoffset = mobj->spriteyoffset = 0;
|
||||
mobj->rollingxoffset = mobj->rollingyoffset = 0;
|
||||
}
|
||||
if (diff2 & MD2_WORLDOFFSET)
|
||||
{
|
||||
|
|
@ -3897,7 +3987,9 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
|
|||
}
|
||||
if (diff2 & MD2_TERRAIN)
|
||||
{
|
||||
mobj->terrain = (terrain_t *)(size_t)READUINT32(save->p);
|
||||
UINT32 terrain_index = READUINT32(save->p);
|
||||
if (terrain_index > 0)
|
||||
mobj->terrain = K_GetTerrainByIndex(terrain_index - 1);
|
||||
mobj->terrainOverlay = (mobj_t *)(size_t)READUINT32(save->p);
|
||||
}
|
||||
else
|
||||
|
|
@ -3912,6 +4004,24 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
|
|||
{
|
||||
mobj->gravity = FRACUNIT;
|
||||
}
|
||||
if (diff3 & MD3_BAKEDOFFSET)
|
||||
{
|
||||
mobj->bakexoff = READFIXED(save->p);
|
||||
mobj->bakeyoff = READFIXED(save->p);
|
||||
mobj->bakezoff = READFIXED(save->p);
|
||||
mobj->bakexpiv = READFIXED(save->p);
|
||||
mobj->bakeypiv = READFIXED(save->p);
|
||||
mobj->bakezpiv = READFIXED(save->p);
|
||||
}
|
||||
else
|
||||
{
|
||||
mobj->bakexoff = mobj->bakeyoff = mobj->bakezoff = 0;
|
||||
mobj->bakexpiv = mobj->bakeypiv = mobj->bakezpiv = 0;
|
||||
}
|
||||
if (diff3 & MD3_EXTVAL3)
|
||||
{
|
||||
mobj->extravalue3 = READINT32(save->p);
|
||||
}
|
||||
|
||||
// Reset some non-synch values
|
||||
mobj->sloperoll = 0;
|
||||
|
|
@ -3952,7 +4062,9 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
|
|||
|
||||
R_AddMobjInterpolator(mobj);
|
||||
|
||||
return &mobj->thinker;
|
||||
// don't allow the mobj's refcount to be reset by P_AddThinker
|
||||
// we might've already called P_SetTarget!
|
||||
return NULL;//&mobj->thinker;
|
||||
}
|
||||
|
||||
static thinker_t* LoadNoEnemiesThinker(savebuffer_t *save, actionf_p1 thinker)
|
||||
|
|
@ -4571,6 +4683,10 @@ static void P_NetUnArchiveThinkers(savebuffer_t *save)
|
|||
if (READUINT32(save->p) != ARCHIVEBLOCK_THINKERS)
|
||||
I_Error("Bad $$$.sav at archive block Thinkers");
|
||||
|
||||
// Pre-calculate this lookup, because it was wasting
|
||||
// a shit ton of time loading mobj thinkers.
|
||||
CalculateDoomednumToMobjtype();
|
||||
|
||||
// remove all the current thinkers
|
||||
for (i = 0; i < NUM_THINKERLISTS; i++)
|
||||
{
|
||||
|
|
@ -4615,7 +4731,7 @@ static void P_NetUnArchiveThinkers(savebuffer_t *save)
|
|||
switch (tclass)
|
||||
{
|
||||
case tc_mobj:
|
||||
th = LoadMobjThinker(save, (actionf_p1)P_MobjThinker);
|
||||
th = LoadMobjThinker(save, (actionf_p1)P_MobjThinker, i);
|
||||
break;
|
||||
|
||||
case tc_ceiling:
|
||||
|
|
@ -4970,15 +5086,6 @@ static void P_RelinkPointers(void)
|
|||
if (!RelinkMobj(&mobj->itnext))
|
||||
CONS_Debug(DBG_GAMELOGIC, "itnext not found on %d\n", mobj->type);
|
||||
}
|
||||
if (mobj->terrain)
|
||||
{
|
||||
temp = (UINT32)(size_t)mobj->terrain;
|
||||
mobj->terrain = K_GetTerrainByIndex(temp);
|
||||
if (mobj->terrain == NULL)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "terrain not found on %d\n", mobj->type);
|
||||
}
|
||||
}
|
||||
if (mobj->terrainOverlay)
|
||||
{
|
||||
if (!RelinkMobj(&mobj->terrainOverlay))
|
||||
|
|
@ -5218,6 +5325,8 @@ static void P_NetArchiveMisc(savebuffer_t *save, boolean resending)
|
|||
WRITEUINT8(save->p, purpledriftactive);
|
||||
WRITEUINT8(save->p, slopeboostactive);
|
||||
WRITEUINT8(save->p, draftingactive);
|
||||
WRITEUINT8(save->p, airdropactive);
|
||||
WRITEUINT8(save->p, bumpsparkactive);
|
||||
|
||||
for (i = 0; i < 12; i++)
|
||||
{
|
||||
|
|
@ -5287,6 +5396,9 @@ static void P_NetArchiveMisc(savebuffer_t *save, boolean resending)
|
|||
WRITESINT8(save->p, speedscramble);
|
||||
WRITESINT8(save->p, encorescramble);
|
||||
|
||||
|
||||
// WANTED system
|
||||
WRITESINT8(save->p, mostwanted);
|
||||
for (i = 0; i < 4; i++)
|
||||
WRITESINT8(save->p, battlewanted[i]);
|
||||
|
||||
|
|
@ -5348,9 +5460,11 @@ FUNCINLINE static ATTRINLINE boolean P_NetUnArchiveMisc(savebuffer_t *save, bool
|
|||
{
|
||||
TracyCZone(__zone, true);
|
||||
|
||||
size_t i;
|
||||
size_t i, j;
|
||||
size_t numTasks;
|
||||
|
||||
const INT16 prevgamemap = gamemap;
|
||||
|
||||
if (READUINT32(save->p) != ARCHIVEBLOCK_MISC)
|
||||
I_Error("Bad $$$.sav at archive block Misc");
|
||||
|
||||
|
|
@ -5390,10 +5504,206 @@ FUNCINLINE static ATTRINLINE boolean P_NetUnArchiveMisc(savebuffer_t *save, bool
|
|||
|
||||
mapmusrng = READUINT8(save->p);
|
||||
|
||||
if (!P_LoadLevel(true, reloading))
|
||||
// Only reload the level during a gamestate reload
|
||||
// if the map is horribly mismatched somehow. Minor
|
||||
// differences in level state are already handled
|
||||
// by other parts of the reload, so doing this
|
||||
// on *every* reload wastes lots of time that we
|
||||
// will need for rollback down the road.
|
||||
if (!reloading || prevgamemap != gamemap)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Can't load the level!\n"));
|
||||
return false;
|
||||
if (!P_LoadLevel(true, reloading))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Can't load the level!\n"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Only reload stuff that can we modify in the save states themselves.
|
||||
// This is still orders of magnitude faster than a full level reload.
|
||||
// Considered memcpy, but it's complicated -- save that for local saves.
|
||||
|
||||
sector_t *ss = sectors;
|
||||
sector_t *spawnss = spawnsectors;
|
||||
for (i = 0; i < numsectors; i++, ss++, spawnss++)
|
||||
{
|
||||
ss->floorheight = spawnss->floorheight;
|
||||
ss->ceilingheight = spawnss->ceilingheight;
|
||||
ss->floorpic = spawnss->floorpic;
|
||||
ss->ceilingpic = spawnss->ceilingpic;
|
||||
ss->lightlevel = spawnss->lightlevel;
|
||||
ss->special = spawnss->special;
|
||||
ss->floor_xoffs = spawnss->floor_xoffs;
|
||||
ss->floor_yoffs = spawnss->floor_yoffs;
|
||||
ss->ceiling_xoffs = spawnss->ceiling_xoffs;
|
||||
ss->ceiling_yoffs = spawnss->ceiling_yoffs;
|
||||
ss->floorpic_angle = spawnss->floorpic_angle;
|
||||
ss->ceilingpic_angle = spawnss->ceilingpic_angle;
|
||||
|
||||
if (Tag_Compare(&ss->tags, &spawnss->tags) == false)
|
||||
{
|
||||
if (spawnss->tags.count)
|
||||
{
|
||||
ss->tags.count = spawnss->tags.count;
|
||||
ss->tags.tags =
|
||||
memcpy(
|
||||
Z_Realloc(
|
||||
ss->tags.tags,
|
||||
spawnss->tags.count * sizeof(mtag_t),
|
||||
PU_LEVEL,
|
||||
NULL
|
||||
),
|
||||
spawnss->tags.tags,
|
||||
spawnss->tags.count * sizeof(mtag_t)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
ss->tags.count = 0;
|
||||
Z_Free(ss->tags.tags);
|
||||
}
|
||||
}
|
||||
|
||||
ss->extra_colormap = ss->spawn_extra_colormap;
|
||||
ss->crumblestate = CRUMBLE_NONE;
|
||||
ss->floorlightlevel = spawnss->floorlightlevel;
|
||||
ss->floorlightabsolute = spawnss->floorlightabsolute;
|
||||
ss->ceilinglightlevel = spawnss->ceilinglightlevel;
|
||||
ss->ceilinglightabsolute = spawnss->ceilinglightabsolute;
|
||||
ss->flags = spawnss->flags;
|
||||
ss->specialflags = spawnss->specialflags;
|
||||
ss->damagetype = spawnss->damagetype;
|
||||
ss->triggertag = spawnss->triggertag;
|
||||
ss->triggerer = spawnss->triggerer;
|
||||
ss->gravity = spawnss->gravity;
|
||||
ss->action = spawnss->action;
|
||||
|
||||
memcpy(ss->args, spawnss->args, NUM_SCRIPT_ARGS * sizeof(*ss->args));
|
||||
|
||||
for (j = 0; j < NUM_SCRIPT_STRINGARGS; j++)
|
||||
{
|
||||
size_t len = 0;
|
||||
|
||||
if (spawnss->stringargs[j])
|
||||
{
|
||||
len = strlen(spawnss->stringargs[j]);
|
||||
}
|
||||
|
||||
if (!len)
|
||||
{
|
||||
Z_Free(ss->stringargs[j]);
|
||||
ss->stringargs[j] = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ss->stringargs[j] = Z_Realloc(ss->stringargs[j], len + 1, PU_LEVEL, NULL);
|
||||
M_Memcpy(ss->stringargs[j], spawnss->stringargs[j], len);
|
||||
ss->stringargs[j][len] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
ss->activation = spawnss->activation;
|
||||
ss->botController.flags = spawnss->botController.flags;
|
||||
ss->botController.forceAngle = spawnss->botController.forceAngle;
|
||||
|
||||
if (ss->ffloors)
|
||||
{
|
||||
ffloor_t *rover;
|
||||
for (rover = ss->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
rover->fofflags = rover->spawnflags;
|
||||
rover->alpha = rover->spawnalpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
line_t *li = lines;
|
||||
line_t *spawnli = spawnlines;
|
||||
side_t *si = NULL;
|
||||
side_t *spawnsi = NULL;
|
||||
for (i = 0; i < numlines; i++, spawnli++, li++)
|
||||
{
|
||||
li->flags = spawnli->flags;
|
||||
li->special = spawnli->special;
|
||||
li->callcount = 0;
|
||||
|
||||
if (Tag_Compare(&li->tags, &spawnli->tags) == false)
|
||||
{
|
||||
if (spawnli->tags.count)
|
||||
{
|
||||
li->tags.count = spawnli->tags.count;
|
||||
li->tags.tags =
|
||||
memcpy(
|
||||
Z_Realloc(
|
||||
li->tags.tags,
|
||||
spawnli->tags.count * sizeof(mtag_t),
|
||||
PU_LEVEL,
|
||||
NULL
|
||||
),
|
||||
spawnli->tags.tags,
|
||||
spawnli->tags.count * sizeof(mtag_t)
|
||||
);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
li->tags.count = 0;
|
||||
Z_Free(li->tags.tags);
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(li->args, spawnli->args, NUM_SCRIPT_ARGS * sizeof(*li->args));
|
||||
|
||||
for (j = 0; j < NUM_SCRIPT_STRINGARGS; j++)
|
||||
{
|
||||
size_t len = 0;
|
||||
|
||||
if (spawnli->stringargs[j])
|
||||
{
|
||||
len = strlen(spawnli->stringargs[j]);
|
||||
}
|
||||
|
||||
if (!len)
|
||||
{
|
||||
Z_Free(li->stringargs[j]);
|
||||
li->stringargs[j] = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
li->stringargs[j] = Z_Realloc(li->stringargs[j], len + 1, PU_LEVEL, NULL);
|
||||
M_Memcpy(li->stringargs[j], spawnli->stringargs[j], len);
|
||||
li->stringargs[j][len] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
li->executordelay = spawnli->executordelay;
|
||||
li->activation = spawnli->activation;
|
||||
|
||||
if (li->sidenum[0] != 0xffff)
|
||||
{
|
||||
si = &sides[li->sidenum[0]];
|
||||
spawnsi = &spawnsides[li->sidenum[0]];
|
||||
|
||||
si->textureoffset = spawnsi->textureoffset;
|
||||
si->toptexture = spawnsi->toptexture;
|
||||
si->bottomtexture = spawnsi->bottomtexture;
|
||||
si->midtexture = spawnsi->midtexture;
|
||||
}
|
||||
|
||||
if (li->sidenum[1] != 0xffff)
|
||||
{
|
||||
si = &sides[li->sidenum[1]];
|
||||
spawnsi = &spawnsides[li->sidenum[1]];
|
||||
|
||||
si->textureoffset = spawnsi->textureoffset;
|
||||
si->toptexture = spawnsi->toptexture;
|
||||
si->bottomtexture = spawnsi->bottomtexture;
|
||||
si->midtexture = spawnsi->midtexture;
|
||||
}
|
||||
}
|
||||
|
||||
Taglist_InitGlobalTables();
|
||||
}
|
||||
|
||||
// get the time
|
||||
|
|
@ -5407,6 +5717,8 @@ FUNCINLINE static ATTRINLINE boolean P_NetUnArchiveMisc(savebuffer_t *save, bool
|
|||
purpledriftactive = READUINT8(save->p);
|
||||
slopeboostactive = READUINT8(save->p);
|
||||
draftingactive = READUINT8(save->p);
|
||||
airdropactive = READUINT8(save->p);
|
||||
bumpsparkactive = READUINT8(save->p);
|
||||
|
||||
for (i = 0; i < 12; i++)
|
||||
{
|
||||
|
|
@ -5473,6 +5785,7 @@ FUNCINLINE static ATTRINLINE boolean P_NetUnArchiveMisc(savebuffer_t *save, bool
|
|||
speedscramble = READSINT8(save->p);
|
||||
encorescramble = READSINT8(save->p);
|
||||
|
||||
mostwanted = READSINT8(save->p);
|
||||
for (i = 0; i < 4; i++)
|
||||
battlewanted[i] = READSINT8(save->p);
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue