Compare commits

..
122 Commits
Author SHA1 Message Date
alufolie91 794fda5ac5 fix issues with interpolation when spawning mobjs
fixes them seemingly coming really fast out of nowhere
needs testing as this may break some things from addons
2026-07-21 15:58:34 +02:00
alufolie91 31517ebebe smol fbo stuff cleanup
was from the water branch
2026-07-21 15:54:18 +02:00
alufolie91 3a2e009d01 have the musiccredit "box" style be colourized 2026-07-21 15:52:02 +02:00
alufolie91 38e50a3cfb bit more p_mobj cleanup
more unnesting stuffs
2026-07-21 15:31:33 +02:00
alufolie91 97555bc263 remove trailing whitespaces from musicdef fields
mostly just to prevent the warning popping from those, but also why not lol
2026-07-21 15:03:38 +02:00
alufolie91 848115d105 print the unedited musicdef field for whitespace warning
otherwise this may just show whitespaces where they arent ones originally
2026-07-21 15:03:27 +02:00
alufolie91 3668c2c4f3 more code cleanups
+ remove duped slopelanding stuff
mostly just unnesting stuffs, some mobj checks, etc
2026-07-21 14:44:56 +02:00
alufolie91 d5f68bf2aa fix compiler warning for sound stuff.....
:chaosleep:
2026-07-20 16:33:51 +02:00
alufolie91 3ae968f060 smol random cleanups 2026-07-20 16:08:55 +02:00
alufolie91 d73f79509e actually reduce pointinsubsector in P_SpawnMapThings in some cases lol
bunch of vanilla maps have rings and stuff present lul
2026-07-20 16:05:04 +02:00
MIDIMan 19e9eedce3 Fix NiGHTS hoops crashing the game for mid-level netgame joiners 2026-07-20 15:50:16 +02:00
alufolie91 8880057ff2 fix and cleanup P_SpawnMapThings
-split emeraldhunt handling into its own function
-merge hoop spawn loop into the main mapthing spawnloop
-continue early for things like rings and coins
- reduce the amount of R_PointInSubsector on maps with nights hoops
hopefully reduces levelload time slightly
2026-07-20 15:50:13 +02:00
alufolie91 9692484d2e fix issues with sound freeslotting
this "works" with a skinlimit of 255
but would cause hard to debug crashes with raised skinlimits and was generally really unsafe and could cause soundnames to not be null terminated aswell as buffer overflows from blind strcpy
the sprintf fix is from Indev originally for neptune
NOTE: if the skinlimit is ever raised above 1024 then freeslotnames NEEDS to be atleast one byte bigger to not truncuate stuff
NOTE2: pretty sure localskins are fucked if any are loaded in servers with 255 skins loaded, but i dont care atm
2026-07-20 11:29:19 +02:00
alufolie91 df3a64339c fix skin search command overflow
when using localskins and going over the skinlimit
this should use numskins not numallskins there
no i dont feel like supporting localskins here the other skin commands also dont care
2026-07-20 01:01:09 +02:00
indev 5a966aa317 Re-add playernode check 2026-07-20 01:54:47 +03:00
indev a132db9e6e Attempt to fix server locking up when trying to kick player that has left already 2026-07-19 23:41:19 +03:00
alufolie91 0acfc96812 attempt to fix kick/ban commands causing dedicated servers to self destruct
if a player was specified which was not being in game
this is what caused dedis to sometimes go to the main menu
2026-07-19 06:16:50 +02:00
alufolie91 f09c61cee9 only play stairjank sound if we have its visuals enabled 2026-07-19 02:42:18 +02:00
alufolie91 735c4b67dc move stairjank particles into K_MoveKartPlayer
to where we also rotate the player
also means we now use K_AltFlip :p
also means the visual toggle now actually does prevent spawning them
2026-07-19 02:40:17 +02:00
alufolie91 267a758447 fix up dedi i_system 2026-07-19 02:36:16 +02:00
indev 6892c212d1 Comment out stairjank particles for now, since spawning mobjs during P_TryMove may mess up some global variables 2026-07-19 03:31:09 +03:00
alufolie91 a1127068df fix wireframe potentially not disabling on toggle
netupdate sucks ass
2026-07-17 22:43:23 +02:00
alufolie91 7ee93d889e remove this from polyvertex_t
was used for optimization but not used anymore
2026-07-16 20:16:42 +02:00
alufolie91 ee9c9e2839 hack: fix paletterender stuff not applying to screenshots/gifs when using downsampling fbo
this sucks
but the final screen texture with the palette render postprocess step will not be in the downsample fbo
so we have to redraw it there with the postprocess step......
this is still better than drawing another screen texture when using paletterender which costs perf
2026-07-14 11:28:49 +02:00
alufolie91 28c4061a26 remove viewsky which doesent exist lol 2026-07-14 09:40:37 +02:00
alufolie91 d0f02f1530 remove pointless skybox check here
if skybox then newview->sky will be false there which R_DrawSkyPlanes will check for
2026-07-14 09:40:35 +02:00
alufolie91 53fbbecbcd fix incrementing garbage in Portal_AddSkyboxPortals 2026-07-14 03:00:42 +02:00
indev 587f24ae85 Add empty I_OpenURL into dedicated server build 2026-07-13 23:56:53 +03:00
alufolie91 ba0b414062 fix paletterender toggle calling setpalette during startup 2026-07-13 20:31:30 +02:00
alufolie91 b27b4bfd7a software: fix cv_spriteclip
scaled sprites should be excluded from the simple viewwindow checks
also R_CheckSpriteVisible should be done AFTER portal adjustments
2026-07-13 07:47:51 +02:00
alufolie91 7971f76885 software: cleanup sky hacks
still horrid, but atleast this wont give me braindamage each time i have to look at it
this also read stale data from the previous frames and was just insanely messy
this still sucks ass but oh well
2026-07-13 07:47:48 +02:00
alufolie91 7048eeacc3 Portal_AddSkybox can be static
its unused anyways
also adds plane bounds check which was missing
2026-07-13 07:44:47 +02:00
alufolie91 8a62f4e978 software: move hom removal to R_RenderPlayerView
gl also has it there so why not
2026-07-13 07:44:38 +02:00
Eidolon f5fdf917bd Support >4GB sys mem in memfree for linux, win32, macOS sys mem counts
Also includes memory counts for the extended allocation functionality
2026-07-13 07:44:33 +02:00
alufolie91 b9ac91c74f fix eggbox crap
:chaosleep:
2026-07-09 23:49:16 +02:00
indev b408a098bd Fix netxcmdnames missing one name 2026-07-09 13:01:13 +03:00
alufolie91 90ab1f4994 cleanup opengl wipe stuff a little
split it like srb2.2
2026-07-09 06:47:26 +02:00
alufolie91 96484c94db fix & cleanup hw_bsp
this basically brings it to the latest state from Doom-Legacy before the big refactor (which i had previously ported and tested as well) + some extra stuff from it
sadly this does not seem to fix plane holes, but its a bit cleaner and more accurate in some places
while the big refactor did fix issues with plane holes, it also introduced a few new issues, like z-fighting sneaker panels and significantly longer loading times
may as well just wait at this point for what (or rather if) RR will be doing
2026-07-09 06:47:26 +02:00
alufolie91 c805fa9f33 remove a bunch of unused crap 2026-07-09 06:46:27 +02:00
alufolie91 29159ca5cd whoopsie
sleeby....
2026-07-08 20:37:16 +02:00
alufolie91 b6b70ae8f0 Add "Report an Issue" button in the Saturn Menu
yoinked from SRB2-Legacy
2026-07-08 20:33:24 +02:00
alufolie91 2b0e4b7468 have fallback if SDL_OpenURL fails or does not exist on the Error box 2026-07-08 20:33:20 +02:00
alufolie91 c374bd75fc menu for controller rumble stuff 2026-07-07 13:10:05 +02:00
alufolie91 ec70e8aa29 only apply LUA controller rumble and led color to local players
what my dumb ass was meaning to do with 2ae1e0f56e
displayplayer[0] does not necessarily map to a local player!
2026-07-06 04:59:33 +02:00
alufolie91 3ad6159e85 make controller rumble types toggable separately
needs a proper menu, but too lazy for that currently
2026-07-05 22:51:29 +02:00
alufolie91 2ae1e0f56e only rumble controllers for local players
also not in replays
2026-07-05 22:25:39 +02:00
alufolie91 2302d4efbd mark R_ThingIsFullBrightT as static 2026-07-05 21:36:51 +02:00
alufolie91 be08c9cd1f changes to some saturn specific visual effects
most of those were added cause they´re cool to look at, but without much thought about potentially giving players that enable such features an "unfair" advantage over others.
- eggboxes wont be rotated while stationary and on the ground anymore (they are meant to deceive players, being rotated makes them stand out alot!)
- players that are about to explode due to eggboxes wont spawn extra red speedlines anymore
- option to show driftlevel per speedlines has been removed
2026-07-05 21:36:48 +02:00
alufolie91 7b91666db9 clean up some frameflags stuff
mfw no FF_VERTICALFLIP
2026-07-04 20:17:03 +02:00
alufolie91 ba5c85ba8a :chaosleep: 2026-07-04 06:21:06 +02:00
alufolie91 05e8771fbc Revert "add warning if theres no music lump for musicdef"
This reverts commit 59b7b0529f.
very fun if the music lumps were split into some other file!
2026-07-03 19:08:54 +02:00
alufolie91 59b7b0529f add warning if theres no music lump for musicdef
if theyre left over or typo´d (which prevents them from showing up)
2026-07-03 19:01:10 +02:00
alufolie91 3fa8ab442a print warning if whitespaces are encountered in musicdef fields
technically that is a non issue for saturn but vanilla will completely explode from this
2026-07-03 18:27:49 +02:00
indev fdd8381258 Fix 'attack or protect' text being offcentered on certain resolutions 2026-07-03 15:10:08 +03:00
alufolie91 41cbce3ed3 hack for kartdebugcheckpoint display
see comment
2026-07-02 19:43:06 +02:00
alufolie91 63e4c5a63d use viewsin and viewcos for spherefrustum checks in gl
dont need all those yaw vars, since they effectively map to gl_viewsin and -gl_viewcos respectively
while those are less accurate due to being fixed point, there appears to be no visual issues from this and seems to even slightly improve performance in some cases
2026-07-02 18:34:32 +02:00
alufolie91 bba86fe4af fix DRAWONLYFORX sprite visability handling
this effectively didnt do anything and had a typo for the player 3 case anyways
2026-07-02 18:34:29 +02:00
alufolie91 1dee3060dd add some more mobj checks to p_map
cross-checked against srb2 next branch
2026-07-02 18:34:22 +02:00
alufolie91 56c2178bde cleanup COMPAT_VANILLA mobj checks
move stuff into a helper func, which just returns if mo != NULL in vanilla compat mode, otherwise returns P_MobjWasRemoved
reasoning for this crap is in the comment above said helper
2026-07-02 18:34:19 +02:00
alufolie91 e445669521 cleanup stuff a bit for unused gametypes
wish could just remove all of this but gotta keep it for compat reasons ig
2026-07-02 18:34:06 +02:00
alufolie91 7a309bc0b8 make this less messy 2026-07-01 22:45:37 +02:00
alufolie91 8b6ebfbad4 promote those null checks again.....
sigh......
atleast this should be right this time
2026-07-01 22:26:50 +02:00
indev 5775c12b16 Disable writing to replay query while replays are loading 2026-07-01 23:23:04 +03:00
alufolie91 78ebc14d88 print performance warning for lua scripts using mobj hooks without specific mobjtype
thx indev for help <3
these may trash performance quite hard at times
and are not visible from just perfstats most of the time
2026-07-01 19:21:41 +02:00
alufolie91 551d7d4d89 add V_DrawRightAlignedSmallStringAtFixed
idk but might be useful
2026-07-01 18:08:56 +02:00
alufolie91 a2184d2bef move cv_audbuffersize register
this stuff kinda grouped some cvars together, makes more sense there
2026-07-01 18:08:53 +02:00
alufolie91 d638baeda6 change mobj hook detection again
so we can restore the actual correct behavior for the HurtMsg hook, which nothing even uses lol
2026-07-01 18:08:50 +02:00
alufolie91 4a06e8a6d1 fix map replacement checks for pwads added on startup
stuff added per -file or whatever
this incorrectly rechecked the iwads again instead of the pwads themselves, which let to the game flagging vanilla maps as replaced, setting the game to be modified
2026-06-30 18:37:04 +02:00
alufolie91 e2a3992787 make online hud / chat menu scrollable
yes i checked green res....
it barely fits like this........
2026-06-29 22:02:18 +02:00
indev ec06150432 This todo is done :3 2026-06-29 20:45:45 +03:00
indev 2413a3503c Add stairjank particle effect using drift dust 2026-06-29 20:44:30 +03:00
alufolie91 d9e339cb56 toggable sound effect for stair jank
not the biggest fan of it but idk how to make this better on stairs with lots of steps
so this will do for now
2026-06-29 18:13:30 +02:00
alufolie91 408db7a2eb use G_KeynumToString for local addon menu key info
just in case we change them dont have to change them everywhere
2026-06-29 15:46:11 +02:00
alufolie91 e12ecabcf0 revert some P_IsObjectOnGround
pretty sure none of those cause issues currently, but rather not risk stuff as that condition might change from smth else in those cases
its not an expensive call anyways really
2026-06-29 15:35:45 +02:00
alufolie91 65c2d2733d clear deathmatch and ctf spawnpoints aswell
prob wont matter much for us but still better to not leave those dangling after map change
2026-06-29 14:43:04 +02:00
alufolie91 00aa023e9e cleanup p_setup a bit again 2026-06-29 14:42:58 +02:00
alufolie91 f43a4a2eb6 have gametype i_error actually print the invalid gametype
bit more informative ig?
2026-06-29 02:14:53 +02:00
alufolie91 4eb108e0a6 add sound thing for reference
does nothing cause it sucks
maybe someone else has a better idea what to do here
2026-06-29 02:13:59 +02:00
alufolie91 ea76af5a81 seenames is stupid
keep that ashnal utils breaks without this crap
2026-06-29 01:46:39 +02:00
alufolie91 4b8f998c85 cast this crap 2026-06-28 22:58:20 +02:00
alufolie91 d687be4997 change K_GetSpeedometerStyle to unsinged
does not need be signed
most other things will cache this into an uint8 eitherway
2026-06-28 22:34:09 +02:00
alufolie91 1bcadf3c46 fix the lap emblem animation thingie 2026-06-28 22:23:32 +02:00
alufolie91 80e4d02c51 dont skip intro sounds if music is disabled 2026-06-28 21:13:28 +02:00
alufolie91 352d1faacf forgor cv_chat_showlimit :chaosleep: 2026-06-28 18:59:28 +02:00
alufolie91 7f9d70285d add new chat stuff to menus + show chat box when hovering over some things
very ugly but i dont care, the hud stuff is done similar
just hoping this doesent explode or whatever
2026-06-28 18:53:28 +02:00
alufolie91 496477fa9a chatbgtint does actually not apply to the chatbox
but only to the also confusingly named "mini chat"
2026-06-28 18:37:11 +02:00
alufolie91 530bb50709 ig "style" is the better word here
lulul
2026-06-28 17:53:57 +02:00
alufolie91 8bb04a68a8 ass well 2026-06-28 17:52:53 +02:00
alufolie91 820ab4b2bc block "addfilelocal" from adding files that contains maps
now we have a more accessible menu for addfile local
i really dont want to risk stuff
2026-06-28 16:25:31 +02:00
alufolie91 af6abb5458 better check for map data within autoloaded files
before this flagged every file with lumps that contained the MAP as string somewhere, like palettes and such

this is kinda messy but i really do not want to dupe this huge block of code, neither do i want to convert this to ceepeepee again to mess about with templates
oh well
2026-06-28 16:23:24 +02:00
alufolie91 5c373b6251 demote those to asserts
never seen srb2, saturn, RR or blan or anything else have this return null
there is a possibility but whatever
just continuing in such cases was wrong eitherways as it wouldve just corrupted the vres thing
2026-06-28 16:05:14 +02:00
alufolie91 24bac9c133 actually print a different message for localskins with lua
tell ppl that this may cause issues
2026-06-28 16:05:11 +02:00
alufolie91 73c7a5a0c4 add better description for skip intro music stuff 2026-06-28 00:40:54 +02:00
alufolie91 49d6374505 have local skin message account for "KCL" prefix
for skins with lua
2026-06-28 00:27:02 +02:00
GLide KS 2ba4757c6a Hopefully a cleaner implementation of Local Addon switch 2026-06-28 00:26:59 +02:00
romoney5 3606b0ae66 Don't disable console on resync 2026-06-28 00:26:56 +02:00
romoney5 ba75523d48 Print a warning when archiving an invalid Lua value 2026-06-28 00:26:54 +02:00
alufolie91 71640202ed better polyobj count error for savegame
from Banpyura
gonna look into their return to menu instead of i_error stuff sometime
2026-06-27 23:42:16 +02:00
alufolie91 5fb5af05be this is P_NetUnArchiveThinkers lululul 2026-06-27 23:39:32 +02:00
indev 4f036c9312 Fix setupm_ip going out of textbox when its not being edited 2026-06-28 00:14:56 +03:00
alufolie91 d99c272a79 have textboxes "reserve" space for cursor
so it wont draw outside the textbox but rather scrolls
2026-06-27 23:14:40 +02:00
alufolie91 c4ed75fbc6 port over some chat stuff from SRB2-Banpyura
per https://git.do.srb2.org/STJr/SRB2/-/merge_requests/2784

chat offsets and character count
offsets are added to the base offset like we do for hud stuff, the og pr will directly use the cvar values for this, but wanna keep consistent with our rest
needs to be added in the menu somewhere but idk where
2026-06-27 22:43:57 +02:00
alufolie91 91927e324b ,
this menu been broken since 4 months lol
2026-06-27 20:40:33 +02:00
alufolie91 13dc0db9a9 add stairjank and skydome stuff to menu
pls someone gib a better description for skydome idk ingles
2026-06-27 20:29:19 +02:00
alufolie91 8aafde4c9d "less" 2026-06-27 20:05:51 +02:00
alufolie91 266a4effb7 fix fogblock not accounting for fake contrast
super old oopsie lulul
2026-06-27 14:18:13 +02:00
alufolie91 948c9399de fix HWR_SplitWall again..
theres guards just above this which should just skip shit but for some reason the clamps still do stuff, idk man
fixes the weird grass fof in green hill
2026-06-27 14:18:10 +02:00
alufolie91 db4aedf498 readd missing setblend for sky bg
oopsie forgor to copy this back
2026-06-27 14:18:04 +02:00
alufolie91 f12d5a246d just dont set shader for this ig
otherwise this breaks when you disable the hud for whatever reason
looks the same so whatever
2026-06-26 19:54:20 +02:00
alufolie91 6efe56808a make sky "dome/barreling" toggable
per "skydome" cvar
using karts old sky code for gl since it appears to differ a bit from srb2 and id want to keep this "authentic" to old kart
2026-06-26 17:44:40 +02:00
alufolie91 ec047151e3 toggable stair "jank" visuals
akin to RR, just toned down for smaller kart chars
also toggable ofc
theres not that many stairs in kart but this looks cute with smol bumps in the road
wish this would work on slopes but theyre kinda messed up lol
2026-06-26 17:44:37 +02:00
alufolie91 b1100d6215 add mobj "temprollangle" field
same as rollangle but resets at beginning on each tic
i dont feel like exposing this to lua atm, so if someone wants to or if even needed at all
2026-06-23 18:24:27 +02:00
alufolie91 cb8df4c3d0 change how banana rotation throw stuff works
noticed sloperoll does not properly work from certain angles
so just reset rollangle if needed in K_RollMobjBySlopes since couldnt find a better place tbh
2026-06-23 18:21:04 +02:00
alufolie91 fbae43f61a move spinoutroll to k_hud
hud thing for minimap so should be in there
2026-06-23 00:11:47 +02:00
mazmazz 7ea95b4495 Fix OSX null-pointer-arithmetic error 2026-06-22 23:14:51 +02:00
alufolie91 07c780dc9c add missing null terminator for player name on server info screen 2026-06-22 23:10:36 +02:00
alufolie91 f6d3ab1f3a more random style cleanup
had those lying around in lugstuff branch
2026-06-22 21:05:10 +02:00
alufolie91 2c8099e228 make builds with more than 16 players undefine COMPAT_VANILLA 2026-06-22 20:57:24 +02:00
alufolie91 7c84dd5661 raise NUMMOBJFREESLOTS to 4096 on non vanilla compat build 2026-06-22 20:57:21 +02:00
alufolie91 cabd8baae5 some P_MobjWasRemoved for non COMPAT_VANILLA builds 2026-06-22 20:57:10 +02:00
alufolie91 593540a3f9 add flag "COMPAT_VANILLA"
undefine to enable features that are not vanilla compatible
2026-06-22 20:56:53 +02:00
alufolie91 407af1d25c Merge branch 'maperrors2' into Saturn-Next 2026-06-22 20:54:53 +02:00
90 changed files with 4054 additions and 4671 deletions

No files matched your search

-2
View File
@@ -42,8 +42,6 @@ include Makefile.d/haiku.mk
else ifdef SOLARIS # FIXME: UNTESTED
UNIX=1
platform=solaris
else ifdef CYGWIN32 # FIXME: UNTESTED
platform=cygwin
else ifdef MINGW
ifdef MINGW64
NONX86=1
-10
View File
@@ -15,16 +15,6 @@ sources+=$(call List,sdl/Sourcefile)
NOUPNP=1
# FIXME: UNTESTED
#ifdef PANDORA
#include sdl/SRB2Pandora/Makefile.cfg
#endif #ifdef PANDORA
# FIXME: UNTESTED
#ifdef CYGWIN32
#include sdl/MakeCYG.cfg
#endif #ifdef CYGWIN32
ifndef NOHW
sources+=sdl/ogl_sdl.c
endif
+5 -5
View File
@@ -34,8 +34,8 @@ size_t I_GetFreeMem(size_t *total)
/* return si.freeram; */
char buf[1024];
char *memTag;
UINT32 freeKBytes;
UINT32 totalKBytes;
size_t freeKBytes;
size_t totalKBytes;
INT32 n;
INT32 meminfo_fd = -1;
@@ -46,7 +46,7 @@ size_t I_GetFreeMem(size_t *total)
if (n < 0)
{
// Error
*total = 0L;
*total = 0;
return 0;
}
@@ -54,7 +54,7 @@ size_t I_GetFreeMem(size_t *total)
if (NULL == (memTag = strstr(buf, MEMTOTAL)))
{
// Error
*total = 0L;
*total = 0;
return 0;
}
@@ -64,7 +64,7 @@ size_t I_GetFreeMem(size_t *total)
if (NULL == (memTag = strstr(buf, MEMFREE)))
{
// Error
*total = 0L;
*total = 0;
return 0;
}
+3
View File
@@ -114,6 +114,7 @@ void* PoolAllocator::allocate()
FreeBlock* ret = head_;
head_ = head_->next;
allocated_blocks_++;
return ret;
}
@@ -125,6 +126,7 @@ void PoolAllocator::deallocate(void* p)
FreeBlock* block = reinterpret_cast<FreeBlock*>(p);
block->next = head_;
head_ = block;
allocated_blocks_--;
}
void PoolAllocator::release()
@@ -144,6 +146,7 @@ void PoolAllocator::release()
first_chunk_ = nullptr;
head_ = nullptr;
allocated_blocks_ = 0;
}
static LinearMemory g_frame_memory {4 * 1024 * 1024};
+4
View File
@@ -37,6 +37,7 @@ class PoolAllocator final
FreeBlock* head_;
size_t block_size_;
size_t blocks_;
size_t allocated_blocks_;
int32_t tag_;
ChunkFooter* allocate_chunk();
@@ -47,6 +48,7 @@ public:
, head_(nullptr)
, block_size_(block_size)
, blocks_(blocks)
, allocated_blocks_(0)
, tag_(tag)
{}
PoolAllocator(const PoolAllocator&) = delete;
@@ -59,6 +61,8 @@ public:
void* allocate();
void deallocate(void* p);
constexpr size_t block_size() const noexcept { return block_size_; };
constexpr size_t allocated_blocks() const noexcept { return allocated_blocks_; };
constexpr size_t allocated_bytes() const noexcept { return allocated_blocks_ * block_size_; };
void release();
};
+39 -5
View File
@@ -110,7 +110,7 @@ SINT8 joinnode = 0; // used for CL_VIEWSERVER
boolean player_muted[MAXPLAYERS] = {};
// Server specific vars
UINT8 playernode[MAXPLAYERS] = {};
UINT8 playernode[MAXPLAYERS] = {UINT8_MAX};
// Minimum timeout for sending the savegame
// The actual timeout will be longer depending on the savegame length
@@ -841,11 +841,13 @@ static void resynch_write_ctf(resynchend_pak *rst)
rst->flagplayer[i] = (SINT8)j;
break;
}
if (j == MAXPLAYERS) // fine, no I_Error
{
CONS_Alert(CONS_ERROR, "One of the flags has gone completely missing...\n");
rst->flagplayer[i] = -2;
}
continue;
}
@@ -1135,6 +1137,7 @@ static void CV_SavePlayerNames(UINT8 **p)
WRITEUINT8(*p, 0);
continue;
}
WRITESTRING(*p, player_names[i]);
}
}
@@ -1148,10 +1151,13 @@ static void CV_LoadPlayerNames(UINT8 **p)
for (; i < MAXPLAYERS; ++i)
{
READSTRING(*p, tmp_name);
if (tmp_name[0] == 0)
continue;
if (tmp_name[MAXPLAYERNAME]) // overflow detected
I_Error("Received bad server config packet when trying to join");
memcpy(player_names[i], tmp_name, MAXPLAYERNAME+1);
}
}
@@ -1449,6 +1455,7 @@ static void CL_DrawConnectionStatus(void)
if (playerinfo[i].node < 255)
{
strncpy(player_name, playerinfo[i].name, MAXPLAYERNAME);
player_name[MAXPLAYERNAME] = '\0';
// if we get a skin color
// try to colourize the player name
@@ -2028,6 +2035,7 @@ static void SV_SendSaveGame(INT32 node, boolean resending)
P_SaveNetGame(&save, resending);
length = save.p - save.buffer;
if (length > SAVEGAMESIZE)
{
Z_Free(save.buffer);
@@ -2180,7 +2188,8 @@ static void CL_LoadReceivedSavegame(boolean reloading)
if (unlink(tmpsave) == -1)
CONS_Alert(CONS_ERROR, M_GetText("Can't delete %s\n"), tmpsave);
consistancy[gametic%BACKUPTICS] = Consistancy();
CON_ToggleOff();
if (!reloading)
CON_ToggleOff();
#ifdef SATURNPAK
// Tell the server we have received and reloaded the gamestate
@@ -3440,7 +3449,7 @@ void CL_ClearPlayer(INT32 playernum)
if (players[playernum].mo)
{
// Don't leave a NiGHTS ghost!
if (UNLIKELY((players[playernum].pflags & PF_NIGHTSMODE) && players[playernum].mo->tracer))
if (nightsplayer(&players[playernum]) && players[playernum].mo->tracer)
P_RemoveMobj(players[playernum].mo->tracer);
P_RemoveMobj(players[playernum].mo);
}
@@ -3758,6 +3767,10 @@ static void Command_Ban(void)
if (pn == -1 || pn == 0)
return;
// player does not exist
if (!playeringame[pn])
return;
WRITEUINT8(p, pn);
if (COM_Argc() == 2)
@@ -3875,6 +3888,10 @@ static void Command_Kick(void)
if (pn == -1 || pn == 0)
return;
// player does not exist
if (!playeringame[pn])
return;
// Special case if we are trying to kick a player who is downloading the game state:
// trigger a timeout instead of kicking them, because a kick would only
// take effect after they have finished downloading
@@ -3924,6 +3941,13 @@ static void Got_KickCmd(const UINT8 **p, INT32 playernum)
pnum = READUINT8(*p);
msg = READUINT8(*p);
if (pnum >= MAXPLAYERS)
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal kick command received from %s for player %d\n"), player_names[playernum], pnum);
return;
}
// FIXME: this does not work at all on dedi, servernode == 0 which is prevented from kick/ban command
if (pnum == serverplayer && IsPlayerAdmin(playernum))
{
CONS_Printf(M_GetText("Server is being shut down remotely. Goodbye!\n"));
@@ -3978,6 +4002,16 @@ static void Got_KickCmd(const UINT8 **p, INT32 playernum)
msg = KICK_MSG_CON_FAIL;
}
// without this the server will remove itself and thus self destruct on dedicated
if (server && (playernode[pnum] == UINT8_MAX || !playeringame[pnum]))
{
CONS_Alert(CONS_WARNING, M_GetText("Attempting to kick player %d which is not in game received from %s\n"), pnum, player_names[playernum]);
return;
}
// make sure we dont read garbage anywhere
memset(reason, 0, sizeof(buf));
if (msg == KICK_MSG_CUSTOM_BAN || msg == KICK_MSG_CUSTOM_KICK)
{
READSTRINGN(*p, reason, MAX_REASONLENGTH+1);
@@ -4798,7 +4832,7 @@ void CL_RemoveSplitscreenPlayer(UINT8 p)
// is there a game running
boolean Playing(void)
{
return (server && serverrunning) || (client && cl_mode == CL_CONNECTED);
return ((server && serverrunning) || (client && cl_mode == CL_CONNECTED));
}
boolean SV_SpawnServer(void)
@@ -5399,7 +5433,7 @@ static void PT_ServerCFG(SINT8 node)
{
maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic);
if ((gametype = netbuffer->u.servercfg.gametype) >= NUMGAMETYPES)
I_Error("Bad gametype in cliserv!");
I_Error("Bad gametype %d in cliserv!", gametype);
modifiedgame = netbuffer->u.servercfg.modifiedgame;
for (j = 0; j < MAXPLAYERS; j++)
adminplayers[j] = netbuffer->u.servercfg.adminplayers[j];
+8 -18
View File
@@ -275,20 +275,6 @@ static void D_Renderview(void)
R_ApplyLevelInterpolators(R_GetTimeFrac(RTF_LEVEL));
if (rendermode == render_soft && cv_homremoval.value)
{
if (cv_homremoval.value == 1)
{
// Clear the software screen buffer to remove HOM
memset(vid.screens[0], 31, vid.width * vid.height);
}
else if (cv_homremoval.value == 2)
{
//'development' HOM removal -- makes it blindingly obvious if HOM is spotted.
memset(vid.screens[0], 32+(timeinmap&15), vid.width * vid.height);
}
}
for (i = 0; i <= splitscreen; i++)
{
if (!P_MobjWasRemoved(players[displayplayers[i]].mo) || players[displayplayers[i]].playerstate == PST_DEAD)
@@ -1159,7 +1145,7 @@ static void D_FindAddonsToAutoload(void)
// you can probably imagine how that goes in a netgame....
if (W_CheckAutoLoadContainsMap(wadsToAutoload))
{
CONS_Printf("Autoload: file %s contains map data! skipping...", wadsToAutoload);
CONS_Alert(CONS_WARNING, "Autoload: file %s contains map data, this WILL cause crashes and desynchs! skipping...\n", wadsToAutoload);
continue;
}
@@ -1353,20 +1339,24 @@ static void IdentifyVersion(void)
//
// search for maps
//
static void D_CheckMapReplacements(boolean checkreplaced)
static void D_CheckMapReplacements(boolean pwad)
{
INT32 i;
char *name;
UINT16 wadnum;
lumpinfo_t *lumpinfo;
size_t numfiles;
for (wadnum = 0; wadnum < mainwads; wadnum++)
wadnum = pwad ? (mainwads+1) : 0;
numfiles = pwad ? numwadfiles : mainwads;
for (; wadnum < numfiles; wadnum++)
{
lumpinfo = wadfiles[wadnum]->lumpinfo;
for (i = 0; i < wadfiles[wadnum]->numlumps; i++, lumpinfo++)
{
name = lumpinfo->name;
P_CheckMapReplacements(name, checkreplaced);
P_CheckMapReplacements(name, pwad);
}
}
}
+27 -14
View File
@@ -566,6 +566,7 @@ const char *netxcmdnames[MAXNETXCMD - 1] =
"MODIFYVOTE",
"PICKVOTE",
"REMOVEPLAYER",
"DISCORD",
"LUACMD",
"LUAVAR"
};
@@ -930,8 +931,6 @@ void D_RegisterClientCommands(void)
COM_AddCommand("displayplayer", Command_Displayplayer_f);
CV_RegisterVar(&cv_audbuffersize);
CV_RegisterVar(&cv_palette);
CV_RegisterVar(&cv_palettenum);
@@ -942,6 +941,9 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_chatspamprotection);
CV_RegisterVar(&cv_consolechat);
CV_RegisterVar(&cv_chatnotifications);
CV_RegisterVar(&cv_chat_xoffset);
CV_RegisterVar(&cv_chat_yoffset);
CV_RegisterVar(&cv_chat_showlimit);
CV_RegisterVar(&cv_chatbacktint);
CV_RegisterVar(&cv_chatcentertext);
CV_RegisterVar(&cv_songcredits);
@@ -1007,9 +1009,17 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_usejoystick[i]);
CV_RegisterVar(&cv_joyscale[i]);
CV_RegisterVar(&cv_rumble[i]);
CV_RegisterVar(&cv_rumblestrength[i]);
CV_RegisterVar(&cv_gamepadled[i]);
CV_RegisterVar(&cv_rumble[i]);
CV_RegisterVar(&cv_rumble_strength[i]);
CV_RegisterVar(&cv_rumble_spinout[i]);
CV_RegisterVar(&cv_rumble_sneakerboost[i]);
CV_RegisterVar(&cv_rumble_offroad[i]);
CV_RegisterVar(&cv_rumble_bananadrag[i]);
CV_RegisterVar(&cv_rumble_stairjank[i]);
CV_RegisterVar(&cv_rumble_brakedrift[i]);
CV_RegisterVar(&cv_rumble_driftcharge[i]);
}
CV_RegisterVar(&cv_gamepadifunfocused);
@@ -1029,6 +1039,7 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_midimusicvolume);
#endif
CV_RegisterVar(&cv_numChannels);
CV_RegisterVar(&cv_audbuffersize);
#ifdef HAVE_OPENMPT
CV_RegisterVar(&cv_modfilter);
@@ -1550,8 +1561,8 @@ static void SendNameAndColor(UINT8 splitplayer)
// TODO: make those cvars arrays
consvar_t *playercolor, *playername, *playerskin;
consvar_t *colorvars[] = {&cv_playercolor, &cv_playercolor2, &cv_playercolor3, &cv_playercolor4};
consvar_t *namevars[] = {&cv_playername, &cv_playername2, &cv_playername3, &cv_playername4};
consvar_t *skinvars[] = {&cv_skin, &cv_skin2, &cv_skin3, &cv_skin4};
consvar_t *namevars[] = {&cv_playername, &cv_playername2, &cv_playername3, &cv_playername4};
consvar_t *skinvars[] = {&cv_skin, &cv_skin2, &cv_skin3, &cv_skin4};
playercolor = colorvars[splitplayer];
playername = namevars[splitplayer];
@@ -1795,7 +1806,7 @@ INT32 D_LookupPlayer(const char *s)
if ((playernum = atoi(s)))
{
playernum = max(min(playernum, MAXPLAYERS-1), 0);/* not out of range */
playernum = max(min(playernum, MAXPLAYERS-1), 0); /* not out of range */
return playernum;
}
@@ -5490,7 +5501,6 @@ static void Name_OnChange(void)
}
SendNameAndColor(0);
}
static void Name2_OnChange(void)
@@ -5681,19 +5691,22 @@ static void Command_SkinSearch(void)
size_t i;
UINT16 s;
UINT16 ic = 0;
//skin_t *skininput = &skins[s];
for (i = 1; i < COM_Argc(); i++){
for( s = 0 ; s < numallskins ; s++ )
for (i = 1; i < COM_Argc(); i++)
{
for (s = 0; s < numskins; s++)
{
skin_t *skininput = &skins[s];
if (strcasestr(skininput->realname,COM_Argv(i)))
if (strcasestr(skininput->realname, COM_Argv(i)))
{
ic++;
CONS_Printf("%d. %s%s:\x80 %s\n", ic,HU_SkinColorToConsoleColor(skininput->prefcolor),skininput->realname,skininput->name);
CONS_Printf("%d. %s%s:\x80 %s\n", ic, HU_SkinColorToConsoleColor(skininput->prefcolor), skininput->realname, skininput->name);
}
}
}
CONS_Printf("Total %d skins.\n", ic);
CONS_Printf("Total %d skins.\n", ic);
}
/** Sends a color change for the console player, unless that player is moving.
+1
View File
@@ -149,6 +149,7 @@ extern consvar_t cv_showminimapnames;
extern consvar_t cv_showminimapfinished;
extern consvar_t cv_minihead;
extern consvar_t cv_showminimapangle;
extern consvar_t cv_spinoutroll;
extern consvar_t cv_showlapemblem;
+2
View File
@@ -566,6 +566,8 @@ typedef struct player_s
fixed_t fovadd; // adjust FOV for hw rendering
SINT8 driftlevel; // just for controller rumble for now
UINT8 stairjank;
} player_t;
#endif
+82 -32
View File
@@ -68,6 +68,12 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T);
#include <time.h>
#if defined (__linux__)
#include <sys/vfs.h>
#elif defined(__APPLE__)
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <mach/mach.h>
#else
#include <sys/param.h>
#include <sys/mount.h>
@@ -156,8 +162,7 @@ const char *wadSearchPaths[] = {
/** \brief WAD file to look for
*/
#define WADKEYWORD1 "srb2.srb"
#define WADKEYWORD2 "srb2.wad"
#define WADKEYWORD "srb2.srb"
/** \brief holds wad path
*/
static char returnWadPath[256];
@@ -520,16 +525,23 @@ void I_OutputMsg(const char *fmt, ...)
{
size_t len;
char *txt;
va_list argptr;
va_list argptr;
va_start(argptr,fmt);
if (!fmt)
return;
va_start(argptr, fmt);
len = vsnprintf(NULL, 0, fmt, argptr);
va_end(argptr);
if (len == 0)
return;
txt = malloc(len+1);
va_start(argptr,fmt);
txt = (char*)(malloc(len+1));
if (!txt)
I_Error("I_OutputMsg: Out of memory!\n");
va_start(argptr, fmt);
vsprintf(txt, fmt, argptr);
va_end(argptr);
@@ -1413,6 +1425,12 @@ static void I_Fork(void)
}
#endif/*NEWSIGNALHANDLER*/
int I_OpenURL(const char *url)
{
(void)url;
return -1;
}
INT32 I_StartupSystem(void)
{
I_StartupConsole();
@@ -1802,20 +1820,12 @@ const char *I_ClipboardPaste(void)
*/
static boolean isWadPathOk(const char *path)
{
char *wad3path = malloc(256);
char *wad3path = (char*)(malloc(256));
if (!wad3path)
return false;
sprintf(wad3path, pandf, path, WADKEYWORD1);
if (FIL_ReadFileOK(wad3path))
{
free(wad3path);
return true;
}
sprintf(wad3path, pandf, path, WADKEYWORD2);
sprintf(wad3path, pandf, path, WADKEYWORD);
if (FIL_ReadFileOK(wad3path))
{
@@ -1832,12 +1842,17 @@ static void pathonly(char *s)
size_t j;
for (j = strlen(s); j != (size_t)-1; j--)
{
if ((s[j] == '\\') || (s[j] == ':') || (s[j] == '/'))
{
if (s[j] == ':') s[j+1] = 0;
else s[j] = 0;
if (s[j] == ':')
s[j+1] = 0;
else
s[j] = 0;
return;
}
}
}
/** \brief search for srb2.srb in the given path
@@ -1853,7 +1868,7 @@ static const char *searchWad(const char *searchDir)
static char tempsw[256] = "";
filestatus_t fstemp;
strcpy(tempsw, WADKEYWORD1);
strcpy(tempsw, WADKEYWORD);
fstemp = filesearch(tempsw, searchDir, NULL, true, 20);
if (fstemp == FS_FOUND)
{
@@ -1974,17 +1989,22 @@ const char *I_LocateWad(void)
static long get_entry(const char* name, const char* buf)
{
long val;
char* hit = strstr(buf, name);
if (hit == NULL) {
const char* hit = strstr(buf, name);
if (hit == NULL)
{
return -1;
}
errno = 0;
val = strtol(hit + strlen(name), NULL, 10);
if (errno != 0) {
if (errno != 0)
{
CONS_Alert(CONS_ERROR, M_GetText("get_entry: strtol() failed: %s\n"), strerror(errno));
return -1;
}
return val;
}
#endif
@@ -2009,13 +2029,13 @@ size_t I_GetFreeMem(size_t *total)
*total = 32 << 20;
return 32 << 20;
#elif defined (_WIN32)
MEMORYSTATUS info;
MEMORYSTATUSEX info;
info.dwLength = sizeof (MEMORYSTATUS);
GlobalMemoryStatus( &info );
info.dwLength = sizeof (MEMORYSTATUSEX);
GlobalMemoryStatusEx( &info );
if (total)
*total = (size_t)info.dwTotalPhys;
return (size_t)info.dwAvailPhys;
*total = (size_t)info.ullTotalPhys;
return (size_t)info.ullAvailPhys;
#elif defined (__OS2__)
UINT32 pr_arena;
@@ -2048,7 +2068,7 @@ size_t I_GetFreeMem(size_t *total)
{
// Error
if (total)
*total = 0L;
*total = 0;
return 0;
}
@@ -2057,12 +2077,12 @@ size_t I_GetFreeMem(size_t *total)
{
// Error
if (total)
*total = 0L;
*total = 0;
return 0;
}
memTag += sizeof (MEMTOTAL);
totalKBytes = (size_t)atoi(memTag);
totalKBytes = strtoul(memTag, NULL, 10);
if ((memTag = strstr(buf, MEMAVAILABLE)) == NULL)
{
@@ -2076,7 +2096,7 @@ size_t I_GetFreeMem(size_t *total)
{
// Error
if (total)
*total = 0L;
*total = 0;
return 0;
}
freeKBytes = MemAvailable;
@@ -2084,16 +2104,46 @@ size_t I_GetFreeMem(size_t *total)
else
{
memTag += sizeof (MEMAVAILABLE);
freeKBytes = atoi(memTag);
freeKBytes = strtoul(memTag, NULL, 10);
}
if (total)
*total = totalKBytes << 10;
return freeKBytes << 10;
#elif defined(__APPLE__)
/* macOS */
mach_port_t host = mach_host_self();
kern_return_t kr;
mach_msg_type_number_t count;
vm_size_t v_page_size;
struct vm_statistics64 vm_stats;
uint64_t total_mem, free_mem;
size_t size;
size = sizeof(total_mem);
if (sysctlbyname("hw.memsize", &total_mem, &size, NULL, 0) < 0)
total_mem = 0;
kr = host_page_size(host, &v_page_size);
if (kr != KERN_SUCCESS)
v_page_size = 4096;
count = HOST_VM_INFO64_COUNT;
kr = host_statistics64(host, HOST_VM_INFO64, (host_info64_t)&vm_stats, &count);
if (kr == KERN_SUCCESS)
free_mem = (uint64_t)(vm_stats.free_count + vm_stats.inactive_count) * v_page_size;
else
free_mem = 0;
if (total)
*total = (size_t)total_mem;
return (size_t)free_mem;
#else
// Guess 48 MB.
if (total)
{
*total = 48<<20;
}
return 48<<20;
#endif
}
+14
View File
@@ -602,6 +602,13 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
// None of these that are disabled in the normal build are guaranteed to work perfectly
// Compile them at your own risk!
// undefine to enable fixes and features that are not vanilla compatible
#define COMPAT_VANILLA
// if we build with 32 player (or more!) support we dont need to care vanilla compat
#if MAXPLAYERS > 16
#undef COMPAT_VANILLA
#endif
//-- SATURN __
/// Detect if a client is on Saturn in the clientconfig.
/// To seperately allow them to join or block joining from vanilla clients.
@@ -666,6 +673,13 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
#undef UPDATE_ALERT
#endif
// overwrite some of those
// when not compiling in vanilla compat mode
#ifndef COMPAT_VANILLA
#define SATURNJOIN
#define SATURNPAK
#endif
#ifdef __cplusplus
} // extern "C"
#endif
+61 -56
View File
@@ -447,7 +447,8 @@ void G_WriteDemoExtraData(void)
{
static UINT8 timeout = 0;
if (timeout) timeout--;
if (timeout)
timeout--;
if (demo_writerng == 1 || (demo_writerng == 2 && timeout == 0))
{
@@ -467,6 +468,7 @@ void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
if (!demobuf.p || !demo.deferstart)
return;
ziptic = READUINT8(demobuf.p);
if (ziptic & ZT_FWD)
@@ -488,11 +490,12 @@ void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
// what in the actual fuck is this???
// SRB2kart: Copy-pasted from ticcmd building, removes that crappy demo cam
if (((players[displayplayers[0]].mo && players[displayplayers[0]].speed > 0) // Moving
const player_t *player = &players[displayplayers[0]];
if (((player->mo && player->speed > 0) // Moving
|| (leveltime > starttime && (cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE)) // Rubber-burn turn
|| (players[displayplayers[0]].kartstuff[k_respawn]) // Respawning
|| (players[displayplayers[0]].spectator || objectplacing)) // Not a physical player
&& !(players[displayplayers[0]].kartstuff[k_spinouttimer] && players[displayplayers[0]].kartstuff[k_sneakertimer])) // Spinning and boosting cancels out spinout
|| (player->kartstuff[k_respawn]) // Respawning
|| (player->spectator || objectplacing)) // Not a physical player
&& !(player->kartstuff[k_spinouttimer] && player->kartstuff[k_sneakertimer])) // Spinning and boosting cancels out spinout
localangle[0] += (cmd->angleturn<<16);
if (!(demoflags & DF_GHOST) && *demobuf.p == DEMOMARKER)
@@ -713,7 +716,7 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum)
if (!(demoflags & DF_GHOST))
return; // No ghost data to write.
if (ghost->player && ghost->player->pflags & PF_NIGHTSMODE && ghost->tracer)
if (ghost->player && nightsplayer(ghost->player) && ghost->tracer)
{
// We're talking about the NiGHTS thing, not the normal platforming thing!
ziptic |= GZT_NIGHTS;
@@ -931,7 +934,7 @@ void G_ConsAllGhostTics(void)
void G_ConsGhostTic(INT32 playernum)
{
UINT8 ziptic;
fixed_t px,py,pz,gx,gy,gz;
fixed_t px, py, pz, gx, gy, gz;
mobj_t *testmo;
fixed_t syncleeway;
boolean nightsfail = false;
@@ -976,7 +979,7 @@ void G_ConsGhostTic(INT32 playernum)
if (ziptic & GZT_NIGHTS)
{
if (!testmo || !testmo->player || !(testmo->player->pflags & PF_NIGHTSMODE) || !testmo->tracer)
if (!testmo || !testmo->player || !nightsplayer(testmo->player) || !testmo->tracer)
nightsfail = true;
else
testmo = testmo->tracer;
@@ -1344,7 +1347,7 @@ fadeghost:
}
else
{
mobj = P_SpawnMobj(g->mo->x, g->mo->y, g->mo->z - FixedDiv(FixedMul(g->mo->info->height, g->mo->scale) - g->mo->height,3*FRACUNIT), MT_THOK);
mobj = P_SpawnMobj(g->mo->x, g->mo->y, g->mo->z - FixedDiv(FixedMul(g->mo->info->height, g->mo->scale) - g->mo->height, 3*FRACUNIT), MT_THOK);
mobj->sprite = states[mobjinfo[type].spawnstate].sprite;
mobj->frame = (states[mobjinfo[type].spawnstate].frame & FF_FRAMEMASK) | tr_trans60<<FF_TRANSSHIFT;
mobj->tics = -1; // nope.
@@ -1518,7 +1521,9 @@ void G_PreviewRewind(tic_t previewtime)
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
player_t *player = &players[i];
if (!playeringame[i] || player->spectator)
{
if (info->playerinfo[i].player.mo)
{
@@ -1530,35 +1535,35 @@ void G_PreviewRewind(tic_t previewtime)
if (!info->playerinfo[i].ingame || !info->playerinfo[i].player.mo)
{
if (players[i].mo)
players[i].mo->flags2 |= MF2_DONTDRAW;
if (player->mo)
player->mo->flags2 |= MF2_DONTDRAW;
continue;
}
if (!players[i].mo)
if (!player->mo)
continue; //@TODO spawn temp object to act as a player display
players[i].mo->flags2 &= ~MF2_DONTDRAW;
player->mo->flags2 &= ~MF2_DONTDRAW;
P_UnsetThingPosition(players[i].mo);
P_UnsetThingPosition(player->mo);
#define TWEEN(pr) info->playerinfo[i].mobj.pr + FixedMul((INT32) (next_info->playerinfo[i].mobj.pr - info->playerinfo[i].mobj.pr), tweenvalue)
players[i].mo->x = TWEEN(x);
players[i].mo->y = TWEEN(y);
players[i].mo->z = TWEEN(z);
players[i].mo->angle = TWEEN(angle);
player->mo->x = TWEEN(x);
player->mo->y = TWEEN(y);
player->mo->z = TWEEN(z);
player->mo->angle = TWEEN(angle);
#undef TWEEN
P_SetThingPosition(players[i].mo);
P_SetThingPosition(player->mo);
players[i].frameangle = info->playerinfo[i].player.frameangle + FixedMul((INT32) (next_info->playerinfo[i].player.frameangle - info->playerinfo[i].player.frameangle), tweenvalue);
player->frameangle = info->playerinfo[i].player.frameangle + FixedMul((INT32) (next_info->playerinfo[i].player.frameangle - info->playerinfo[i].player.frameangle), tweenvalue);
players[i].mo->sprite = info->playerinfo[i].mobj.sprite;
players[i].mo->frame = info->playerinfo[i].mobj.frame;
player->mo->sprite = info->playerinfo[i].mobj.sprite;
player->mo->frame = info->playerinfo[i].mobj.frame;
players[i].realtime = info->playerinfo[i].player.realtime;
player->realtime = info->playerinfo[i].player.realtime;
for (j = 0; j < NUMKARTSTUFF; j++)
players[i].kartstuff[j] = info->playerinfo[i].player.kartstuff[j];
player->kartstuff[j] = info->playerinfo[i].player.kartstuff[j];
}
for (i = splitscreen; i >= 0; i--)
@@ -1691,7 +1696,7 @@ void G_BeginRecording(void)
return;
}
memset(name,0,sizeof(name));
memset(name, 0, sizeof(name));
demobuf.p = demobuf.buffer;
demoflags = DF_GHOST|(multiplayer ? DF_MULTIPLAYER : (modeattacking<<DF_ATTACKSHIFT));
@@ -1705,9 +1710,9 @@ void G_BeginRecording(void)
// Setup header.
memcpy(demobuf.p, DEMOHEADER, 12); demobuf.p += 12;
WRITEUINT8(demobuf.p,VERSION);
WRITEUINT8(demobuf.p,SUBVERSION);
WRITEUINT16(demobuf.p,DEMOVERSION);
WRITEUINT8(demobuf.p, VERSION);
WRITEUINT8(demobuf.p, SUBVERSION);
WRITEUINT16(demobuf.p, DEMOVERSION);
// Full replay title
demobuf.p += 64;
@@ -1736,7 +1741,7 @@ void G_BeginRecording(void)
// game data
memcpy(demobuf.p, "PLAY", 4); demobuf.p += 4;
WRITEINT16(demobuf.p,gamemap);
WRITEINT16(demobuf.p, gamemap);
memcpy(demobuf.p, mapmd5, 16); demobuf.p += 16;
WRITEUINT8(demobuf.p, demoflags);
@@ -1768,8 +1773,8 @@ void G_BeginRecording(void)
break;
case ATTACKING_RECORD: // 1
demotime_p = demobuf.p;
WRITEUINT32(demobuf.p,UINT32_MAX); // time
WRITEUINT32(demobuf.p,UINT32_MAX); // lap
WRITEUINT32(demobuf.p, UINT32_MAX); // time
WRITEUINT32(demobuf.p, UINT32_MAX); // lap
break;
default: // 3
break;
@@ -1826,9 +1831,9 @@ void G_BeginRecording(void)
if (demoflags & DF_LUAVARS)
LUA_Archive(&demobuf, false);
memset(&oldcmd,0,sizeof(oldcmd));
memset(&oldghost,0,sizeof(oldghost));
memset(&ghostext,0,sizeof(ghostext));
memset(&oldcmd, 0, sizeof(oldcmd));
memset(&oldghost, 0, sizeof(oldghost));
memset(&ghostext, 0, sizeof(ghostext));
for (i = 0; i < MAXPLAYERS; i++)
{
@@ -1868,19 +1873,19 @@ void G_WriteStanding(UINT8 ranking, char *name, INT32 skinnum, UINT8 color, UINT
// Name
memset(temp, 0, 16);
strncpy(temp, name, 16);
memcpy(demobuf.p,temp,16);
memcpy(demobuf.p, temp, 16);
demobuf.p += 16;
// Skin
memset(temp, 0, 16);
strncpy(temp, skins[skinnum].name, 16);
memcpy(demobuf.p,temp,16);
memcpy(demobuf.p, temp, 16);
demobuf.p += 16;
// Color
memset(temp, 0, 16);
strncpy(temp, KartColor_Names[color], 16);
memcpy(demobuf.p,temp,16);
memcpy(demobuf.p, temp, 16);
demobuf.p += 16;
// Score/time/whatever
@@ -2339,7 +2344,7 @@ void G_LoadDemoInfo(menudemo_t *pdemo)
extrainfo_p += 16;
// Skin
memcpy(temp,extrainfo_p,16);
memcpy(temp, extrainfo_p, 16);
extrainfo_p += 16;
pdemo->standings[count].skin = UINT8_MAX;
@@ -2353,12 +2358,12 @@ void G_LoadDemoInfo(menudemo_t *pdemo)
}
// Color
memcpy(temp,extrainfo_p,16);
memcpy(temp, extrainfo_p, 16);
extrainfo_p += 16;
for (i = 0; i < MAXSKINCOLORS; i++)
{
if (fasticmp(KartColor_Names[i],temp)) // SRB2kart
if (fasticmp(KartColor_Names[i], temp)) // SRB2kart
{
pdemo->standings[count].color = i;
break;
@@ -2827,15 +2832,15 @@ void G_DoPlayDemo(char *defdemoname)
if (demo.version == 0x0001)
{
// Player name
memcpy(player_names[0],demobuf.p,16);
memcpy(player_names[0], demobuf.p, 16);
demobuf.p += 16;
// Skin
memcpy(skin,demobuf.p,16);
memcpy(skin, demobuf.p, 16);
demobuf.p += 16;
// Color
memcpy(color,demobuf.p,16);
memcpy(color, demobuf.p, 16);
demobuf.p += 16;
demobuf.p += 5; // Backwards compat - some stats
@@ -2868,7 +2873,7 @@ void G_DoPlayDemo(char *defdemoname)
// Set color
for (i = 0; i < MAXSKINCOLORS; i++)
{
if (fasticmp(KartColor_Names[i],color)) // SRB2kart
if (fasticmp(KartColor_Names[i], color)) // SRB2kart
{
players[0].skincolor = i;
break;
@@ -2888,9 +2893,9 @@ void G_DoPlayDemo(char *defdemoname)
return;
}
memset(&oldcmd,0,sizeof(oldcmd));
memset(&oldghost,0,sizeof(oldghost));
memset(&ghostext,0,sizeof(ghostext));
memset(&oldcmd, 0, sizeof(oldcmd));
memset(&oldghost, 0, sizeof(oldghost));
memset(&ghostext, 0, sizeof(ghostext));
CONS_Alert(CONS_WARNING, M_GetText("Demo version does not match game version. Desyncs may occur.\n"));
@@ -2994,16 +2999,16 @@ void G_DoPlayDemo(char *defdemoname)
players[p].spectator = spectator;
// Name
memcpy(player_names[p],demobuf.p,16);
memcpy(player_names[p], demobuf.p, 16);
demobuf.p += 16;
// Skin
memcpy(skin,demobuf.p,16);
memcpy(skin, demobuf.p, 16);
demobuf.p += 16;
SetPlayerSkin(p, skin);
// Color
memcpy(color,demobuf.p,16);
memcpy(color, demobuf.p, 16);
demobuf.p += 16;
for (i = 0; i < MAXSKINCOLORS; i++)
@@ -3221,15 +3226,15 @@ void G_AddGhost(char *defdemoname)
if (ghostversion == 0x0001)
{
// Player name (TODO: Display this somehow if it doesn't match cv_playername!)
memcpy(name, p,16);
memcpy(name, p, 16);
p += 16;
// Skin
memcpy(skin, p,16);
memcpy(skin, p, 16);
p += 16;
// Color
memcpy(color, p,16);
memcpy(color, p, 16);
p += 16;
// Ghosts do not have a player structure to put this in.
@@ -3381,7 +3386,7 @@ void G_AddGhost(char *defdemoname)
for (i = 0; i < MAXSKINCOLORS; i++)
{
if (fasticmp(KartColor_Names[i],color)) // SRB2kart
if (fasticmp(KartColor_Names[i], color)) // SRB2kart
{
gh->mo->color = (UINT8)i;
break;
@@ -3473,7 +3478,7 @@ void G_UpdateStaffGhostName(lumpnum_t l)
if (ghostversion == 0x0001)
{
// Player name
memcpy(dummystaffname, p,16);
memcpy(dummystaffname, p, 16);
dummystaffname[16] = '\0';
return; // Not really a failure but whatever
}
+6 -4
View File
@@ -118,10 +118,11 @@ extern consvar_t cv_driftsparkpulse;
extern consvar_t cv_gravstretch;
extern consvar_t cv_sloperoll;
extern consvar_t cv_sliptideroll;
extern consvar_t cv_stairjank;
extern consvar_t cv_stairjanksfx;
extern consvar_t cv_slamsound;
extern consvar_t cv_sloperolldist;
extern consvar_t cv_sparkroll;
extern consvar_t cv_spinoutroll;
extern consvar_t cv_squishdance, cv_squishdancespeed;
@@ -227,10 +228,11 @@ void G_SaveGameData(boolean force);
void G_SaveGame(UINT32 slot);
#define G_GametypeHasTeams() (G_IsGameType(GT_TEAMMATCH) || G_IsGameType(GT_CTF))
#define G_RaceGametype() (G_IsGameType(GT_RACE))
#define G_BattleGametype() (G_IsGameType(GT_MATCH))
#define G_RaceGametype() (G_IsGameType(GT_RACE))
#define G_TagGametype() (G_IsGameType(GT_TAG) || G_IsGameType(GT_HIDEANDSEEK))
#define G_GametypeHasTeams() (UNLIKELY(G_IsGameType(GT_TEAMMATCH) || G_IsGameType(GT_CTF)))
#define G_TagGametype() (UNLIKELY(G_IsGameType(GT_TAG) || G_IsGameType(GT_HIDEANDSEEK)))
FUNCINLINE static ATTRINLINE boolean G_IsGameType(int type)
{
+48 -12
View File
@@ -66,13 +66,30 @@ consvar_t cv_rumble[MAXSPLITSCREENPLAYERS] = {
static CV_PossibleValue_t rumblestrength_cons_t[] = {{FRACUNIT/4, "MIN"}, {FRACUNIT*4, "MAX"}, {0, NULL}};
consvar_t cv_rumblestrength[MAXSPLITSCREENPLAYERS] = {
consvar_t cv_rumble_strength[MAXSPLITSCREENPLAYERS] = {
{"rumblestrength", "1.0", CV_SAVE|CV_FLOAT, rumblestrength_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
{"rumblestrength2", "1.0", CV_SAVE|CV_FLOAT, rumblestrength_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
{"rumblestrength3", "1.0", CV_SAVE|CV_FLOAT, rumblestrength_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
{"rumblestrength4", "1.0", CV_SAVE|CV_FLOAT, rumblestrength_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}
};
#define IMPL_RUMBLE_TYPE(type)\
consvar_t cv_rumble_##type [MAXSPLITSCREENPLAYERS] = {\
{"rumble_" #type, "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL},\
{"rumble2_" #type, "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL},\
{"rumble3_" #type, "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL},\
{"rumble4_" #type, "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}\
};
IMPL_RUMBLE_TYPE(spinout);
IMPL_RUMBLE_TYPE(sneakerboost);
IMPL_RUMBLE_TYPE(offroad);
IMPL_RUMBLE_TYPE(bananadrag);
IMPL_RUMBLE_TYPE(stairjank);
IMPL_RUMBLE_TYPE(brakedrift);
IMPL_RUMBLE_TYPE(driftcharge);
static CV_PossibleValue_t gamepadled_cons_t[] = {{0, "Off"}, {1, "Skincolor"}, {2, "Mobjcolor"}, {0, NULL}};
consvar_t cv_gamepadled[MAXSPLITSCREENPLAYERS] = {
{"gamepadled", "Skincolor", CV_SAVE|CV_CALL|CV_NOINIT, gamepadled_cons_t, led_off_handle, 0, NULL, NULL, 0, 0, NULL},
@@ -1036,8 +1053,8 @@ void G_PlayerDeviceRumble(INT32 playernum, UINT16 low_strength, UINT16 high_stre
// doesent need to be super precise
// but ensure this is within range (0-65535)
// placed here so it applies to lua aswell
low_strength = (UINT16)min(FixedMul(low_strength, cv_rumblestrength[playernum].value), UINT16_MAX);
high_strength = (UINT16)min(FixedMul(high_strength, cv_rumblestrength[playernum].value), UINT16_MAX);
low_strength = (UINT16)min(FixedMul(low_strength, cv_rumble_strength[playernum].value), UINT16_MAX);
high_strength = (UINT16)min(FixedMul(high_strength, cv_rumble_strength[playernum].value), UINT16_MAX);
I_GamepadRumble(playernum, low_strength, high_strength, duration);
}
@@ -1059,7 +1076,7 @@ void G_DeviceRumbleTick(void)
{
UINT8 i;
if (dedicated || numcontrollers == 0 || gamestate != GS_LEVEL)
if (dedicated || numcontrollers == 0 || gamestate != GS_LEVEL || demo.playback)
{
return;
}
@@ -1090,6 +1107,11 @@ void G_DeviceRumbleTick(void)
const player_t *player = P_GetLocalPlayerForNum(i);
if (!player)
{
continue;
}
// allow lua to do some crap for spectators
if (player->spectator || !player->mo)
{
@@ -1105,17 +1127,20 @@ void G_DeviceRumbleTick(void)
continue;
}
if (player->kartstuff[k_spinouttimer])
if (cv_rumble_spinout[i].value
&& player->kartstuff[k_spinouttimer])
{
//low = high = FRACUNIT / 6;
low = high = FixedMul((RUMBLE_VERYSTRONG), (FixedDiv(player->kartstuff[k_spinouttimer], (3*TICRATE / 2)))); // try do some some kinda fadeout, 3*TICRATE / 2 is the "default" spinout time
}
else if (player->kartstuff[k_sneakertimer] > (sneakertime-(TICRATE/2)))
else if (cv_rumble_sneakerboost[i].value
&& (player->kartstuff[k_sneakertimer] > (sneakertime-(TICRATE/2))))
{
low = high = RUMBLE_STRONG;
}
else if ((player->kartstuff[k_offroad])
&& player->speed != 0
else if (cv_rumble_offroad[i].value
&& (player->kartstuff[k_offroad])
&& (player->speed != 0)
&& P_IsObjectOnGround(player->mo))
{
// weaken this depending on if you got hyu or invinc
@@ -1132,26 +1157,37 @@ void G_DeviceRumbleTick(void)
low = high = RUMBLE_MODERATE;
}
}
else if ((player->kartstuff[k_bananadrag] > TICRATE)
&& player->speed != 0
else if (cv_rumble_bananadrag[i].value
&& (player->kartstuff[k_bananadrag] > TICRATE)
&& (player->speed != 0)
&& P_IsObjectOnGround(player->mo))
{
if (leveltime & 1) // this is actually funny lel
high = RUMBLE_MODERATE;
}
else if (cv_rumble_stairjank[i].value
&& (player->stairjank > 8)
&& (player->speed != 0)
&& P_IsObjectOnGround(player->mo))
{
low = high = RUMBLE_VERYWEAK;
}
if (player->kartstuff[k_brakedrift])
if (cv_rumble_brakedrift[i].value
&& player->kartstuff[k_brakedrift])
{
high = CLAMP((high + RUMBLE_VERYWEAK), 0, UINT16_MAX);
}
// pulse when gettin new driftlevel
// let this come last
if (player->kartstuff[k_driftcharge]
if (cv_rumble_driftcharge[i].value
&& player->kartstuff[k_driftcharge]
&& player->driftlevel)
{
high = CLAMP((high + RUMBLE_VERYWEAK), 0, UINT16_MAX);
// make it rumble slightly longer the higher your driftlevel!
if (player->driftlevel == 2)
lenght = 114;
else if (player->driftlevel == 3)
+15 -5
View File
@@ -100,9 +100,10 @@ typedef enum
gc_custom2, // Lua scriptable
gc_custom3, // Lua scriptable
gc_director,
gc_freecam, // Toggle for freecam while ingame
gc_camfloat, // alternative button for raising cam
gc_camsink, // alternative button for sinking
// freecam specific controls
gc_freecam, // Toggle for freecam while ingame
gc_camfloat, // alternative button for raising camera
gc_camsink, // alternative button for sinking camera
gc_strafeleft,
gc_straferight,
num_gamecontrols
@@ -112,10 +113,19 @@ typedef enum
extern consvar_t cv_mousexsens, cv_mouseysens;
extern consvar_t cv_controlperkey;
extern consvar_t cv_turnsmooth[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_rumble[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_rumblestrength[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_gamepadled[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_rumble[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_rumble_strength[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_rumble_spinout[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_rumble_sneakerboost[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_rumble_offroad[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_rumble_bananadrag[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_rumble_stairjank[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_rumble_brakedrift[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_rumble_driftcharge[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_gamepadifunfocused;
extern consvar_t cv_gamepadledifunfocused;
extern consvar_t cv_rumbleifunfocused;
+1
View File
@@ -183,6 +183,7 @@ static int comparePolygons(const void *p1, const void *p2)
UINT32 downloaded1 = poly1->texture ? poly1->texture->downloaded : 0; // there should be a opengl texture name here, usable for comparisons
UINT32 downloaded2 = poly2->texture ? poly2->texture->downloaded : 0;
diff64 = downloaded1 - downloaded2;
if (diff64 != 0) return diff64;
+292 -243
View File
@@ -12,20 +12,21 @@
/// \brief convert SRB2 map
#include "../doomdef.h"
#include "../doomstat.h"
#ifdef HWRENDER
#include "hw_main.h"
#include "hw_glob.h"
#include "../r_local.h"
#include "../z_zone.h"
#ifdef HWR_LOADING_SCREEN
#include "../console.h"
#include "../v_video.h"
#include "../m_menu.h"
#include "../i_system.h"
#include "../m_argv.h"
#include "../i_video.h"
#include "../w_wad.h"
#include "../p_setup.h" // levelfadecol
#include "../i_video.h"
#endif
//#define DEBUG_HWBSP
// --------------------------------------------------------------------------
// This is global data for planes rendering
@@ -33,19 +34,20 @@
extrasubsector_t *extrasubsectors = NULL;
// newsubsectors are subsectors without segs, added for the plane polygons
#define NEWSUBSECTORS 50
static size_t totsubsectors;
// extra subsectors are subsectors without segs, added for the plane polygons
#define NUM_EXTRA_SUBSECTORS 50
static size_t num_alloc_extra_subsector;
#ifdef PARANOIA
size_t addsubsector;
size_t num_extra_subsector;
#else
static size_t addsubsector;
static size_t num_extra_subsector;
#endif
typedef struct
{
typedef struct {
float x, y;
float dx, dy;
polyvertex_t divpt;
float divfrac;
} fdivline_t;
// when loading the map, this is set to true if portals are found.
@@ -53,7 +55,7 @@ typedef struct
boolean gl_maphasportals = false;
// Determine on mapload if current map has any Horizonlines present
// so we can avoid rather hot checks in HWR_Subsector
// avoids doing a bunch of work during rendering
boolean gl_maphashorizonlines = false;
// ==========================================================================
@@ -80,26 +82,25 @@ static poly_t *HWR_AllocPoly(INT32 numpts)
return p;
}
/// \todo polygons should be freed in reverse order for efficiency,
/// TODO: polygons should be freed in reverse order for efficiency,
/// for now don't free because it doesn't free in reverse order
static void HWR_FreePoly(poly_t *poly)
{
Z_Free(poly);
}
// Return interception along bsp line,
// Return interception along bsp line (partline),
// with the polygon segment
//
static float bspfrac;
static polyvertex_t *fracdivline(fdivline_t *bsp, polyvertex_t *v1,
polyvertex_t *v2)
// Return the division in partline div fields.
// divfrac = how far along partline vector is crossing pt
static boolean fracdivline(fdivline_t *partline, polyvertex_t *v1, polyvertex_t *v2)
{
static polyvertex_t pt;
double frac;
double num;
double den;
double v1x, v1y, v1dx, v1dy;
double v2x, v2y, v2dx, v2dy;
double frac1, frac2;
double num; // numerator
double den; // denominator
double v1x, v1y, v1dx, v1dy; // polygon side vector, v1->v2
double v3x, v3y, v3dx, v3dy; // partline vector
// a segment of a polygon
v1x = v1->x;
@@ -108,111 +109,118 @@ static polyvertex_t *fracdivline(fdivline_t *bsp, polyvertex_t *v1,
v1dy = v2->y - v1->y;
// the bsp partition line
v2x = bsp->x;
v2y = bsp->y;
v2dx = bsp->dx;
v2dy = bsp->dy;
v3x = partline->x;
v3y = partline->y;
v3dx = partline->dx;
v3dy = partline->dy;
den = v2dy*v1dx - v2dx*v1dy;
den = v3dy*v1dx - v3dx*v1dy;
if (fabsf((float)den) < 1.0E-36f) // avoid checking exactly for 0.0
return NULL; // parallel
if (fabs(den) < 1.0E-36) // avoid check of float for exact 0
return false; // partline and polygon side are effectively parallel
// first check the frac along the polygon segment,
// (do not accept hit with the extensions)
num = (v2x - v1x)*v2dy + (v1y - v2y)*v2dx;
frac = num / den;
num = (v3x - v1x)*v3dy + (v1y - v3y)*v3dx;
frac1 = num / den;
if (frac < 0.0l || frac > 1.0l)
return NULL;
// 0= cross at v1, 1.0= cross at v2
if (frac1 < 0.0 || frac1 > 1.0) // double
return false; // not within the polygon side
// now get the frac along the BSP line
// which is useful to determine what is left, what is right
num = (v2x - v1x)*v1dy + (v1y - v2y)*v1dx;
frac = num / den;
bspfrac = (float)frac;
num = (v3x - v1x)*v1dy + (v1y - v3y)*v1dx;
frac2 = num / den;
// find the interception point along the partition line
pt.x = (float)(v2x + v2dx*frac);
pt.y = (float)(v2y + v2dy*frac);
partline->divfrac = frac2; // how far along partline vector
return &pt;
// [WDJ] find the interception point along the segment.
// It should be slightly more accurate because it is always closer to the
// crossing point than arbitrary positions on the partition line.
partline->divpt.x = v1x + v1dx*frac1;
partline->divpt.y = v1y + v1dy*frac1;
return true;
}
// BOOMEDIT.WAD has a vertex error of .21
#define DIVLINE_VERTEX_DIFF 0.45f
// if two vertice coords have a x and/or y difference
// of less or equal than 1 FRACUNIT, they are considered the same
// point. Note: hardcoded value, 1.0f could be anything else.
static boolean SameVertice (polyvertex_t *p1, polyvertex_t *p2)
static boolean SameVertex(polyvertex_t *p1, polyvertex_t *p2)
{
if (fabsf( p2->x - p1->x ) > DIVLINE_VERTEX_DIFF)
if (fabsf(p2->x - p1->x) > DIVLINE_VERTEX_DIFF)
return false;
if (fabsf( p2->y - p1->y ) > DIVLINE_VERTEX_DIFF)
if (fabsf(p2->y - p1->y) > DIVLINE_VERTEX_DIFF)
return false;
// p1 and p2 are considered the same vertex
return true;
}
// split a _CONVEX_ polygon in two convex polygons
// outputs:
// frontpoly : polygon on right side of bsp line
// backpoly : polygon on left side
//
static void SplitPoly (fdivline_t *bsp, //splitting parametric line
poly_t *poly, //the convex poly we split
poly_t **frontpoly, //return one poly here
poly_t **backpoly) //return the other here
// Called from: WalkBSPNode
static void SplitPoly (fdivline_t *dlnp, // splitting parametric line
poly_t *poly, // the convex poly we split
poly_t **frontpoly, // return one poly here
poly_t **backpoly) // return the other here
{
INT32 i, j;
polyvertex_t *pv;
INT32 ps = -1, pe = -1;
INT32 nptfront, nptback;
INT32 ps, pe; // poly start, end
INT32 ps_online, pe_online;
INT32 nptfront, nptback;
polyvertex_t vs = {};
polyvertex_t ve = {};
polyvertex_t lastpv = {};
float fracs = 0.0f, frace = 0.0f; //used to tell which poly is on
// the front side of the bsp partition line
INT32 psonline = 0, peonline = 0;
float ps_frac = 0.0f, pe_frac = 0.0f; // used to tell which poly is on
// the front side of the bsp partition line
ps = pe = -1;
ps_online = pe_online = 0;
for (i = 0; i < poly->numpts; i++)
{
j = i + 1;
// i, j are one side of the poly
j = i+1;
if (j == poly->numpts)
j = 0;
j = 0; // wrap poly
// start & end points
pv = fracdivline(bsp, &poly->pts[i], &poly->pts[j]);
if (pv == NULL)
if (!fracdivline(dlnp, &poly->pts[i], &poly->pts[j]))
continue;
// have dividing pt
if (ps < 0)
{
// first point
ps = i;
vs = *pv;
fracs = bspfrac;
vs = dlnp->divpt;
ps_frac = dlnp->divfrac;
}
else
{
//the partition line traverse a junction between two segments
// the partition line can traverse a junction between two segments
// or the two points are so close, they can be considered as one
// thus, don't accept, since split 2 must be another vertex
if (SameVertice(pv, &lastpv))
if (SameVertex(&dlnp->divpt, &lastpv))
{
if (pe < 0)
{
ps = i;
psonline = 1;
ps_online = 1;
}
else
{
pe = i;
peonline = 1;
pe_online = 1;
}
}
else
@@ -220,24 +228,25 @@ static void SplitPoly (fdivline_t *bsp, //splitting parametric line
if (pe < 0)
{
pe = i;
ve = *pv;
frace = bspfrac;
ve = dlnp->divpt;
pe_frac = dlnp->divfrac;
}
else
{
// a frac, not same vertice as last one
// we already got pt2 so pt 2 is not on the line,
// so we probably got back to the start point
// which is on the line
if (SameVertice(pv, &vs))
psonline = 1;
// a frac, not same vertice as last one
// we already got pt2 so pt 2 is not on the line,
// so we probably got back to the start point
// which is on the line
if (SameVertex(&dlnp->divpt, &vs))
ps_online = 1;
break;
}
}
}
// remember last point intercept to detect identical points
lastpv = *pv;
lastpv = dlnp->divpt;
}
// no split: the partition line is either parallel and
@@ -254,28 +263,34 @@ static void SplitPoly (fdivline_t *bsp, //splitting parametric line
// linedefs where each side point the same sector, that is:
// the deep water effect with the original Doom
/// \todo make sure front poly is to front of partition line?
//TODO: make sure front poly is to front of partition line?
*frontpoly = poly;
*backpoly = NULL;
*backpoly = NULL;
return;
}
//if (ps >= 0 && pe < 0)
if (pe < 0)
{
//I_Error("SplitPoly: only one point for split line (%d %d)", ps, pe);
*frontpoly = poly;
*backpoly = NULL;
*backpoly = NULL;
return;
}
if (UNLIKELY(pe <= ps))
I_Error("SplitPoly: invalid splitting line (%d %d)", ps, pe);
if (pe <= ps)
{
//I_Error("SplitPoly: invalid splitting line (%d %d)", ps, pe);
*frontpoly = poly;
*backpoly = NULL;
return;
}
// number of points on each side, _not_ counting those
// that may lie just one the line
nptback = pe - ps - peonline;
nptfront = poly->numpts - peonline - psonline - nptback;
// Number of points on each side, _not_ counting those
// that may lie just on the line.
nptback = pe - ps - pe_online;
nptfront = poly->numpts - pe_online - ps_online - nptback;
if (nptback > 0)
*backpoly = HWR_AllocPoly(2 + nptback);
@@ -295,11 +310,9 @@ static void SplitPoly (fdivline_t *bsp, //splitting parametric line
*pv++ = ve;
i = pe;
do
{
do {
if (++i == poly->numpts)
i = 0;
*pv++ = poly->pts[i];
} while (i != ps && --nptfront);
}
@@ -312,66 +325,79 @@ static void SplitPoly (fdivline_t *bsp, //splitting parametric line
*pv++ = vs;
i = ps;
do
{
do {
if (++i == poly->numpts)
i = 0;
*pv++ = poly->pts[i];
} while (i != pe && --nptback);
}
// make sure frontpoly is the one on the 'right' side
// of the partition line
if (fracs > frace)
if (ps_frac > pe_frac)
{
poly_t *swappoly;
swappoly = *backpoly;
*backpoly = *frontpoly;
poly_t* swappoly;
swappoly = *backpoly;
*backpoly = *frontpoly;
*frontpoly = swappoly;
}
HWR_FreePoly (poly);
HWR_FreePoly(poly);
}
// checks if any line is a portal or horizonline, for optimization
static inline void CheckForPortalsAndHorizonLines(seg_t *lseg, const line_t *line)
{
// portal check
if (!gl_maphasportals && lseg->side == 0 && line->special == PORTALSPECIAL)
{
// Find the other side!
INT32 line2 = P_FindSpecialLineFromTag(PORTALSPECIAL, line->tag, -1);
// use each seg of the poly as a partition line, keep only the
if (line == &lines[line2])
line2 = P_FindSpecialLineFromTag(PORTALSPECIAL, line->tag, line2);
if (line2 >= 0) // found it!
gl_maphasportals = 1;
}
// horizonline check
if (!gl_maphashorizonlines && line->special == HORIZONSPECIAL)
gl_maphashorizonlines = true;
}
// Use each seg of the poly as a partition line, keep only the
// part of the convex poly to the front of the seg (that is,
// the part inside the sector), the part behind the seg, is
// the void space and is cut out
// the part inside the sector). The part behind the seg, is
// the void space and is cut out.
//
static poly_t *CutOutSubsecPoly(seg_t *lseg, INT32 count, poly_t *poly)
// poly : surrounding convex polygon, non-destructive
// lseg : array of seg
// segcount : number of seg in the array
// Return frontpoly, which may be new or ptr to poly.
// Called from: HWR_SubsecPoly
static poly_t *CutOutSubsecPoly(seg_t *lseg, INT32 segcount, poly_t *poly)
{
INT32 i, j;
poly_t* frontpoly = poly; // default, return same poly
polyvertex_t *pv;
INT32 nump = 0, ps, pe;
INT32 poly_num_pts = 0, ps, pe;
polyvertex_t vs = {}, ve = {},
p1 = {}, p2 = {};
float fracs = 0.0f;
float ps_frac = 0.0f;
vertex_t *v1, *v2;
fdivline_t cutseg; // x, y, dx, dy as start of node_t struct
poly_t *temppoly;
// for each seg of the subsector
for (; count--; lseg++)
for (; segcount--; lseg++)
{
// x, y, dx, dy (like a divline)
const line_t *line = lseg->linedef;
// portal check
if (UNLIKELY(!gl_maphasportals && line->special == PORTALSPECIAL && lseg->side == 0))
{
// Find the other side!
INT32 line2 = P_FindSpecialLineFromTag(PORTALSPECIAL, line->tag, -1);
if (!line)
continue;
if (line == &lines[line2])
line2 = P_FindSpecialLineFromTag(PORTALSPECIAL, line->tag, line2);
if (line2 >= 0) // found it!
gl_maphasportals = 1;
}
if (!gl_maphashorizonlines && line->special == HORIZONSPECIAL)
gl_maphashorizonlines = true;
CheckForPortalsAndHorizonLines(lseg, line);
if (line->sidenum[1] != NO_INDEX)
{
@@ -385,10 +411,21 @@ static poly_t *CutOutSubsecPoly(seg_t *lseg, INT32 count, poly_t *poly)
}
}
p1.x = FIXED_TO_FLOAT(lseg->side ? line->v2->x : line->v1->x);
p1.y = FIXED_TO_FLOAT(lseg->side ? line->v2->y : line->v1->y);
p2.x = FIXED_TO_FLOAT(lseg->side ? line->v1->x : line->v2->x);
p2.y = FIXED_TO_FLOAT(lseg->side ? line->v1->y : line->v2->y);
if (lseg->side) // side 1
{
v1 = line->v2;
v2 = line->v1;
}
else // side 0
{
v1 = line->v1;
v2 = line->v2;
}
p1.x = FixedToFloat(v1->x);
p1.y = FixedToFloat(v1->y);
p2.x = FixedToFloat(v2->x);
p2.y = FixedToFloat(v2->y);
cutseg.x = p1.x;
cutseg.y = p1.y;
@@ -401,125 +438,130 @@ static poly_t *CutOutSubsecPoly(seg_t *lseg, INT32 count, poly_t *poly)
for (i = 0; i < poly->numpts; i++)
{
j = i + 1;
// i, j are one side of the poly
j = i+1;
if (j == poly->numpts)
j = 0;
pv = fracdivline(&cutseg, &poly->pts[i], &poly->pts[j]);
if (pv == NULL)
if (!fracdivline(&cutseg, &poly->pts[i], &poly->pts[j]))
continue;
// have dividing pt
if (ps < 0)
{
ps = i;
vs = *pv;
fracs = bspfrac;
vs = cutseg.divpt;
ps_frac = cutseg.divfrac;
continue;
}
// frac 1 on previous segment,
// 0 on the next,
// the split line goes through one of the convex poly
// vertices, happens quite often since the convex
// poly is already adjacent to the subsector segs
// on most borders
if (SameVertex(&cutseg.divpt, &vs))
continue;
if (ps_frac <= cutseg.divfrac)
{
poly_num_pts = 2 + poly->numpts - (i-ps);
pe = ps;
ps = i;
ve = cutseg.divpt;
}
else
{
//frac 1 on previous segment,
// 0 on the next,
//the split line goes through one of the convex poly
// vertices, happens quite often since the convex
// poly is already adjacent to the subsector segs
// on most borders
if (SameVertice(pv, &vs))
continue;
if (fracs <= bspfrac)
{
nump = 2 + poly->numpts - (i-ps);
pe = ps;
ps = i;
ve = *pv;
}
else
{
nump = 2 + (i-ps);
pe = i;
ve = vs;
vs = *pv;
}
//found 2nd point
break;
poly_num_pts = 2 + (i-ps);
pe = i;
ve = vs;
vs = cutseg.divpt;
}
// found 2nd point
break;
}
// there was a split
if (ps >= 0)
{
//need 2 points
// need 2 points
if (pe >= 0)
{
// generate FRONT poly
temppoly = HWR_AllocPoly(nump);
frontpoly = HWR_AllocPoly(poly_num_pts);
pv = temppoly->pts;
pv = frontpoly->pts;
*pv++ = vs;
*pv++ = ve;
do
{
if (++ps == poly->numpts)
do {
if (++ps == poly->numpts) // poly wrap
ps = 0;
*pv++ = poly->pts[ps];
} while (ps != pe);
HWR_FreePoly(poly);
poly = temppoly;
poly = frontpoly;
}
#ifdef DEBUG_HWBSP
// hmmm... maybe we should NOT accept this, but this happens
// only when the cut is not needed it seems (when the cut
// line is aligned to one of the borders of the poly, and
// only some times..)
else
{
// hmmm... maybe we should NOT accept this, but this happens
// only when the cut is not needed it seems (when the cut
// line is aligned to one of the borders of the poly, and
// only some times..)
// [WDJ] This happens often (27 times in Doom2 map01).
skipcut++;
I_Error("CutOutPoly: only one point for split line (%d %d) %d", ps, pe, debugpos);
//I_Error("CutOutPoly: only one point for split line (%d %d) %d", ps, pe, debugpos);
}
#endif
}
}
return poly;
return frontpoly;
}
// At this point, the poly should be convex and the exact
// layout of the subsector, it is not always the case,
// layout of the subsector. It is not always the case,
// so continue to cut off the poly into smaller parts with
// each seg of the subsector.
//
static inline void HWR_SubsecPoly(INT32 num, poly_t *poly)
// ssindex : subsec index, 0..(numsubsectors-1)
// poly : surrounding convex polygon, non-destructive
// Called from WalkBSPNode
static inline void HWR_SubsecPoly(INT32 ssindex, poly_t *poly)
{
INT16 count;
INT16 segcount;
subsector_t *sub;
seg_t *lseg;
sub = &subsectors[num];
count = sub->numlines;
sub = &subsectors[ssindex];
segcount = sub->numlines;
lseg = &segs[sub->firstline];
if (poly)
{
poly = CutOutSubsecPoly(lseg,count,poly);
poly = CutOutSubsecPoly(lseg, segcount, poly);
#ifdef DEBUG_HWBSP
totalsubsecpolys++;
#endif
//extra data for this subsector
extrasubsectors[num].planepoly = poly;
extrasubsectors[ssindex].planepoly = poly;
}
}
// the bsp divline have not enouth presition
// search for the segs source of this divline
static inline void SearchDivline(node_t *bsp, fdivline_t *divline)
// The bsp divline does not have enough precision.
// Search for the segs source of this divline.
static inline void SetDivline(node_t *bsp, fdivline_t *divline)
{
divline->x = FIXED_TO_FLOAT(bsp->x);
divline->y = FIXED_TO_FLOAT(bsp->y);
divline->dx = FIXED_TO_FLOAT(bsp->dx);
divline->dy = FIXED_TO_FLOAT(bsp->dy);
// MAR - If you don't use the same partition line that the BSP uses,
// the front/back polys won't match the subsectors in the BSP!
divline->x = FixedToFloat(bsp->x);
divline->y = FixedToFloat(bsp->y);
divline->dx = FixedToFloat(bsp->dx);
divline->dy = FixedToFloat(bsp->dy);
}
//Hurdler: implement a loading status
@@ -532,20 +574,25 @@ static void loading_status(void)
char s[16];
int x, y;
/*if (g_reloadinggamestate)
{
return;
}*/
I_OsPolling();
CON_Drawer();
sprintf(s, "%d%%", (++ls_percent)<<1);
x = BASEVIDWIDTH/2;
y = BASEVIDHEIGHT/2;
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // Black background to match fade in effect
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol); // Black background to match fade in effect
//V_DrawPatchFill(srb2back); // SRB2 background, ehhh too bright.
M_DrawTextBox(x-58, y-8, 13, 1);
V_DrawString(x-50, y, V_YELLOWMAP, "Loading...");
V_DrawRightAlignedString(x+50, y, V_YELLOWMAP, s);
// Is this really necessary at this point..?
V_DrawCenteredString(BASEVIDWIDTH/2, 40, V_YELLOWMAP, "OPENGL MODE IS INCOMPLETE AND MAY");
V_DrawCenteredString(BASEVIDWIDTH/2, 50, V_YELLOWMAP, "NOT DISPLAY SOME SURFACES.");
V_DrawCenteredString(BASEVIDWIDTH/2, 40, V_YELLOWMAP, "OPENGL MODE IS INCOMPLETE AND SOME");
V_DrawCenteredString(BASEVIDWIDTH/2, 50, V_YELLOWMAP, "VISUAL FEATURES ARE MISSING/BROKEN.");
V_DrawCenteredString(BASEVIDWIDTH/2, 70, V_YELLOWMAP, "USE AT SONIC'S RISK.");
I_UpdateNoVsync();
@@ -576,14 +623,14 @@ static void WalkBSPNode(INT32 bspnum, poly_t *poly, UINT16 *leafnode, fixed_t *b
{
CONS_Debug(DBG_RENDER, "Adding a new subsector\n");
if (UNLIKELY(addsubsector == numsubsectors + NEWSUBSECTORS))
I_Error("WalkBSPNode: not enough addsubsectors\n");
else if (UNLIKELY(addsubsector > 0x7fff))
I_Error("WalkBSPNode: addsubsector > 0x7fff\n");
if (num_extra_subsector == numsubsectors + NUM_EXTRA_SUBSECTORS)
I_Error("WalkBSPNode: not enough num_extra_subsectors\n");
else if (num_extra_subsector > 0x7fff)
I_Error("WalkBSPNode: num_extra_subsector > 0x7fff\n");
*leafnode = (UINT16)((UINT16)addsubsector | NF_SUBSECTOR);
extrasubsectors[addsubsector].planepoly = poly;
addsubsector++;
*leafnode = (UINT16)((UINT16)num_extra_subsector | NF_SUBSECTOR);
extrasubsectors[num_extra_subsector].planepoly = poly;
num_extra_subsector++;
}
//add subsectors without segs here?
@@ -593,8 +640,8 @@ static void WalkBSPNode(INT32 bspnum, poly_t *poly, UINT16 *leafnode, fixed_t *b
{
HWR_SubsecPoly(bspnum & ~NF_SUBSECTOR, poly);
//Hurdler: implement a loading status
#ifdef HWR_LOADING_SCREEN
//Hurdler: implement a loading status
if (ls_count-- <= 0)
{
ls_count = numsubsectors/50;
@@ -613,7 +660,7 @@ static void WalkBSPNode(INT32 bspnum, poly_t *poly, UINT16 *leafnode, fixed_t *b
}
bsp = &nodes[bspnum];
SearchDivline(bsp, &fdivline);
SetDivline(bsp, &fdivline);
SplitPoly(&fdivline, poly, &frontpoly, &backpoly);
poly = NULL;
@@ -656,12 +703,12 @@ void HWR_FreeExtraSubsectors(void)
extrasubsectors = NULL;
}
#define MAXDIST 1.5f
#define MAXDIST (1.5f)
// BP: can't move vertex: DON'T change polygon geometry! (convex)
//#define MOVEVERTEX
// Is vertex va within the seg v1, v2
static boolean PointInSeg(polyvertex_t *va,polyvertex_t *v1,polyvertex_t *v2)
static boolean PointInSeg(polyvertex_t *va, polyvertex_t *v1, polyvertex_t *v2)
{
register float ax, ay, bx, by, cx, cy, d, norm;
@@ -736,8 +783,8 @@ static boolean PointInSeg(polyvertex_t *va,polyvertex_t *v1,polyvertex_t *v2)
if (cx*cx+cy*cy <= MAXDIST*MAXDIST)
{
// ajust a little the point position
a->x = ax*d+v1->x;
a->y = ay*d+v1->y;
va->x = ax*d+v1->x;
va->y = ay*d+v1->y;
// anyway the correction is not enouth
return true;
}
@@ -749,10 +796,10 @@ static boolean PointInSeg(polyvertex_t *va,polyvertex_t *v1,polyvertex_t *v2)
static INT32 numsplitpoly;
static void SearchSegInBSP(INT32 bspnum,polyvertex_t *p,poly_t *poly)
static void SearchSegInBSP(INT32 bspnum, polyvertex_t *p, poly_t *poly)
{
poly_t *q;
INT32 j,k;
INT32 j, k;
if (bspnum & NF_SUBSECTOR)
{
@@ -772,12 +819,12 @@ static void SearchSegInBSP(INT32 bspnum,polyvertex_t *p,poly_t *poly)
if (k == numpts)
k = 0;
if (!SameVertice(p, &q->pts[j])
&& !SameVertice(p, &q->pts[k])
&& PointInSeg(p, &q->pts[j], &q->pts[k]))
if (!SameVertex(p, &q->pts[j]) &&
!SameVertex(p, &q->pts[k]) &&
PointInSeg(p, &q->pts[j], &q->pts[k]))
{
poly_t *newpoly = HWR_AllocPoly(numpts+1);
INT32 n;
poly_t *newpoly = HWR_AllocPoly(numpts+1);
for (n = 0; n <= j; n++)
newpoly->pts[n] = q->pts[n];
@@ -798,16 +845,17 @@ static void SearchSegInBSP(INT32 bspnum,polyvertex_t *p,poly_t *poly)
return;
}
if ((FIXED_TO_FLOAT(nodes[bspnum].bbox[0][BOXBOTTOM])-MAXDIST <= p->y) &&
(FIXED_TO_FLOAT(nodes[bspnum].bbox[0][BOXTOP ])+MAXDIST >= p->y) &&
(FIXED_TO_FLOAT(nodes[bspnum].bbox[0][BOXLEFT ])-MAXDIST <= p->x) &&
(FIXED_TO_FLOAT(nodes[bspnum].bbox[0][BOXRIGHT ])+MAXDIST >= p->x))
// Not a subsector, visit left and right children.
if ((FixedToFloat(nodes[bspnum].bbox[0][BOXBOTTOM])-MAXDIST <= p->y) &&
(FixedToFloat(nodes[bspnum].bbox[0][BOXTOP ])+MAXDIST >= p->y) &&
(FixedToFloat(nodes[bspnum].bbox[0][BOXLEFT ])-MAXDIST <= p->x) &&
(FixedToFloat(nodes[bspnum].bbox[0][BOXRIGHT ])+MAXDIST >= p->x))
SearchSegInBSP(nodes[bspnum].children[0], p, poly);
if ((FIXED_TO_FLOAT(nodes[bspnum].bbox[1][BOXBOTTOM])-MAXDIST <= p->y) &&
(FIXED_TO_FLOAT(nodes[bspnum].bbox[1][BOXTOP ])+MAXDIST >= p->y) &&
(FIXED_TO_FLOAT(nodes[bspnum].bbox[1][BOXLEFT ])-MAXDIST <= p->x) &&
(FIXED_TO_FLOAT(nodes[bspnum].bbox[1][BOXRIGHT ])+MAXDIST >= p->x))
if ((FixedToFloat(nodes[bspnum].bbox[1][BOXBOTTOM])-MAXDIST <= p->y) &&
(FixedToFloat(nodes[bspnum].bbox[1][BOXTOP ])+MAXDIST >= p->y) &&
(FixedToFloat(nodes[bspnum].bbox[1][BOXLEFT ])-MAXDIST <= p->x) &&
(FixedToFloat(nodes[bspnum].bbox[1][BOXRIGHT ])+MAXDIST >= p->x))
SearchSegInBSP(nodes[bspnum].children[1], p, poly);
}
@@ -816,38 +864,43 @@ static void SearchSegInBSP(INT32 bspnum,polyvertex_t *p,poly_t *poly)
// but we must use a different structure : polygone pointing on segs
// segs pointing on polygone and on vertex (too mush complicated, well not
// realy but i am soo lasy), the methode discibed is also better for segs presition
static INT32 SolveTProblem(void)
static void SolveTProblem(void)
{
poly_t *p;
INT32 i;
size_t l;
INT32 i, numpts;
size_t ssnum;
if (cv_glsolvetjoin.value == 0)
return 0;
if (!cv_glsolvetjoin.value)
return;
CONS_Debug(DBG_RENDER, "Solving T-joins. This may take a while. Please wait...\n");
#ifdef HWR_LOADING_SCREEN
CON_Drawer(); //let the user know what we are doing
I_FinishUpdate(); // page flip or blit buffer
#endif
numsplitpoly = 0;
for (l = 0; l < addsubsector; l++)
for (ssnum = 0; ssnum < num_extra_subsector; ssnum++)
{
p = extrasubsectors[l].planepoly;
p = extrasubsectors[ssnum].planepoly;
if (!p)
if (!p || p->numpts == 0)
continue;
for (i = 0; i < p->numpts; i++)
numpts = p->numpts;
for (i = 0; i < numpts; i++)
SearchSegInBSP((INT32)numnodes-1, &p->pts[i], p);
}
#ifdef DEBUG_HWBSP
CONS_Debug(DBG_RENDER, "numsplitpoly %d\n", numsplitpoly);
CONS_Debug(DBG_RENDER, "%d point divides a polygon line\n", numsplitpoly);
#endif
return numsplitpoly;
}
// call this routine after the BSP of a Doom wad file is loaded,
// and it will generate all the convex polys for the hardware renderer
void HWR_CreatePlanePolygons(INT32 bspnum)
@@ -865,7 +918,7 @@ void HWR_CreatePlanePolygons(INT32 bspnum)
#endif
// reset the portal and horizonline flag
gl_maphasportals = gl_maphashorizonlines = 0;
gl_maphasportals = gl_maphashorizonlines = false;
// find min/max boundaries of map
#ifdef DEBUG_HWBSP
@@ -882,39 +935,35 @@ void HWR_CreatePlanePolygons(INT32 bspnum)
HWR_FreeExtraSubsectors();
// allocate extra data for each subsector present in map
totsubsectors = numsubsectors + NEWSUBSECTORS;
extrasubsectors = calloc(totsubsectors, sizeof(*extrasubsectors));
num_alloc_extra_subsector = numsubsectors + NUM_EXTRA_SUBSECTORS;
extrasubsectors = (extrasubsector_t*)calloc(num_alloc_extra_subsector, sizeof(*extrasubsectors));
if (UNLIKELY(!extrasubsectors))
I_Error("couldn't malloc extrasubsectors totsubsectors %s\n", sizeu1(totsubsectors));
I_Error("couldn't malloc extrasubsectors num_alloc_extra_subsector %s\n", sizeu1(num_alloc_extra_subsector));
// number of the first new subsector that might be added
addsubsector = numsubsectors;
num_extra_subsector = numsubsectors;
// construct the initial convex poly that encloses the full map
rootp = HWR_AllocPoly(4);
rootpv = rootp->pts;
rootpv->x = FIXED_TO_FLOAT(rootbbox[BOXLEFT ]);
rootpv->y = FIXED_TO_FLOAT(rootbbox[BOXBOTTOM]); //lr
// clockwise polygon
rootpv->x = FixedToFloat(rootbbox[BOXLEFT ]);
rootpv->y = FixedToFloat(rootbbox[BOXBOTTOM]); //lr
rootpv++;
rootpv->x = FIXED_TO_FLOAT(rootbbox[BOXLEFT ]);
rootpv->y = FIXED_TO_FLOAT(rootbbox[BOXTOP ]); //ur
rootpv->x = FixedToFloat(rootbbox[BOXLEFT ]);
rootpv->y = FixedToFloat(rootbbox[BOXTOP ]); //ur
rootpv++;
rootpv->x = FIXED_TO_FLOAT(rootbbox[BOXRIGHT ]);
rootpv->y = FIXED_TO_FLOAT(rootbbox[BOXTOP ]); //ul
rootpv->x = FixedToFloat(rootbbox[BOXRIGHT ]);
rootpv->y = FixedToFloat(rootbbox[BOXTOP ]); //ul
rootpv++;
rootpv->x = FIXED_TO_FLOAT(rootbbox[BOXRIGHT ]);
rootpv->y = FIXED_TO_FLOAT(rootbbox[BOXBOTTOM]); //ll
rootpv->x = FixedToFloat(rootbbox[BOXRIGHT ]);
rootpv->y = FixedToFloat(rootbbox[BOXBOTTOM]); //ll
rootpv++;
WalkBSPNode(bspnum, rootp, NULL, rootbbox);
#ifdef DEBUG_HWBSP
i = SolveTProblem();
CONS_Debug(DBG_RENDER, "%d point divides a polygon line\n",i);
#else
SolveTProblem();
#endif
#ifdef DEBUG_HWBSP
//debug debug..
-1
View File
@@ -96,7 +96,6 @@ typedef struct
typedef struct
{
float x, y, z;
fixed_t x2, y2, z2;
} polyvertex_t;
// a convex 'plane' polygon, clockwise order
+1 -1
View File
@@ -54,7 +54,7 @@ void HWR_ObjectLightLevelPost(gl_vissprite_t *spr, const sector_t *sector, INT32
// --------
extern extrasubsector_t *extrasubsectors;
#ifdef PARANOIA
extern size_t addsubsector;
extern size_t num_extra_subsector;
#endif
void HWR_FreeExtraSubsectors(void);
+195 -71
View File
@@ -84,11 +84,6 @@ float gl_viewsin = 0.0f, gl_viewcos = 0.0f;
static float gl_viewludsin, gl_viewludcos;
static angle_t gl_aimingangle;
static float yaw = 0.0f;
static float inv_yaw = 0.0f;
static float cos_inv_yaw = 0.0f;
static float sin_inv_yaw = 0.0f;
static constexpr float deg2radians = (M_PIf / 180.0f);
seg_t *gl_curline = NULL;
@@ -1001,8 +996,9 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum,
const fixed_t v2y = FloatToFixed(wallVerts[1].z);
const UINT8 alpha = Surf->PolyColor.s.alpha;
FUINT lightnum = HWR_CalcWallLight(sector->lightlevel, gl_curline, NULL);
FUINT lightnum = sector->lightlevel;
extracolormap_t *colormap = NULL;
lightnum = HWR_CalcWallLight(lightnum, gl_curline, NULL);
realtop = top = wallVerts[3].y;
realbot = bot = wallVerts[0].y;
@@ -1071,11 +1067,11 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum,
else
solid = false;
height = FixedToFloat(P_GetLightZAt(&list[i], v1x, v1y));
endheight = FixedToFloat(P_GetLightZAt(&list[i], v2x, v2y));
if (solid)
{
height = FixedToFloat(P_GetLightZAt(&list[i], v1x, v1y));
endheight = FixedToFloat(P_GetLightZAt(&list[i], v2x, v2y));
bheight = FixedToFloat(P_GetFFloorBottomZAt(list[i].caster, v1x, v1y));
endbheight = FixedToFloat(P_GetFFloorBottomZAt(list[i].caster, v2x, v2y));
@@ -1105,8 +1101,8 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum,
// Found a break
// The heights are clamped to ensure the polygon doesn't cross itself.
bot = std::max(bheight, realbot);
endbot = std::max(endbheight, endrealbot);
bot = std::clamp(bheight, realbot, top);
endbot = std::clamp(endbheight, endrealbot, endtop);
Surf->PolyColor.s.alpha = alpha;
@@ -2050,11 +2046,10 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
lightnum = rover->master->frontsector->lightlevel;
colormap = rover->master->frontsector->extra_colormap;
lightnum = HWR_CalcWallLight(lightnum, gl_curline, colormap);
Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(lightnum, colormap);
lightnum = HWR_CalcWallLight(lightnum, gl_curline, colormap);
if (other_sector->numlights)
HWR_SplitWall(other_sector, wallVerts, 0, false, &Surf, roverflags, rover, blendmode);
else
@@ -2784,9 +2779,9 @@ static void HWR_Subsector(size_t num)
ffloor_t *rover;
#ifdef PARANOIA // no risk while developing, enough debugging nights!
if (num >= addsubsector)
if (num >= num_extra_subsector)
I_Error("HWR_Subsector: ss %s with numss = %s, addss = %s\n",
sizeu1(num), sizeu2(numsubsectors), sizeu3(addsubsector));
sizeu1(num), sizeu2(numsubsectors), sizeu3(num_extra_subsector));
#endif
if (num < numsubsectors)
@@ -3488,6 +3483,8 @@ static void HWR_SplitSprite(gl_vissprite_t *spr, const boolean papersprite)
fixed_t v1x, v1y, v2x, v2y;
INT32 shader = SHADER_NONE;
const boolean billboarding = (cv_glspritebillboarding.value && !cv_glshearing.value && !papersprite);
gpatch = spr->gpatch;
// cache the patch in the graphics card memory
@@ -3671,8 +3668,8 @@ static void HWR_SplitSprite(gl_vissprite_t *spr, const boolean papersprite)
// Found a break
// The heights are clamped to ensure the polygon doesn't cross itself.
bot = std::max(bheight, realbot);
endbot = std::max(endbheight, endrealbot);
bot = std::clamp(bheight, realbot, top);
endbot = std::clamp(endbheight, endrealbot, endtop);
wallVerts[3].t = towtop + ((realtop - top) * towmult);
wallVerts[2].t = towtop + ((endrealtop - endtop) * towmult);
@@ -3685,7 +3682,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr, const boolean papersprite)
wallVerts[1].y = endbot;
// The x and y only need to be adjusted in the case that it's not a papersprite
if (cv_glspritebillboarding.value && !cv_glshearing.value && !papersprite)
if (billboarding)
{
// Get the x and z of the vertices so billboarding draws correctly
realheight = realbot - realtop;
@@ -3707,7 +3704,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr, const boolean papersprite)
wallVerts[1].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult;
}
HWR_Lighting(&Surf, lightlevel, colormap, P_SectorUsesDirectionalLighting(sector) && !(sprmo->frame & FF_FULLBRIGHT));
HWR_Lighting(&Surf, lightlevel, colormap, P_SectorUsesDirectionalLighting(sector) && !R_ThingIsFullBright(sprmo));
Surf.PolyColor.s.alpha = alpha;
@@ -3761,7 +3758,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
if (!sprmo->subsector)
return;
const boolean papersprite = (sprmo->frame & FF_PAPERSPRITE);
const boolean papersprite = R_ThingIsPaperSprite(sprmo);
const sector_t *sector = sprmo->subsector->sector;
if (sector->numlights)
@@ -3920,7 +3917,7 @@ static void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr)
INT32 shader = SHADER_NONE;
const precipmobj_t *sprmo = spr->precip;
precipmobj_t *sprmo = spr->precip;
if (!sprmo->subsector)
return;
@@ -3966,11 +3963,10 @@ static void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr)
if (sector->numlights)
{
INT32 light;
// Always use the light at the top instead of whatever I was doing before
INT32 light = R_GetPlaneLight(sector, sprmo->z, false); // sprmo->z + sprmo->height
light = R_GetPlaneLight(sector, sprmo->z, false); // Always use the light at the top instead of whatever I was doing before
if (!(sprmo->frame & FF_FULLBRIGHT))
if (!R_PrecipThingIsFullBright(sprmo))
lightlevel = static_cast<INT32>(*sector->lightlist[light].lightlevel);
if (sector->lightlist[light].extra_colormap)
@@ -3978,7 +3974,7 @@ static void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr)
}
else
{
if (!(sprmo->frame & FF_FULLBRIGHT))
if (!R_PrecipThingIsFullBright(sprmo))
lightlevel = static_cast<INT32>(sector->lightlevel);
if (sector->extra_colormap)
@@ -4562,7 +4558,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
return;
}
const boolean papersprite = (thing->frame & FF_PAPERSPRITE);
const boolean papersprite = R_ThingIsPaperSprite(thing);
// transform the origin point
tr_x = FixedToFloat(interp.x);
@@ -4576,8 +4572,8 @@ static void HWR_ProjectSprite(mobj_t *thing)
return;
const boolean mirrored = thing->mirrored;
const boolean vflip = (thing->eflags & MFE_VERTICALFLIP);
const boolean hflip = (!(thing->frame & FF_HORIZONTALFLIP) != !mirrored);
const boolean vflip = R_ThingVerticallyFlipped(thing);
const boolean hflip = (!R_ThingHorizontallyFlipped(thing) != !mirrored);
// decide which patch to use for sprite relative to player
#ifdef RANGECHECK
@@ -4630,7 +4626,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
#ifdef ROTSPRITE
// determine here if sprite should rotate for optimization
const boolean sliprollrotate = (cv_sliptideroll.value && (thing->player && thing->player->sliproll));
const boolean shouldrotate = (interp.sloperoll || interp.slopepitch || interp.roll || interp.pitch || thing->rollangle || sliprollrotate);
const boolean shouldrotate = (interp.sloperoll || interp.slopepitch || interp.roll || interp.pitch || thing->rollangle || thing->temprollangle || sliprollrotate);
#endif
if (sprframe->rotate != SRF_SINGLE || papersprite
@@ -4688,7 +4684,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
// this is very messy, but it on-the-fly calculates rotations for all the
// pitch and roll variables
pitchnroll = R_RotationAngle(ang, camang, &interp);
rollangle = thing->rollangle;
rollangle = (thing->rollangle - thing->temprollangle);
if (rollangle || pitchnroll || sliprollrotate)
{
@@ -4764,9 +4760,9 @@ static void HWR_ProjectSprite(mobj_t *thing)
// if the sprite is out of our view, dont need to draw it X)
if (!gld_SphereInFrustum(
(FixedToFloat(interp.x)) + cos_inv_yaw * (x1 + x2) / 2.0f,
(FixedToFloat(interp.x)) + gl_viewsin * (x1 + x2) / 2.0f,
FixedToFloat(interp.z) + (y1 + y2) / 2.0f,
FixedToFloat(interp.y) - sin_inv_yaw * (x1 + x2) / 2.0f,
FixedToFloat(interp.y) - (-gl_viewcos) * (x1 + x2) / 2.0f,
//1.5 == sqrt(2) + small delta for MF_FOREGROUND
std::max<float>(FixedToFloat(spr_width) * spritexscale,
FixedToFloat(spr_height) * spriteyscale) / 2.0f * 1.5f))
@@ -4984,9 +4980,9 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
y2 *= thing_scale;
if (!gld_SphereInFrustum(
(FixedToFloat(interp.x)) + cos_inv_yaw * (x1 + x2) / 2.0f,
(FixedToFloat(interp.x)) + gl_viewsin * (x1 + x2) / 2.0f,
FixedToFloat(interp.z) + (y1 + y2) / 2.0f,
FixedToFloat(interp.y) - sin_inv_yaw * (x1 + x2) / 2.0f,
FixedToFloat(interp.y) - (-gl_viewcos) * (x1 + x2) / 2.0f,
//1.5 == sqrt(2) + small delta for MF_FOREGROUND
std::max<float>(FixedToFloat(spr_width) * thing_scale,
FixedToFloat(spr_height) * thing_scale) / 2.0f * 1.5f))
@@ -5116,24 +5112,22 @@ void HWR_BuildSkyDome(void)
int c, r;
signed char yflip;
static constexpr int row_count = 4;
int col_count = 4;
static constexpr int col_count = (4 * 16);
float delta;
gl_sky_t *sky = &gl_sky;
gl_skyvertex_t *vertex_p;
const texture_t *texture = textures[texturetranslation[skytexture]];
col_count *= 16;
if ((sky->columns != col_count) || (sky->rows != row_count))
HWR_ClearSkyDome();
sky->columns = col_count;
sky->rows = row_count;
sky->vertex_count = 2 * sky->rows * (sky->columns * 2 + 2) + sky->columns * 2;
sky->vertex_count = 2 * row_count * (col_count * 2 + 2) + col_count * 2;
if (!sky->loops)
sky->loops = static_cast<gl_skyloopdef_t*>(malloc((sky->rows * 2 + 2) * sizeof(sky->loops[0])));
sky->loops = static_cast<gl_skyloopdef_t*>(malloc((row_count * 2 + 2) * sizeof(sky->loops[0])));
// create vertex array
if (!sky->data)
@@ -5186,15 +5180,10 @@ void HWR_BuildSkyDome(void)
// precompute to save a bit of division
static constexpr float FINEDEGREE = (360.0f/static_cast<float>(FINEANGLES));
static void HWR_DrawSkyBackground(void)
static void HWR_DrawSkyDome(void)
{
FTransform dometransform;
if (HWR_IsWireframeMode())
return;
GL_SetBlend(PF_Translucent|PF_NoDepthTest|PF_Modulated);
memcpy(&dometransform, &atransform, sizeof(FTransform));
dometransform.x = dometransform.y = dometransform.z = 0.0;
@@ -5219,6 +5208,124 @@ static void HWR_DrawSkyBackground(void)
GL_RenderSkyDome(&gl_sky);
}
// the following is karts old sky code from before the skydome stuff
// this appears to differ a bit from srb2´s old sky code
static void HWR_DrawSkyTexture(void)
{
FOutVector v[4];
angle_t angle;
float dimensionmultiply;
float aspectratio;
float angleturn;
HWR_GetTexture(texturetranslation[skytexture], false);
aspectratio = (float)vid.width/(float)vid.height;
//Hurdler: the sky is the only texture who need 4.0f instead of 1.0
// because it's called just after clearing the screen
// and thus, the near clipping plane is set to 3.99
// Sryder: Just use the near clipping plane value then
// 3--2
// | /|
// |/ |
// 0--1
v[0].x = v[3].x = -ZCLIP_PLANE-1;
v[1].x = v[2].x = ZCLIP_PLANE+1;
v[0].y = v[1].y = -ZCLIP_PLANE-1;
v[2].y = v[3].y = ZCLIP_PLANE+1;
v[0].z = v[1].z = v[2].z = v[3].z = ZCLIP_PLANE+1;
// X
// NOTE: This doesn't work right with texture widths greater than 1024
// software doesn't draw any further than 1024 for skies anyway, but this doesn't overlap properly
// The only time this will probably be an issue is when a sky wider than 1024 is used as a sky AND a regular wall texture
//angle = (viewangle + ANGLE_45);
angle = (viewangle + xtoviewangle[0]);
dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f);
if (atransform.fliptype == TRANSFORM_MIRROR ||
atransform.fliptype == TRANSFORM_MIRRORFLIP)
{
angle = InvAngle(angle);
dimensionmultiply *= -1;
}
v[0].s = v[3].s = ((float)angle / ((float)(ANGLE_90-1)*dimensionmultiply));
v[2].s = v[1].s = (-1.0f/dimensionmultiply)+((float) angle / ((float)(ANGLE_90-1)*dimensionmultiply));
// Y
angle = aimingangle;
dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->height/(128.0f*aspectratio));
if (splitscreen == 1)
{
dimensionmultiply *= 2;
angle *= 2;
}
// Middle of the sky should always be at angle 0
// need to keep correct aspect ratio with X
if (atransform.fliptype == TRANSFORM_FLIP ||
atransform.fliptype == TRANSFORM_MIRRORFLIP)
{
// During vertical flip the sky should be flipped and it's y movement should also be flipped obviously
v[3].t = v[2].t = -(0.5f-(0.5f/dimensionmultiply));
v[0].t = v[1].t = (-1.0f/dimensionmultiply)-(0.5f-(0.5f/dimensionmultiply));
}
else
{
v[3].t = v[2].t = (-1.0f/dimensionmultiply)-(0.5f-(0.5f/dimensionmultiply));
v[0].t = v[1].t = -(0.5f-(0.5f/dimensionmultiply));
}
angleturn = (((float)ANGLE_45-1.0f)*aspectratio)*dimensionmultiply;
if (cv_glshearing.value)
{
// Doesn't really make sense, but what can I do?
angle_t dy = FixedAngle(FixedMul(360*FRACUNIT, FixedDiv(AIMINGTODY(aimingangle), 900*FRACUNIT)));
v[3].t = v[2].t -= ((float) dy / angleturn);
v[0].t = v[1].t -= ((float) dy / angleturn);
}
else
{
if (angle > ANGLE_180) // Do this because we don't want the sky to suddenly teleport when crossing over 0 to 360 and vice versa
{
angle = InvAngle(angle);
v[3].t = v[2].t += ((float) angle / angleturn);
v[0].t = v[1].t += ((float) angle / angleturn);
}
else
{
v[3].t = v[2].t -= ((float) angle / angleturn);
v[0].t = v[1].t -= ((float) angle / angleturn);
}
}
// since sky is drawn as a "flat quad" this way, we have to unset any view transformations for it to work
GL_SetTransform(NULL);
GL_UnSetShader();
GL_DrawPolygon(NULL, v, 4, 0);
}
static void HWR_DrawSkyBackground(void)
{
if (HWR_IsWireframeMode())
return;
GL_SetBlend(PF_Translucent|PF_NoDepthTest|PF_Modulated);
if (cv_skydome.value)
HWR_DrawSkyDome();
else
HWR_DrawSkyTexture();
}
// -----------------+
// HWR_ClearView : clear the viewwindow, with maximum z value. also clears stencil buffer.
// -----------------+
@@ -5284,12 +5391,6 @@ void HWR_SetTransform(float fpov)
HWR_SetTransformAiming(&atransform);
atransform.angley = static_cast<float>(viewangle >> ANGLETOFINESHIFT)*(FINEDEGREE);
yaw = 270.0f - atransform.angley;
inv_yaw = 180.0f - yaw;
const float inv_yaw_radians = inv_yaw * deg2radians;
cos_inv_yaw = cosf(inv_yaw_radians);
sin_inv_yaw = sinf(inv_yaw_radians);
// only needed for sprite billboarding
if (cv_glspritebillboarding.value && !cv_glshearing.value)
{
@@ -5352,6 +5453,8 @@ static void HWR_RenderViewpoint(gl_portal_t *rootportal, int stencil_level, bool
{
gl_portallist_t portallist;
const boolean wireframe = HWR_IsWireframeMode();
player_t *viewplayer = &players[displayplayers[viewssnum]];
const float fpov = FixedToFloat(R_GetPlayerFov(viewplayer));
@@ -5412,7 +5515,7 @@ static void HWR_RenderViewpoint(gl_portal_t *rootportal, int stencil_level, bool
}
}
if (HWR_IsWireframeMode())
if (wireframe)
GL_SetSpecialState(HWD_SET_WIREFRAME, 1);
// FIXME: perfstats does not account for portal rendering!
@@ -5427,7 +5530,8 @@ static void HWR_RenderViewpoint(gl_portal_t *rootportal, int stencil_level, bool
if constexpr (Type == RenderViewpointType::kPortal)
{
gl_collect_skywalls = (allow_portals && !rootportal && portallist.base && (!skyboxmo[0] || !cv_skybox.value)); // if portals have been drawn in the main view, then render skywalls differently
// if portals have been drawn in the main view, then render skywalls differently
gl_collect_skywalls = (allow_portals && !rootportal && portallist.base && (!skyboxmo[0] || !cv_skybox.value));
// HAYA: Save the old portal state, and turn portals off while normally rendering the BSP tree.
// This fixes specific effects not working, such as horizon lines.
@@ -5497,7 +5601,7 @@ static void HWR_RenderViewpoint(gl_portal_t *rootportal, int stencil_level, bool
HWR_RenderDrawNodes();
if (HWR_IsWireframeMode())
if (wireframe)
GL_SetSpecialState(HWD_SET_WIREFRAME, 0);
HWR_FreePortalList(portallist); // always call this just in case
@@ -5886,6 +5990,10 @@ static void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD
static void HWR_DoPostProcessor(void)
{
// no flashes or screen waving if we want less vfx!
if (cv_reducevfx.value)
return;
// Armageddon Blast Flash!
// Could this even be considered postprocessor?
if (!HWR_ShouldUsePaletteRendering())
@@ -5925,7 +6033,7 @@ static void HWR_DoPostProcessor(void)
return;
// Not supported in splitscreen - someone want to add support?
if (splitscreen || cv_reducevfx.value)
if (splitscreen)
return;
//UINT8 viewnum = R_GetViewNumber();
@@ -5983,44 +6091,60 @@ static void HWR_DoPostProcessor(void)
// Flipping of the screen isn't done here anymore
}
void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum)
//
// wipes
//
static lumpnum_t wipelumpnum;
// puts wipe lumpname in wipename[9]
static boolean HWR_WipeCheck(UINT8 wipenum, UINT8 scrnnum)
{
static char lumpname[9] = "FADEmmss";
lumpnum_t lumpnum;
size_t lsize;
// screen textures disabled completely
if (cv_glscreentextures.value == 0)
{
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // just draw a black screen instead of flashing and crap
return;
return false;
}
if (wipenum > 99 || scrnnum > 99) // not a valid wipe number
// not a valid wipe number
if (wipenum > 99 || scrnnum > 99)
{
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // just draw a black screen instead of flashing and crap
return; // shouldn't end up here really, the loop should've stopped running beforehand
return false; // shouldn't end up here really, the loop should've stopped running beforehand
}
// puts the numbers into the lumpname
sprintf(&lumpname[4], "%.2hu%.2hu", (UINT16)wipenum, (UINT16)scrnnum);
lumpnum = W_CheckNumForName(lumpname);
wipelumpnum = W_CheckNumForName(lumpname);
if (lumpnum == LUMPERROR) // again, shouldn't be here really
// again, shouldn't be here really
if (wipelumpnum == LUMPERROR)
{
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // just draw a black screen instead of flashing and crap
return;
return false;
}
lsize = W_LumpLength(lumpnum);
lsize = W_LumpLength(wipelumpnum);
if (!(lsize == 256000 || lsize == 64000 || lsize == 16000 || lsize == 4000))
{
CONS_Alert(CONS_WARNING, "Fade mask lump %s of incorrect size, ignored\n", lumpname);
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // just draw a black screen instead of flashing and crap
return; // again, shouldn't get here if it is a bad size
return false; // again, shouldn't get here if it is a bad size
}
HWR_GetFadeMask(lumpnum);
return true;
}
void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum)
{
if (!HWR_WipeCheck(wipenum, scrnnum))
{
// just draw a black screen instead of rapidly flashing a white screen
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
return;
}
HWR_GetFadeMask(wipelumpnum);
GL_DoScreenWipe(HWD_SCREENTEXTURE_WIPE_START, HWD_SCREENTEXTURE_WIPE_END);
}
+7 -5
View File
@@ -1153,8 +1153,11 @@ void HWR_DrawMD2(gl_vissprite_t *spr)
INT32 durs = spr->mobj->state->tics;
INT32 tics = spr->mobj->tics;
//mdlframe_t *next = NULL;
//const UINT8 flip = (UINT8)(!(spr->mobj->eflags & MFE_VERTICALFLIP) != !R_ThingVerticallyFlipped(spr->mobj)); // :chaosleep:
const UINT8 flip = (UINT8)((spr->mobj->eflags & MFE_VERTICALFLIP) == MFE_VERTICALFLIP);
const UINT8 hflip = (UINT8)(!(spr->mobj->mirrored) != !(spr->mobj->frame & FF_HORIZONTALFLIP));
const UINT8 hflip = (UINT8)(!(spr->mobj->mirrored) != !R_ThingHorizontallyFlipped(spr->mobj));
spritedef_t *sprdef;
spriteframe_t *sprframe;
spriteinfo_t *sprinfo;
@@ -1400,12 +1403,11 @@ void HWR_DrawMD2(gl_vissprite_t *spr)
const angle_t sliptideroll = ((cv_sliptideroll.value && spr->mobj->player) ? spr->mobj->player->sliproll : 0);
const SINT8 flipfactor = flip ? -1 : 1;
const angle_t thingrollangle = (spr->mobj->rollangle - spr->mobj->temprollangle);
if (spr->mobj->rollangle || sliptideroll)
if (thingrollangle || sliptideroll)
{
angle_t rollang = sliptideroll
? (spr->mobj->rollangle) + (sliptideroll * spr->mobj->player->kartstuff[k_aizdriftstrat])
: (spr->mobj->rollangle);
angle_t rollang = sliptideroll ? (thingrollangle + (sliptideroll * spr->mobj->player->kartstuff[k_aizdriftstrat])) : thingrollangle;
rollang *= flipfactor;
-549
View File
@@ -1,549 +0,0 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// Copyright (C) 1998-2000 by DooM Legacy Team.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//-----------------------------------------------------------------------------
/// \file
/// \brief Windows specific part of the OpenGL API for Doom Legacy
///
/// TODO:
/// - check if windowed mode works
/// - support different pixel formats
#if defined (_WIN32)
//#define WIN32_LEAN_AND_MEAN
#define RPC_NO_WINDOWS_H
#include <windows.h>
#include <time.h>
#include "r_opengl.h"
// **************************************************************************
// GLOBALS
// **************************************************************************
#ifdef DEBUG_TO_FILE
static unsigned long nb_frames = 0;
static clock_t my_clock;
FILE *gllogstream;
#endif
static HDC hDC = NULL; // the window's device context
static HGLRC hGLRC = NULL; // the OpenGL rendering context
static HWND hWnd = NULL;
static BOOL WasFullScreen = FALSE;
static void UnSetRes(void);
#ifdef USE_WGL_SWAP
PFNWGLEXTSWAPCONTROLPROC wglSwapIntervalEXT = NULL;
#endif
PFNglClear pglClear;
PFNglGetIntegerv pglGetIntegerv;
PFNglGetString pglGetString;
#define MAX_VIDEO_MODES 32
static vmode_t video_modes[MAX_VIDEO_MODES];
INT32 oglflags = 0;
// **************************************************************************
// FUNCTIONS
// **************************************************************************
// -----------------+
// APIENTRY DllMain : DLL Entry Point,
// : open/close debug log
// Returns :
// -----------------+
BOOL WINAPI DllMain(HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpvReserved) // reserved
{
// Perform actions based on the reason for calling.
UNREFERENCED_PARAMETER(lpvReserved);
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
// Initialize once for each new process.
// Return FALSE to fail DLL load.
#ifdef DEBUG_TO_FILE
gllogstream = fopen("ogllog.txt", "wt");
if (gllogstream == NULL)
return FALSE;
#endif
DisableThreadLibraryCalls(hinstDLL);
break;
case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
break;
case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;
case DLL_PROCESS_DETACH:
// Perform any necessary cleanup.
#ifdef DEBUG_TO_FILE
if (gllogstream)
{
fclose(gllogstream);
gllogstream = NULL;
}
#endif
break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
}
#ifdef STATIC_OPENGL
#define pwglGetProcAddress wglGetProcAddress;
#define pwglCreateContext wglCreateContext;
#define pwglDeleteContext wglDeleteContext;
#define pwglMakeCurrent wglMakeCurrent;
#else
static HMODULE OGL32;
typedef void *(WINAPI *PFNwglGetProcAddress) (const char *);
static PFNwglGetProcAddress pwglGetProcAddress;
typedef HGLRC (WINAPI *PFNwglCreateContext) (HDC hdc);
static PFNwglCreateContext pwglCreateContext;
typedef BOOL (WINAPI *PFNwglDeleteContext) (HGLRC hglrc);
static PFNwglDeleteContext pwglDeleteContext;
typedef BOOL (WINAPI *PFNwglMakeCurrent) (HDC hdc, HGLRC hglrc);
static PFNwglMakeCurrent pwglMakeCurrent;
#endif
#ifndef STATIC_OPENGL
void *GetGLFunc(const char *proc)
{
void *func = NULL;
if (pwglGetProcAddress)
func = pwglGetProcAddress(proc);
if (!func)
func = GetProcAddress(OGL32, proc);
return func;
}
#endif
boolean LoadGL(void)
{
#ifndef STATIC_OPENGL
OGL32 = LoadLibrary("OPENGL32.DLL");
if (!OGL32)
return 0;
pwglGetProcAddress = GetGLFunc("wglGetProcAddress");
pwglCreateContext = GetGLFunc("wglCreateContext");
pwglDeleteContext = GetGLFunc("wglDeleteContext");
pwglMakeCurrent = GetGLFunc("wglMakeCurrent");
#endif
return SetupGLfunc();
}
// -----------------+
// SetupPixelFormat : Set the device context's pixel format
// Note : Because we currently use only the desktop's BPP format, all the
// : video modes in Doom Legacy OpenGL are of the same BPP, thus the
// : PixelFormat is set only once.
// : Setting the pixel format more than once on the same window
// : doesn't work. (ultimately for different pixel formats, we
// : should close the window, and re-create it)
// -----------------+
int SetupPixelFormat(INT32 WantColorBits, INT32 WantStencilBits, INT32 WantDepthBits)
{
static DWORD iLastPFD = 0;
INT32 nPixelFormat;
PIXELFORMATDESCRIPTOR pfd =
{
sizeof (PIXELFORMATDESCRIPTOR), // size
1, // version
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA, // color type
32 /*WantColorBits*/, // cColorBits : prefered color depth
0, 0, // cRedBits, cRedShift
0, 0, // cGreenBits, cGreenShift
0, 0, // cBlueBits, cBlueShift
0, 0, // cAlphaBits, cAlphaShift
0, // cAccumBits
0, 0, 0, 0, // cAccum Red/Green/Blue/Alpha Bits
0, // cDepthBits (0,16,24,32)
0, // cStencilBits
0, // cAuxBuffers
PFD_MAIN_PLANE, // iLayerType
0, // reserved, must be zero
0, 0, 0, // dwLayerMask, dwVisibleMask, dwDamageMask
};
DWORD iPFD = (WantColorBits<<16) | (WantStencilBits<<8) | WantDepthBits;
pfd.cDepthBits = (BYTE)WantDepthBits;
pfd.cStencilBits = (BYTE)WantStencilBits;
if (iLastPFD)
{
DBG_Printf("WARNING : SetPixelFormat() called twise not supported by all drivers !\n");
}
// set the pixel format only if different than the current
if (iPFD == iLastPFD)
return 2;
else
iLastPFD = iPFD;
DBG_Printf("SetupPixelFormat() - %d ColorBits - %d StencilBits - %d DepthBits\n",
WantColorBits, WantStencilBits, WantDepthBits);
nPixelFormat = ChoosePixelFormat(hDC, &pfd);
if (nPixelFormat == 0)
DBG_Printf("ChoosePixelFormat() FAILED\n");
if (SetPixelFormat(hDC, nPixelFormat, &pfd) == 0)
{
DBG_Printf("SetPixelFormat() FAILED\n");
return 0;
}
return 1;
}
// -----------------+
// SetRes : Set a display mode
// Notes : pcurrentmode is actually not used
// -----------------+
static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode)
{
LPCSTR renderer;
BOOL WantFullScreen = !(lvid->u.windowed); //(lvid->u.windowed ? 0 : CDS_FULLSCREEN);
UNREFERENCED_PARAMETER(pcurrentmode);
DBG_Printf ("SetMode(): %dx%d %d bits (%s)\n",
lvid->width, lvid->height, lvid->bpp*8,
WantFullScreen ? "fullscreen" : "windowed");
hWnd = lvid->WndParent;
// BP : why flush texture ?
// if important flush also the first one (white texture) and restore it !
Flush(); // Flush textures.
// TODO: if not fullscreen, skip display stuff and just resize viewport stuff ...
// Exit previous mode
//if (hGLRC) //Hurdler: TODO: check if this is valid
// UnSetRes();
if (WasFullScreen)
ChangeDisplaySettings(NULL, CDS_FULLSCREEN); //switch in and out of fullscreen
// Change display settings.
if (WantFullScreen)
{
DEVMODE dm;
ZeroMemory(&dm, sizeof (dm));
dm.dmSize = sizeof (dm);
dm.dmPelsWidth = lvid->width;
dm.dmPelsHeight = lvid->height;
dm.dmBitsPerPel = lvid->bpp*8;
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
if (ChangeDisplaySettings(&dm, CDS_TEST) != DISP_CHANGE_SUCCESSFUL)
return -2;
if (ChangeDisplaySettings(&dm, CDS_FULLSCREEN) !=DISP_CHANGE_SUCCESSFUL)
return -3;
SetWindowLong(hWnd, GWL_STYLE, WS_POPUP|WS_VISIBLE);
// faB : book says to put these, surely for windowed mode
//WS_CLIPCHILDREN|WS_CLIPSIBLINGS);
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, lvid->width, lvid->height, SWP_NOACTIVATE|SWP_NOZORDER);
}
else
{
RECT bounds;
INT32 x, y;
INT32 w = lvid->width, h = lvid->height;
GetWindowRect(hWnd, &bounds);
bounds.right = bounds.left+w;
bounds.bottom = bounds.top+h;
AdjustWindowRectEx(&bounds, GetWindowLong(hWnd, GWL_STYLE), (GetMenu(hWnd) != NULL), 0);
w = bounds.right-bounds.left;
h = bounds.bottom-bounds.top;
x = (GetSystemMetrics(SM_CXSCREEN)-w)/2;
y = (GetSystemMetrics(SM_CYSCREEN)-h)/2;
SetWindowPos(hWnd, NULL, x, y, w, h, SWP_NOACTIVATE|SWP_NOZORDER);
}
if (!hDC)
hDC = GetDC(hWnd);
if (!hDC)
{
DBG_Printf("GetDC() FAILED\n");
return 0;
}
{
INT32 res;
// Set res.
res = SetupPixelFormat(lvid->bpp*8, 0, 16);
if (res == 0)
return 0;
else if (res == 1)
{
// Exit previous mode
if (hGLRC)
UnSetRes();
hGLRC = pwglCreateContext(hDC);
if (!hGLRC)
{
DBG_Printf("pwglCreateContext() FAILED\n");
return 0;
}
if (!pwglMakeCurrent(hDC, hGLRC))
{
DBG_Printf("wglMakeCurrent() FAILED\n");
return 0;
}
}
}
gl_extensions = pglGetString(GL_EXTENSIONS);
// Get info and extensions.
//BP: why don't we make it earlier ?
//Hurdler: we cannot do that before intialising gl context
renderer = (LPCSTR)pglGetString(GL_RENDERER);
DBG_Printf("Vendor : %s\n", pglGetString(GL_VENDOR));
DBG_Printf("Renderer : %s\n", renderer);
DBG_Printf("Version : %s\n", pglGetString(GL_VERSION));
DBG_Printf("Extensions : %s\n", gl_extensions);
// BP: disable advenced feature that don't work on somes hardware
// Hurdler: Now works on G400 with bios 1.6 and certified drivers 6.04
if (strstr(renderer, "810")) oglflags |= GLF_NOZBUFREAD;
DBG_Printf("oglflags : 0x%X\n", oglflags);
#ifdef USE_WGL_SWAP
if (isExtAvailable("WGL_EXT_swap_control",gl_extensions))
wglSwapIntervalEXT = GetGLFunc("wglSwapIntervalEXT");
else
wglSwapIntervalEXT = NULL;
#endif
if (isExtAvailable("GL_EXT_texture_filter_anisotropic",gl_extensions))
pglGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maximumAnisotropy);
else
maximumAnisotropy = 0;
SetupGLFunc13();
screen_depth = (GLbyte)(lvid->bpp*8);
if (screen_depth > 16)
textureformatGL = GL_RGBA;
else
textureformatGL = GL_RGB5_A1;
GL_SetModelView(lvid->width, lvid->height);
GL_SetStates();
// we need to clear the depth buffer. Very important!!!
pglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
lvid->buffer = NULL; // unless we use the software view
lvid->direct = NULL; // direct access to video memory, old DOS crap
WasFullScreen = WantFullScreen;
return 1; // on renvoie une valeur pour dire que cela s'est bien pass�
}
// -----------------+
// UnSetRes : Restore the original display mode
// -----------------+
static void UnSetRes(void)
{
DBG_Printf("UnSetRes()\n");
pwglMakeCurrent(hDC, NULL);
pwglDeleteContext(hGLRC);
hGLRC = NULL;
if (WasFullScreen)
ChangeDisplaySettings(NULL, CDS_FULLSCREEN);
}
// -----------------+
// GetModeList : Return the list of available display modes.
// Returns : pvidmodes - points to list of detected OpenGL video modes
// : numvidmodes - number of detected OpenGL video modes
// -----------------+
EXPORT void HWRAPI(GetModeList) (vmode_t** pvidmodes, INT32 *numvidmodes)
{
INT32 i;
#if 1
INT32 iMode;
/*
faB test code
Commented out because there might be a problem with combo (Voodoo2 + other card),
we need to get the 3D card's display modes only.
*/
(*pvidmodes) = &video_modes[0];
// Get list of device modes
for (i = 0,iMode = 0; iMode < MAX_VIDEO_MODES; i++)
{
DEVMODE Tmp;
ZeroMemory(&Tmp, sizeof (Tmp));
Tmp.dmSize = sizeof (Tmp);
if (!EnumDisplaySettings(NULL, i, &Tmp))
break;
// add video mode
if (Tmp.dmBitsPerPel == 16 &&
(iMode == 0 || !
(Tmp.dmPelsWidth == video_modes[iMode-1].width &&
Tmp.dmPelsHeight == video_modes[iMode-1].height)
)
)
{
video_modes[iMode].pnext = &video_modes[iMode+1];
video_modes[iMode].windowed = 0; // fullscreen is the default
video_modes[iMode].misc = 0;
video_modes[iMode].name = malloc(12 * sizeof (CHAR));
sprintf(video_modes[iMode].name, "%dx%d", (INT32)Tmp.dmPelsWidth, (INT32)Tmp.dmPelsHeight);
DBG_Printf ("Mode: %s\n", video_modes[iMode].name);
video_modes[iMode].width = Tmp.dmPelsWidth;
video_modes[iMode].height = Tmp.dmPelsHeight;
video_modes[iMode].bytesperpixel = Tmp.dmBitsPerPel/8;
video_modes[iMode].rowbytes = Tmp.dmPelsWidth * video_modes[iMode].bytesperpixel;
video_modes[iMode].pextradata = NULL;
video_modes[iMode].setmode = SetRes;
iMode++;
}
}
(*numvidmodes) = iMode;
#else
// classic video modes (fullscreen/windowed)
// Added some. Tails
INT32 res[][2] = {
{ 320, 200},
{ 320, 240},
{ 400, 300},
{ 512, 384},
{ 640, 400},
{ 640, 480},
{ 800, 600},
{ 960, 600},
{1024, 768},
{1152, 864},
{1280, 800},
{1280, 960},
{1280,1024},
{1600,1000},
{1680,1050},
{1920,1200},
};
HDC bpphdc;
INT32 iBitsPerPel;
DBG_Printf ("HWRAPI GetModeList()\n");
bpphdc = GetDC(NULL); // on obtient le bpp actuel
iBitsPerPel = GetDeviceCaps(bpphdc, BITSPIXEL);
ReleaseDC(NULL, bpphdc);
(*pvidmodes) = &video_modes[0];
(*numvidmodes) = sizeof (res) / sizeof (res[0]);
for (i = 0; i < (*numvidmodes); i++)
{
video_modes[i].pnext = &video_modes[i+1];
video_modes[i].windowed = 0; // fullscreen is the default
video_modes[i].misc = 0;
video_modes[i].name = malloc(12 * sizeof (CHAR));
sprintf(video_modes[i].name, "%dx%d", res[i][0], res[i][1]);
DBG_Printf ("Mode: %s\n", video_modes[i].name);
video_modes[i].width = res[i][0];
video_modes[i].height = res[i][1];
video_modes[i].bytesperpixel = iBitsPerPel/8;
video_modes[i].rowbytes = res[i][0] * video_modes[i].bytesperpixel;
video_modes[i].pextradata = NULL;
video_modes[i].setmode = SetRes;
}
#endif
video_modes[(*numvidmodes)-1].pnext = NULL;
}
// -----------------+
// Shutdown : Shutdown OpenGL, restore the display mode
// -----------------+
EXPORT void HWRAPI(Shutdown) (void)
{
#ifdef DEBUG_TO_FILE
long nb_centiemes;
DBG_Printf ("HWRAPI Shutdown()\n");
nb_centiemes = ((clock()-my_clock)*100)/CLOCKS_PER_SEC;
DBG_Printf("Nb frames: %li; Nb sec: %2.2f -> %2.1f fps\n",
nb_frames, nb_centiemes/100.0f, (100*nb_frames)/(double)nb_centiemes);
#endif
Flush();
// Exit previous mode
if (hGLRC)
UnSetRes();
if (hDC)
{
ReleaseDC(hWnd, hDC);
hDC = NULL;
}
FreeLibrary(OGL32);
DBG_Printf ("HWRAPI Shutdown(DONE)\n");
}
// -----------------+
// FinishUpdate : Swap front and back buffers
// -----------------+
void GL_FinishUpdate (INT32 waitvbl)
{
#ifdef USE_WGL_SWAP
static INT32 oldwaitvbl = 0;
#else
UNREFERENCED_PARAMETER(waitvbl);
#endif
// DBG_Printf ("FinishUpdate()\n");
#ifdef DEBUG_TO_FILE
if ((++nb_frames)==2) // on ne commence pas � la premi�re frame
my_clock = clock();
#endif
#ifdef USE_WGL_SWAP
if (oldwaitvbl != waitvbl && wglSwapIntervalEXT)
wglSwapIntervalEXT(waitvbl);
oldwaitvbl = waitvbl;
#endif
SwapBuffers(hDC);
}
#endif
+32 -19
View File
@@ -776,15 +776,15 @@ static int GLFramebuffer_CheckExt(void)
// gl versions from 2.1 may still support framebuffer objects
// maybe, just maybe, we support the standart extensions
if (GL_isExtAvailable("GL_ARB_framebuffer_no_attachments", gl_extensions)
&& GL_isExtAvailable("GL_ARB_framebuffer_object", gl_extensions)
&& GL_isExtAvailable("GL_ARB_framebuffer_sRGB", gl_extensions))
if (GL_isExtAvailable("GL_ARB_framebuffer_no_attachments", gl_extensions) &&
GL_isExtAvailable("GL_ARB_framebuffer_object", gl_extensions) &&
GL_isExtAvailable("GL_ARB_framebuffer_sRGB", gl_extensions))
return FBO_ARB;
// nope, try the older 2.1 extensions
if (GL_isExtAvailable("GL_EXT_framebuffer_no_attachments", gl_extensions)
&& GL_isExtAvailable("GL_EXT_framebuffer_object", gl_extensions)
&& GL_isExtAvailable("GL_EXT_framebuffer_sRGB", gl_extensions))
if (GL_isExtAvailable("GL_EXT_framebuffer_no_attachments", gl_extensions) &&
GL_isExtAvailable("GL_EXT_framebuffer_object", gl_extensions) &&
GL_isExtAvailable("GL_EXT_framebuffer_sRGB", gl_extensions))
{
// perhaps we may even support a stencil attachment
if (GL_isExtAvailable("GL_EXT_packed_depth_stencil", gl_extensions))
@@ -885,7 +885,7 @@ void SetupGLFunc4(void)
{ \
GL_MSG_Warning("failed to get OpenGL FBO function: %s\n", #func); \
GL_DBG_Printf("\nFBO: No framebuffer object support\n"); \
supportFBO = false; \
supportFBO = FBO_NONE; \
return; \
} \
@@ -1465,6 +1465,19 @@ void GL_ReadScreenTexture(int tex, UINT8 *restrict dest, INT32 scale)
if (tex != HWD_SCREENTEXTURE_GENERIC2)
GL_DrawScreenTexture(tex, NULL, 0);
#ifdef USE_FBO_OGL
// FIXME: this is incredibly stupid
// but the final screen texture will NOT be drawn in the downsample fbo
if (tex == HWD_SCREENTEXTURE_GENERIC2 &&
UseScreenFBO() && HWR_ShouldUsePaletteRendering())
{
GL_SetShader(HWR_GetShaderFromTarget(SHADER_PALETTE_POSTPROCESS));
GL_EnableShader();
GL_DrawScreenTexture(HWD_SCREENTEXTURE_GENERIC2, NULL, 0);
GL_UnSetShader();
}
#endif
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);
@@ -2490,7 +2503,7 @@ void GL_RenderSkyDome(gl_sky_t *sky)
GL_Shader_SetUniforms(NULL, NULL, NULL, NULL);
// Build the sky dome! Yes!
if (sky->rebuild)
if (sky->rebuild || !sky->vbo)
{
// delete VBO when already exists
if (sky->vbo)
@@ -2915,7 +2928,7 @@ void GL_CreateModelVBOs(model_t *model)
}
}
#define BUFFER_OFFSET(i) ((char*)(i))
#define BUFFER_OFFSET(i) ((void*)(i))
void GL_DrawModelEx(model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface)
{
@@ -3208,8 +3221,8 @@ void GL_SetTransform(FTransform *stransform)
{
float dy = stransform->viewaiming * 2;
if (stransform->fliptype == TRANSFORM_FLIP
|| stransform->fliptype == TRANSFORM_MIRRORFLIP)
if (stransform->fliptype == TRANSFORM_FLIP ||
stransform->fliptype == TRANSFORM_MIRRORFLIP)
dy *= -1.0f;
pglTranslatef(0.0f, -dy/BASEVIDHEIGHT, 0.0f);
@@ -3234,7 +3247,7 @@ void GL_SetTransform(FTransform *stransform)
#ifdef USE_FBO_OGL
static void GL_Framebuffer_DeleteAttachments(void)
{
if (!supportFBO || !framebufferobject.init)
if (supportFBO == FBO_NONE || !framebufferobject.init)
return;
// Unbind the framebuffer
@@ -3254,7 +3267,7 @@ static void GL_Framebuffer_DeleteAttachments(void)
static void GL_Framebuffer_Generate(void)
{
if (!supportFBO || framebufferobject.init || !UseScreenFBO())
if (supportFBO == FBO_NONE || framebufferobject.init || !UseScreenFBO())
return;
// Generate the framebuffer
@@ -3274,10 +3287,10 @@ static void GL_Framebuffer_Generate(void)
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
Clamp2D(GL_TEXTURE_WRAP_S);
Clamp2D(GL_TEXTURE_WRAP_T);
pglBindTexture(GL_TEXTURE_2D, 0);
// Attach the framebuffer texture to the framebuffer
pglFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, framebufferobject.tex, 0);
pglBindTexture(GL_TEXTURE_2D, 0);
}
// Generate the renderbuffer
@@ -3319,7 +3332,7 @@ static void GL_Framebuffer_Generate(void)
// if this fails, dont retry it a gazillion times
// this wouldnt recover
supportFBO = false;
supportFBO = FBO_NONE;
pglBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
return;
}
@@ -3332,7 +3345,7 @@ static void GL_Framebuffer_Generate(void)
void GL_Framebuffer_Unbind(void)
{
if (!supportFBO || !framebufferobject.init)
if (supportFBO == FBO_NONE || !framebufferobject.init)
return;
pglBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
@@ -3341,13 +3354,13 @@ void GL_Framebuffer_Unbind(void)
void GL_Framebuffer_Enable(void)
{
if (!supportFBO || !UseScreenFBO())
if (supportFBO == FBO_NONE || !UseScreenFBO())
return;
GL_Framebuffer_Generate();
// failed
if (!supportFBO || !framebufferobject.init)
if (supportFBO == FBO_NONE || !framebufferobject.init)
return;
pglBindFramebuffer(GL_FRAMEBUFFER_EXT, framebufferobject.fboobj);
@@ -3356,7 +3369,7 @@ void GL_Framebuffer_Enable(void)
void GL_Framebuffer_Disable(void)
{
if (!supportFBO || !framebufferobject.init)
if (supportFBO == FBO_NONE || !framebufferobject.init)
return;
pglBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
-79
View File
@@ -1,79 +0,0 @@
[Project]
FileName=r_opengl.dev
Name=r_opengl
Ver=1
IsCpp=1
Type=3
Compiler=-D_M_IX86=500_@@_-Wall_@@_-D_WINDOWS_@@_-DUSE_WGL_SWAP_@@_-Os_@@_-fomit-frame-pointer_@@_
CppCompiler=
Includes=
Linker=--def ../r_mingw.def_@@_-lgdi32_@@_
Libs=
UnitCount=3
Folders=
ObjFiles=
PrivateResource=
ResourceIncludes=
MakeIncludes=
Icon=
ExeOutput=C:\srb2demo2
ObjectOutput=..\..\..\objs\Mingw\r_opengl
OverrideOutput=1
OverrideOutputName=r_opengl.dll
HostApplication=
CommandLine=
IncludeVersionInfo=0
SupportXPThemes=0
CompilerSet=0
CompilerSettings=00000000000000000111d0
UseCustomMakefile=0
CustomMakefile=
[Unit1]
FileName=ogl_win.c
Folder=
Compile=1
CompileCpp=0
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit2]
FileName=r_opengl.c
Folder=
Compile=1
CompileCpp=0
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit3]
FileName=r_opengl.h
Folder=
Compile=1
CompileCpp=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[VersionInfo]
Major=0
Minor=1
Release=1
Build=1
LanguageID=1033
CharsetID=1252
CompanyName=
FileVersion=0.1
FileDescription=Developed using the Dev-C++ IDE
InternalName=
LegalCopyright=
LegalTrademarks=
OriginalFilename=r_opengl.exe
ProductName=r_opengl
ProductVersion=0.1
AutoIncBuildNr=0
-105
View File
@@ -1,105 +0,0 @@
# Microsoft Developer Studio Project File - Name="r_opengl" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=r_opengl - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "r_opengl.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "r_opengl.mak" CFG="r_opengl - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "r_opengl - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "r_opengl - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "r_opengl - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "r_opengl___Win32_Release"
# PROP BASE Intermediate_Dir "r_opengl___Win32_Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "..\..\..\bin\VC\Release\r_opengl"
# PROP Intermediate_Dir "..\..\..\objs\VC\Release\r_opengl"
# PROP Ignore_Export_Lib 1
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "R_OPENGL_EXPORTS" /YX /FD /c
# ADD CPP /nologo /G5 /W3 /GX /Zi /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "__WIN32__" /D "__MSC__" /D "USE_WGL_SWAP" /FR /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x80c /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 user32.lib gdi32.lib /nologo /dll /pdb:"..\..\..\bin\VC\Release\r_opengl.pdb" /machine:I386 /out:"C:\srb2demo2\r_opengl.dll"
# SUBTRACT LINK32 /pdb:none /debug
!ELSEIF "$(CFG)" == "r_opengl - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "..\..\..\objs\Debug"
# PROP BASE Intermediate_Dir "..\..\..\objs\Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "..\..\..\bin\VC\Debug\r_opengl"
# PROP Intermediate_Dir "..\..\..\objs\VC\Debug\r_opengl"
# PROP Ignore_Export_Lib 1
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "R_OPENGL_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /G6 /W4 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "__WIN32__" /D "__MSC__" /D "USE_WGL_SWAP" /FR /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x80c /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 user32.lib gdi32.lib /nologo /dll /pdb:"..\..\..\bin\VC\Debug\r_opengl.pdb" /debug /machine:I386 /out:"C:\srb2demo2\r_opengld.dll" /pdbtype:sept
# SUBTRACT LINK32 /pdb:none
!ENDIF
# Begin Target
# Name "r_opengl - Win32 Release"
# Name "r_opengl - Win32 Debug"
# Begin Source File
SOURCE=.\ogl_win.c
# End Source File
# Begin Source File
SOURCE=.\r_opengl.c
# End Source File
# Begin Source File
SOURCE=.\r_opengl.h
# End Source File
# End Target
# End Project
+105 -40
View File
@@ -117,6 +117,11 @@ static void HU_DrawRankings(void);
consvar_t cv_showspecstuff = {"showspecstuff", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
// stuff from SRB2-Banpyura thx alot! :3
consvar_t cv_chat_xoffset = {"chat_xoffset", "0", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chat_yoffset = {"chat_yoffset", "0", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chat_showlimit = {"chat_showlimit", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
static char cechotext[1024];
static tic_t cechotimer = 0;
static tic_t cechoduration = 5*TICRATE;
@@ -966,7 +971,7 @@ void HU_Ticker(void)
size_t i = 0;
// handle spam while we're at it:
for(; (i < MAXPLAYERS); i++)
for (; (i < MAXPLAYERS); i++)
{
if (stop_spamming[i] > 0)
stop_spamming[i]--;
@@ -1370,7 +1375,12 @@ static char *CHAT_WordWrap(INT32 x, INT32 w, INT32 option, const char *string)
// 30/7/18: chaty is now the distance at which the lowest point of the chat will be drawn if that makes any sense.
INT16 chatx = 13, chaty = 169; // let's use this as our coordinates, shh
// let's use this as our coordinates, shh
// :chao: guess this just works lol
#define chatx ((INT16)(13 + (cv_chat_xoffset.value)))
#define chaty ((INT16)(169 + (cv_chat_yoffset.value)))
#define CHATSNAP (V_SNAPTOBOTTOM|V_SNAPTOLEFT)
// chat stuff by VincyTM LOL XD!
@@ -1397,7 +1407,7 @@ static void HU_drawMiniChat(void)
for (; i > 0; i--)
{
char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i-1]);
char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), CHATSNAP|V_ALLOWLOWERCASE, chat_mini[i-1]);
size_t j = 0;
INT32 linescount = 0;
emote_t *emote = NULL;
@@ -1457,6 +1467,7 @@ static void HU_drawMiniChat(void)
if (splitscreen)
{
y -= BASEVIDHEIGHT/2;
if (splitscreen > 1)
y += 16;
}
@@ -1474,7 +1485,7 @@ static void HU_drawMiniChat(void)
INT32 timer = ((cv_chattime.value*TICRATE)-chat_timers[i]) - cv_chattime.value*TICRATE+9; // see below...
INT32 transflag = (timer >= 0 && timer <= 9) ? (timer*V_10TRANS) : 0; // you can make bad jokes out of this one.
size_t j = 0;
char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i]); // get the current message, and word wrap it.
char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), CHATSNAP|V_ALLOWLOWERCASE, chat_mini[i]); // get the current message, and word wrap it.
UINT8 *colormap = NULL;
emote_t *emote = NULL;
int emotelen = 0;
@@ -1507,9 +1518,9 @@ static void HU_drawMiniChat(void)
else if ((emote = M_VerifyEmote(msg+j, &emotelen)))
{
if (cv_chatbacktint.value) // on request of wolfy
V_DrawFillConsoleMap(x + dx + 2, y+dy, EMOTEWIDTH, charheight, 239|V_SNAPTOBOTTOM|V_SNAPTOLEFT);
V_DrawFillConsoleMap(x + dx + 2, y+dy, EMOTEWIDTH, charheight, 239|CHATSNAP);
M_DrawEmote(x+dx+2, y+dy, emote, V_SNAPTOBOTTOM|V_SNAPTOLEFT|transflag);
M_DrawEmote(x+dx+2, y+dy, emote, CHATSNAP|transflag);
dx += EMOTEWIDTH - charwidth;
j += emotelen;
@@ -1517,9 +1528,9 @@ static void HU_drawMiniChat(void)
else
{
if (cv_chatbacktint.value) // on request of wolfy
V_DrawFillConsoleMap(x + dx + 2, y+dy, charwidth, charheight, 239|V_SNAPTOBOTTOM|V_SNAPTOLEFT);
V_DrawFillConsoleMap(x + dx + 2, y+dy, charwidth, charheight, 239|CHATSNAP);
V_DrawChatCharacter(x + dx + 2, y+dy+cv_chatcentertext.value, msg[j++] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|transflag, !cv_allcaps.value, colormap);
V_DrawChatCharacter(x + dx + 2, y+dy+cv_chatcentertext.value, msg[j++] |CHATSNAP|transflag, !cv_allcaps.value, colormap);
}
dx += charwidth;
@@ -1580,13 +1591,13 @@ static void HU_drawChatLog(INT32 offset)
chat_topy = y + chat_scroll*charheight;
chat_bottomy = chat_topy + boxh*charheight;
V_DrawFillConsoleMap(chatx, chat_topy, boxw, boxh*charheight +2, 239|V_SNAPTOBOTTOM|V_SNAPTOLEFT); // log box
V_DrawFillConsoleMap(chatx, chat_topy, boxw, boxh*charheight +2, 239|CHATSNAP); // log box
for (i = 0; i < chat_nummsg_log; i++) // iterate through our chatlog
{
INT32 clrflag = 0;
INT32 j = 0;
char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_log[i]); // get the current message, and word wrap it.
char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), CHATSNAP|V_ALLOWLOWERCASE, chat_log[i]); // get the current message, and word wrap it.
UINT8 *colormap = NULL;
emote_t *emote = NULL;
int emotelen = 0;
@@ -1616,7 +1627,7 @@ static void HU_drawChatLog(INT32 offset)
{
if ((y+dy+2 >= chat_topy) && (y+dy < (chat_bottomy)))
{
M_DrawEmote(x+dx+2, y+dy+1, emote, V_SNAPTOBOTTOM|V_SNAPTOLEFT);
M_DrawEmote(x+dx+2, y+dy+1, emote, CHATSNAP);
dx += EMOTEWIDTH - charwidth;
}
j += emotelen;
@@ -1624,7 +1635,7 @@ static void HU_drawChatLog(INT32 offset)
else
{
if ((y+dy+2 >= chat_topy) && (y+dy < (chat_bottomy)))
V_DrawChatCharacter(x + dx + 2, y+dy+2, msg[j++] |V_SNAPTOBOTTOM|V_SNAPTOLEFT, !cv_allcaps.value, colormap);
V_DrawChatCharacter(x + dx + 2, y+dy+2, msg[j++] |CHATSNAP, !cv_allcaps.value, colormap);
else
j++; // don't forget to increment this or we'll get stuck in the limbo.
}
@@ -1661,9 +1672,9 @@ static void HU_drawChatLog(INT32 offset)
// draw arrows to indicate that we can (or not) scroll.
if (chat_scroll > 0)
V_DrawCharacter(chatx-9, ((justscrolledup) ? (chat_topy-1) : (chat_topy)), V_SNAPTOBOTTOM | V_SNAPTOLEFT | highlight | '\x1A', false); // up arrow
V_DrawCharacter(chatx-9, ((justscrolledup) ? (chat_topy-1) : (chat_topy)), CHATSNAP | highlight | '\x1A', false); // up arrow
if (chat_scroll < chat_maxscroll)
V_DrawCharacter(chatx-9, chat_bottomy-((justscrolleddown) ? 5 : 6), V_SNAPTOBOTTOM | V_SNAPTOLEFT | highlight | '\x1B', false); // down arrow
V_DrawCharacter(chatx-9, chat_bottomy-((justscrolleddown) ? 5 : 6), CHATSNAP | highlight | '\x1B', false); // down arrow
justscrolleddown = false;
justscrolledup = false;
@@ -1681,6 +1692,7 @@ static void HU_DrawChat(void)
INT32 boxw = cv_chatwidth.value;
INT32 t = 0, c = 0, y = chaty - (typelines*charheight);
UINT32 i = 0, saylen = strlen(w_chat_buf); // You learn new things everyday!
UINT32 charcount = 0;
INT32 cflag = 0;
INT32 pm_offset = 0; // for cases when you type emote while also doing /pm
size_t select_start = 0, select_end = 0;
@@ -1712,7 +1724,7 @@ static void HU_DrawChat(void)
cflag = V_GRAYMAP; // set text in gray if chat is muted.
}
V_DrawFillConsoleMap(chatx, y-1, boxw, (typelines*charheight), 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT);
V_DrawFillConsoleMap(chatx, y-1, boxw, (typelines*charheight), 239 | CHATSNAP);
while (talk[i])
{
@@ -1720,7 +1732,7 @@ static void HU_DrawChat(void)
++i;
else
{
V_DrawChatCharacter(chatx + c + 2, y, talk[i] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|cflag, !cv_allcaps.value, V_GetStringColormap(talk[i]|cflag));
V_DrawChatCharacter(chatx + c + 2, y, talk[i] |CHATSNAP|cflag, !cv_allcaps.value, V_GetStringColormap(talk[i]|cflag));
i++;
}
@@ -1738,7 +1750,7 @@ static void HU_DrawChat(void)
typelines = 1;
if ((w_chat.cursor == 0 || w_chat.length == 0) && hu_tick < 4)
V_DrawChatCharacter(chatx+2+c, y+1, '_'|V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, !cv_allcaps.value, NULL);
V_DrawChatCharacter(chatx+2+c, y+1, '_'|CHATSNAP|t, !cv_allcaps.value, NULL);
if (w_chat.select != w_chat.cursor)
{
@@ -1755,17 +1767,23 @@ static void HU_DrawChat(void)
if ((emote = M_VerifyEmote(w_chat_buf+i, &emotelen)))
{
M_DrawEmote(chatx + c + 2, y-1, emote, V_SNAPTOBOTTOM|V_SNAPTOLEFT|t);
M_DrawEmote(chatx + c + 2, y-1, emote, CHATSNAP|t);
c += EMOTEWIDTH - charwidth;
i += emotelen-1;
drawwidth = EMOTEWIDTH;
if (cv_chat_showlimit.value)
charcount += emotelen;
}
else if (w_chat_buf[i] >= HU_FONTSTART) //Hurdler: isn't it better like that?
V_DrawChatCharacter(chatx + c + 2, y, w_chat_buf[i] | V_SNAPTOBOTTOM|V_SNAPTOLEFT | t, !cv_allcaps.value, NULL);
{
V_DrawChatCharacter(chatx + c + 2, y, w_chat_buf[i] | CHATSNAP | t, !cv_allcaps.value, NULL);
if (cv_chat_showlimit.value)
charcount++;
}
// Draw selection
if (i >= select_start && i < select_end)
V_DrawFill(chatx + c + 2 - (drawwidth-charwidth), y-1, drawwidth, charheight, 103|V_TRANSLUCENT|V_SNAPTOBOTTOM|V_SNAPTOLEFT|t);
V_DrawFill(chatx + c + 2 - (drawwidth-charwidth), y-1, drawwidth, charheight, 103|V_TRANSLUCENT|CHATSNAP|t);
++i;
@@ -1774,7 +1792,7 @@ static void HU_DrawChat(void)
INT32 cursorx = (c+charwidth < boxw-charwidth) ? (chatx + 2 + c+charwidth) : (chatx+1); // we may have to go down.
INT32 cursory = (cursorx != chatx+1) ? (y) : (y+charheight);
if (hu_tick < 4)
V_DrawChatCharacter(cursorx, cursory+1, '_' |V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, !cv_allcaps.value, NULL);
V_DrawChatCharacter(cursorx, cursory+1, '_' |CHATSNAP|t, !cv_allcaps.value, NULL);
if (cursorx == chatx+1 && saylen == i-1) // a weirdo hack
{
@@ -1792,6 +1810,13 @@ static void HU_DrawChat(void)
}
}
if (cv_chat_showlimit.value)
{
// Limit
const INT32 clr = ((HU_MAXMSGLEN - charcount) > 64 ? V_TRANSLUCENT : (charcount == HU_MAXMSGLEN ? V_REDMAP : V_YELLOWMAP));
V_DrawSmallString(chatx, y+7, CHATSNAP|clr, va("%d/%d", charcount, HU_MAXMSGLEN));
}
// handle /pm list. It's messy, horrible and I don't care.
if (strnicmp(w_chat_buf, "/pm", 3) == 0 && vid.width >= 400 && !teamtalk) // 320x200 unsupported kthxbai
{
@@ -1827,6 +1852,7 @@ static void HU_DrawChat(void)
{
char nodenum[3];
UINT32 n;
// right, that's half important: (w_chat_buf[4] may be a space since /pm0 msg is perfectly acceptable!)
if (!isdigit(w_chat_buf[3]) || !(isdigit(w_chat_buf[4]) || (w_chat_buf[4] == ' ') || (w_chat_buf[4] == 0)))
break;
@@ -1864,17 +1890,17 @@ static void HU_DrawChat(void)
}
// fill it like the chat so the text doesn't become hard to read because of the hud.
V_DrawFillConsoleMap(chatx + boxw + 2, p_dispy - (6*count), (longest_name_length+4)*4, 6, 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT);
V_DrawFillConsoleMap(chatx + boxw + 2, p_dispy - (6*count), (longest_name_length+4)*4, 6, 239 | CHATSNAP);
V_DrawSmallString(chatx + boxw + 4, p_dispy - (6*count), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, va("\x82%d\x80 - %s", i, player_names[i]));
V_DrawSmallString(chatx + boxw + 4, p_dispy - (6*count), CHATSNAP|V_ALLOWLOWERCASE, va("\x82%d\x80 - %s", i, player_names[i]));
count++;
}
if (count == 0) // no results.
{
pm_offset = 48 + 2;
V_DrawFillConsoleMap(chatx + boxw + 2, p_dispy - (6*count), 48, 6, 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT); // fill it like the chat so the text doesn't become hard to read because of the hud.
V_DrawSmallString(chatx + boxw + 4, p_dispy - (6*count), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, "NO RESULT.");
V_DrawFillConsoleMap(chatx + boxw + 2, p_dispy - (6*count), 48, 6, 239 | CHATSNAP); // fill it like the chat so the text doesn't become hard to read because of the hud.
V_DrawSmallString(chatx + boxw + 4, p_dispy - (6*count), CHATSNAP|V_ALLOWLOWERCASE, "NO RESULT.");
}
else
{
@@ -1926,15 +1952,15 @@ static void HU_DrawChat(void)
while ((suggest = M_FindEmote(complete, complete_len, skip)) != NULL)
{
V_DrawFillConsoleMap(chatx + boxw + pm_offset + 2, suggesty - (7*skip), emote_suggest_boxw, 6, V_SNAPTOBOTTOM|V_SNAPTOLEFT);
V_DrawFillConsoleMap(chatx + boxw + pm_offset + 2, suggesty - (7*skip), emote_suggest_boxw, 6, CHATSNAP);
// Highlight currently suggested emote
int hlflag = 0;
if (skip == emote_autocomplete.skip && emote_autocomplete.complete[0])
hlflag = V_YELLOWMAP;
V_DrawSmallString(chatx + boxw + pm_offset + 4 + EMOTEWIDTH, suggesty - (7*skip), hlflag|V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, va(":%s:", suggest->name));
M_DrawEmote(chatx + boxw + pm_offset + 2, suggesty - skip*7, suggest, V_SNAPTOBOTTOM|V_SNAPTOLEFT);
V_DrawSmallString(chatx + boxw + pm_offset + 4 + EMOTEWIDTH, suggesty - (7*skip), hlflag|CHATSNAP|V_ALLOWLOWERCASE, va(":%s:", suggest->name));
M_DrawEmote(chatx + boxw + pm_offset + 2, suggesty - skip*7, suggest, CHATSNAP);
++skip;
}
@@ -1948,6 +1974,7 @@ static void HU_DrawChat(void)
static void HU_DrawChat_Old(void)
{
INT32 t = 0, c = 0, y = HU_INPUTY;
UINT32 charcount = 0;
size_t i = 0;
const char *ntalk = "Say: ", *ttalk = "Say-Team: ";
const char *talk = ntalk;
@@ -1993,11 +2020,17 @@ static void HU_DrawChat_Old(void)
{
M_DrawScaledEmote((HU_INPUTX + c)<<FRACBITS, (y+con_scalefactor*2)<<FRACBITS, charwidth*FRACUNIT/EMOTEWIDTH, emote, V_NOSCALESTART | V_NOSCALEPATCH | t);
i += emotelen-1;
if (cv_chat_showlimit.value)
charcount += emotelen;
}
else if (w_chat_buf[i] >= HU_FONTSTART) //Hurdler: isn't it better like that?
{
//charwidth = hu_font[w_chat[i]-HU_FONTSTART]->width * con_scalefactor;
V_DrawCharacter(HU_INPUTX + c, y, w_chat_buf[i] | cv_constextsize.value | V_NOSCALESTART | t, !cv_allcaps.value);
if (cv_chat_showlimit.value)
charcount++;
}
// Draw selection
@@ -2010,7 +2043,7 @@ static void HU_DrawChat_Old(void)
{
INT32 cursorx = (HU_INPUTX+c+charwidth < vid.width) ? (HU_INPUTX + c + charwidth) : (HU_INPUTX); // we may have to go down.
INT32 cursory = (cursorx != HU_INPUTX) ? (y) : (y+charheight);
V_DrawCharacter(cursorx, cursory+2*con_scalefactor, '_' |cv_constextsize.value | V_NOSCALESTART|t, !cv_allcaps.value);
V_DrawCharacter(cursorx, cursory+2*con_scalefactor, '_' | cv_constextsize.value | V_NOSCALESTART |t, !cv_allcaps.value);
}
c += charwidth;
@@ -2020,6 +2053,24 @@ static void HU_DrawChat_Old(void)
y += charheight;
}
}
// console chat users are FINALLY being fed!
if (cv_chat_showlimit.value)
{
const char *lim = va(" (%i/%i)", charcount, HU_MAXMSGLEN);
for (i = 0; lim[i]; i++)
{
V_DrawCharacter(HU_INPUTX + c, y, lim[i] | cv_constextsize.value | V_NOSCALESTART | t, !cv_allcaps.value);
c += charwidth;
if (c >= vid.width) // text wrapping
{
c = 0;
y += charheight;
}
}
}
}
static void HU_DrawCEcho(void)
@@ -2208,12 +2259,13 @@ static void HU_DrawSongCreditsBox(void)
y = -BOXCREDITHEIGHT*dup + (FixedMul(BOXCREDITHEIGHT*FRACUNIT, FixedDiv(t*FRACUNIT, TICRATE*FRACUNIT/2))*dup - interpoffset)/FRACUNIT;
}
bgt = (NUMTRANSMAPS/2) + (cursongcredit.trans/2);
bgt = (NUMTRANSMAPS/2) + (cursongcredit.trans/2) - 2; // arbitrary value, looks a bit better
if (bgt < NUMTRANSMAPS)
{
V_DrawFill(x, y, strwidth*dup, BOXCREDITHEIGHT*dup, 28|flags|(bgt<<V_ALPHASHIFT));
V_DrawFill(x+dup, y+dup, (strwidth-2)*dup, (BOXCREDITHEIGHT-2)*dup, 30|flags|(bgt<<V_ALPHASHIFT));
const UINT8 accent = colortranslations[K_GetHudColor()][7];
V_DrawFill(x, y, strwidth*dup, BOXCREDITHEIGHT*dup, accent|flags|(bgt<<V_ALPHASHIFT));
V_DrawFill(x+dup, y+dup, (strwidth-2)*dup, (BOXCREDITHEIGHT-2)*dup, accent|flags|(bgt<<V_ALPHASHIFT));
}
if (cursongcredit.trans < NUMTRANSMAPS)
@@ -2240,7 +2292,22 @@ void HU_DrawSongCredits(void)
}
}
static void HU_ForceShowChat(void)
{
// only matters for non console chat
// see m_menu for how forceshowchat is set
if (!chat_on && forceshowchat)
{
// only print this if theres nothing in chat already
if (chat_nummsg_log == 0)
{
HU_AddChatText("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", false);
}
HU_DrawChat();
}
}
// Heads up displays drawer, call each frame
//
void HU_Drawer(void)
@@ -2248,6 +2315,8 @@ void HU_Drawer(void)
if (cv_vhseffect.value && ((paused && !camera[R_GetViewNumber()].freecam) || (demo.playback && cv_playbackspeed.value > 1)))
V_DrawVhsEffect(demo.rewinding);
HU_ForceShowChat();
// draw chat string plus cursor
if (chat_on)
{
@@ -2327,8 +2396,7 @@ void HU_Drawer(void)
// IN-LEVEL MULTIPLAYER RANKINGS
//======================================================================
static int
Ping_gfx_num (int lag)
static int Ping_gfx_num(int lag)
{
if (lag < 2)
return 0;
@@ -2342,8 +2410,7 @@ Ping_gfx_num (int lag)
return 4;
}
static int
Ping_gfx_color (UINT32 lag)
static int Ping_gfx_color(UINT32 lag)
{
if (lag < 2)
return SKINCOLOR_JAWZ;
@@ -2366,8 +2433,7 @@ Ping_gfx_color (UINT32 lag)
return SKINCOLOR_WHITE; // to make the flashing work
}
static const UINT8 *
Ping_gfx_colormap (UINT32 lag, boolean gentleman)
static const UINT8 *Ping_gfx_colormap(UINT32 lag, boolean gentleman)
{
const UINT8 *colormap = NULL;
@@ -2387,8 +2453,7 @@ Ping_gfx_colormap (UINT32 lag, boolean gentleman)
return colormap;
}
static UINT32
Ping_conversion (UINT32 lag)
static UINT32 Ping_conversion(UINT32 lag)
{
if (cv_pingmeasurement.value)
{
+4
View File
@@ -88,6 +88,10 @@ extern patch_t *tallminus;
// set true whenever the tab rankings are being shown for any reason
extern boolean hu_showscores;
extern consvar_t cv_chat_xoffset;
extern consvar_t cv_chat_yoffset;
extern consvar_t cv_chat_showlimit;
// init heads up data at game startup.
void HU_Init(void);
+7
View File
@@ -14,6 +14,9 @@
#ifndef __I_SYSTEM__
#define __I_SYSTEM__
// page for Saturn issue reports
#define SATURNISSUEPAGE "https://github.com/Indev450/SRB2Kart-Saturn/issues"
#ifdef __cplusplus
extern "C" {
#endif
@@ -209,6 +212,10 @@ static inline void I_HandleInterrupt(void)
I_Quit();
}
/** \brief Open A URL
*/
int I_OpenURL(const char *url);
/** \brief The I_GetDiskFreeSpace function
\param freespace a INT64 pointer to hold the free space amount
+1
View File
@@ -1694,6 +1694,7 @@ boolean I_InitTcpNetwork(void)
hardware_MAXPACKETLENGTH = MAXPACKETLENGTH;
}
}
if (M_CheckProtoParam("ip"))
{
COM_ImmedExecute(va("exec \"%s"PATHSEP"kartexec.cfg\" -noerror\n", srb2home));
+4
View File
@@ -452,7 +452,11 @@ void A_SpawnFreshCopy(void *actor);
extern boolean actionsoverridden[NUMACTIONS];
// ratio of states to sprites to mobj types is roughly 6 : 1 : 1
#ifdef COMPAT_VANILLA
#define NUMMOBJFREESLOTS 1024
#else
#define NUMMOBJFREESLOTS 4096 // should be sufficient
#endif
#define NUMSPRITEFREESLOTS NUMMOBJFREESLOTS
#define NUMSTATEFREESLOTS (NUMMOBJFREESLOTS*8)
+33 -9
View File
@@ -98,6 +98,8 @@ consvar_t cv_showminimapfinished = {"showminimapfinished", "On", CV_SAVE, CV_OnO
CV_PossibleValue_t minimapdot_cons_t[NUMMINIMAPDOTSTUFF];
consvar_t cv_showminimapangle = {"showminimapangle", "Off", CV_SAVE, minimapdot_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_spinoutroll = {"spinoutroll", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t posanim_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Smooth"}, {0, NULL}};
consvar_t cv_posanim = {"postitionanimation", "On", CV_SAVE, posanim_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_smallposnum = {"smallpositionnumber", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -231,6 +233,7 @@ void K_RegisterKartHudStuff(void)
CV_RegisterVar(&cv_showminimapnames);
CV_RegisterVar(&cv_showminimapfinished);
CV_RegisterVar(&cv_showminimapangle);
CV_RegisterVar(&cv_spinoutroll);
CV_RegisterVar(&cv_showlapemblem);
@@ -1143,7 +1146,7 @@ enum
SPEEDO_PMETERSMOL,
};
static SINT8 K_GetSpeedometerStyle(void)
static UINT8 K_GetSpeedometerStyle(void)
{
if (cv_newspeedometer.value == 2 && xtra_speedo)
return SPEEDO_EXTRA;
@@ -3938,10 +3941,23 @@ static void K_drawBattleFullscreen(void)
INT32 x = BASEVIDWIDTH/2;
INT32 y = (-64*FRACUNIT) + cardanim; // card animation goes from 0 to 164, 164 is the middle of the screen
INT32 splitflags = V_SNAPTOTOP; // I don't feel like properly supporting non-green resolutions, so you can have a misuse of SNAPTO instead
INT32 splitflags = splitscreen ? V_SNAPTOTOP : 0; // I don't feel like properly supporting non-green resolutions, so you can have a misuse of SNAPTO instead
fixed_t scale = FRACUNIT;
boolean drawcomebacktimer = true; // lazy hack because it's cleaner in the long run.
// Small hack, if we're not in splitscreen we will not use V_SNAPTOTOP, instead we will just slightly offset
// y position so "attack or protect" doesn't slightly show before popping in
// We will also reduce this when is closer to finishing so when its at the bottom, the "hack offset" is 0
if (!splitscreen)
{
fixed_t offset = ((vid.height - vid.dup*BASEVIDHEIGHT)/vid.dup) * FRACUNIT/2;
// cardanim goes from 0 to 164, so when it is 164 offset will be multiplied by (1 - 164/164) = 0 :3
offset = FixedMul(offset, FRACUNIT - FixedDiv(cardanim, 164*FRACUNIT));
y -= offset;
}
if (!LUA_HudEnabled(hud_battlecomebacktimer))
drawcomebacktimer = false;
@@ -4029,12 +4045,12 @@ static void K_drawBattleFullscreen(void)
if (K_UseColorHud()) // Colourized hud
{
UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, K_GetHudColor(), GTC_CACHE);
V_DrawFixedPatch(x<<FRACBITS, ty<<FRACBITS, scale, 0, kp_timeoutstickerclr, colormap);
V_DrawFixedPatch(x<<FRACBITS, ty<<FRACBITS, scale, splitflags, kp_timeoutstickerclr, colormap);
}
else
V_DrawFixedPatch(x<<FRACBITS, ty<<FRACBITS, scale, 0, kp_timeoutsticker, NULL);
V_DrawFixedPatch(x<<FRACBITS, ty<<FRACBITS, scale, splitflags, kp_timeoutsticker, NULL);
V_DrawKartString(x-txoff, ty, 0, va("%d", stplyr->kartstuff[k_comebacktimer]/TICRATE));
V_DrawKartString(x-txoff, ty, splitflags, va("%d", stplyr->kartstuff[k_comebacktimer]/TICRATE));
}
}
@@ -4394,6 +4410,9 @@ static void K_drawChallengerScreen(void)
static void K_drawLapStartAnim(void)
{
if (!cv_showlapemblem.value)
return;
// This is an EVEN MORE insanely complicated animation.
const UINT8 progress = 80-stplyr->kartstuff[k_lapanimation];
UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, K_GetHudColor(), GTC_CACHE);
@@ -4437,9 +4456,10 @@ static void K_drawLapStartAnim(void)
V_DrawFixedPatch(leftx, y, FRACUNIT, vflags, kp_lapanim_lap[min(progress/2, 6)], NULL);
char *lapnum = va("%02d", stplyr->laps + 1);
const size_t laplength = strlen(lapnum);
for (size_t i = 0; i < laplength; i++)
const int laplength = (int)strlen(lapnum);
for (int i = 0; i < laplength; i++)
{
int digit = lapnum[i] - '0';
int frame = min(2, progress/2 - 8 - (i*2));
@@ -4569,7 +4589,11 @@ static void K_drawCheckpointDebugger(void)
else
V_DrawString(8, 184, 0, va("Checkpoint: %d / %d (Skip: %d)", stplyr->starpostnum, numstarposts, ((numstarposts/2) + stplyr->starpostnum)));
V_DrawString(8, 192, 0, va("Waypoint dist: Prev %d, Next %d", stplyr->kartstuff[k_prevcheck], stplyr->kartstuff[k_nextcheck]));
// really gnarly hack
const INT32 prevcheck = (stprevnextchecks[0] != INT32_MAX) ? stprevnextchecks[0]: stplyr->kartstuff[k_prevcheck];
const INT32 nextcheck = (stprevnextchecks[1] != INT32_MAX) ? stprevnextchecks[1]: stplyr->kartstuff[k_nextcheck];
V_DrawString(8, 192, 0, va("Waypoint dist: Prev %d, Next %d", prevcheck, nextcheck));
}
// determines if gametype info (laps/bumpers) should be hidden
@@ -4821,7 +4845,7 @@ void K_drawKartHUD(void)
{
if (stplyr->exiting)
K_drawKartFinish();
else if (stplyr->kartstuff[k_lapanimation] && !splitscreen && cv_showlapemblem.value)
else if (stplyr->kartstuff[k_lapanimation] && !splitscreen)
K_drawLapStartAnim();
}
+140 -85
View File
@@ -34,7 +34,7 @@
// extra colourisation stuff
static CV_PossibleValue_t colorspeedlines_cons_t[] = {{0, "Off"}, {1, "Normal"}, {2, "+Driftcharge"}, {3, "Drift only"}, {0, NULL}};
static CV_PossibleValue_t colorspeedlines_cons_t[] = {{0, "Off"}, {1, "On"}, {0, NULL}};
consvar_t cv_coloredspeedlines = {"colorizedspeedlines", "Off", CV_SAVE, colorspeedlines_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_coloredsneakertrail = {"sneakertrailcolor", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -67,7 +67,8 @@ static CV_PossibleValue_t sloperoll_cons_t[] = {{0, "Off"}, {1, "Players"}, {2,
consvar_t cv_sloperoll = {"sloperoll", "Off", CV_SAVE|CV_CALL, sloperoll_cons_t, PDistort_menu_Onchange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_sparkroll = {"sparkroll", "Off", CV_SAVE|CV_CALL, CV_OnOff, PDistort_menu_Onchange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_sliptideroll = {"sliptideroll", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_spinoutroll = {"spinoutroll", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_stairjank = {"stairjank", "Off", CV_SAVE|CV_CALL, CV_OnOff, PDistort_menu_Onchange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_stairjanksfx = {"stairjanksfx", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
//hardcode saltyhop mhhm
static void saltyhop_onchange(void);
@@ -3511,6 +3512,16 @@ boolean K_ShouldSlopeRoll(mobj_t *mobj)
return K_CheckSlopeRollDist(mobj);
}
static INT32 K_AltFlip(INT32 n, tic_t tics)
{
return leveltime % (2 * tics) < tics ? n : -(n);
}
static INT32 K_StairJankFlip(INT32 value)
{
return K_AltFlip(value, 2);
}
#define SLOPEROLL_DIV 3
void K_RollMobjBySlopes(mobj_t* mo, pslope_t *slope)
{
@@ -3945,11 +3956,9 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map
if (cv_bananthrowroll.value && (mapthing == MT_BANANA))
{
//mo->angle = FixedAngle(M_RandomRange(-180, 180) << FRACBITS);
if (cv_bananthrowroll.value == 1 && K_CheckSlopeRollDist(mo))
mo->sloperoll = (angle_t)FixedAngle(M_RandomRange(-180, 180) << FRACBITS); // im lazy but this makes sure the banan goes back to upright when it lands lmao
else if (cv_bananthrowroll.value == 2)
mo->rollangle = (angle_t)FixedAngle(M_RandomRange(-180, 180) << FRACBITS);
const angle_t speen = (angle_t)FixedAngle(M_RandomRange(-180, 180) << FRACBITS);
//mo->angle = speen;
mo->rollangle = speen;
}
}
@@ -4629,7 +4638,7 @@ void K_DropRocketSneaker(player_t *player)
while ((shoe = shoe->hnext) && !P_MobjWasRemoved(shoe))
{
if (shoe->type != MT_ROCKETSNEAKER)
return; //woah, not a rocketsneaker, bail! safeguard in case this gets used when you're holding non-rocketsneakers
return; // woah, not a rocketsneaker, bail! safeguard in case this gets used when you're holding non-rocketsneakers
shoe->flags2 &= ~MF2_DONTDRAW;
shoe->flags &= ~MF_NOGRAVITY;
@@ -4693,7 +4702,7 @@ void K_RepairOrbitChain(mobj_t *orbit)
}
// Then recount to make sure item amount is correct
if (orbit->target && orbit->target->player) // !P_MobjWasRemoved(orbit->target)
if (!P_MobjWasRemovedCompat(orbit->target) && orbit->target->player)
{
INT32 num = 0;
@@ -4710,7 +4719,7 @@ void K_RepairOrbitChain(mobj_t *orbit)
prev->movedir = num;
}
if (orbit->target) // !P_MobjWasRemoved(orbit->target)
if (!P_MobjWasRemovedCompat(orbit->target))
orbit->target->player->kartstuff[k_itemamount] = num;
}
}
@@ -4857,7 +4866,7 @@ static void K_CalculateBananaSlope(mobj_t *mobj, fixed_t x, fixed_t y, fixed_t z
// Move the hnext chain!
static void K_MoveHeldObjects(player_t *player)
{
if (!player->mo)
if (P_MobjWasRemovedCompat(player->mo))
return;
if (!player->mo->hnext)
@@ -4980,9 +4989,7 @@ static void K_MoveHeldObjects(player_t *player)
mobj_t *cur = player->mo->hnext;
mobj_t *targ = player->mo;
const boolean ponground = P_IsObjectOnGround(player->mo);
if (ponground && player->speed > 0)
if (player->speed > 0 && P_IsObjectOnGround(player->mo))
player->kartstuff[k_bananadrag]++;
while (!P_MobjWasRemoved(cur))
@@ -5031,7 +5038,8 @@ static void K_MoveHeldObjects(player_t *player)
cur->angle = R_PointToAngle2(cur->x, cur->y, targx, targy);
/*if (P_IsObjectOnGround(player->mo) && player->speed > 0 && player->kartstuff[k_bananadrag] > TICRATE
/*if (player->speed > 0 && P_IsObjectOnGround(player->mo)
&& player->kartstuff[k_bananadrag] > TICRATE
&& P_RandomChance(min(FRACUNIT/2, FixedDiv(player->speed, K_GetKartSpeed(player, false))/2)))
{
if (leveltime & 1)
@@ -5040,8 +5048,9 @@ static void K_MoveHeldObjects(player_t *player)
targz -= 8*(2*FRACUNIT)/7;
}*/
if (cv_bananajitter.value && ponground
&& player->speed > 0 && player->kartstuff[k_bananadrag] > TICRATE)
// "jitter" dragged bananas around
if (cv_bananajitter.value &&
player->speed > 0 && P_IsObjectOnGround(player->mo) && player->kartstuff[k_bananadrag] > TICRATE)
{
const fixed_t halfpspeed = FixedDiv(player->speed, K_GetKartSpeed(player, false))/2;
@@ -5453,59 +5462,15 @@ boolean K_PlayerEffectsShouldBlend(player_t *player)
return false;
}
static UINT8 K_GetSpeedLineColor(player_t *player, boolean colorSpeed)
FUNCINLINE static ATTRINLINE void K_SpawnNormalSpeedLines(player_t *player)
{
UINT8 speedcolor = SKINCOLOR_NONE;
const UINT8 playercolor = player->mo->color;
if (colorSpeed)
{
if (cv_coloredspeedlines.value != 3)
speedcolor = playercolor;
if (cv_coloredspeedlines.value >= 2 && player->kartstuff[k_driftboost])
{
if (player->kartstuff[k_driftboost] <= 20)
speedcolor = SKINCOLOR_SAPPHIRE;
else if (player->kartstuff[k_driftboost] <= 50)
speedcolor = SKINCOLOR_RASPBERRY;
else if (player->kartstuff[k_driftboost] <= 125)
speedcolor = K_RainbowColor();
if (cv_coloredspeedlines.value == 2)
speedcolor = (leveltime & 1) ? playercolor : speedcolor;
}
}
if (cv_coloredspeedlines.value != 3)
{
if (player->kartstuff[k_eggmanexplode])
{
// Make it red when you have the eggman speed boost
speedcolor = SKINCOLOR_RED;
}
else if (player->kartstuff[k_invincibilitytimer])
{
speedcolor = playercolor;
}
}
return speedcolor;
}
typedef INT32 (*randomFunc)(INT32 min, INT32 max);
FUNCINLINE static ATTRINLINE void K_SpawnNormalSpeedLines(player_t *player, boolean synched)
{
const randomFunc randomfunc = synched ? P_RandomRange : M_RandomRange;
fixed_t rand_x;
fixed_t rand_y;
fixed_t rand_z;
rand_z = player->mo->z + (player->mo->height/2) + (randomfunc(-20,20) * player->mo->scale);
rand_y = player->mo->y + (randomfunc(-36,36) * player->mo->scale);
rand_x = player->mo->x + (randomfunc(-36,36) * player->mo->scale);
rand_z = player->mo->z + (player->mo->height/2) + (P_RandomRange(-20, 20) * player->mo->scale);
rand_y = player->mo->y + (P_RandomRange(-36, 36) * player->mo->scale);
rand_x = player->mo->x + (P_RandomRange(-36, 36) * player->mo->scale);
mobj_t *fast = P_SpawnMobj(rand_x, rand_y, rand_z, MT_FASTLINE);
@@ -5513,7 +5478,7 @@ FUNCINLINE static ATTRINLINE void K_SpawnNormalSpeedLines(player_t *player, bool
fast->momx = 3*player->mo->momx/4;
fast->momy = 3*player->mo->momy/4;
fast->momz = 3*player->mo->momz/4;
fast->islocal = !synched;
//fast->islocal = false;
P_SetTarget(&fast->target, player->mo); // easier lua access
K_MatchGenericExtraFlags(fast, player->mo);
@@ -5524,8 +5489,11 @@ FUNCINLINE static ATTRINLINE void K_SpawnNormalSpeedLines(player_t *player, bool
if (cv_coloredspeedlines.value)
{
fast->color = K_GetSpeedLineColor(player, colorSpeed);
fast->colorized = true;
if (colorSpeed || player->kartstuff[k_invincibilitytimer]) // let invul color them even when players go rather slow
{
fast->color = player->mo->color;
fast->colorized = true;
}
}
if (colorSpeed && K_PlayerEffectsShouldBlend(player))
@@ -5542,8 +5510,6 @@ FUNCINLINE static ATTRINLINE void K_SpawnNormalSpeedLines(player_t *player, bool
*/
void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
{
const boolean onground = P_IsObjectOnGround(player->mo);
K_UpdateOffroad(player);
K_UpdateEngineSounds(player, cmd); // Thanks, VAda!
@@ -5556,11 +5522,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
// Speed lines
if ((player->kartstuff[k_sneakertimer] || player->kartstuff[k_driftboost] || player->kartstuff[k_startboost]) && player->speed > 0)
{
K_SpawnNormalSpeedLines(player, true);
}
else if ((cv_coloredspeedlines.value == 1 || cv_coloredspeedlines.value == 2) && player->kartstuff[k_eggmanexplode]) // gotta love the speedlines calling synched rng :chaosleep:
{
K_SpawnNormalSpeedLines(player, false);
K_SpawnNormalSpeedLines(player);
}
if (player->playerstate == PST_DEAD || player->kartstuff[k_respawn] > 1) // Ensure these are set correctly here
@@ -5660,7 +5622,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
if (player->kartstuff[k_spinouttimer])
{
if ((onground || ((player->kartstuff[k_spinouttype]+1)/2 == 1)) // spinouttype 1 and 2 - explosion and spb
if ((P_IsObjectOnGround(player->mo) || ((player->kartstuff[k_spinouttype]+1)/2 == 1)) // spinouttype 1 and 2 - explosion and spb
&& (player->kartstuff[k_sneakertimer] == 0))
{
player->kartstuff[k_spinouttimer]--;
@@ -5759,7 +5721,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
if (G_BattleGametype() && player->kartstuff[k_bumper] > 0)
player->kartstuff[k_wanted]++;
if (onground)
if (P_IsObjectOnGround(player->mo))
player->kartstuff[k_waterskip] = 0;
if (player->kartstuff[k_instashield])
@@ -5803,7 +5765,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
if (player->kartstuff[k_comebacktimer])
player->kartstuff[k_comebackmode] = 0;
if (onground && player->kartstuff[k_pogospring])
if (player->kartstuff[k_pogospring] && P_IsObjectOnGround(player->mo))
{
if (P_MobjFlip(player->mo)*player->mo->momz <= 0)
player->kartstuff[k_pogospring] = 0;
@@ -6182,6 +6144,64 @@ static void K_KartDrift(player_t *player, boolean onground)
player->kartstuff[k_brakedrift] = 0;
}
INT32 stprevnextchecks[2] = {INT32_MAX, INT32_MAX}; // there wont be any map this big, wont there?.....
// K_KartUpdatePosition has a bug where whatever player comes last in the players array
// gets its distance calculations applied twice
// since we cannot fix this due to compat concerns (kartstuff is exposed after all)
// we gotta do this shit hack to atleast fix the debugcheckpoint display
static void K_KartUpdatePositionDebugHack(player_t *player, player_t *otherplayer)
{
mobj_t *mo;
fixed_t pmo;
fixed_t ppcd, pncd;
// dont need this crap
if (!cv_kartdebugcheckpoint.value)
return;
// not checking against ourselves
if (player != otherplayer)
return;
// dont care if its not first displayplayer
// since this is only used for the debug display
if (player != &players[displayplayers[0]])
return;
ppcd = pncd = 0;
stprevnextchecks[0] = stprevnextchecks[1] = 0;
// This checks every thing on the map, and looks for MT_BOSS3WAYPOINT (the thing we're using for checkpoint wp's, for now)
for (mo = waypointcap; mo != NULL; mo = mo->tracer)
{
const boolean isprevcheckpointp = mo->health == player->starpostnum;
const boolean isnextcheckpointp = mo->health == (player->starpostnum + 1);
if ((isprevcheckpointp || isnextcheckpointp) && (!mo->movecount || mo->movecount == player->laps+1))
{
pmo = P_AproxDistance(P_AproxDistance( mo->x - player->mo->x,
mo->y - player->mo->y),
mo->z - player->mo->z) / FRACUNIT;
if (isprevcheckpointp)
{
stprevnextchecks[0] += pmo;
ppcd++;
}
if (isnextcheckpointp)
{
stprevnextchecks[1] += pmo;
pncd++;
}
}
}
if (ppcd > 1) stprevnextchecks[0] /= ppcd;
if (pncd > 1) stprevnextchecks[1] /= pncd;
}
//
// K_KartUpdatePosition
//
@@ -6193,6 +6213,9 @@ void K_KartUpdatePosition(player_t *player)
fixed_t pmo, imo;
mobj_t *mo;
// always reset this
stprevnextchecks[0] = stprevnextchecks[1] = INT32_MAX;
if (player->spectator || !player->mo)
return;
@@ -6205,11 +6228,12 @@ void K_KartUpdatePosition(player_t *player)
if (G_RaceGametype())
{
if ((((players[i].starpostnum) + (numstarposts + 1) * players[i].laps) >
((player->starpostnum) + (numstarposts + 1) * player->laps)))
const INT32 iplayerlaps = (players[i].starpostnum + (numstarposts + 1) * players[i].laps);
const INT32 pplayerlaps = (player->starpostnum + (numstarposts + 1) * player->laps);
if (iplayerlaps > pplayerlaps)
position++;
else if (((players[i].starpostnum) + (numstarposts+1)*players[i].laps) ==
((player->starpostnum) + (numstarposts+1)*player->laps))
else if (iplayerlaps == pplayerlaps)
{
ppcd = pncd = ipcd = incd = 0;
@@ -6292,6 +6316,9 @@ void K_KartUpdatePosition(player_t *player)
if (players[i].starposttime < player->starposttime)
position++;
}
// stupid hack
K_KartUpdatePositionDebugHack(player, &players[i]);
}
}
else if (G_BattleGametype())
@@ -6561,7 +6588,7 @@ static void K_PlayerItemThink(player_t *player, boolean onground, boolean oldatt
{
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BANANA_SHIELD);
if (!mo)
if (P_MobjWasRemovedCompat(mo))
{
player->kartstuff[k_itemamount] = moloop;
break;
@@ -6622,7 +6649,7 @@ static void K_PlayerItemThink(player_t *player, boolean onground, boolean oldatt
newangle = (player->mo->angle + ANGLE_157h) + FixedAngle(((360 / player->kartstuff[k_itemamount]) * moloop) << FRACBITS) + ANGLE_90;
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_ORBINAUT_SHIELD);
if (!mo)
if (P_MobjWasRemovedCompat(mo))
{
player->kartstuff[k_itemamount] = moloop;
break;
@@ -6665,7 +6692,7 @@ static void K_PlayerItemThink(player_t *player, boolean onground, boolean oldatt
newangle = (player->mo->angle + ANGLE_157h) + FixedAngle(((360 / player->kartstuff[k_itemamount]) * moloop) << FRACBITS) + ANGLE_90;
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_JAWZ_SHIELD);
if (!mo)
if (P_MobjWasRemovedCompat(mo))
{
player->kartstuff[k_itemamount] = moloop;
break;
@@ -7025,6 +7052,34 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
K_RollMobjBySlopes(player->mo, player->mo->standingslope);
// "Stair jank" visuals akin to RR
if (cv_stairjank.value && player->stairjank > 0)
{
// only spawn em once
if (player->stairjank > 8)
{
// 90 degrees to direction you're facing
fixed_t dirx = -FINESINE(player->mo->angle>>ANGLETOFINESHIFT);
fixed_t diry = FINECOSINE(player->mo->angle>>ANGLETOFINESHIFT);
fixed_t offset = player->mo->radius;
dirx = K_AltFlip(-dirx, 4);
diry = K_AltFlip(-diry, 4);
mobj_t * spark = P_SpawnMobj(player->mo->x + FixedMul(dirx, offset), player->mo->y + FixedMul(diry, offset), player->mo->z, MT_DRIFTDUST);
spark->momx = FixedMul(dirx, FRACUNIT) + (6 + ((int)leveltime % 5))*(player->mo->momx)/10;
spark->momy = FixedMul(diry, FRACUNIT) + (6 + ((int)leveltime % 5))*(player->mo->momy)/10;
spark->momz = 5*FRACUNIT;
spark->scale = mapobjectscale/5;
spark->destscale = mapobjectscale/2;
spark->islocal = true;
spark->color = SKINCOLOR_WHITE;
P_SetTarget(&spark->target, player->mo);
}
player->mo->temprollangle += K_StairJankFlip(ANGLE_11hh / 2 / (17 / player->stairjank)); // TODO: make strength adjustable?
}
////
// Quick Turning
+2
View File
@@ -32,6 +32,8 @@ extern consvar_t cv_bananajitter;
extern consvar_t cv_bananthrowroll;
extern consvar_t cv_airsparks;
extern INT32 stprevnextchecks[2];
boolean K_IsPlayerLosing(player_t *player);
boolean K_IsPlayerWanted(player_t *player);
INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush);
+12 -26
View File
@@ -3055,58 +3055,44 @@ static int lib_kSetHyuCountdown(lua_State *L)
static int lib_gSetPlayerGamepadIndicatorColor(lua_State *L)
{
INT32 player = -1;
player_t *plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); // retrieve player
INT32 pnum = -1;
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); // retrieve player
UINT8 color = (UINT8)luaL_checkinteger(L, 2); // skincolor
if (!plr)
if (!player)
return LUA_ErrInvalid(L, "player_t");
if (color >= MAXTRANSLATIONS)
return luaL_error(L, "color %d out of range (0 - %d).", color, MAXTRANSLATIONS-1);
for (int i = 0; i < MAXSPLITSCREENPLAYERS; ++i)
{
if (plr - players == displayplayers[i])
{
player = i;
break;
}
}
pnum = P_GetLocalPlayerNumForPlayer(player);
// Not a local player
if (player == -1) return 0;
if (pnum == -1) return 0;
// pls update with color 0 when youre done with changing led stuff so it can get player color again
G_SetPlayerGamepadIndicatorColor(player, color);
G_SetPlayerGamepadIndicatorColor(pnum, color);
return 0;
}
static int lib_gPlayerDeviceRumble(lua_State *L)
{
INT32 player = -1;
player_t *plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); // retrieve player
INT32 pnum = -1;
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); // retrieve player
UINT16 low_strength = (UINT16)luaL_checkinteger(L, 2); // low frequency rumble motor strenght
UINT16 high_strength = (UINT16)luaL_checkinteger(L, 3); // high frequency rumble motor strenght
UINT32 duration = (UINT32)luaL_optinteger(L, 4, 84); // duration of rumble in ms
if (!plr)
if (!player)
return LUA_ErrInvalid(L, "player_t");
for (int i = 0; i < MAXSPLITSCREENPLAYERS; ++i)
{
if (plr - players == displayplayers[i])
{
player = i;
break;
}
}
pnum = P_GetLocalPlayerNumForPlayer(player);
// Not a local player
if (player == -1) return 0;
if (pnum == -1) return 0;
G_PlayerDeviceRumble(player, low_strength, high_strength, duration);
G_PlayerDeviceRumble(pnum, low_strength, high_strength, duration);
return 0;
}
+48 -6
View File
@@ -65,6 +65,8 @@ static stringhook_t stringHooks[STRING_HOOK(MAX)];
bool hook_important = true;
#define NONMOHOOK ((mobjtype_t)-1)
// This will be indexed by hook id, the value of which fetches the registry.
static int * hookRefs;
static int nextid;
@@ -296,7 +298,7 @@ struct Hook_State {
INT32 status; /* return status to calling function */
void * userdata;
int hook_type;
mobjtype_t mobj_type; /* < NUMMOBJTYPES if mobj hook */
mobjtype_t mobj_type; /* != NONMOHOOK if mobj hook */
const char * string; /* used to fetch table, ran first if set */
int top; /* index of last argument passed to hook */
int id; /* id to fetch ref */
@@ -364,7 +366,7 @@ FUNCINLINE static ATTRINLINE boolean prepare_hook
int hook_type
){
return init_hook_type(hook, default_status,
hook_type, NUMMOBJTYPES, NULL,
hook_type, NONMOHOOK, NULL,
hookIds[hook_type].numHooks);
}
@@ -391,7 +393,7 @@ FUNCINLINE static ATTRINLINE boolean prepare_string_hook
const char * string
){
if (init_hook_type(hook, default_status,
hook_type, NUMMOBJTYPES, string,
hook_type, NONMOHOOK, string,
stringHooks[hook_type].ref))
{
lua_pushstring(gL, string);
@@ -407,7 +409,7 @@ FUNCINLINE static ATTRINLINE boolean prepare_hud_hook
int hook_type
){
return init_hook_type(hook, 0,
hook_type, NUMMOBJTYPES, NULL,
hook_type, NONMOHOOK, NULL,
hudHookIds[hook_type].numHooks);
}
@@ -528,10 +530,48 @@ static int call_string_hooks(Hook_State *hook)
return calls;
}
FUNCINLINE static ATTRINLINE int call_mobj_type_hooks(Hook_State *hook, mobjtype_t mobj_type)
{
static UINT8 seen = 0; // so we dont have to check all this shit constantly
int numCalls = call_mapped(hook, &mobjHookIds[mobj_type][hook->hook_type]);
if (!seen && numCalls > 0 && mobj_type == MT_NULL && (
hook->hook_type == MOBJ_HOOK(MobjThinker )
|| hook->hook_type == MOBJ_HOOK(MobjCollide )
|| hook->hook_type == MOBJ_HOOK(MobjMoveCollide)
|| hook->hook_type == MOBJ_HOOK(MobjFuse )
|| hook->hook_type == MOBJ_HOOK(MobjThinker )
|| hook->hook_type == MOBJ_HOOK(BossThinker )
))
{
seen = 1;
CONS_Alert(
CONS_WARNING, "%s\n", va(
"%s hooks not attached to a specific mobj type may cause performance issues!",
mobjHookNames[hook->hook_type])
);
// print which script triggered it, ty indev <3
for (int k = 0; k < mobjHookIds[mobj_type][hook->hook_type].numHooks; ++k)
{
lua_getref(gL, hookRefs[mobjHookIds[mobj_type][hook->hook_type].ids[k].id]);
lua_Debug ar;
lua_getinfo(gL, ">S", &ar);
CONS_Printf("%s:%d\n", ar.short_src, ar.linedefined);
}
}
return numCalls;
}
/*
FUNCINLINE static ATTRINLINE int call_mobj_type_hooks(Hook_State *hook, mobjtype_t mobj_type)
{
return call_mapped(hook, &mobjHookIds[mobj_type][hook->hook_type]);
}
*/
static int call_hooks
(
@@ -547,11 +587,13 @@ static int call_hooks
{
calls += call_string_hooks(hook);
}
else if (hook->mobj_type < NUMMOBJTYPES)
//else if (hook->mobj_type > 0)
else if (hook->mobj_type != NONMOHOOK)
{
/* call generic mobj hooks first */
calls += call_mobj_type_hooks(hook, MT_NULL);
calls += call_mobj_type_hooks(hook, hook->mobj_type);
if (hook->mobj_type < NUMMOBJTYPES)
calls += call_mobj_type_hooks(hook, hook->mobj_type);
ps_lua_mobjhooks.value.i += calls;
}
else
+13 -8
View File
@@ -644,20 +644,22 @@ static int libd_drawScaled(lua_State *L)
// KART: draw patch on minimap from x, y coordinates on the map
static int libd_drawOnMinimap(lua_State *L)
{
fixed_t x, y, scale; // coordinates of the object
patch_t *patch; // patch we want to draw
UINT8 *colormap = NULL; // do we want to colormap this patch?
boolean centered; // the patch is centered and doesn't need readjusting on x/y coordinates.
fixed_t x, y, scale; // coordinates of the object
patch_t *patch; // patch we want to draw
UINT8 *colormap = NULL; // do we want to colormap this patch?
boolean centered; // the patch is centered and doesn't need readjusting on x/y coordinates.
huddrawlist_h list;
patch_t *AutomapPic = NULL;
drawinfo_t info;
// variables used to replicate k_kart's mmap drawer:
patch_t *AutomapPic;
// variables used for actually drawing the icon:
INT32 splitflags, minimaptrans;
fixed_t amnumxpos, amnumypos;
fixed_t amxpos, amypos;
INT32 mm_x, mm_y;
fixed_t patchw = 0, patchh = 0;
fixed_t patchw, patchh;
HUDONLY // only run this function in hud hooks
@@ -722,8 +724,11 @@ static int libd_drawOnMinimap(lua_State *L)
mm_y -= AutomapPic->topoffset;
// patch is supposedly already centered, don't butt in.
if (!centered)
if (centered)
{
patchw = patchh = 0; // patch is supposedly already centered, don't butt in.
}
else
{
// scale patch coords
patchw = (patch->width * scale / 2);
+8 -1
View File
@@ -713,9 +713,12 @@ static UINT8 GetUserdataArchType(int index)
static UINT8 ArchiveValue(UINT8 **p, int TABLESINDEX, int myindex)
{
int type = lua_type(gL, myindex);
if (myindex < 0)
myindex = lua_gettop(gL)+1+myindex;
switch (lua_type(gL, myindex))
switch (type)
{
case LUA_TNONE:
case LUA_TNIL:
@@ -725,8 +728,12 @@ static UINT8 ArchiveValue(UINT8 **p, int TABLESINDEX, int myindex)
case LUA_TLIGHTUSERDATA:
case LUA_TTHREAD:
case LUA_TFUNCTION:
{
const char *typestr = (type == LUA_TLIGHTUSERDATA ? "light userdata" : (type == LUA_TTHREAD ? "thread" : (type == LUA_TFUNCTION ? "function" : "??")));
CONS_Alert(CONS_ERROR, M_GetText("Archived an invalid value! (%s)\n"), typestr);
WRITEUINT8(*p, ARCH_NULL);
return 2;
}
case LUA_TBOOLEAN:
WRITEUINT8(*p, ARCH_BOOLEAN);
WRITEUINT8(*p, lua_toboolean(gL, myindex));
+3 -3
View File
@@ -766,7 +766,7 @@ boolean OP_FreezeObjectplace(void)
if (!objectplacing)
return false;
if ((maptol & TOL_NIGHTS) && (players[consoleplayer].pflags & PF_NIGHTSMODE))
if (nightsmode && nightsplayer(&players[consoleplayer]))
return false;
return true;
@@ -1049,7 +1049,7 @@ void Command_ObjectPlace_f(void)
{
objectplacing = true;
if ((players[0].pflags & PF_NIGHTSMODE))
if (nightsplayer(&players[0]))
return;
if (!COM_CheckParm("-silent"))
@@ -1120,7 +1120,7 @@ void Command_ObjectPlace_f(void)
// Don't touch the NiGHTS Objectplace stuff.
// ... or if the mo mysteriously vanished.
if (!players[0].mo || (players[0].pflags & PF_NIGHTSMODE))
if (!players[0].mo || nightsplayer(&players[0]))
return;
// If still in dummy state, get out of it.
+126 -55
View File
@@ -25,6 +25,7 @@
#include "d_netcmd.h"
#include "d_clisrv.h"
#include "i_net.h"
#include "i_system.h"
#include "console.h"
#include "r_fps.h"
#include "r_local.h"
@@ -151,8 +152,6 @@ const char *quitmsg[NUM_QUITMESSAGES] = {};
INT32 mapwads[NUMMAPS] = {};
boolean browselocalskins = false;
boolean menuactive = false;
boolean fromlevelselect = false;
@@ -214,12 +213,19 @@ static INT32 setupm_fakeskin;
static INT32 setupm_fakecolor;
static UINT8 setupm_pselect = 1;
//variables used for other skin select menus
// variables used for other skin select menus
static UINT8 setupm_skinypos;
static INT32 setupm_skinselect;
static boolean setupm_skinlockedselect;
static UINT8 setupm_playernum; //brap
static UINT8 setupm_playernum; // brap
// Addons Menu: Local mode
static void M_LocalAddons(INT32 choice);
static boolean addons_localmode = false;
#define LOCALMODE_KEY (KEY_RALT)
#define AUTOLOAD_KEY (KEY_END)
//
// PROTOTYPES
@@ -271,6 +277,8 @@ static void M_ConfirmTeamChange(INT32 choice);
static void M_ConfirmSpectateChange(INT32 choice);
static void M_QuitSRB2(INT32 choice);
static void M_SaturnReportIssue(INT32 choice);
// Single Player
static void M_TimeAttack(INT32 choice);
static boolean M_QuitTimeAttackMenu(void);
@@ -325,7 +333,6 @@ static void M_EraseData(INT32 choice);
static void M_AddonsInternal();
static void M_Addons(INT32 choice);
static void M_LocalSkins(INT32 choice);
static void M_AddonsOptions(INT32 choice);
#define addonmenusize 9 // number of items actually displayed in the addons menu view, formerly (2*numaddonsshown + 1)
#define numaddonsshown 4 // number of items to each side of the currently selected item, unless at top/bottom ends of directory
@@ -409,6 +416,7 @@ static INT32 M_GetFirstLevelInList(void);
// crap to force hud to show when in saturns hud options
boolean forceshowhud = false;
boolean forceshowchat = false;
// smol text indicating if game is modified
// so ppl dont wonder where their ra times went and stuff
@@ -447,13 +455,13 @@ consvar_t cv_showallmaps = {"showallmaps", "No", CV_SAVE, CV_YesNo, NULL, 0, NUL
consvar_t cv_showmusicfilename = {"showmusicfilename", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t serversort_cons_t[] = {
{0,"Ping"},
{1,"Modified State"},
{2,"Most Players"},
{3,"Least Players"},
{4,"Max Player Slots"},
{5,"Gametype"},
{0,NULL}
{0, "Ping"},
{1, "Modified State"},
{2, "Most Players"},
{3, "Least Players"},
{4, "Max Player Slots"},
{5, "Gametype"},
{0, NULL}
};
consvar_t cv_serversort = {"serversort", "Ping", CV_CALL, serversort_cons_t, M_SortServerList, 0, NULL, NULL, 0, 0, NULL};
@@ -702,7 +710,7 @@ static void Dummystaff_OnChange(void)
dummystaffname[0] = '\0';
if ((l = W_CheckNumForName(va("%sS01",G_BuildMapName(cv_nextmap.value)))) == LUMPERROR)
if ((l = W_CheckNumForName(va("%sS01", G_BuildMapName(cv_nextmap.value)))) == LUMPERROR)
{
CV_StealthSetValue(&cv_dummystaff, 0);
return;
@@ -711,7 +719,7 @@ static void Dummystaff_OnChange(void)
{
char *temp = dummystaffname;
UINT8 numstaff = 1;
while (numstaff < 99 && (l = W_CheckNumForName(va("%sS%02u",G_BuildMapName(cv_nextmap.value),numstaff+1))) != LUMPERROR)
while (numstaff < 99 && (l = W_CheckNumForName(va("%sS%02u", G_BuildMapName(cv_nextmap.value), numstaff+1))) != LUMPERROR)
numstaff++;
if (cv_dummystaff.value < 1)
@@ -719,7 +727,7 @@ static void Dummystaff_OnChange(void)
else if (cv_dummystaff.value > numstaff)
CV_StealthSetValue(&cv_dummystaff, 1);
if ((l = W_CheckNumForName(va("%sS%02u",G_BuildMapName(cv_nextmap.value), cv_dummystaff.value))) == LUMPERROR)
if ((l = W_CheckNumForName(va("%sS%02u", G_BuildMapName(cv_nextmap.value), cv_dummystaff.value))) == LUMPERROR)
return; // shouldn't happen but might as well check...
G_UpdateStaffGhostName(l);
@@ -804,7 +812,8 @@ static void M_ChangeCvar(INT32 choice)
CV_SetValue(cv,skins[skinno].prefcolor);
return;
}
CV_Set(cv,cv->defaultvalue);
CV_Set(cv, cv->defaultvalue);
return;
}
@@ -953,6 +962,7 @@ static void Command_Manual_f(void)
{
if (modeattacking)
return;
M_StartControlPanel();
M_Manual(INT32_MAX);
itemOn = 0;
@@ -1014,6 +1024,24 @@ boolean M_Responder(event_t *ev)
case KEY_HAT1 + 3:
ch = KEY_RIGHTARROW;
break;
//Local Addon Mode
case LOCALMODE_KEY:
{
if (!(server || IsPlayerAdmin(consoleplayer)))
break;
if (!addons_localmode)
{
S_StartSound(NULL, sfx_ding);
addons_localmode = true;
}
else
{
S_StartSound(NULL, sfx_jshard);
addons_localmode = false;
}
}
break;
}
}
else if (menuactive)
@@ -1579,11 +1607,16 @@ static boolean ShouldDrawMenuBG(void)
if (forceshowhud)
return false;
if (forceshowchat)
return false;
// camera options stuff, only do when in level
if (gamestate == GS_LEVEL &&
(currentMenu == &OP_CamOptionsDef || currentMenu == &OP_Player1CamOptionsDef
|| currentMenu == &OP_Player2CamOptionsDef || currentMenu == &OP_Player3CamOptionsDef
|| currentMenu == &OP_Player4CamOptionsDef))
(currentMenu == &OP_CamOptionsDef ||
currentMenu == &OP_Player1CamOptionsDef ||
currentMenu == &OP_Player2CamOptionsDef ||
currentMenu == &OP_Player3CamOptionsDef ||
currentMenu == &OP_Player4CamOptionsDef))
return false;
return true;
@@ -1599,7 +1632,9 @@ void M_Drawer(void)
if (currentMenu == &MessageDef)
menuactive = true;
// pain and suffering
forceshowhud = (gamestate == GS_LEVEL && menuactive && (currentMenu == &OP_SaturnHudDef || currentMenu == &OP_HudOffsetDef || currentMenu == &OP_NametagDef || currentMenu == &OP_DriftGaugeDef)); // holy fuick
forceshowchat = (gamestate == GS_LEVEL && menuactive && currentMenu == &OP_ChatOptionsDef && (!OLDCHAT) && (itemOn == op_chat_boxwidth || itemOn == op_chat_boxheight || itemOn == op_chat_xoffs || itemOn == op_chat_yoffs || itemOn == op_chat_charlmt)); // man i dont gaf anymore lmao
if (menuactive)
{
@@ -1718,19 +1753,16 @@ void M_StartControlPanel(void)
MPauseMenu[mpause_switchteam].status = IT_DISABLED;
MPauseMenu[mpause_switchspectate].status = IT_DISABLED;
MPauseMenu[mpause_psetup].status = IT_DISABLED;
MPauseMenu[mpause_localaddons].status = IT_STRING | IT_CALL;
MISC_ChangeTeamMenu[0].status = IT_DISABLED;
MISC_ChangeSpectateMenu[0].status = IT_DISABLED;
MPauseMenu[mpause_addlocalskins].status = IT_STRING | IT_CALL;
MPauseMenu[mpause_localskin].status = IT_STRING | IT_CALL;
// Reset these in case splitscreen messes things up
MPauseMenu[mpause_addons].alphaKey = 8;
if (IsPlayerAdmin(consoleplayer))
MPauseMenu[mpause_addlocalskins].alphaKey = 16;
else
MPauseMenu[mpause_addlocalskins].alphaKey = 24;
MPauseMenu[mpause_localaddons].alphaKey = 24;
MPauseMenu[mpause_scramble].alphaKey = 8;
MPauseMenu[mpause_switchmap].alphaKey = 24;
@@ -1748,14 +1780,13 @@ void M_StartControlPanel(void)
{
MPauseMenu[mpause_switchmap].status = IT_STRING | IT_CALL;
MPauseMenu[mpause_addons].status = IT_STRING | IT_CALL;
MPauseMenu[mpause_localaddons].status = IT_DISABLED;
if (G_GametypeHasTeams())
MPauseMenu[mpause_scramble].status = IT_STRING | IT_SUBMENU;
}
if (server || (!cv_showlocalskinmenus.value))
{
MPauseMenu[mpause_addlocalskins].status = IT_DISABLED;
MPauseMenu[mpause_localskin].status = IT_DISABLED;
MPauseMenu[mpause_options].alphaKey = 64;
@@ -1763,7 +1794,6 @@ void M_StartControlPanel(void)
MPauseMenu[mpause_quit].alphaKey = 88;
}
if (splitscreen)
{
MPauseMenu[mpause_psetupsplit].status = MPauseMenu[mpause_psetupsplit2].status = IT_STRING | IT_CALL;
@@ -3308,14 +3338,14 @@ static void M_AddonsInternal(void)
static void M_Addons(INT32 choice)
{
(void)choice;
browselocalskins = false;
addons_localmode = false;
M_AddonsInternal();
}
static void M_LocalSkins(INT32 choice)
static void M_LocalAddons(INT32 choice)
{
(void)choice;
browselocalskins = true;
addons_localmode = true;
M_AddonsInternal();
}
@@ -3484,8 +3514,8 @@ static void M_DrawAddons(void)
if (Playing())
{
if (browselocalskins)
V_DrawCenteredString(BASEVIDWIDTH/2, 5, V_ALLOWLOWERCASE, "Load \x83local skins\x80 from addons!");
if (addons_localmode) // Draw notice that you're adding locally
V_DrawCenteredString(BASEVIDWIDTH/2, 5, V_ALLOWLOWERCASE, "Load addons or \x83local skins\x80 locally!");
else
V_DrawCenteredString(BASEVIDWIDTH/2, 5, warningflags, "Adding files mid-game may cause problems.");
}
@@ -3648,7 +3678,10 @@ static void M_DrawAddons(void)
//m = numwadfiles-(mainwads+2+1);
//V_DrawCenteredString(BASEVIDWIDTH/2, y+24, (majormods ? highlightflags : V_TRANSLUCENT), va("%d ADD-ON%s LOADED", (int)m, (m == 1) ? "" : "S")); //+2 for music, sounds, +1 for main.kart
V_DrawThinString(0, BASEVIDHEIGHT-10, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_TRANSLUCENT|V_ALLOWLOWERCASE, ("END Key - Add addon to autoload"));
V_DrawThinString(0, BASEVIDHEIGHT-10, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_TRANSLUCENT|V_ALLOWLOWERCASE, va("%s Key - Add addon to autoload", G_KeynumToString(AUTOLOAD_KEY)));
if (Playing() && (server || IsPlayerAdmin(consoleplayer)))
V_DrawThinString(0, BASEVIDHEIGHT-20, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_TRANSLUCENT|V_ALLOWLOWERCASE, va("%s Key - Switch to local addon mode", G_KeynumToString(LOCALMODE_KEY)));
}
static void M_AddonExec(INT32 ch)
@@ -3670,7 +3703,7 @@ static void M_AddonAutoLoad(INT32 ch)
FILE *autoloadconfigfile;
// check our controls //
if (ch != 'y' && ch != KEY_ENTER && ch != KEY_END)
if (ch != 'y' && ch != KEY_ENTER && ch != AUTOLOAD_KEY)
{
S_StartSound(NULL, sfx_s26d);
return;
@@ -3684,7 +3717,7 @@ static void M_AddonAutoLoad(INT32 ch)
switch (dirmenu[dir_on[menudepthleft]][DIR_TYPE])
{
case EXT_FOLDER:
M_StartMessage(va("%c%s\x80\nAutoloading folders is not supported as of yet. \n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), dirmenu[dir_on[menudepthleft]]+DIR_STRING),NULL,MM_NOTHING);
M_StartMessage(va("%c%s\x80\nAutoloading folders is not supported as of yet. \n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), dirmenu[dir_on[menudepthleft]]+DIR_STRING), NULL, MM_NOTHING);
break;
case EXT_TXT:
case EXT_CFG:
@@ -3825,7 +3858,7 @@ static void M_HandleAddons(INT32 choice)
}
break;
case EXT_TXT:
M_StartMessage(va("%c%s\x80\nThis file may not be a console script.\nAttempt to run anyways? \n\n(Press 'Y' to confirm)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), dirmenu[dir_on[menudepthleft]]+DIR_STRING),M_AddonExec,MM_YESNO);
M_StartMessage(va("%c%s\x80\nThis file may not be a console script.\nAttempt to run anyways? \n\n(Press 'Y' to confirm)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), dirmenu[dir_on[menudepthleft]]+DIR_STRING), M_AddonExec, MM_YESNO);
break;
case EXT_CFG:
M_AddonExec(KEY_ENTER);
@@ -3838,30 +3871,40 @@ static void M_HandleAddons(INT32 choice)
case EXT_KART:
#endif
case EXT_PK3:
if (browselocalskins)
{
if (DumbStartsWith("KC_", dirmenu[dir_on[menudepthleft]]+DIR_STRING) || DumbStartsWith("kc_", dirmenu[dir_on[menudepthleft]]+DIR_STRING)) {
M_StartMessage(va("%c%s\x80\nYou are loading a local skin.\nLocal skins will not be usable\nafter going back from\nthe title screen.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), dirmenu[dir_on[menudepthleft]]+DIR_STRING),NULL,MM_NOTHING);
COM_BufAddText(va("addfilelocal \"%s%s\"", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING));
const char *addonname = dirmenu[dir_on[menudepthleft]]+DIR_STRING;
if (addons_localmode)
{
if (DumbStartsWith("KC_", addonname) || DumbStartsWith("kc_", addonname))
{
M_StartMessage(va("%c%s\x80\nYou are loading a local skin.\nLocal skins will not be usable\nafter going back from\nthe title screen.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), addonname), NULL, MM_NOTHING);
}
else if (DumbStartsWith("KCL_", addonname) || DumbStartsWith("kcl_", addonname)) // skins with lua
{
M_StartMessage(va("%c%s\x80\nYou are loading a local skin with lua.\nBeware that this may cause issues like crashes or desyncs in some cases!\nLocal skins will not be usable\nafter going back from\nthe title screen.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), addonname), NULL, MM_NOTHING);
}
// no need to account for KRC cases
COM_BufAddText(va("addfilelocal \"%s%s\"", menupath, addonname));
}
else
S_StartSound(NULL, sfx_s26d);
}
else
{
COM_BufAddText(va("addfile \"%s%s\"", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING));
{
COM_BufAddText(va("addfile \"%s%s\"", menupath, addonname));
}
}
break;
default:
S_StartSound(NULL, sfx_s26d);
}
}
if (refresh)
refreshdirmenu |= REFRESHDIR_NORMAL;
}
break;
case KEY_END:
case AUTOLOAD_KEY:
{
boolean refresh = true;
if (!dirmenu[dir_on[menudepthleft]])
@@ -3928,6 +3971,8 @@ static void M_HandleAddons(INT32 choice)
M_SetupNextMenu(currentMenu->prevMenu);
else
M_ClearMenus(true);
addons_localmode = false; //Exiting this menu, disable addons_localmode already.
}
}
@@ -4205,6 +4250,14 @@ static boolean M_HandleReplayHutQuery(INT32 choice)
char tmp[MAXREPLAYQUERY+1];
memcpy(tmp, replayqueryinput_buffer, MAXREPLAYQUERY+1);
Lock_search_state();
if (!replaynamesloaded)
{
Unlock_search_state();
return false;
}
Unlock_search_state();
if (M_TextInputHandle(&replayqueryinput, choice))
{
S_StartSound(NULL, sfx_menu1);
@@ -7608,7 +7661,11 @@ Update the maxplayers label...
// draw name string
if (itemOn != 9)
V_DrawString(x+8,y+12, V_ALLOWLOWERCASE, setupm_ip);
{
char buf[28];
strlcpy(buf, setupm_ip, sizeof(buf));
V_DrawString(x+8,y+12, V_ALLOWLOWERCASE, buf);
}
else
M_DrawTextInputScroll(x+8, y+12, &setupm_input_ip, 0, SETUPM_IP_MAXSIZE);
@@ -7740,7 +7797,7 @@ static void M_SetupMultiHandler(INT32 choice)
if (exitmenu)
{
if (currentMenu->prevMenu)
M_SetupNextMenu (currentMenu->prevMenu);
M_SetupNextMenu(currentMenu->prevMenu);
else
M_ClearMenus(true);
}
@@ -8991,15 +9048,15 @@ static boolean M_QuitMultiPlayerMenu(void)
if (!fastcmp(setupm_name, setupm_cvname->string))
{
// remove trailing whitespaces
for (l = strlen(setupm_name)-1;
(signed)l >= 0 && setupm_name[l] ==' '; l--)
setupm_name[l] =0;
COM_BufAddText(va("%s \"%s\"\n",setupm_cvname->name,setupm_name));
l = strlen(setupm_name)-1;
for (;(signed)l >= 0 && setupm_name[l] ==' '; l--)
setupm_name[l] = 0;
COM_BufAddText(va("%s \"%s\"\n", setupm_cvname->name, setupm_name));
}
// you know what? always putting these in the buffer won't hurt anything.
COM_BufAddText(va("%s \"%s\"\n",setupm_cvskin->name,skins[setupm_fakeskin].name));
COM_BufAddText(va("%s %d\n",setupm_cvcolor->name,setupm_fakecolor));
COM_BufAddText(va("%s \"%s\"\n", setupm_cvskin->name, skins[setupm_fakeskin].name));
COM_BufAddText(va("%s %d\n", setupm_cvcolor->name, setupm_fakecolor));
return true;
}
@@ -10535,6 +10592,20 @@ static void M_QuitSRB2(INT32 choice)
M_StartMessage(quitmsg[M_RandomKey(NUM_QUITMESSAGES)], M_QuitResponse, MM_YESNO);
}
// ===========
// SATURN MENU
// ===========
static void M_SaturnReportIssue(INT32 choice)
{
(void)choice;
int url = I_OpenURL(SATURNISSUEPAGE);
// SDL_OpenURL unsupported or failed
if (url == -1)
M_StartMessage(M_GetText("Failed to Open Web Page.\nPlease open the following page in your web browser:\n\n" SATURNISSUEPAGE "\n\n(Press a key)\n"), NULL, MM_NOTHING);
}
#ifdef HAVE_DISCORDRPC
// =====================================================================
+1 -1
View File
@@ -26,7 +26,7 @@ extern "C" {
#include "mserv.h"
#include "r_things.h" // for SKINNAMESIZE
extern boolean forceshowhud;
extern boolean forceshowhud, forceshowchat;
//
// MENUS
+187 -92
View File
@@ -36,6 +36,7 @@ static menu_t SP_TimeAttackDef, SP_ReplayDef, SP_GuestReplayDef, SP_GhostDef;
menu_t OP_ControlsDef, OP_AllControlsDef;
menu_t OP_MouseOptionsDef;
menu_t OP_Joystick1Def, OP_Joystick2Def, OP_Joystick3Def, OP_Joystick4Def;
menu_t OP_Joystick1RumbleDef, OP_Joystick2RumbleDef, OP_Joystick3RumbleDef, OP_Joystick4RumbleDef;
// Custom cvar menu
menu_t OP_CustomCvarMenuDef;
@@ -208,7 +209,7 @@ typedef enum
static menuitem_t MPauseMenu[] =
{
{IT_STRING | IT_CALL, NULL, "Addons...", M_Addons, 8},
{IT_STRING | IT_CALL, NULL, "Add local skins...", M_LocalSkins, 16},
{IT_STRING | IT_CALL, NULL, "Local Add-ons...", M_LocalAddons, 8},
{IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 24},
{IT_STRING | IT_CALL, NULL, "Switch Map..." , M_MapChange, 32},
@@ -238,7 +239,7 @@ static menuitem_t MPauseMenu[] =
typedef enum
{
mpause_addons = 0,
mpause_addlocalskins,
mpause_localaddons,
mpause_scramble,
mpause_switchmap,
#ifdef HAVE_DISCORDRPC
@@ -446,25 +447,25 @@ enum
static menuitem_t SP_ReplayMenu[] =
{
{IT_WHITESTRING|IT_CALL, NULL, "Replay Best Time", M_ReplayTimeAttack, 90},
{IT_WHITESTRING|IT_CALL, NULL, "Replay Best Lap", M_ReplayTimeAttack, 98},
{IT_WHITESTRING|IT_CALL, NULL, "Replay Best Time", M_ReplayTimeAttack, 90},
{IT_WHITESTRING|IT_CALL, NULL, "Replay Best Lap", M_ReplayTimeAttack, 98},
{IT_WHITESTRING|IT_CALL, NULL, "Replay Last", M_ReplayTimeAttack, 106},
{IT_WHITESTRING|IT_CALL, NULL, "Replay Guest", M_ReplayTimeAttack, 114},
{IT_WHITESTRING|IT_KEYHANDLER, NULL, "Replay Staff",M_HandleStaffReplay,122},
{IT_WHITESTRING|IT_CALL, NULL, "Replay Last", M_ReplayTimeAttack, 106},
{IT_WHITESTRING|IT_CALL, NULL, "Replay Guest", M_ReplayTimeAttack, 114},
{IT_WHITESTRING|IT_KEYHANDLER, NULL, "Replay Staff",M_HandleStaffReplay, 122},
{IT_WHITESTRING|IT_SUBMENU, NULL, "Back", &SP_TimeAttackDef, 130}
{IT_WHITESTRING|IT_SUBMENU, NULL, "Back", &SP_TimeAttackDef, 130}
};
static menuitem_t SP_GuestReplayMenu[] =
{
{IT_WHITESTRING|IT_CALL, NULL, "Save Best Time as Guest", M_SetGuestReplay, 94},
{IT_WHITESTRING|IT_CALL, NULL, "Save Best Lap as Guest", M_SetGuestReplay,102},
{IT_WHITESTRING|IT_CALL, NULL, "Save Last as Guest", M_SetGuestReplay,110},
{IT_WHITESTRING|IT_CALL, NULL, "Save Best Time as Guest", M_SetGuestReplay, 94},
{IT_WHITESTRING|IT_CALL, NULL, "Save Best Lap as Guest", M_SetGuestReplay, 102},
{IT_WHITESTRING|IT_CALL, NULL, "Save Last as Guest", M_SetGuestReplay, 110},
{IT_WHITESTRING|IT_CALL, NULL, "Delete Guest Replay", M_SetGuestReplay,120},
{IT_WHITESTRING|IT_CALL, NULL, "Delete Guest Replay", M_SetGuestReplay, 120},
{IT_WHITESTRING|IT_SUBMENU, NULL, "Back", &SP_TimeAttackDef, 130}
{IT_WHITESTRING|IT_SUBMENU, NULL, "Back", &SP_TimeAttackDef, 130}
};
static menuitem_t SP_GhostMenu[] =
@@ -555,10 +556,10 @@ static menuitem_t MP_PlayerSetupMenu[] =
static menuitem_t MP_ConnectMenu[] =
{
{IT_STRING | IT_CVAR, NULL, "Sort By", &cv_serversort, 0},
{IT_STRING | IT_KEYHANDLER, NULL, "Page", M_HandleServerPage, 8},
{IT_STRING | IT_CALL, NULL, "Refresh", M_Refresh, 16},
{IT_STRING | IT_KEYHANDLER, NULL, "", M_HandleServerSearch,25},
{IT_STRING | IT_CVAR, NULL, "Sort By", &cv_serversort, 0},
{IT_STRING | IT_KEYHANDLER, NULL, "Page", M_HandleServerPage, 8},
{IT_STRING | IT_CALL, NULL, "Refresh", M_Refresh, 16},
{IT_STRING | IT_KEYHANDLER, NULL, "", M_HandleServerSearch, 25},
{IT_STRING | IT_SPACE, NULL, "", M_Connect, 48},
{IT_STRING | IT_SPACE, NULL, "", M_Connect, 60},
@@ -725,29 +726,36 @@ static const char* OP_AllControlsTooltips[sizeof(OP_AllControlsMenu)/sizeof(OP_A
// The rest is null, for now
};
#define OP_JOYMENU(pnum) \
{IT_HEADER, NULL, "Gameplay Controls", NULL, 7}, \
{IT_STRING | IT_CVAR, NULL, "Aim Forward/Back" , &cv_aimaxis[pnum] , 15}, \
{IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_turnaxis[pnum] , 20}, \
{IT_STRING | IT_CVAR, NULL, "Accelerate" , &cv_moveaxis[pnum] , 25}, \
{IT_STRING | IT_CVAR, NULL, "Brake" , &cv_brakeaxis[pnum] , 30}, \
{IT_STRING | IT_CVAR, NULL, "Drift" , &cv_driftaxis[pnum] , 35}, \
{IT_STRING | IT_CVAR, NULL, "Use Item" , &cv_fireaxis[pnum] , 40}, \
{IT_STRING | IT_CVAR, NULL, "Look Backward" , &cv_lookbackaxis[pnum] , 45}, \
{IT_STRING | IT_CVAR, NULL, "Custom Button 1" , &cv_custom1axis[pnum] , 50}, \
{IT_STRING | IT_CVAR, NULL, "Custom Button 2" , &cv_custom2axis[pnum] , 55}, \
{IT_STRING | IT_CVAR, NULL, "Custom Button 3" , &cv_custom3axis[pnum] , 60}, \
{IT_HEADER, NULL, "Camera Controls", NULL, 67}, \
{IT_STRING | IT_CVAR, NULL, "Look Up/Down" , &cv_lookaxis[pnum] , 75}, \
{IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_camturnaxis[pnum] , 80}, \
{IT_STRING | IT_CVAR, NULL, "Strafe Left/Right" , &cv_camstrafeaxis[pnum] , 85}, \
{IT_HEADER, NULL, "Deadzones", NULL, 92}, \
{IT_STRING | IT_CVAR, NULL, "X deadzone" , &cv_xdeadzone[pnum] , 100}, \
{IT_STRING | IT_CVAR, NULL, "Y deadzone" , &cv_ydeadzone[pnum] , 105}, \
{IT_HEADER, NULL, "Miscellaneous", NULL, 112}, \
{IT_STRING | IT_CVAR, NULL, "Controller Rumble" , &cv_rumble[pnum] , 120}, \
{IT_STRING | IT_CVAR, NULL, "Controller Rumble Strength" , &cv_rumblestrength[pnum] , 125}, \
{IT_STRING | IT_CVAR, NULL, "Set LED to Player color" , &cv_gamepadled[pnum] , 130},
// i really do not feel like messing with setup routines
// and macro preprocessor cannot eval maths for string shit like this :chaosleep:
#define RUMBDEF_0 OP_Joystick1RumbleDef
#define RUMBDEF_1 OP_Joystick2RumbleDef
#define RUMBDEF_2 OP_Joystick3RumbleDef
#define RUMBDEF_3 OP_Joystick4RumbleDef
#define RUMBDEF(x) RUMBDEF_##x
#define OP_JOYMENU(pnum) \
{IT_HEADER, NULL, "Gameplay Controls", NULL, 7}, \
{IT_STRING | IT_CVAR, NULL, "Aim Forward/Back" , &cv_aimaxis[pnum] , 15}, \
{IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_turnaxis[pnum] , 20}, \
{IT_STRING | IT_CVAR, NULL, "Accelerate" , &cv_moveaxis[pnum] , 25}, \
{IT_STRING | IT_CVAR, NULL, "Brake" , &cv_brakeaxis[pnum] , 30}, \
{IT_STRING | IT_CVAR, NULL, "Drift" , &cv_driftaxis[pnum] , 35}, \
{IT_STRING | IT_CVAR, NULL, "Use Item" , &cv_fireaxis[pnum] , 40}, \
{IT_STRING | IT_CVAR, NULL, "Look Backward" , &cv_lookbackaxis[pnum] , 45}, \
{IT_STRING | IT_CVAR, NULL, "Custom Button 1" , &cv_custom1axis[pnum] , 50}, \
{IT_STRING | IT_CVAR, NULL, "Custom Button 2" , &cv_custom2axis[pnum] , 55}, \
{IT_STRING | IT_CVAR, NULL, "Custom Button 3" , &cv_custom3axis[pnum] , 60}, \
{IT_HEADER, NULL, "Camera Controls", NULL, 67}, \
{IT_STRING | IT_CVAR, NULL, "Look Up/Down" , &cv_lookaxis[pnum] , 75}, \
{IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_camturnaxis[pnum] , 80}, \
{IT_STRING | IT_CVAR, NULL, "Strafe Left/Right" , &cv_camstrafeaxis[pnum] , 85}, \
{IT_HEADER, NULL, "Deadzones", NULL, 92}, \
{IT_STRING | IT_CVAR, NULL, "X deadzone" , &cv_xdeadzone[pnum] , 100}, \
{IT_STRING | IT_CVAR, NULL, "Y deadzone" , &cv_ydeadzone[pnum] , 105}, \
{IT_HEADER, NULL, "Miscellaneous", NULL, 112}, \
{IT_SUBMENU|IT_STRING, NULL, "Rumble Options..." , &RUMBDEF(pnum) , 120}, \
{IT_STRING | IT_CVAR, NULL, "Set LED to Player color" , &cv_gamepadled[pnum] , 125},
static menuitem_t OP_Joystick1Menu[] =
{
@@ -773,6 +781,46 @@ static menuitem_t OP_Joystick4Menu[] =
OP_JOYMENU(3)
};
#undef RUMBDEF
#undef RUMBDEF_0
#undef RUMBDEF_1
#undef RUMBDEF_2
#undef RUMBDEF_3
// FIXME: stair jank rumble should be greyed out if its disabled, but menus suck butt!
#define OP_JOYRUMBLEMENU(pnum) \
{IT_HEADER, NULL, "Global", NULL, 7}, \
{IT_STRING | IT_CVAR, NULL, "Controller Rumble" , &cv_rumble[pnum] , 15}, \
{IT_STRING | IT_CVAR, NULL, "Controller Rumble Strength" , &cv_rumble_strength[pnum] , 20}, \
{IT_HEADER, NULL, "Rumble Types", NULL, 27}, \
{IT_STRING | IT_CVAR, NULL, "Spinout" , &cv_rumble_spinout[pnum] , 35}, \
{IT_STRING | IT_CVAR, NULL, "Sneaker Boost" , &cv_rumble_sneakerboost[pnum] , 40}, \
{IT_STRING | IT_CVAR, NULL, "Offroad" , &cv_rumble_offroad[pnum] , 45}, \
{IT_STRING | IT_CVAR, NULL, "Banana Dragging" , &cv_rumble_bananadrag[pnum] , 50}, \
{IT_STRING | IT_CVAR, NULL, "Stair Jank" , &cv_rumble_stairjank[pnum] , 55}, \
{IT_STRING | IT_CVAR, NULL, "Brake Drift" , &cv_rumble_brakedrift[pnum] , 60}, \
{IT_STRING | IT_CVAR, NULL, "Drift Charge" , &cv_rumble_driftcharge[pnum] , 65}, \
static menuitem_t OP_Joystick1RumbleMenu[] =
{
OP_JOYRUMBLEMENU(0)
};
static menuitem_t OP_Joystick2RumbleMenu[] =
{
OP_JOYRUMBLEMENU(1)
};
static menuitem_t OP_Joystick3RumbleMenu[] =
{
OP_JOYRUMBLEMENU(2)
};
static menuitem_t OP_Joystick4RumbleMenu[] =
{
OP_JOYRUMBLEMENU(3)
};
static menuitem_t OP_JoystickSetMenu[] =
{
{IT_CALL | IT_NOTHING, "None", NULL, M_AssignJoystick, LINEHEIGHT+5},
@@ -789,10 +837,9 @@ static menuitem_t OP_JoystickSetMenu[] =
static menuitem_t OP_MouseOptionsMenu[] =
{
{IT_STRING | IT_CVAR, NULL, "Use Mouse", &cv_usemouse, 10},
{IT_STRING | IT_CVAR, NULL, "Mouse Turning", &cv_mouseturn, 20},
{IT_STRING | IT_CVAR, NULL, "Invert Mouse", &cv_invertmouse, 30},
{IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Mouse X Speed", &cv_mousexsens, 40},
{IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Mouse X Speed", &cv_mousexsens, 40},
{IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Mouse Y Speed", &cv_mouseysens, 50},
};
@@ -861,7 +908,6 @@ static const char* OP_VideoTooltips[] =
"Advanced graphical options.",
};
enum
{
op_video_res = 0,
@@ -945,24 +991,25 @@ static menuitem_t OP_ExpOptionsMenu[] =
//{IT_STRING | IT_CVAR, NULL, "Randomized Directional Light", &cv_randomdirlight, 45}, // should this ever come back
{IT_STRING | IT_CVAR, NULL, "Skyboxes", &cv_skybox, 40},
{IT_STRING | IT_CVAR, NULL, "Skydome", &cv_skydome, 45},
{IT_STRING | IT_CVAR, NULL, "Precache Level Textures", &cv_precachetextures, 50},
{IT_STRING | IT_CVAR, NULL, "Precache Level Textures", &cv_precachetextures, 55},
{IT_STRING | IT_CVAR, NULL, "FPS counter sampling", &cv_accuratefps, 60},
{IT_STRING | IT_CVAR, NULL, "FPS counter sampling", &cv_accuratefps, 65},
{IT_STRING | IT_CVAR, NULL, "Frameskip", &cv_frameskip, 70},
{IT_STRING | IT_CVAR, NULL, "Frameskip", &cv_frameskip, 75},
{IT_STRING | IT_CVAR, NULL, "Votescreen Scaling", &cv_votebgscaling, 80},
{IT_STRING | IT_CVAR, NULL, "Votescreen Scaling", &cv_votebgscaling, 85},
#ifdef HWRENDER
{IT_STRING | IT_CVAR, NULL, "Screen Textures", &cv_glscreentextures, 90},
{IT_STRING | IT_CVAR, NULL, "Screen Textures", &cv_glscreentextures, 95},
#ifdef USE_FBO_OGL
{IT_STRING | IT_CVAR, NULL, "FBO Downsampling support", &cv_glframebuffer, 95},
{IT_STRING | IT_CVAR, NULL, "Palette Depth", &cv_glpalettedepth, 105},
{IT_DISABLED, NULL, "", NULL, 115}, // dummy text
{IT_STRING | IT_CVAR, NULL, "FBO Downsampling support", &cv_glframebuffer, 100},
{IT_STRING | IT_CVAR, NULL, "Palette Depth", &cv_glpalettedepth, 110},
{IT_DISABLED, NULL, "", NULL, 120}, // dummy text
#else
{IT_STRING | IT_CVAR, NULL, "Palette Depth", &cv_glpalettedepth, 100},
{IT_DISABLED, NULL, "", NULL, 110}, // dummy text
{IT_STRING | IT_CVAR, NULL, "Palette Depth", &cv_glpalettedepth, 110},
{IT_DISABLED, NULL, "", NULL, 120}, // dummy text
#endif
#endif
};
@@ -975,12 +1022,13 @@ static const char* OP_ExpTooltips[] =
"Sets minimum sector brightness, useful for dark areas.",
//"Should the directional lightning be randomized each map?\nTakes effect on next map load.",
"Toggle being able to see the sky.",
"Toggle skydome.", // idk man someone give a better description of this
"Preload all level textures on level load.\nMassively reduces texture related stuttering during gameplay\nat the cost of longer level loading times.\nDisable this if you experience timeouts during level switches.",
"Change the FPS counter sampling method\nInaccurate updates slower\nand might miss sudden framerate changes and drops,\nproviding a more averaged result.\nAccurate updates faster, but might be less readable.", // how to ingles??
"Skips rendering frames if game logic takes too long\npreventing gameplay issues during performance drops.", // idk im shit as describing things
"Different methods of scaling the votescreen backgrounds.",
#ifdef HWRENDER
"Disabling Screen Textures may result in a performance boost\nbut will break certain effects.\nScreen textures are required at resolutions lower than your desktop resolution!"
"Disabling Screen Textures may result in a performance boost\nbut will break certain effects.\nScreen textures are required at resolutions lower than your desktop resolution!",
#ifdef USE_FBO_OGL
"Allows the game to downsample from a higher resolution\nthan your display in OpenGL renderer mode.\nRequires a GPU with atleast OpenGL 2.1 support.",
#endif
@@ -996,6 +1044,7 @@ enum
op_exp_secbright,
//op_exp_dirlight,
op_exp_skybox,
op_exp_skydome,
op_exp_texcache,
op_exp_accuratefps,
op_exp_frameskip,
@@ -1009,7 +1058,6 @@ enum
#endif
};
#ifdef HWRENDER
static menuitem_t OP_OpenGLOptionsMenu[] =
{
@@ -1066,7 +1114,6 @@ enum
op_gl_shearing,
op_gl_renderdist,
};
#endif
static menuitem_t OP_SoundOptionsMenu[] =
@@ -1077,8 +1124,7 @@ static menuitem_t OP_SoundOptionsMenu[] =
{IT_STRING|IT_CVAR|IT_CV_NOPRINT, NULL, "Music", &cv_gamedigimusic, 30},
{IT_STRING|IT_CVAR|IT_CV_SLIDER, NULL, "Music Volume", &cv_digmusicvolume, 38},
//#ifndef NO_MIDI
#if 0
#if 0 //#ifndef NO_MIDI
{IT_STRING|IT_CVAR|IT_CV_SLIDER, NULL, "MIDI Volume", &cv_midimusicvolume, 46},
{IT_STRING|IT_CVAR, NULL, "Reverse L/R Channels", &stereoreverse, 60},
@@ -1113,8 +1159,7 @@ static const char* OP_SoundTooltips[] =
"Volume of Sound effects.",
"Turn Music on or off.",
"Volume of Music.",
//#ifndef NO_MIDI
#if 0
#if 0 //#ifndef NO_MIDI
"Volume of Midi Music.",
#endif
"Reverse left and right channels of audio.",
@@ -1174,7 +1219,7 @@ static const char* OP_SoundAdvancedTooltips[] =
"Should the Grow music be on or off?",
"Should the Invulnerability music be on or off?",
"Should music be kept when restarting the map?",
"Should the Intro fanfare be skipped\nand map music be played on map start?",
"Should the Intro fanfare be skipped\nand map music be played on map start?\nNote that this WILL skip sounds played by the map before round start as well!",
"Controls Sound effects caching.\nKeep will retain previously played sound effects in cache." // man idk how to describe this in a non awful way lmao
"\nOn will preload all sound effects.\nEliminates sound-related lag and stutters but increases memory usage.",
"Size of the Audio Buffer\nreducing it will result in less sound latency\nbut may cause issues such as crackling or distorted Sound.",
@@ -1408,44 +1453,70 @@ static const char* OP_PlayerCamOptionsTooltips[] =
static menuitem_t OP_ChatOptionsMenu[] =
{
// will ANYONE who doesn't know how to use the console want to touch this one?
{IT_STRING | IT_CVAR, NULL, "Chat Mode", &cv_consolechat, 5}, // nonetheless...
{IT_STRING | IT_CVAR, NULL, "Chat Mode", &cv_consolechat, 5}, // nonetheless...
{IT_STRING | IT_CVAR | IT_CV_SLIDER,
NULL, "Chat Box Width", &cv_chatwidth, 20},
NULL, "Chat Box Width", &cv_chatwidth, 10},
{IT_STRING | IT_CVAR | IT_CV_SLIDER,
NULL, "Chat Box Height", &cv_chatheight, 30},
{IT_STRING | IT_CVAR, NULL, "Center Text in Chat", &cv_chatcentertext, 40},
NULL, "Chat Box Height", &cv_chatheight, 15},
{IT_STRING | IT_CVAR, NULL, "Chat Horizontal Offset", &cv_chat_xoffset, 20},
{IT_STRING | IT_CVAR, NULL, "Chat Vertical Offset", &cv_chat_yoffset, 25},
{IT_STRING | IT_CVAR, NULL, "Chat Background Tint", &cv_chatbacktint, 55},
{IT_STRING | IT_CVAR, NULL, "Message Fadeout Time", &cv_chattime, 65},
{IT_STRING | IT_CVAR, NULL, "Spam Protection", &cv_chatspamprotection, 75},
{IT_STRING | IT_CVAR, NULL, "Max Chat Messages", &cv_chatlogsize, 85},
{IT_STRING | IT_CVAR, NULL, "Center Text in Chat", &cv_chatcentertext, 35},
{IT_STRING | IT_CVAR, NULL, "Chat Background Tint", &cv_chatbacktint, 40},
{IT_STRING | IT_CVAR, NULL, "Message Fadeout Time", &cv_chattime, 45},
{IT_STRING | IT_CVAR, NULL, "Spam Protection", &cv_chatspamprotection, 50},
{IT_STRING | IT_CVAR, NULL, "Max Chat Messages", &cv_chatlogsize, 55},
{IT_STRING | IT_CVAR, NULL, "Display Character Limit", &cv_chat_showlimit, 60},
{IT_STRING | IT_CVAR, NULL, "Local ping display", &cv_showping, 105}, // shows ping above the framerate if we want to.
{IT_STRING | IT_CVAR, NULL, "Ping display style", &cv_pingstyle, 115},
{IT_STRING | IT_CVAR, NULL, "Ping measurement", &cv_pingmeasurement, 125},
{IT_STRING | IT_CVAR, NULL, "Ping icon", &cv_pingicon, 135},
{IT_STRING | IT_CVAR, NULL, "Local ping display", &cv_showping, 70}, // shows ping above the framerate if we want to.
{IT_STRING | IT_CVAR, NULL, "Ping display style", &cv_pingstyle, 75},
{IT_STRING | IT_CVAR, NULL, "Ping measurement", &cv_pingmeasurement, 80},
{IT_STRING | IT_CVAR, NULL, "Ping icon", &cv_pingicon, 85},
{IT_STRING | IT_CVAR, NULL, "Show IP address in playerlist", &cv_shownodeip, 145},
{IT_STRING | IT_CVAR, NULL, "Show IP address in playerlist", &cv_shownodeip, 90},
};
static const char* OP_ChatOptionsTooltips[] =
{
"Chat mode used for in-game chat.",
"Width of chat box.",
"Height of chat box.",
"Width of the chat box.",
"Height of the chat box.",
"Horizontal Offset of the chat box.",
"Vertical Offset of the chat box.",
"Center text in the chat message pop ups.",
"Chatbox background.",
"Background for the chat message pop ups.",
"Fadeout time for new chat message.",
"Spam protection for in-game chat.",
"Maxiumum amount of chat messages to look back at.",
"Show how many characters you have left to type in the chat.",
"Show player ping.",
"Choose the looks of the ping display.", // this is ass idk english lmao
"Choose the style of the ping display.",
"Measurement used for ping.",
"Visibility of ping icon.",
"Should Player IP addresses be printed when using\nthe nodes or listplayers command?",
};
enum
{
op_chat_mode,
op_chat_boxwidth,
op_chat_boxheight,
op_chat_yoffs,
op_chat_xoffs,
op_chat_centertxt,
op_chat_bgtint,
op_chat_fadetime,
op_chat_spamprotect,
op_chat_maxmsg,
op_chat_charlmt,
op_chat_showping,
op_chat_pingstyle,
op_chat_pingmeasr,
op_chat_pingico,
op_chat_nodeip,
};
static menuitem_t OP_GameOptionsMenu[] =
{
{IT_STRING | IT_SUBMENU, NULL, "Random Item Toggles...", &OP_MonitorToggleDef, 10},
@@ -1631,7 +1702,7 @@ static menuitem_t OP_AccessibilityMenu[] =
{IT_SUBMENU|IT_STRING, NULL, "Video Color Settings...", &OP_ColorOptionsDef, 30},
{IT_STRING|IT_CVAR, NULL, "Reduce Effects", &cv_reducevfx, 35},
{IT_STRING|IT_CVAR, NULL, "Midnight Channel Flicker", &cv_lessflicker, 40}, // obsolete now? or still better be a seperate toggle?
{IT_STRING|IT_CVAR, NULL, "Less Midnight Channel Flicker", &cv_lessflicker, 40}, // obsolete now? or still better be a seperate toggle?
{IT_STRING|IT_CVAR, NULL, "Minimum Sector Brightness", &cv_secbright, 45},
@@ -1713,6 +1784,7 @@ static menuitem_t OP_SaturnMenu[] =
{IT_SUBMENU|IT_STRING, NULL, "Saturn Hud...", &OP_SaturnHudDef, 140},
{IT_SUBMENU|IT_STRING, NULL, "Sprite Distortion...", &OP_PlayerDistortDef, 145},
{IT_SUBMENU|IT_STRING, NULL, "Saturn Credits", &OP_SaturnCreditsDef, 150}, // uwu
{IT_STRING|IT_CALL, NULL, "Report an Issue", M_SaturnReportIssue, 155}
};
static const char* OP_SaturnTooltips[] =
@@ -1736,6 +1808,7 @@ static const char* OP_SaturnTooltips[] =
"Options for Saturn specific HUD things.",
"Options for sprite distortion effects.",
"See the people who helped make this project possible!",
"Noticed a bug, have a Suggestion or other Feedback?\nFeel free to tell us!",
};
enum
@@ -1757,6 +1830,7 @@ enum
sm_hud,
sm_distortionmenu,
sm_credits,
sm_issue,
};
static menuitem_t OP_PlayerDistortMenu[] =
@@ -1767,20 +1841,23 @@ static menuitem_t OP_PlayerDistortMenu[] =
{IT_STRING | IT_CVAR, NULL, "Slope Rotation Distance", &cv_sloperolldist, 15},
{IT_STRING | IT_CVAR, NULL, "Rotate Players when Sliptiding", &cv_sliptideroll, 25},
{IT_STRING | IT_CVAR, NULL, "Rotate Sparks and Boost Trails", &cv_sparkroll, 30},
{IT_STRING | IT_CVAR, NULL, "Rotate Bananas on Throw", &cv_bananthrowroll, 35},
{IT_STRING | IT_CVAR, NULL, "Stair Janking Effect", &cv_stairjank, 30},
{IT_STRING | IT_CVAR, NULL, "Stair Janking Sound Effect", &cv_stairjanksfx, 35}, // idk if that should be here but i dont care atm
{IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Player Stretch Factor", &cv_gravstretch, 45},
{IT_STRING | IT_CVAR, NULL, "Squish Sound Effect", &cv_slamsound, 50},
{IT_STRING | IT_CVAR, NULL, "Rotate Sparks and Boost Trails", &cv_sparkroll, 40},
{IT_STRING | IT_CVAR, NULL, "Rotate Bananas on Throw", &cv_bananthrowroll, 45},
{IT_STRING | IT_CVAR, NULL, "Saltyhop", &cv_saltyhop, 60},
{IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Saltyhop Height", &cv_saltyheight, 65},
{IT_STRING | IT_CVAR, NULL, "Saltyhop Sound Effect", &cv_saltyhopsfx, 70},
{IT_STRING | IT_CVAR, NULL, "Saltyhop Squish", &cv_saltysquish, 75},
{IT_STRING | IT_CVAR, NULL, "Saltyhop Roll", &cv_saltyroll, 80},
{IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Player Stretch Factor", &cv_gravstretch, 55},
{IT_STRING | IT_CVAR, NULL, "Squish Sound Effect", &cv_slamsound, 60},
{IT_STRING | IT_CVAR, NULL, "Squishdance", &cv_squishdance, 90},
{IT_STRING | IT_CVAR, NULL, "Squishdance Speed", &cv_squishdancespeed, 96},
{IT_STRING | IT_CVAR, NULL, "Saltyhop", &cv_saltyhop, 70},
{IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Saltyhop Height", &cv_saltyheight, 75},
{IT_STRING | IT_CVAR, NULL, "Saltyhop Sound Effect", &cv_saltyhopsfx, 80},
{IT_STRING | IT_CVAR, NULL, "Saltyhop Squish", &cv_saltysquish, 85},
{IT_STRING | IT_CVAR, NULL, "Saltyhop Roll", &cv_saltyroll, 90},
{IT_STRING | IT_CVAR, NULL, "Squishdance", &cv_squishdance, 100},
{IT_STRING | IT_CVAR, NULL, "Squishdance Speed", &cv_squishdancespeed, 106}, // why is this offset by 6? idk cant remember lulul
};
static const char* OP_PlayerDistortTooltips[] =
@@ -1789,6 +1866,8 @@ static const char* OP_PlayerDistortTooltips[] =
"Sprite rotation on slopes. Can either be just players or all objects.",
"Distance object rotation should be visable.",
"Player rotation when sliptiding.",
"Slightly tilt the player when driving over stairs or small bumps.",
"Sound effect when driving over stairs or small bumps.",
"Rotation of a player's boost trails and drift sparks.",
"Should banans rotate when thrown?\nAnd should they stay rotated when on the ground?",
"Player squash and stretch.",
@@ -1799,7 +1878,7 @@ static const char* OP_PlayerDistortTooltips[] =
"Player hop squash and stretch.",
"Should the player rotation be kept during player hop.",
"Do a funny squishy dance when holding CUSTOM 3.",
"Speed of the Squishy dance in BPM.",
"Speed of the Squishy dance in SPM (Squishes Per Minute).",
};
enum
@@ -1808,6 +1887,8 @@ enum
sloperotate,
slrotatedist,
sliptide,
stairjank,
stairjanksfx,
sparkrotate,
bananrotat,
stretchyplayer,
@@ -2500,6 +2581,11 @@ menu_t OP_Joystick2Def = DEFAULTSCROLLSTYLE("M_CONTRO", OP_Joystick2Menu, &OP
menu_t OP_Joystick3Def = DEFAULTSCROLLSTYLE("M_CONTRO", OP_Joystick3Menu, &OP_AllControlsDef, 30, 36, NULL);
menu_t OP_Joystick4Def = DEFAULTSCROLLSTYLE("M_CONTRO", OP_Joystick4Menu, &OP_AllControlsDef, 30, 36, NULL);
menu_t OP_Joystick1RumbleDef = DEFAULTSCROLLSTYLE("M_CONTRO", OP_Joystick1RumbleMenu, &OP_Joystick1Def, 30, 36, NULL);
menu_t OP_Joystick2RumbleDef = DEFAULTSCROLLSTYLE("M_CONTRO", OP_Joystick2RumbleMenu, &OP_Joystick2Def, 30, 36, NULL);
menu_t OP_Joystick3RumbleDef = DEFAULTSCROLLSTYLE("M_CONTRO", OP_Joystick3RumbleMenu, &OP_Joystick3Def, 30, 36, NULL);
menu_t OP_Joystick4RumbleDef = DEFAULTSCROLLSTYLE("M_CONTRO", OP_Joystick4RumbleMenu, &OP_Joystick4Def, 30, 36, NULL);
menu_t OP_JoystickSetDef =
{
"M_CONTRO",
@@ -2591,7 +2677,7 @@ menu_t OP_Player2CamOptionsDef = DEFAULTMENUSTYLE(NULL, OP_Player2CamOptionsMenu
menu_t OP_Player3CamOptionsDef = DEFAULTMENUSTYLE(NULL, OP_Player3CamOptionsMenu, &OP_CamOptionsDef, 30, 30, OP_PlayerCamOptionsTooltips);
menu_t OP_Player4CamOptionsDef = DEFAULTMENUSTYLE(NULL, OP_Player4CamOptionsMenu, &OP_CamOptionsDef, 30, 30, OP_PlayerCamOptionsTooltips);
menu_t OP_ChatOptionsDef = DEFAULTMENUSTYLE("M_HUD", OP_ChatOptionsMenu, &OP_HUDOptionsDef, 30, 30, OP_ChatOptionsTooltips);
menu_t OP_ChatOptionsDef = DEFAULTSCROLLSTYLE("M_HUD", OP_ChatOptionsMenu, &OP_HUDOptionsDef, 30, 25, OP_ChatOptionsTooltips);
menu_t OP_SoundAdvancedDef = DEFAULTSCROLLSTYLE("M_SOUND", OP_SoundAdvancedMenu, &OP_SoundOptionsDef, 30, 30, OP_SoundAdvancedTooltips);
@@ -2716,6 +2802,15 @@ void PDistort_menu_Onchange(void)
OP_PlayerDistortMenu[slrotatedist].status = IT_GRAYEDOUT;
OP_PlayerDistortMenu[saltroll].status = IT_GRAYEDOUT;
}
if (cv_stairjank.value)
{
OP_PlayerDistortMenu[stairjanksfx].status = IT_STRING | IT_CVAR;
}
else
{
OP_PlayerDistortMenu[stairjanksfx].status = IT_GRAYEDOUT;
}
}
void Bird_menu_Onchange(void)
+1 -1
View File
@@ -44,7 +44,7 @@ boolean M_TextInputHandle(textinput_t *input, INT32 key);
// If currently typing something that looks like an existing emote, return suggestions for it
boolean M_TextInputHandleEmotes(textinput_t *input, INT32 key, emote_autocomplete_t *autocomplete);
#define M_DrawTextInput(x, y, input, flags) M_DrawTextInputScroll((x), (y), (input), (flags), ((input)->buffer_size-1)*8)
#define M_DrawTextInput(x, y, input, flags) M_DrawTextInputScroll((x), (y), (input), (flags), ((input)->buffer_size-2)*8)
void M_DrawTextInputScroll(INT32 x, INT32 y, textinput_t *input, INT32 flags, INT32 MAXINPUTWIDTH);
#endif
+8 -13
View File
@@ -250,7 +250,8 @@ boolean P_Move(mobj_t *actor, fixed_t speed)
I_Assert(movedir < NUMDIRS);
tryx = actor->x + FixedMul(speed*xspeed[movedir], actor->scale);
if (UNLIKELY(twodlevel || actor->flags2 & MF2_TWOD))
if (twodmo(actor))
tryy = actor->y;
else
tryy = actor->y + FixedMul(speed*yspeed[movedir], actor->scale);
@@ -328,7 +329,7 @@ void P_NewChaseDir(mobj_t *actor)
else
d[1] = DI_NODIR;
if (UNLIKELY(twodlevel || actor->flags2 & MF2_TWOD))
if (twodmo(actor))
d[2] = DI_NODIR;
if (deltay < -FixedMul(10*FRACUNIT, actor->scale))
d[2] = DI_SOUTH;
@@ -2762,10 +2763,10 @@ void A_Invincibility(void *thing)
{
S_StopMusic();
if (UNLIKELY(mariomode))
if (mariomode)
G_GhostAddColor((INT32) (player - players), GHC_INVINCIBLE);
S_ChangeMusicInternal((UNLIKELY(mariomode)) ? "minvnc" : "invinc", false);
S_ChangeMusicInternal(mariomode ? "minvnc" : "invinc", false);
}
}
@@ -4359,7 +4360,7 @@ void A_MouseThink(void *thing)
|| (actor->eflags & MFE_VERTICALFLIP && actor->z + actor->height == actor->ceilingz))
&& !actor->reactiontime)
{
if (UNLIKELY(twodlevel || actor->flags2 & MF2_TWOD))
if (twodmo(actor))
{
if (P_RandomChance(FRACUNIT/2))
actor->angle += ANGLE_180;
@@ -10878,10 +10879,7 @@ void A_BrakLobShot(void *thing)
return; // Don't even bother if we've got nothing to aim at.
// Look up actor's current gravity situation
if (actor->subsector->sector->gravity)
g = FixedMul(gravity,(FixedDiv(*actor->subsector->sector->gravity>>FRACBITS, 1000)));
else
g = gravity;
g = P_GetSectorGravity(actor->subsector->sector);
// Look up distance between actor and its target
x = P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y);
@@ -10996,10 +10994,7 @@ void A_NapalmScatter(void *thing)
airtime = 16<<FRACBITS;
// Look up actor's current gravity situation
if (actor->subsector->sector->gravity)
g = FixedMul(gravity,(FixedDiv(*actor->subsector->sector->gravity>>FRACBITS, 1000)));
else
g = gravity;
g = P_GetSectorGravity(actor->subsector->sector);
// vy = (g*(airtime-1))/2
vy = FixedMul(g,(airtime-(1<<FRACBITS)))>>1;
+2 -2
View File
@@ -2338,7 +2338,7 @@ void T_RaiseSector(levelspecthink_t *raise)
fixed_t origspeed = raise->vars[3];
// Slow down as you get closer to the bottom
raise->vars[3] = FixedMul(raise->vars[3],FixedDiv(raise->sector->ceilingheight - raise->vars[7], (raise->vars[5] - raise->vars[7])>>5));
raise->vars[3] = FixedMul(raise->vars[3], FixedDiv(raise->sector->ceilingheight - raise->vars[7], (raise->vars[5] - raise->vars[7])>>5));
if (raise->vars[3] <= origspeed/16)
raise->vars[3] = origspeed/16;
@@ -2349,7 +2349,7 @@ void T_RaiseSector(levelspecthink_t *raise)
{
fixed_t origspeed = raise->vars[3];
// Slow down as you get closer to the top
raise->vars[3] = FixedMul(raise->vars[3],FixedDiv(raise->vars[5] - raise->sector->ceilingheight, (raise->vars[5] - raise->vars[7])>>5));
raise->vars[3] = FixedMul(raise->vars[3], FixedDiv(raise->vars[5] - raise->sector->ceilingheight, (raise->vars[5] - raise->vars[7])>>5));
if (raise->vars[3] <= origspeed/16)
raise->vars[3] = origspeed/16;
+39 -31
View File
@@ -589,7 +589,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
special->momx = special->momy = special->momz = 0;
P_GivePlayerRings(player, 1);
if (UNLIKELY((maptol & TOL_NIGHTS) && special->type != MT_FLINGRING))
if (nightsmode && special->type != MT_FLINGRING)
P_DoNightsScore(player);
break;
@@ -601,7 +601,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
special->momx = special->momy = 0;
P_GivePlayerRings(player, 1);
if (UNLIKELY((maptol & TOL_NIGHTS) && special->type != MT_FLINGCOIN))
if (nightsmode && special->type != MT_FLINGCOIN)
P_DoNightsScore(player);
break;
case MT_BLUEBALL:
@@ -617,7 +617,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
else
special->scalespeed = 4*FRACUNIT/5;
if (UNLIKELY(maptol & TOL_NIGHTS))
if (nightsmode)
P_DoNightsScore(player);
break;
case MT_AUTOPICKUP:
@@ -831,7 +831,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
{
S_StartSound(toucher, special->info->seesound);
if (UNLIKELY(player->pflags & PF_NIGHTSMODE))
if (nightsplayer(player))
{
player->bumpertime = TICRATE/2;
if (special->threshold > 0)
@@ -883,18 +883,20 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
break;
case MT_HOOPCOLLIDE:
// This produces a kind of 'domino effect' with the hoop's pieces.
for (; special->hprev != NULL; special = special->hprev); // Move to the first sprite in the hoop
for (; special != NULL && special->hprev != NULL; special = special->hprev); // Move to the first sprite in the hoop
i = 0;
for (; special->hnext != NULL && special->type == MT_HOOP; special = special->hnext)
for (; special != NULL && special->type == MT_HOOP; special = special->hnext)
{
if (!P_MobjWasRemoved(special->target))
if (!P_MobjWasRemoved(special))
{
special->fuse = 11;
special->movedir = i;
special->extravalue1 = special->target->extravalue1;
special->extravalue2 = special->target->extravalue2;
special->target->threshold = 4242;
if (!P_MobjWasRemoved(special->target))
{
special->extravalue1 = special->target->extravalue1;
special->extravalue2 = special->target->extravalue2;
special->target->threshold = 4242;
}
}
i++;
}
@@ -1131,7 +1133,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
S_StartSound(toucher, special->info->painsound);
return;
}
else if (UNLIKELY((player->pflags & PF_NIGHTSMODE) && (player->pflags & PF_DRILLING)) || (player->pflags & (PF_JUMPED|PF_SPINNING|PF_GLIDING))
else if ((nightsplayer(player) && (player->pflags & PF_DRILLING)) || (player->pflags & (PF_JUMPED|PF_SPINNING|PF_GLIDING))
|| player->powers[pw_invulnerability] || player->powers[pw_super]) // Do you possess the ability to subdue the object?
{
// Shatter the shield!
@@ -1466,8 +1468,7 @@ static void P_UpdateRemovedOrbital(mobj_t *target, mobj_t *inflictor, mobj_t *so
{
// SRB2kart
// I wish I knew a better way to do this
//if (!P_MobjWasRemoved(target->target) && target->target->player && !P_MobjWasRemoved(target->target->player->mo))
if (target->target && target->target->player && target->target->player->mo)
if (!P_MobjWasRemovedCompat(target->target) && target->target->player && !P_MobjWasRemovedCompat(target->target->player->mo))
{
if (target->target->player->kartstuff[k_eggmanheld] && target->type == MT_EGGMANITEM_SHIELD)
target->target->player->kartstuff[k_eggmanheld] = 0;
@@ -1480,7 +1481,7 @@ static void P_UpdateRemovedOrbital(mobj_t *target, mobj_t *inflictor, mobj_t *so
{
if (target->movedir != 0 && target->movedir < (UINT16)target->target->player->kartstuff[k_itemamount])
{
if (target->target->hnext) // !P_MobjWasRemoved(target->target->hnext))
if (!P_MobjWasRemovedCompat(target->target->hnext))
K_KillBananaChain(target->target->hnext, inflictor, source);
target->target->player->kartstuff[k_itemamount] = 0;
@@ -1694,7 +1695,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
else
prandom = P_RandomKey(5); // No placable object, just use a random number.
switch(prandom)
switch (prandom)
{
default: item = MT_BUNNY; break;
case 1: item = MT_BIRD; break;
@@ -2238,18 +2239,24 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
return false;
// well no clue but this may happen ig
if (!target || (target->health <= 0))
if (P_MobjWasRemovedCompat(target))
return false;
if (target->health <= 0)
return false;
// Spectator handling
if (netgame)
{
if (damage == DMG_SPECTATOR && target->player && target->player->spectator)
damage = DMG_INSTAKILL;
else if (target->player && target->player->spectator)
return false;
if (target->player && target->player->spectator)
{
if (damage == DMG_SPECTATOR)
damage = DMG_INSTAKILL;
else
return false;
}
if (source && source->player && source->player->spectator)
if (!P_MobjWasRemovedCompat(source) && source->player && source->player->spectator)
return false;
}
@@ -2343,16 +2350,17 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if (player->exiting)
return false;
if (UNLIKELY(!(target->player->pflags & (PF_NIGHTSMODE|PF_NIGHTSFALL)) && (maptol & TOL_NIGHTS)))
if (UNLIKELY(!(target->player->pflags & (PF_NIGHTSMODE|PF_NIGHTSFALL)) && nightsmode))
return false;
}
if (UNLIKELY(player->pflags & PF_NIGHTSMODE)) // NiGHTS damage handling
if (nightsplayer(player)) // NiGHTS damage handling
{
if (!force)
{
if (source == target)
return false; // Don't hit yourself with your own paraloop, baka
if (source && source->player && !cv_friendlyfire.value
&& (gametype == GT_COOP
|| (G_GametypeHasTeams() && target->player->ctfteam == source->player->ctfteam)))
@@ -2402,7 +2410,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
else if (player->kartstuff[k_invincibilitytimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->powers[pw_flashing])
{
if (!force) // shoulddamage bypasses all of that.
if (!force) // shoulddamage bypasses all of that.
{
K_DoInstashield(player);
return false;
@@ -2591,7 +2599,7 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings)
ns = FixedMul(((i*FRACUNIT)/16)+2*FRACUNIT, mo->scale);
mo->momx = FixedMul(FINECOSINE(fa),ns);
if (LIKELY(!(twodlevel || (player->mo->flags2 & MF2_TWOD))))
if (!twodmo(player->mo))
mo->momy = FixedMul(FINESINE(fa),ns);
P_SetObjectMomZ(mo, 8*FRACUNIT, false);
@@ -2615,7 +2623,7 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings)
ns = FixedMul(momxy, mo->scale);
mo->momx = FixedMul(FINECOSINE(fa),ns);
if (LIKELY(!(twodlevel || (player->mo->flags2 & MF2_TWOD))))
if (!twodmo(player->mo))
mo->momy = FixedMul(FINESINE(fa),ns);
ns = momz;
@@ -2722,7 +2730,7 @@ void P_PlayerWeaponPanelBurst(player_t *player)
ns = FixedMul(3*FRACUNIT, mo->scale);
mo->momx = FixedMul(FINECOSINE(fa),ns);
if (LIKELY(!(twodlevel || (player->mo->flags2 & MF2_TWOD))))
if (!twodmo(player->mo))
mo->momy = FixedMul(FINESINE(fa),ns);
P_SetObjectMomZ(mo, 4*FRACUNIT, false);
@@ -2806,7 +2814,7 @@ void P_PlayerWeaponAmmoBurst(player_t *player)
ns = FixedMul(2*FRACUNIT, mo->scale);
mo->momx = FixedMul(FINECOSINE(fa), ns);
if (LIKELY(!(twodlevel || (player->mo->flags2 & MF2_TWOD))))
if (!twodmo(player->mo))
mo->momy = FixedMul(FINESINE(fa),ns);
P_SetObjectMomZ(mo, 3*FRACUNIT, false);
@@ -2922,7 +2930,7 @@ void P_PlayerEmeraldBurst(player_t *player, boolean toss)
momx = FixedMul(FINECOSINE(fa), ns);
if (LIKELY(!(twodlevel || (player->mo->flags2 & MF2_TWOD))))
if (!twodmo(player->mo))
momy = FixedMul(FINESINE(fa),ns);
else
momy = 0;
@@ -2979,7 +2987,7 @@ void P_PlayerFlagBurst(player_t *player, boolean toss)
{
angle_t fa = P_RandomByte()*FINEANGLES/256;
flag->momx = FixedMul(FINECOSINE(fa), FixedMul(6*FRACUNIT, player->mo->scale));
if (LIKELY(!(twodlevel || (player->mo->flags2 & MF2_TWOD))))
if (!twodmo(player->mo))
flag->momy = FixedMul(FINESINE(fa), FixedMul(6*FRACUNIT, player->mo->scale));
}
+17 -2
View File
@@ -59,8 +59,12 @@ extern "C" {
#define AIMINGTOSLOPE(aiming) FINESINE((aiming>>ANGLETOFINESHIFT) & FINEMASK)
#define mariomode (maptol & TOL_MARIO)
#define twodlevel (maptol & TOL_2D)
// unused modes, kept for compat
#define nightsmode (UNLIKELY(maptol & TOL_NIGHTS))
#define nightsplayer(player) (UNLIKELY((player)->pflags & PF_NIGHTSMODE))
#define mariomode (UNLIKELY(maptol & TOL_MARIO))
#define twodlevel (UNLIKELY(maptol & TOL_2D))
#define twodmo(mobj) (UNLIKELY(twodlevel || ((mobj)->flags2 & MF2_TWOD)))
//
// P_TICK
@@ -287,6 +291,17 @@ FUNCINLINE static ATTRINLINE boolean P_MobjWasRemoved(const mobj_t *mobj)
return (!mobj || mobj->thinker.function != (actionf_p1)P_MobjThinker);
}
// stupid, but kart allows mobjs that are marked to be removed to be accessed and modified in many cases
// so can only check if its not NULL in vanilla compat mode
FUNCINLINE static ATTRINLINE boolean P_MobjWasRemovedCompat(const mobj_t *mobj)
{
#ifdef COMPAT_VANILLA
return (!mobj);
#else
return P_MobjWasRemoved(mobj);
#endif
}
fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect);
fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect);
#define P_GetFloorZ(mobj, sector, x, y, line) P_MobjFloorZ(mobj, sector, NULL, x, y, line, false, false)
+133 -34
View File
@@ -136,14 +136,17 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
if (object->eflags & MFE_SPRUNG) // Object was already sprung this tic
return false;
// Spectators don't trigger springs.
if (object->player && object->player->spectator)
return false;
if (UNLIKELY(object->player && (object->player->pflags & PF_NIGHTSMODE)))
if (object->player)
{
/*Someone want to make these work like bumpers?*/
return false;
// Spectators don't trigger springs.
if (object->player->spectator)
return false;
if (nightsplayer(object->player))
{
/*Someone want to make these work like bumpers?*/
return false;
}
}
object->standingslope = NULL; // Okay, now we can't return - no launching off at silly angles for you.
@@ -160,10 +163,15 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
if (spring->eflags & MFE_VERTICALFLIP)
vertispeed *= -1;
// Vertical springs teleport you on TOP of them.
if (vertispeed > 0)
{
object->z = spring->z + spring->height + 1;
}
else if (vertispeed < 0)
{
object->z = spring->z - object->height - 1;
}
else
{
// Horizontal springs teleport you in FRONT of them.
@@ -215,7 +223,9 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
if (object->player)
{
if (spring->flags & MF_ENEMY) // Spring shells
{
P_SetTarget(&spring->target, object);
}
if (horizspeed && object->player->cmd.forwardmove == 0 && object->player->cmd.sidemove == 0)
{
@@ -312,13 +322,13 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing == tmthing)
return true;
// Ignore... things.
if (!tmthing || P_MobjWasRemoved(thing))
return true;
I_Assert(!P_MobjWasRemoved(tmthing));
I_Assert(!P_MobjWasRemoved(thing));
// Ignore... things.
if (P_MobjWasRemovedCompat(tmthing) || P_MobjWasRemoved(thing))
return true;
// Ignore spectators
if ((tmthing->player && tmthing->player->spectator)
|| (thing->player && thing->player->spectator))
@@ -350,12 +360,13 @@ static boolean PIT_CheckThing(mobj_t *thing)
}
#endif
if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_PAIN|MF_SHOOTABLE)) || (thing->flags & MF_NOCLIPTHING))
if ((thing->flags & MF_NOCLIPTHING) || !(thing->flags & (MF_SOLID|MF_SPECIAL|MF_PAIN|MF_SHOOTABLE)))
return true;
// Don't collide with your buddies while NiGHTS-flying.
if (UNLIKELY(tmthing->player && thing->player && (maptol & TOL_NIGHTS)
&& ((tmthing->player->pflags & PF_NIGHTSMODE) || (thing->player->pflags & PF_NIGHTSMODE))))
if (nightsmode &&
tmthing->player && thing->player &&
(nightsplayer(tmthing->player) || nightsplayer(thing->player)))
return true;
blockdist = thing->radius + tmthing->radius;
@@ -719,11 +730,11 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->type != MT_PLAYER)
return true;
if (thing->player && thing->player->powers[pw_flashing])
return true;
if (thing->type == MT_PLAYER && thing->player)
if (thing->player)
{
if (thing->player->powers[pw_flashing])
return true;
if (tmthing->state == &states[S_MINEEXPLOSION1])
K_ExplodePlayer(thing->player, tmthing->target, tmthing);
else
@@ -1077,6 +1088,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
thing->momy -= FixedMul(PUSHACCEL, thing->scale);
tmthing->momy += FixedMul(PUSHACCEL, thing->scale);
}
if (tmthing->momx > 0 && tmthing->momx > FixedMul(4*FRACUNIT, thing->scale)
&& tmthing->momx > thing->momx)
{
@@ -1094,6 +1106,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
thing->momx = FixedMul(thing->info->speed, thing->scale);
else if (thing->momx < -FixedMul(thing->info->speed, thing->scale))
thing->momx = -FixedMul(thing->info->speed, thing->scale);
if (thing->momy > FixedMul(thing->info->speed, thing->scale))
thing->momy = FixedMul(thing->info->speed, thing->scale);
else if (thing->momy < -FixedMul(thing->info->speed, thing->scale))
@@ -1105,6 +1118,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
tmthing->momx = FixedMul(4*FRACUNIT, thing->scale);
else if (tmthing->momx < FixedMul(-4*FRACUNIT, thing->scale))
tmthing->momx = FixedMul(-4*FRACUNIT, thing->scale);
if (tmthing->momy > FixedMul(4*FRACUNIT, thing->scale))
tmthing->momy = FixedMul(4*FRACUNIT, thing->scale);
else if (tmthing->momy < FixedMul(-4*FRACUNIT, thing->scale))
@@ -1126,6 +1140,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
P_TouchSpecialThing(thing, tmthing, true); // can remove thing
return true;
}
// check again for special pickup
if (tmthing->flags & MF_SPECIAL && thing->player)
{
@@ -1813,14 +1828,14 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
delta1 = abs(thing->z - midheight);
delta2 = abs(thingtop - midheight);
if (topheight > tmfloorz && delta1 < delta2
if ((topheight > tmfloorz) && (delta1 < delta2)
&& !(rover->flags & FF_REVERSEPLATFORM))
{
tmfloorz = tmdropoffz = topheight;
tmfloorslope = *rover->t_slope;
}
if (bottomheight < tmceilingz && delta1 >= delta2
if ((bottomheight < tmceilingz) && (delta1 >= delta2)
&& !(rover->flags & FF_PLATFORM)
&& !(thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE)))
{
@@ -1875,8 +1890,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
po->validcount = validcount;
if (!P_BBoxInsidePolyobj(po, tmbbox)
|| !(po->flags & POF_SOLID))
if (!(po->flags & POF_SOLID) || !P_BBoxInsidePolyobj(po, tmbbox))
{
plink = (polymaplink_t *)(plink->link.next);
continue;
@@ -2121,7 +2135,7 @@ static boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam)
po->validcount = validcount;
if (!P_PointInsidePolyobj(po, x, y) || !(po->flags & POF_SOLID))
if (!(po->flags & POF_SOLID) || !P_PointInsidePolyobj(po, x, y))
{
plink = (polymaplink_t *)(plink->link.next);
continue;
@@ -2371,8 +2385,10 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
fixed_t tryx = thing->x;
fixed_t tryy = thing->y;
fixed_t radius = thing->radius;
fixed_t thingtop ;//= thing->z + thing->height;
fixed_t thingtop;//= thing->z + thing->height;
fixed_t startingonground = P_IsObjectOnGround(thing);
fixed_t stairjank = 0;
pslope_t *oldslope = thing->standingslope;
INT32 special = -1;
floatok = false;
@@ -2422,7 +2438,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
if (thing->player)
{
if (special == -1)
if (special == -1) // this should use the target coords not the ones were started with, but cant fix that for compat reasons!
special = GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1);
// If using type Section1:13, double the maxstep.
@@ -2446,11 +2462,19 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
thingtop = thing->z + thing->height;
const boolean flipped =
(thing->eflags & MFE_VERTICALFLIP) != 0;
// Step up
if (thing->z < tmfloorz)
{
if (tmfloorz - thing->z <= maxstep)
{
if (maxstep > 0 && !flipped)
{
stairjank = (tmfloorz - thing->z);
}
thing->z = thing->floorz = tmfloorz;
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
}
@@ -2463,6 +2487,11 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
{
if (thingtop - tmceilingz <= maxstep)
{
if (maxstep > 0 && flipped)
{
stairjank = (thingtop - tmceilingz);
}
thing->z = ( thing->ceilingz = tmceilingz ) - thing->height;
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
}
@@ -2479,11 +2508,21 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
if (thingtop == thing->ceilingz && tmceilingz > thingtop && tmceilingz - thingtop <= maxstep)
{
if (flipped)
{
stairjank = (tmceilingz - thingtop);
}
thing->z = (thing->ceilingz = tmceilingz) - thing->height;
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
}
else if (thing->z == thing->floorz && tmfloorz < thing->z && thing->z - tmfloorz <= maxstep)
{
if (!flipped)
{
stairjank = (thing->z - tmfloorz);
}
thing->z = thing->floorz = tmfloorz;
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
}
@@ -2559,6 +2598,26 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
else // don't set standingslope if you're not going to clip against it
thing->standingslope = NULL;
/* FIXME: slope step down (even up) has some false
positives, so just ignore them entirely. */
if (stairjank && !oldslope && !thing->standingslope && thing->player && !thing->player->spectator)
{
/* use a shorter sound if not two tics have passed
* since the last step */
//S_ReducedVFXSound(thing, (thing->player->stairjank >= 16 ? sfx_s23b : sfx_s268), NULL);
//S_StartSound(thing, (thing->player->stairjank >= 16 ? sfx_s23b : sfx_s268));
// sound does not work out all that well for kart maps
// best i can do...
if (cv_stairjank.value && cv_stairjanksfx.value)
S_StartSoundAtVolume(thing, (thing->player->stairjank >= 8 ? sfx_s23b : sfx_s268), 192); // dont blast this at full volume lul
// Can't spawn things during P_TryMove, because global variables :)
thing->player->stairjank = 9;
//thing->player->stairjank = 17;
}
thing->x = x;
thing->y = y;
@@ -2609,7 +2668,7 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y)
if (tmfloorz - thing->z > maxstep)
return false; // too big a step up
}
} while(tryx != x || tryy != y);
} while (tryx != x || tryy != y);
// the move is ok,
// so link the thing into its new position
@@ -3104,6 +3163,9 @@ void P_SlideMove(mobj_t *mo, boolean forceslide)
INT16 hitcount = 0;
boolean success = false;
if (P_MobjWasRemovedCompat(mo))
return;
if (tmhitthing && mo->z + mo->height > tmhitthing->z && mo->z < tmhitthing->z + tmhitthing->height)
{
// Don't mess with your momentum if it's a pushable object. Pushables do their own crazy things already.
@@ -3140,6 +3202,9 @@ void P_SlideMove(mobj_t *mo, boolean forceslide)
bestslideline = NULL;
retry:
if (P_MobjWasRemovedCompat(mo))
return;
if (++hitcount == 3)
goto stairstep; // don't loop forever
@@ -3188,7 +3253,13 @@ retry:
// the move must have hit the middle, so stairstep
stairstep:
if (!P_TryMove(mo, mo->x, mo->y + mo->momy, true)) //Allow things to drop off.
{
if (P_MobjWasRemovedCompat(mo))
return;
P_TryMove(mo, mo->x + mo->momx, mo->y, true);
}
return;
}
@@ -3200,7 +3271,12 @@ stairstep:
newy = FixedMul(mo->momy, bestslidefrac);
if (!P_TryMove(mo, mo->x + newx, mo->y + newy, true))
{
goto stairstep;
}
if (P_MobjWasRemovedCompat(mo))
return;
}
// Now continue along the wall.
@@ -3219,7 +3295,7 @@ stairstep:
if (bestslideline != NULL)
P_HitSlideLine(bestslideline); // clip the moves
if (UNLIKELY((twodlevel || (mo->flags2 & MF2_TWOD)) && mo->player))
if (twodmo(mo) && mo->player)
{
mo->momx = tmxmove;
tmymove = 0;
@@ -3271,8 +3347,11 @@ stairstep:
goto retry;
}
if (P_MobjWasRemovedCompat(mo))
return;
success = true;
} while(tmxmove || tmymove);
} while (tmxmove || tmymove);
}
//
@@ -3285,12 +3364,18 @@ void P_BouncePlayerMove(mobj_t *mo)
{
fixed_t leadx, leady;
fixed_t trailx, traily;
fixed_t mmomx = 0, mmomy = 0;
fixed_t oldmomx = mo->momx, oldmomy = mo->momy;
fixed_t mmomx, mmomy;
fixed_t oldmomx, oldmomy;
if (!mo->player)
if (P_MobjWasRemovedCompat(mo))
return;
if (mo->player == NULL)
return;
oldmomx = mo->momx;
oldmomy = mo->momy;
if (mo->player->spectator)
{
P_SlideMove(mo, true);
@@ -3379,6 +3464,9 @@ void P_BouncePlayerMove(mobj_t *mo)
if (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove, true))
{
if (P_MobjWasRemovedCompat(mo))
return;
P_TryMove(mo, mo->x - oldmomx, mo->y - oldmomy, true);
}
}
@@ -3396,6 +3484,9 @@ void P_BounceMove(mobj_t *mo)
INT32 hitcount;
fixed_t mmomx = 0, mmomy = 0;
if (P_MobjWasRemovedCompat(mo))
return;
if (mo->player)
{
P_BouncePlayerMove(mo);
@@ -3412,6 +3503,9 @@ void P_BounceMove(mobj_t *mo)
hitcount = 0;
retry:
if (P_MobjWasRemovedCompat(mo))
return;
if (++hitcount == 3)
goto bounceback; // don't loop forever
@@ -3470,7 +3564,12 @@ bounceback:
newy = FixedMul(mmomy, bestslidefrac);
if (!P_TryMove(mo, mo->x + newx, mo->y + newy, true))
{
if (P_MobjWasRemovedCompat(mo))
return;
goto bounceback;
}
}
// Now continue along the wall.
@@ -3667,7 +3766,7 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush)
delta1 = abs(thing->z - midheight);
delta2 = abs(thingtop - midheight);
if (bottomheight <= thing->ceilingz && delta1 >= delta2)
if ((bottomheight <= thing->ceilingz) && (delta1 >= delta2))
{
if (thing->flags & MF_PUSHABLE)
{
@@ -4125,7 +4224,7 @@ void P_CreateSecNodeList(mobj_t *thing, fixed_t x, fixed_t y)
* Must clear tmthing at tic end, as it might contain a pointer to a removed thinker, or the level might have ended/been ended and we clear the objects it was pointing too. Hopefully we don't need to carry this between tics for sync. */
void P_MapStart(void)
{
if (UNLIKELY(tmthing))
if (tmthing)
I_Error("P_MapStart: tmthing set!");
}
@@ -4177,7 +4276,7 @@ fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height)
delta1 = abs(z - midheight);
delta2 = abs(thingtop - midheight);
if (topheight > floorz && delta1 < delta2)
if ((topheight > floorz) && (delta1 < delta2))
floorz = topheight;
}
}
+29 -15
View File
@@ -326,7 +326,7 @@ void P_CameraLineOpening(line_t *linedef)
{
for (rover = front->ffloors; rover; rover = rover->next)
{
fixed_t topheight, bottomheight;
fixed_t topheight, bottomheight, midheight;
if (!(rover->flags & FF_BLOCKOTHERS) || !(rover->flags & FF_RENDERALL) || !(rover->flags & FF_EXISTS) || UNLIKELY(GETSECSPECIAL(rover->master->frontsector->special, 4) == 12))
continue;
@@ -334,8 +334,10 @@ void P_CameraLineOpening(line_t *linedef)
topheight = P_CameraGetFOFTopZ(mapcampointer, front, rover, tmx, tmy, linedef);
bottomheight = P_CameraGetFOFBottomZ(mapcampointer, front, rover, tmx, tmy, linedef);
delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2)));
delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
midheight = (bottomheight + ((topheight - bottomheight) / 2));
delta1 = abs(mapcampointer->z - midheight);
delta2 = abs(thingtop - midheight);
if (bottomheight < lowestceiling && delta1 >= delta2)
lowestceiling = bottomheight;
@@ -354,7 +356,7 @@ void P_CameraLineOpening(line_t *linedef)
{
for (rover = back->ffloors; rover; rover = rover->next)
{
fixed_t topheight, bottomheight;
fixed_t topheight, bottomheight, midheight;
if (!(rover->flags & FF_BLOCKOTHERS) || !(rover->flags & FF_RENDERALL) || !(rover->flags & FF_EXISTS) || UNLIKELY(GETSECSPECIAL(rover->master->frontsector->special, 4) == 12))
continue;
@@ -362,8 +364,10 @@ void P_CameraLineOpening(line_t *linedef)
topheight = P_CameraGetFOFTopZ(mapcampointer, back, rover, tmx, tmy, linedef);
bottomheight = P_CameraGetFOFBottomZ(mapcampointer, back, rover, tmx, tmy, linedef);
delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2)));
delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
midheight = (bottomheight + ((topheight - bottomheight) / 2));
delta1 = abs(mapcampointer->z - midheight);
delta2 = abs(thingtop - midheight);
if (bottomheight < lowestceiling && delta1 >= delta2)
lowestceiling = bottomheight;
@@ -524,7 +528,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
// Check for frontsector's fake floors
for (rover = front->ffloors; rover; rover = rover->next)
{
fixed_t topheight, bottomheight;
fixed_t topheight, bottomheight, midheight;
if (!(rover->flags & FF_EXISTS))
continue;
@@ -538,8 +542,10 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
topheight = P_GetFOFTopZ(mobj, front, rover, tmx, tmy, linedef);
bottomheight = P_GetFOFBottomZ(mobj, front, rover, tmx, tmy, linedef);
delta1 = abs(mobj->z - (bottomheight + ((topheight - bottomheight)/2)));
delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
midheight = (bottomheight + ((topheight - bottomheight) / 2));
delta1 = abs(mobj->z - midheight);
delta2 = abs(thingtop - midheight);
if (delta1 >= delta2 && !(rover->flags & FF_PLATFORM)) // thing is below FOF
{
@@ -567,7 +573,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
// Check for backsectors fake floors
for (rover = back->ffloors; rover; rover = rover->next)
{
fixed_t topheight, bottomheight;
fixed_t topheight, bottomheight, midheight;
if (!(rover->flags & FF_EXISTS))
continue;
@@ -580,8 +586,10 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
topheight = P_GetFOFTopZ(mobj, back, rover, tmx, tmy, linedef);
bottomheight = P_GetFOFBottomZ(mobj, back, rover, tmx, tmy, linedef);
delta1 = abs(mobj->z - (bottomheight + ((topheight - bottomheight)/2)));
delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
midheight = (bottomheight + ((topheight - bottomheight) / 2));
delta1 = abs(mobj->z - midheight);
delta2 = abs(thingtop - midheight);
if (delta1 >= delta2 && !(rover->flags & FF_PLATFORM)) // thing is below FOF
{
@@ -611,8 +619,10 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
{
const sector_t *polysec = linedef->backsector;
delta1 = abs(mobj->z - (polysec->floorheight + ((polysec->ceilingheight - polysec->floorheight)/2)));
delta2 = abs(thingtop - (polysec->floorheight + ((polysec->ceilingheight - polysec->floorheight)/2)));
const fixed_t polymid = (polysec->floorheight + ((polysec->ceilingheight - polysec->floorheight) / 2));
delta1 = abs(mobj->z - polymid);
delta2 = abs(thingtop - polymid);
if (polysec->floorheight < lowestceiling && delta1 >= delta2)
{
@@ -620,7 +630,9 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
ceilingslope = NULL;
}
else if (polysec->floorheight < highestceiling && delta1 >= delta2)
{
highestceiling = polysec->floorheight;
}
if (polysec->ceilingheight > highestfloor && delta1 < delta2)
{
@@ -628,7 +640,9 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
floorslope = NULL;
}
else if (polysec->ceilingheight > lowestfloor && delta1 < delta2)
{
lowestfloor = polysec->ceilingheight;
}
}
if (highestceiling < highceiling)
@@ -842,7 +856,7 @@ void P_SetThingPosition(mobj_t *thing)
// at sector_t->touching_thinglist) are broken. When a node is
// added, new sector links are created.
P_CreateSecNodeList(thing,thing->x,thing->y);
P_CreateSecNodeList(thing, thing->x, thing->y);
thing->touching_sectorlist = sector_list; // Attach to Thing's mobj_t
sector_list = NULL; // clear for next time
}
+595 -495
View File
File diff suppressed because it is too large. Load diff
+1
View File
@@ -298,6 +298,7 @@ typedef struct mobj_s
angle_t angle, pitch, roll; // orientation
angle_t old_angle, old_pitch, old_roll; // orientation interpolation
angle_t rollangle;
angle_t temprollangle; // same as rollangle but resets each tic, idk either man. // cba exposing this to lua either
spritenum_t sprite; // used to find patch_t and flip value
UINT32 frame; // frame number, plus bits see p_pspr.h
UINT16 anim_duration; // for FF_ANIMATE states
+2 -2
View File
@@ -3059,7 +3059,7 @@ static void P_NetUnArchiveThinkers(savebuffer_t *save)
break;
default:
I_Error("P_UnarchiveSpecials: Unknown tclass %d in savegame", tclass);
I_Error("P_NetUnArchiveThinkers: Unknown tclass %d in savegame", tclass);
}
}
@@ -3170,7 +3170,7 @@ FUNCINLINE static ATTRINLINE void P_UnArchivePolyObjects(savebuffer_t *save)
numSavedPolys = READINT32(save->p);
if (numSavedPolys != numPolyObjects)
I_Error("P_UnArchivePolyObjects: polyobj count inconsistency\n");
I_Error("P_UnArchivePolyObjects: polyobj count inconsistency (expected %d, got %d)\n", numPolyObjects, numSavedPolys);
for (i = 0; i < numSavedPolys; ++i)
P_UnArchivePolyObj(save, &PolyObjects[i]);
+251 -172
View File
@@ -117,6 +117,7 @@ line_t *spawnlines = NULL;
side_t *spawnsides = NULL;
INT32 numstarposts = 0;
boolean levelloading = false;
UINT8 levelfadecol = 120;
virtres_t *curmapvirt = NULL;
@@ -456,10 +457,10 @@ static void P_SetupDirectionalLight(void)
if (gamemap != oldmap || encoremode != oldencore || reinitmaplight)
{
lighting->light_contrast = M_RandomRange(0, 58);
lighting->light_contrast = (UINT8)M_RandomRange(0, 58);
lighting->sprite_backlight = 0;
lighting->use_light_angle = M_RandomRange(0, 1); // either on or off
lighting->light_angle = M_RandomRange(-382, 382);
lighting->use_light_angle = (boolean)M_RandomRange(0, 1); // either on or off
lighting->light_angle = (angle_t)M_RandomRange(-382, 382);
reinitmaplight = false;
}
@@ -920,7 +921,48 @@ static void P_LoadThings(UINT8 *data)
}
}
static void P_SpawnMapThings(void)
static void P_SpawnEmeraldHunt(void)
{
INT32 i;
INT32 emer[3] = {0, 0, 0};
INT32 timeout = 0; // keeps from getting stuck
fixed_t x, y, z;
// increment spawn numbers because zero is valid.
emer[0] = (P_RandomKey(numhuntemeralds)) + 1;
while (timeout++ < 100)
{
emer[1] = (P_RandomKey(numhuntemeralds)) + 1;
if (emer[1] != emer[0])
break;
}
timeout = 0;
while (timeout++ < 100)
{
emer[2] = (P_RandomKey(numhuntemeralds)) + 1;
if (emer[2] != emer[1] && emer[2] != emer[0])
break;
}
for (i = 0; i < 3; i++)
{
if (!emer[i])
continue;
// decrement spawn values to the actual number because zero is valid.
x = huntemeralds[emer[i] - 1]->x<<FRACBITS;
y = huntemeralds[emer[i] - 1]->y<<FRACBITS;
z = huntemeralds[emer[i] - 1]->z<<FRACBITS;
// spawn emerald
P_SpawnMobj(x, y, z, MT_EMERHUNT);
}
}
static void P_SpawnMapThings(boolean spawnhoops)
{
size_t i;
mapthing_t *mt;
@@ -930,97 +972,68 @@ static void P_SpawnMapThings(void)
// Spawn axis points first so they are at the front of the list for fast searching.
for (i = 0, mt = mapthings; i < nummapthings; i++, mt++)
{
switch (mt->type)
if (mt->type == 1700 || // MT_AXIS
mt->type == 1701 || // MT_AXISTRANSFER
mt->type == 1702) // MT_AXISTRANSFERLINE
{
case 1700: // MT_AXIS
case 1701: // MT_AXISTRANSFER
case 1702: // MT_AXISTRANSFERLINE
mt->mobj = NULL;
P_SpawnMapThing(mt);
break;
default:
break;
mt->mobj = NULL;
P_SpawnMapThing(mt);
}
}
for (i = 0, mt = mapthings; i < nummapthings; i++, mt++)
{
sector_t *mtsector = R_PointInSubsector((mt->x << FRACBITS), (mt->y << FRACBITS))->sector;
sector_t *mtsector;
// srb2kart - ignore rings, coins and item patterns!
if (mt->type == 300 || mt->type == 308 || mt->type == 309 ||
(mt->type >= 600 && mt->type <= 609) ||
mt->type == 1706 || mt->type == 1800)
{
mt->mobj = NULL;
continue;
}
mtsector = R_PointInSubsector((mt->x << FRACBITS), (mt->y << FRACBITS))->sector;
// Z for objects
mt->z = (INT16)(P_GetSectorFloorZAt(mtsector, (mt->x << FRACBITS), (mt->y << FRACBITS))) >> FRACBITS;
if (mt->type == 1700 // MT_AXIS
|| mt->type == 1701 // MT_AXISTRANSFER
|| mt->type == 1702) // MT_AXISTRANSFERLINE
if (mt->type == 1700 || // MT_AXIS
mt->type == 1701 || // MT_AXISTRANSFER
mt->type == 1702) // MT_AXISTRANSFERLINE
{
continue; // These were already spawned
}
mt->mobj = NULL;
// spawn hoops
if (mt->type == 1705 || mt->type == 1713)
{
// Check for spawnhoops here so the hoops don't spawn ghost variants for players joining a netgame mid-level
// ...It's a long story.
if (spawnhoops)
{
// Z for objects Tails 05-26-2002
mt->z = (INT16)(mtsector->floorheight >> FRACBITS);
P_SpawnHoops(mt);
}
continue;
}
if (mt->type == mobjinfo[MT_RANDOMITEM].doomednum)
nummapboxes++;
mt->mobj = NULL;
// Everything else
P_SpawnMapThing(mt);
}
// random emeralds for hunt
if (numhuntemeralds)
{
INT32 emer1, emer2, emer3;
INT32 timeout = 0; // keeps from getting stuck
emer1 = emer2 = emer3 = 0;
//increment spawn numbers because zero is valid.
emer1 = (P_RandomKey(numhuntemeralds)) + 1;
while (timeout++ < 100)
{
emer2 = (P_RandomKey(numhuntemeralds)) + 1;
if (emer2 != emer1)
break;
}
timeout = 0;
while (timeout++ < 100)
{
emer3 = (P_RandomKey(numhuntemeralds)) + 1;
if (emer3 != emer2 && emer3 != emer1)
break;
}
//decrement spawn values to the actual number because zero is valid.
if (emer1)
P_SpawnMobj(huntemeralds[emer1 - 1]->x<<FRACBITS,
huntemeralds[emer1 - 1]->y<<FRACBITS,
huntemeralds[emer1 - 1]->z<<FRACBITS, MT_EMERHUNT);
if (emer2)
P_SpawnMobj(huntemeralds[emer2 - 1]->x<<FRACBITS,
huntemeralds[emer2 - 1]->y<<FRACBITS,
huntemeralds[emer2 - 1]->z<<FRACBITS, MT_EMERHUNT);
if (emer3)
P_SpawnMobj(huntemeralds[emer3 - 1]->x<<FRACBITS,
huntemeralds[emer3 - 1]->y<<FRACBITS,
huntemeralds[emer3 - 1]->z<<FRACBITS, MT_EMERHUNT);
}
// Run through the list of mapthings again to spawn hoops and rings
for (i = 0, mt = mapthings; i < nummapthings; i++, mt++)
{
if (mt->type == 300 || mt->type == 308 || mt->type == 309
|| mt->type == 1706 || (mt->type >= 600 && mt->type <= 609)
|| mt->type == 1705 || mt->type == 1713 || mt->type == 1800)
{
mt->mobj = NULL;
// Z for objects Tails 05-26-2002
mt->z = (INT16)(R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)->sector->floorheight>>FRACBITS);
P_SpawnHoops(mt);
}
}
P_SpawnEmeraldHunt();
}
static void P_SpawnEmblems(boolean loademblems)
@@ -1034,22 +1047,22 @@ static void P_SpawnEmblems(boolean loademblems)
for (i = 0; i < numemblems; i++)
{
if (emblemlocations[i].level != gamemap || emblemlocations[i].type > ET_SKIN)
const emblem_t *emblemlocation = &emblemlocations[i];
if (emblemlocation->level != gamemap || emblemlocation->type > ET_SKIN)
continue;
emblemmobj = P_SpawnMobj(emblemlocations[i].x<<FRACBITS, emblemlocations[i].y<<FRACBITS,
emblemlocations[i].z<<FRACBITS, MT_EMBLEM);
emblemmobj = P_SpawnMobj(emblemlocation->x<<FRACBITS, emblemlocation->y<<FRACBITS, emblemlocation->z<<FRACBITS, MT_EMBLEM);
I_Assert(emblemlocations[i].sprite >= 'A' && emblemlocations[i].sprite <= 'Z');
P_SetMobjStateNF(emblemmobj, emblemmobj->info->spawnstate + (emblemlocations[i].sprite - 'A'));
I_Assert(emblemlocation->sprite >= 'A' && emblemlocation->sprite <= 'Z');
P_SetMobjStateNF(emblemmobj, emblemmobj->info->spawnstate + (emblemlocation->sprite - 'A'));
emblemmobj->health = i+1;
color = M_GetEmblemColor(&emblemlocations[i]);
emblemmobj->color = (UINT8)color;
if (emblemlocations[i].collected
|| (emblemlocations[i].type == ET_SKIN && emblemlocations[i].var != players[0].skin))
if (emblemlocation->collected || (emblemlocation->type == ET_SKIN && emblemlocation->var != players[0].skin))
{
P_UnsetThingPosition(emblemmobj);
emblemmobj->flags |= MF_NOCLIP;
@@ -2559,6 +2572,31 @@ static void P_LoadRecordGhosts(void)
free(gpath);
}
static void P_ResetSpawnpoints(void)
{
UINT8 i;
numdmstarts = numredctfstarts = numbluectfstarts = 0;
// reset the player starts
for (i = 0; i < MAXPLAYERS; i++)
{
playerstarts[i] = NULL;
redctfstarts[i] = NULL;
bluectfstarts[i] = NULL;
}
for (i = 0; i < MAX_DM_STARTS; i++)
{
deathmatchstarts[i] = NULL;
}
for (i = 0; i < 2; i++)
{
skyboxmo[i] = NULL;
}
}
static void P_InitCamera(void)
{
INT32 i;
@@ -2568,6 +2606,7 @@ static void P_InitCamera(void)
for (i = 0; i <= splitscreen; i++)
{
camera[i].postimg = 0;
P_SetupCamera(&camera[i]);
}
@@ -2667,10 +2706,14 @@ static boolean P_RunSpecialWipe(boolean reloadinggamestate)
{
// Cancel all d_main.c fadeouts (keep fade in though).
if (reloadinggamestate)
{
wipegamestate = gamestate; // Don't fade if reloading the gamestate
return false;
}
// Encore mode fade to pink to white
// This is handled BEFORE sounds are stopped.
else if (encoremode && !prevencoremode && !demo.rewinding)
if (encoremode && !prevencoremode && !demo.rewinding)
{
tic_t locstarttime, endtime, nowtime;
@@ -2704,6 +2747,8 @@ static boolean P_RunSpecialWipe(boolean reloadinggamestate)
// Hold on white for extra effect.
while (nowtime < endtime)
{
I_HandleInterrupt();
// wait loop
while (!((nowtime = I_GetTime()) - lastwipetic))
{
@@ -2726,6 +2771,69 @@ static boolean P_RunSpecialWipe(boolean reloadinggamestate)
return false;
}
static void P_InitTagGametype(void)
{
UINT8 i;
INT32 realnumplayers = 0;
INT32 playersactive[MAXPLAYERS];
//I just realized how problematic this code can be.
//D_NumPlayers() will not always cover the scope of the netgame.
//What if one player is node 0 and the other node 31?
//The solution? Make a temp array of all players that are currently playing and pick from them.
//Future todo? When a player leaves, shift all nodes down so D_NumPlayers() can be used as intended?
//Also, you'd never have to loop through all 32 players slots to find anything ever again.
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && !players[i].spectator)
{
playersactive[realnumplayers] = i; //stores the player's node in the array.
realnumplayers++;
}
}
if (!realnumplayers) // this should also fix the dedicated crash bug. You only pick a player if one exists to be picked.
{
CONS_Printf(M_GetText("No player currently available to become IT. Awaiting available players.\n"));
return;
}
i = P_RandomKey(realnumplayers);
players[playersactive[i]].pflags |= PF_TAGIT; //choose our initial tagger before map starts.
// Taken and modified from G_DoReborn()
// Remove the player so he can respawn elsewhere.
// first dissasociate the corpse
if (players[playersactive[i]].mo)
P_RemoveMobj(players[playersactive[i]].mo);
G_SpawnPlayer(playersactive[i], false); //respawn the lucky player in his dedicated spawn location.
}
static void P_InitGametype(void)
{
if (modeattacking == ATTACKING_RECORD && !demo.playback)
P_LoadRecordGhosts();
if (G_RaceGametype() && server)
{
INT32 numLaps;
const mapheader_t *mapheader = mapheaderinfo[gamemap - 1];
if ((netgame || multiplayer) && cv_basenumlaps.value &&
(!(mapheader->levelflags & LF_SECTIONRACE) || (mapheader->numlaps > cv_basenumlaps.value)))
numLaps = cv_basenumlaps.value;
else
numLaps = mapheader->numlaps;
CV_StealthSetValue(&cv_numlaps, numLaps);
}
else if (G_TagGametype())
{
P_InitTagGametype();
}
}
static void P_SetupPlayer(void)
{
INT32 i;
@@ -2739,76 +2847,27 @@ static void P_SetupPlayer(void)
// Start players with pity shields if possible
players[i].pity = -1;
players[i].mo = NULL;
if (!G_RaceGametype())
{
players[i].mo = NULL;
G_DoReborn(i);
}
else // gametype is GT_COOP or GT_RACE
{
players[i].mo = NULL;
G_SpawnPlayer(i, (players[i].starposttime));
}
}
}
if (modeattacking == ATTACKING_RECORD && !demo.playback)
P_LoadRecordGhosts();
if (G_TagGametype())
{
INT32 realnumplayers = 0;
INT32 playersactive[MAXPLAYERS];
//I just realized how problematic this code can be.
//D_NumPlayers() will not always cover the scope of the netgame.
//What if one player is node 0 and the other node 31?
//The solution? Make a temp array of all players that are currently playing and pick from them.
//Future todo? When a player leaves, shift all nodes down so D_NumPlayers() can be used as intended?
//Also, you'd never have to loop through all 32 players slots to find anything ever again.
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && !players[i].spectator)
{
playersactive[realnumplayers] = i; //stores the player's node in the array.
realnumplayers++;
}
}
if (realnumplayers) // this should also fix the dedicated crash bug. You only pick a player if one exists to be picked.
{
i = P_RandomKey(realnumplayers);
players[playersactive[i]].pflags |= PF_TAGIT; //choose our initial tagger before map starts.
// Taken and modified from G_DoReborn()
// Remove the player so he can respawn elsewhere.
// first dissasociate the corpse
if (players[playersactive[i]].mo)
P_RemoveMobj(players[playersactive[i]].mo);
G_SpawnPlayer(playersactive[i], false); //respawn the lucky player in his dedicated spawn location.
}
else
CONS_Printf(M_GetText("No player currently available to become IT. Awaiting available players.\n"));
}
else if (G_RaceGametype() && server)
{
INT32 numLaps = ((netgame || multiplayer) && cv_basenumlaps.value
&& (!(mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE)
|| (mapheaderinfo[gamemap - 1]->numlaps > cv_basenumlaps.value)))
? cv_basenumlaps.value
: mapheaderinfo[gamemap - 1]->numlaps;
CV_StealthSetValue(&cv_numlaps, numLaps);
}
P_InitGametype();
// Start recording replay in multiplayer with a temp filename
// Ensure dedis only record a replay if there is a player at the start of the map, otherwise we get invalid replays!
if (!demo.playback && multiplayer && D_NumPlayers())
{
static char buf[256];
sprintf(buf, "replay"PATHSEP"online"PATHSEP"%d-%s", (int) (time(NULL)), G_BuildMapName(gamemap));
sprintf(buf, "replay"PATHSEP"online"PATHSEP"%d-%s", (int)(time(NULL)), G_BuildMapName(gamemap));
I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755);
I_mkdir(va("%s"PATHSEP"replay"PATHSEP"online", srb2home), 0755);
@@ -2912,7 +2971,7 @@ boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate)
INT32 i;
boolean ranspecialwipe = false;
lumpnum_t encoreLump = LUMPERROR;
UINT8 levelfadecol;
const mapheader_t *mapheader = mapheaderinfo[gamemap - 1];
midgamejoin = fromnetsave; // makes dynslopes run in P_Ticker to avoid synch issues and other stuff
@@ -2920,7 +2979,7 @@ boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate)
levelloading = true;
// This is needed. Don't touch.
maptol = mapheaderinfo[gamemap-1]->typeoflevel;
maptol = mapheader->typeoflevel;
CON_Drawer(); // let the user know what we are going to do
I_FinishUpdate(); // page flip or blit buffer
@@ -2931,17 +2990,17 @@ boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate)
// Clear CECHO messages
HU_ClearCEcho();
if (mapheaderinfo[gamemap-1]->runsoc[0] != '#')
P_RunSOC(mapheaderinfo[gamemap-1]->runsoc);
if (mapheader->runsoc[0] != '#')
P_RunSOC(mapheader->runsoc);
if (cv_runscripts.value && mapheaderinfo[gamemap-1]->scriptname[0] != '#')
P_RunLevelScript(mapheaderinfo[gamemap-1]->scriptname);
if (cv_runscripts.value && mapheader->scriptname[0] != '#')
P_RunLevelScript(mapheader->scriptname);
P_LevelInitStuff(reloadinggamestate);
if (mapheaderinfo[gamemap-1]->forcecharacter[0] != '\0'
&& atoi(mapheaderinfo[gamemap-1]->forcecharacter) != 255)
P_ForceCharacter(mapheaderinfo[gamemap-1]->forcecharacter);
if (mapheader->forcecharacter[0] != '\0'
&& atoi(mapheader->forcecharacter) != 255)
P_ForceCharacter(mapheader->forcecharacter);
// Initial height of PointOfView
// will be set by player think.
@@ -2991,10 +3050,10 @@ boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate)
char tx[64];
V_DrawSmallString(1, 191, V_ALLOWLOWERCASE, M_GetText("Speeding off to..."));
snprintf(tx, 63, "%s%s%s",
mapheaderinfo[gamemap-1]->lvlttl,
(strlen(mapheaderinfo[gamemap-1]->zonttl) > 0) ? va(" %s",mapheaderinfo[gamemap-1]->zonttl) : // SRB2kart
((mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE) ? "" : " Zone"),
(strlen(mapheaderinfo[gamemap-1]->actnum) > 0) ? va(", Act %s",mapheaderinfo[gamemap-1]->actnum) : "");
mapheader->lvlttl,
(strlen(mapheader->zonttl) > 0) ? va(" %s",mapheader->zonttl) : // SRB2kart
((mapheader->levelflags & LF_NOZONE) ? "" : " Zone"),
(strlen(mapheader->actnum) > 0) ? va(", Act %s",mapheader->actnum) : "");
V_DrawSmallString(1, 195, V_ALLOWLOWERCASE, tx);
I_UpdateNoVsync();
}*/
@@ -3013,20 +3072,16 @@ boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate)
curmapvirt = vres_GetMap(lastloadedmaplumpnum);
encoreLump = W_CheckNumForName(va("%s%c", maplumpname, (encoremode ? 'E' : 'T')));
R_ReInitColormaps(mapheaderinfo[gamemap-1]->palette, encoreLump);
R_ReInitColormaps(mapheader->palette, encoreLump);
CON_SetupBackColormap();
// SRB2 determines the sky texture to be used depending on the map header.
P_SetupLevelSky(mapheaderinfo[gamemap-1]->skynum, true);
P_SetupLevelSky(mapheader->skynum, true);
numdmstarts = numredctfstarts = numbluectfstarts = 0;
P_ResetSpawnpoints();
// reset the player starts
memset(playerstarts, 0, sizeof(playerstarts));
memset(skyboxmo, 0, sizeof(skyboxmo));
P_MapStart();
P_MapStart(); // tmthing can be used starting from this point
P_LoadMapFromFile();
@@ -3036,7 +3091,7 @@ boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate)
// a shit ton of time loading mobj thinkers.
CalculateDoomednumToMobjtype();
P_SpawnMapThings();
P_SpawnMapThings(!fromnetsave);
P_SpawnEmblems(!fromnetsave);
@@ -3046,7 +3101,7 @@ boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate)
if (!playerstarts[numcoopstarts])
break;
globalweather = mapheaderinfo[gamemap-1]->weather;
globalweather = mapheader->weather;
// set up world state
P_SpawnSpecials(fromnetsave, reloadinggamestate);
@@ -3093,7 +3148,7 @@ boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate)
// clear special respawning que
iquehead = iquetail = 0;
P_MapEnd();
P_MapEnd(); // tmthing is no longer needed from this point onwards
// Remove the loading shit from the screen
if (rendermode != render_none && !reloadinggamestate)
@@ -3124,9 +3179,15 @@ boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate)
savedata.lives = 0;
}
// assume the skybox is visible on level load.
skyVisible = true;
memset(skyVisiblePerPlayer, true, sizeof(skyVisiblePerPlayer));
if (!reloadinggamestate)
{
// assume the skybox is visible on level load.
skyVisible = true;
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
skyVisiblePerPlayer[i] = true;
}
}
if (!fromnetsave) // uglier hack
{ // to make a newly loaded level start on the second frame.
@@ -3146,14 +3207,18 @@ boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate)
LUA_HookInt(gamemap, HOOK(MapLoad));
}
if (rendermode != render_none && !reloadinggamestate)
// reloading gamestate, stop here.
if (reloadinggamestate)
return true;
G_AddMapToBuffer(gamemap-1);
if (rendermode != render_none)
{
R_ResetViewInterpolation(0);
R_UpdateMobjInterpolators();
}
G_AddMapToBuffer(gamemap-1);
G_ResetDeviceLED();
return true;
@@ -3334,6 +3399,17 @@ UINT16 P_PartialAddWadFile(const char *wadfilename, boolean local)
sreplaces = mreplaces = digmreplaces = 0;
if (local)
{
// check if someone tries to load maps locally lol
// do this here so we can skip loading the file anyways
if (W_CheckAutoLoadContainsMap(wadfilename))
{
CONS_Alert(CONS_WARNING, "addilelocal: locally added file %s contains map data, this WILL cause crashes and desynchs! not added.\n", wadfilename);
return UINT16_MAX;
}
}
if ((numlumps = W_InitFile(wadfilename, local, false)) == INT16_MAX)
{
refreshdirmenu |= REFRESHDIR_NOTLOADED;
@@ -3364,12 +3440,15 @@ UINT16 P_PartialAddWadFile(const char *wadfilename, boolean local)
allvotereplaced = true;
}
if (!devparm && sreplaces)
CONS_Printf(M_GetText("%s sounds replaced\n"), sizeu1(sreplaces));
if (!devparm && mreplaces)
CONS_Printf(M_GetText("%s midi musics ignored\n"), sizeu1(mreplaces));
if (!devparm && digmreplaces)
CONS_Printf(M_GetText("%s digital musics replaced\n"), sizeu1(digmreplaces));
if (!devparm)
{
if (sreplaces)
CONS_Printf(M_GetText("%s sounds replaced\n"), sizeu1(sreplaces));
if (mreplaces)
CONS_Printf(M_GetText("%s midi musics ignored\n"), sizeu1(mreplaces));
if (digmreplaces)
CONS_Printf(M_GetText("%s digital musics replaced\n"), sizeu1(digmreplaces));
}
if (!mapsadded)
CONS_Printf(M_GetText("No maps added\n"));
+1
View File
@@ -35,6 +35,7 @@ extern mapthing_t *deathmatchstarts[MAX_DM_STARTS];
extern INT32 numdmstarts, numcoopstarts, numredctfstarts, numbluectfstarts;
extern boolean levelloading;
extern UINT8 levelfadecol;
extern lumpnum_t lastloadedmaplumpnum; // for comparative savegame
extern virtres_t *curmapvirt;
+5
View File
@@ -901,6 +901,11 @@ void P_SlopeLaunch(mobj_t *mo)
//CONS_Printf("Launched off of slope.\n");
mo->standingslope = NULL;
if (mo->player)
{
mo->player->stairjank = 0; // fuck you
}
}
// Function to help handle landing on slopes
+24 -7
View File
@@ -538,6 +538,7 @@ static sector_t *getNextSector(line_t *line, sector_t *sec)
else
return NULL;
}
return line->frontsector;
}
@@ -568,6 +569,7 @@ fixed_t P_FindLowestFloorSurrounding(sector_t *sec)
if (other->floorheight < floorh)
floorh = other->floorheight;
}
return floorh;
}
@@ -1180,7 +1182,7 @@ INT32 P_FindMinSurroundingLight(sector_t *sector, INT32 max)
for (i = 0; i < sector->linecount; i++)
{
line = sector->lines[i];
check = getNextSector(line,sector);
check = getNextSector(line, sector);
if (!check)
continue;
@@ -2098,7 +2100,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
ffloor_t *rover;
boolean foundit = false;
for(rover = mo->subsector->sector->ffloors; rover; rover = rover->next)
for (rover = mo->subsector->sector->ffloors; rover; rover = rover->next)
{
if (rover->master->frontsector->tag != line->tag)
continue;
@@ -2988,10 +2990,10 @@ sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 n
{
fixed_t topheight, bottomheight;
if (GETSECSPECIAL(rover->master->frontsector->special, section) != number)
if (!(rover->flags & FF_EXISTS))
continue;
if (!(rover->flags & FF_EXISTS))
if (GETSECSPECIAL(rover->master->frontsector->special, section) != number)
continue;
topheight = P_GetSpecialTopZ(player->mo, sectors + rover->secnum, player->mo->subsector->sector);
@@ -3878,7 +3880,7 @@ DoneSection2:
player->kartstuff[k_lapanimation] = 80;
if (UNLIKELY(player->pflags & PF_NIGHTSMODE))
if (nightsplayer(player))
player->drillmeter += 48*20;
if (netgame && player->laps >= (UINT8)cv_numlaps.value)
@@ -4609,11 +4611,13 @@ void P_UpdateSpecials(void)
// POINT LIMIT
P_CheckPointLimit();
#ifdef COMPAT_VANILLA
// Dynamic slopeness
// we run this here only when not joined midrace
// for vanilla compat reasons :chaosleep:
if (!midgamejoin)
P_RunDynamicSlopes();
#endif
P_UpdateAnimFlats();
}
@@ -5298,6 +5302,18 @@ static void P_RunLevelLoadExecutors(void)
}
}
static fixed_t P_GetSectorGravityFactor(sector_t *sec)
{
return FixedDiv(*sec->gravity >> FRACBITS, 1000);
}
fixed_t P_GetSectorGravity(sector_t *sec)
{
if (sec && sec->gravity)
return FixedMul(gravity, P_GetSectorGravityFactor(sec));
return gravity;
}
/** After the map has loaded, scans for specials that spawn 3Dfloors and
* thinkers.
*
@@ -5484,6 +5500,7 @@ void P_SpawnSpecials(INT32 fromnetsave, boolean reloadinggamestate)
if ((lines[i].flags & (ML_NOSONIC|ML_NOTAILS)) != (ML_NOSONIC|ML_NOTAILS)) // If you can do something...
{
angle_t flatangle = InvAngle(lines[i].angle);
fixed_t xoffs;
fixed_t yoffs;
@@ -7121,7 +7138,7 @@ static inline boolean PIT_PushThing(mobj_t *thing)
return false;
// Allow this to affect pushable objects at some point?
if (thing->player && (!(thing->flags & (MF_NOGRAVITY | MF_NOCLIP)) || UNLIKELY(thing->player->pflags & PF_NIGHTSMODE)))
if (thing->player && (!(thing->flags & (MF_NOGRAVITY | MF_NOCLIP)) || nightsplayer(thing->player)))
{
INT32 dist;
INT32 speed;
@@ -7151,7 +7168,7 @@ static inline boolean PIT_PushThing(mobj_t *thing)
// Written with bits and pieces of P_HomingAttack
if ((speed > 0) && (P_CheckSight(thing, tmpusher->source)))
{
if (LIKELY(!(thing->player->pflags & PF_NIGHTSMODE)))
if (!nightsplayer(thing->player))
{
// only push wrt Z if health & 1 (mapthing has ambush flag)
if (tmpusher->source->health & 1)
+2
View File
@@ -56,6 +56,8 @@ sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 n
void P_PlayerInSpecialSector(player_t *player);
void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *roversector);
fixed_t P_GetSectorGravity(sector_t *sec);
fixed_t P_FindLowestFloorSurrounding(sector_t *sec);
fixed_t P_FindHighestFloorSurrounding(sector_t *sec);
+2
View File
@@ -646,7 +646,9 @@ void P_Ticker(boolean run)
if (run)
{
// Dynamic slopeness
#ifdef COMPAT_VANILLA
if (midgamejoin) // only run here if we joined midgame to fix some desynchs
#endif
P_RunDynamicSlopes();
PS_START_TIMING(ps_thinkertime);
+20 -14
View File
@@ -74,7 +74,7 @@ void P_Thrust(mobj_t *mo, angle_t angle, fixed_t move)
mo->momx += FixedMul(move, FINECOSINE(angle));
if (LIKELY(!(twodlevel || (mo->flags2 & MF2_TWOD))))
if (!twodmo(mo))
mo->momy += FixedMul(move, FINESINE(angle));
}
@@ -90,7 +90,7 @@ void P_InstaThrust(mobj_t *mo, angle_t angle, fixed_t move)
mo->momx = FixedMul(move, FINECOSINE(angle));
if (LIKELY(!(twodlevel || (mo->flags2 & MF2_TWOD))))
if (!twodmo(mo))
mo->momy = FixedMul(move,FINESINE(angle));
}
@@ -475,7 +475,7 @@ void P_PlayLivesJingle(player_t *player)
if (UNLIKELY(use1upSound))
S_StartSound(NULL, sfx_oneup);
else if (UNLIKELY(mariomode))
else if (mariomode)
S_StartSound(NULL, sfx_marioa);
else
{
@@ -503,7 +503,7 @@ void P_PlayRinglossSound(mobj_t *source, mobj_t *damager)
S_StartSound(NULL, sfx);
}
else
S_StartSound(source, UNLIKELY(mariomode) ? sfx_mario8 : sfx_khurt1 + key);
S_StartSound(source, mariomode ? sfx_mario8 : sfx_khurt1 + key);
}
else
S_StartSound(source, sfx_slip);
@@ -1206,6 +1206,7 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj)
ghost->pitch = mobj->pitch;
ghost->roll = mobj->roll;
ghost->rollangle = mobj->rollangle;
ghost->temprollangle = mobj->temprollangle;
ghost->sloperoll = mobj->sloperoll;
ghost->slopepitch = mobj->slopepitch;
@@ -1724,7 +1725,7 @@ static void P_DoBubbleBreath(player_t *player)
else
zh = player->mo->z + FixedDiv(player->mo->height,5*(FRACUNIT/4));
if (!(player->mo->eflags & MFE_UNDERWATER) || player->spectator || ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL && !(player->pflags & PF_NIGHTSMODE)))
if (!(player->mo->eflags & MFE_UNDERWATER) || player->spectator || ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL && !nightsplayer(player)))
return;
if (P_RandomChance(FRACUNIT/16))
@@ -2297,7 +2298,7 @@ static void P_MovePlayer(player_t *player)
P_3dMovement(player);
}
if (UNLIKELY(maptol & TOL_2D)) // psure this doesent even work at all
if (twodlevel) // psure this doesent even work at all
runspd = FixedMul(runspd, 2*FRACUNIT/3);
/////////////////////////
@@ -2747,8 +2748,8 @@ boolean P_LookForEnemies(player_t *player)
if (modist > FixedMul(RING_DIST, player->mo->scale))
continue; // out of range
if (UNLIKELY((twodlevel || player->mo->flags2 & MF2_TWOD)
&& abs(player->mo->y-mo->y) > player->mo->radius))
if (twodmo(player->mo) && abs(player->mo->y-mo->y) > player->mo->radius)
continue; // not in your 2d plane
if (closestmo && modist > P_AproxDistance(P_AproxDistance(player->mo->x-closestmo->x,
@@ -3507,7 +3508,7 @@ static boolean P_CheckNoclipCameraPosition(player_t *player, camera_t *thiscam,
boolean cameranoclip;
mobj_t *mo = player->mo;
cameranoclip = ((player->pflags & (PF_NOCLIP|PF_NIGHTSMODE))
cameranoclip = (nightsplayer(player)
|| (mo->flags & (MF_NOCLIP|MF_NOCLIPHEIGHT)) // Noclipping player camera noclips too!!
|| (leveltime < introtime)); // Kart intro cam
@@ -4096,7 +4097,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
angle -= (angle - thiscam->pitch)/2;
}
if (player->playerstate != PST_DEAD && LIKELY(!((player->pflags & PF_NIGHTSMODE) && player->exiting)))
if (player->playerstate != PST_DEAD && !(nightsplayer(player) && player->exiting))
angle += (focusaiming < ANGLE_180 ? focusaiming/2 : InvAngle(InvAngle(focusaiming)/2)); // overcomplicated version of '((signed)focusaiming)/2;'
if (!camstill && !timeover) // Keep the view still...
@@ -4173,7 +4174,7 @@ boolean P_SpectatorJoinGame(player_t *player)
// Team changing in Team Match and CTF
// Pressing fire assigns you to a team that needs players if allowed.
// Partial code reproduction from p_tick.c autobalance code.
else if (UNLIKELY(G_GametypeHasTeams()))
else if (G_GametypeHasTeams())
{
INT32 changeto = 0;
INT32 z, numplayersred = 0, numplayersblue = 0;
@@ -4870,7 +4871,7 @@ void P_PlayerThink(player_t *player)
// Even if not NiGHTS, pull in nearby objects when walking around as John Q. Elliot.
if (UNLIKELY(!objectplacing && !((netgame || multiplayer) && player->spectator)
&& maptol & TOL_NIGHTS && (!(player->pflags & PF_NIGHTSMODE) || player->powers[pw_nights_helper])))
&& nightsmode && (!nightsplayer(player) || player->powers[pw_nights_helper])))
{
thinker_t *th;
mobj_t *mo2;
@@ -4972,7 +4973,7 @@ void P_PlayerThink(player_t *player)
#endif
// check for use
if (LIKELY(!(player->pflags & PF_NIGHTSMODE)))
if (!nightsplayer(player))
{
if (cmd->buttons & BT_BRAKE)
player->pflags |= PF_USEDOWN;
@@ -5089,6 +5090,11 @@ void P_PlayerThink(player_t *player)
player->squishdance.time = 0;
}
if (player->stairjank > 0)
{
player->stairjank--;
}
// Flash player after being hit.
if (!(player->kartstuff[k_hyudorotimer] // SRB2kart - fixes Hyudoro not flashing when it should.
|| player->kartstuff[k_growshrinktimer] > 0 // Grow doesn't flash either.
@@ -5158,7 +5164,7 @@ void P_PlayerAfterThink(player_t *player)
}
}
if (UNLIKELY(player->pflags & PF_NIGHTSMODE))
if (nightsplayer(player))
{
player->powers[pw_gravityboots] = 0;
}
+48 -14
View File
@@ -340,14 +340,18 @@ void R_InterpolateMobjState(mobj_t *mobj, fixed_t frac, interpmobjstate_t *out)
return;
}
out->x = R_LerpFixed(mobj->old_x, mobj->x, frac);
out->y = R_LerpFixed(mobj->old_y, mobj->y, frac);
out->z = R_LerpFixed(mobj->old_z, mobj->z, frac);
const boolean doreset = mobj->resetinterp && (mobj->type != MT_GHOST) && (mobj->type != MT_PLAYERRETICULE) && (mobj->type != MT_SHADOW);
out->x = doreset ? mobj->x : R_LerpFixed(mobj->old_x, mobj->x, frac);
out->y = doreset ? mobj->y : R_LerpFixed(mobj->old_y, mobj->y, frac);
out->z = doreset ? mobj->z : R_LerpFixed(mobj->old_z, mobj->z, frac);
out->scale = mobj->resetinterp ? mobj->scale : R_LerpFixed(mobj->old_scale, mobj->scale, frac);
out->spritexscale = mobj->resetinterp ? mobj->spritexscale : R_LerpFixed(mobj->old_spritexscale, mobj->spritexscale, frac);
out->spriteyscale = mobj->resetinterp ? mobj->spriteyscale : R_LerpFixed(mobj->old_spriteyscale, mobj->spriteyscale, frac);
out->spritexoffset = mobj->resetinterp ? mobj->spritexoffset : R_LerpFixed(mobj->old_spritexoffset, mobj->spritexoffset, frac);
out->spriteyoffset = mobj->resetinterp ? mobj->spriteyoffset : R_LerpFixed(mobj->old_spriteyoffset, mobj->spriteyoffset, frac);
out->scale = mobj->resetinterp ? mobj->scale : R_LerpFixed(mobj->old_scale, mobj->scale, frac);
//out->subsector = R_PointInSubsector(out->x, out->y); // this is unused
if (mobj->player)
@@ -757,6 +761,45 @@ void R_UpdateMobjInterpolators(void)
}
}
// reset banan and eggbox rollangle when they´re on the ground
// if not cv_bananthrowroll option "+Onground"
static void R_ResetBananaRollangle(mobj_t* mobj)
{
if (!mobj->rollangle)
return;
if (mobj->type != MT_BANANA && mobj->type != MT_EGGMANITEM) // always reset eggboxes
return;
// keep banans "rotated" if we want them to
if (mobj->type == MT_BANANA && cv_bananthrowroll.value == 2)
return;
// only reset if on ground
if (!P_IsObjectOnGround(mobj))
return;
mobj->rollangle = 0;
}
// Reset our Sprite scales and offsets
// at the start of the tic
// this is just to make things simpler
// as we dont have to reset it ourselves after use
// done at the start so lua can still overwrite everything
static void R_ResetMobjSpriteStuff(mobj_t *mobj)
{
mobj->spritexscale = mobj->realxscale;
mobj->spriteyscale = mobj->realyscale;
mobj->spritexoffset = mobj->realxoffset;
mobj->spriteyoffset = mobj->realyoffset;
mobj->temprollangle = 0;
// kinda stupid but idk where else to put this
R_ResetBananaRollangle(mobj);
}
//
// P_ResetMobjInterpolationState
//
@@ -795,18 +838,9 @@ void R_ResetMobjInterpolationState(mobj_t *mobj)
mobj->player->old_frameangle = mobj->player->frameangle;
}
// Reset our Sprite scales and offsets
// at the start of the tic
// this is just to make things simpler
// as we dont have to reset it ourselves after use
// done at the start so lua can still overwrite everything
// technically not interpolation related
// but this saves us another thinkerloop and multiple checks lel
mobj->spritexscale = mobj->realxscale;
mobj->spriteyscale = mobj->realyscale;
mobj->spritexoffset = mobj->realxoffset;
mobj->spriteyoffset = mobj->realyoffset;
R_ResetMobjSpriteStuff(mobj);
mobj->resetinterp = false;
}
+25 -5
View File
@@ -188,6 +188,7 @@ consvar_t cv_flipcammode = {"flipcammode", "Displayplayer", CV_SAVE, flipcammod
consvar_t cv_shadow = {"shadow", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_shadowoffs = {"offsetshadows", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_skydome = {"skydome", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ffloorclip = {"r_ffloorclip", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_spriteclip = {"r_spriteclip", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_softcyancut = {"softwarecyancut", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -410,7 +411,7 @@ angle_t R_PlayerSliptideAngle(player_t *player)
if (!sprframe)
return 0;
if (sprframe->rotate != SRF_SINGLE || (mo->frame & FF_PAPERSPRITE))
if (sprframe->rotate != SRF_SINGLE || R_ThingIsPaperSprite(mo))
ang = R_PointToAngle(mo->x, mo->y) - mo->angle;
return FixedMul(FINECOSINE((ang) >> ANGLETOFINESHIFT), mo->player->sliproll * mo->player->kartstuff[k_aizdriftstrat]);
@@ -1388,6 +1389,21 @@ void R_RenderPlayerView(player_t *player)
maskcount_t* masks = static_cast<maskcount_t*>(malloc(sizeof(maskcount_t)));
const boolean skybox = (skyboxmo[0] && cv_skybox.value);
// Only do it if it's the first screen being rendered
if (cv_homremoval.value && viewssnum == 0)
{
if (cv_homremoval.value == 1)
{
// Clear the software screen buffer to remove HOM
memset(vid.screens[0], 31, vid.width * vid.height);
}
else if (cv_homremoval.value == 2)
{
//'development' HOM removal -- makes it blindingly obvious if HOM is spotted.
memset(vid.screens[0], 32+(timeinmap&15), vid.width * vid.height);
}
}
// load previous saved value of skyVisible for the player
skyVisible = skyVisiblePerPlayer[viewssnum];
@@ -1454,10 +1470,12 @@ void R_RenderPlayerView(player_t *player)
NetUpdate();
R_SetColumnContext(COLUMNCONTEXT_FLUSH);
ps_numbspcalls.value.i = ps_numpolyobjects.value.i = ps_numdrawnodes.value.i = 0;
PS_START_TIMING(ps_bsptime);
R_RenderViewpoint(&masks[nummasks - 1], true);
PS_STOP_TIMING(ps_bsptime);
PS_START_TIMING(ps_sw_spritecliptime);
R_ClipSprites(drawsegs, NULL);
PS_STOP_TIMING(ps_sw_spritecliptime);
@@ -1465,8 +1483,8 @@ void R_RenderPlayerView(player_t *player)
ps_numsprites.value.i = numvisiblesprites;
PS_START_TIMING(ps_sw_portaltime);
// Portal rendering. Hijacks the BSP traversal.
PS_START_TIMING(ps_sw_portaltime);
if (portal_base)
{
portal_t *portal;
@@ -1507,8 +1525,7 @@ void R_RenderPlayerView(player_t *player)
R_SetColumnContext(COLUMNCONTEXT_DIRECT);
PS_START_TIMING(ps_sw_planetime);
if (!skybox)
R_DrawSkyPlanes();
R_DrawSkyPlanes();
R_DrawPlanes();
PS_STOP_TIMING(ps_sw_planetime);
// draw mid texture and sprite
@@ -1516,6 +1533,7 @@ void R_RenderPlayerView(player_t *player)
PS_START_TIMING(ps_sw_maskedtime);
R_DrawMasked(masks, nummasks);
PS_STOP_TIMING(ps_sw_maskedtime);
free(masks);
// Check for new console commands.
@@ -1564,6 +1582,7 @@ void R_RegisterEngineStuff(void)
CV_RegisterVar(&cv_shadow);
CV_RegisterVar(&cv_shadowoffs);
CV_RegisterVar(&cv_skybox);
CV_RegisterVar(&cv_skydome);
CV_RegisterVar(&cv_ffloorclip);
CV_RegisterVar(&cv_spriteclip);
CV_RegisterVar(&cv_secbright);
@@ -1598,7 +1617,8 @@ void R_RegisterEngineStuff(void)
CV_RegisterVar(&cv_sliptideroll);
CV_RegisterVar(&cv_sloperolldist);
CV_RegisterVar(&cv_sparkroll);
CV_RegisterVar(&cv_spinoutroll);
CV_RegisterVar(&cv_stairjank);
CV_RegisterVar(&cv_stairjanksfx);
CV_RegisterVar(&cv_showhud);
CV_RegisterVar(&cv_translucenthud);
+1
View File
@@ -213,6 +213,7 @@ extern consvar_t cv_translucency;
extern consvar_t cv_drawdist, cv_drawdist_precip, cv_lessprecip;
extern consvar_t cv_fov, cv_fovchange;
extern consvar_t cv_skybox;
extern consvar_t cv_skydome;
extern consvar_t cv_tailspickup;
extern consvar_t cv_maxinterpdist;
extern consvar_t cv_playerfade;
+6 -3
View File
@@ -785,6 +785,8 @@ static void R_DrawSkyPlane(visplane_t *pl, void(*skycolfunc)(drawcolumndata_t*),
drawcolumndata_t dc = {};
const INT32 texture = texturetranslation[skytexture];
const boolean skydome = cv_skydome.value != 0;
// Reset column drawer function (note: couldn't we just call colfuncs[BASEDRAWFUNC] directly?)
// (that is, unless we'll need to switch drawers in future for some reason)
R_SetColumnFunc(BASEDRAWFUNC);
@@ -830,8 +832,8 @@ static void R_DrawSkyPlane(visplane_t *pl, void(*skycolfunc)(drawcolumndata_t*),
INT32 angle = (pl->viewangle + xtoviewangle[x + i])>>ANGLETOSKYSHIFT;
angle -= (skytextureoffset >> FRACBITS);
dc.iscale = FixedMul(skyscale, FINECOSINE(xtoviewangle[x + i]>>ANGLETOFINESHIFT));
if (skydome)
dc.iscale = FixedMul(skyscale, FINECOSINE(xtoviewangle[x + i]>>ANGLETOFINESHIFT));
dc.x = x + i;
dc.source = R_GetColumn(texture, -angle); // get negative of angle for each column to display sky correct way round! --Monster Iestyn 27/01/18
@@ -866,7 +868,8 @@ static void R_DrawSkyPlane(visplane_t *pl, void(*skycolfunc)(drawcolumndata_t*),
INT32 angle = (pl->viewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT;
angle -= (skytextureoffset >> FRACBITS);
dc.iscale = FixedMul(skyscale, FINECOSINE(xtoviewangle[x]>>ANGLETOFINESHIFT));
if (skydome)
dc.iscale = FixedMul(skyscale, FINECOSINE(xtoviewangle[x]>>ANGLETOFINESHIFT));
dc.x = x;
dc.source =
R_GetColumn(texturetranslation[skytexture], -angle); // get negative of angle for each column to display sky correct way round! --Monster Iestyn 27/01/18
+5 -2
View File
@@ -272,7 +272,7 @@ static boolean TrimVisplaneBounds(const visplane_t* plane, INT16* start, INT16*
* Applies the necessary offsets and rotation to give
* a depth illusion to the skybox.
*/
void Portal_AddSkybox(const visplane_t* plane)
static void Portal_AddSkybox(const visplane_t* plane)
{
INT16 start, end;
mapheader_t *mh;
@@ -333,10 +333,13 @@ void Portal_AddSkyboxPortals(void)
INT32 i;
UINT16 count = 0;
for (i = 0; i < MAXVISPLANES; i++, pl++)
for (i = 0; i < MAXVISPLANES; i++)
{
for (pl = visplanes[i]; pl; pl = pl->next)
{
if (pl->minx >= pl->maxx)
continue;
if (pl->picnum == skyflatnum)
{
Portal_AddSkybox(pl);
-1
View File
@@ -58,7 +58,6 @@ void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, con
void Portal_ClipApply (const portal_t* portal);
void Portal_AddSkybox(const visplane_t* plane);
void Portal_AddSkyboxPortals(void);
#ifdef __cplusplus
+71 -57
View File
@@ -713,16 +713,11 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf
rw_scalestep = drawseg->scalestep;
spryscale = drawseg->scale1 + (x1 - drawseg->x1)*rw_scalestep;
#define CLAMPMAX INT32_MAX
#define CLAMPMIN (-INT32_MAX) // This is not INT32_MIN on purpose! INT32_MIN makes the drawers freak out.
auto overflow_clamp = [&](INT64 overflow_test)
{
return (overflow_test > (INT64)CLAMPMAX) ? CLAMPMAX :
(overflow_test > (INT64)CLAMPMIN) ? (fixed_t)overflow_test :
CLAMPMIN;
// This is not INT32_MIN on purpose! INT32_MIN makes the drawers freak out.
return (fixed_t)std::clamp<INT64>(overflow_test, (-INT32_MAX), INT32_MAX);
};
#undef CLAMPMAX
#undef CLAMPMIN
dc->numlights = 0;
if (frontsector->numlights)
@@ -2604,71 +2599,91 @@ void R_StoreWallRange(INT32 start, INT32 stop)
if (linedef->special == HORIZONSPECIAL) // HORIZON LINES
{
topstep = bottomstep = 0;
topfrac = bottomfrac = (centeryfrac>>4);
topfrac = bottomfrac = (centeryfrac >> 4);
topfrac++; // Prevent 1px HOM
}
else
{
topstep = -FixedMul(rw_scalestep, worldtop);
topfrac = (centeryfrac >> 4) - FixedMul(worldtop, rw_scale);
// for anyone that sees this
// dont.
// this is absolute shit-tier hacks
// but i just cant determine this in any sane way
// but this checks a shitton of things to make software handle skies better
auto set_topstep_normal = [&]
{
topstep = -FixedMul(rw_scalestep, worldtop);
topfrac = (centeryfrac>>4) - FixedMul(worldtop, rw_scale);
};
// untextured seg
if (!segtextured && !curline->polyseg)
if (!segtextured && !curline->polyseg) // not for polyobjects.....
{
const bool tophigh = (worldhigh <= worldtop && worldhighslope <= worldtopslope);
const boolean nofrontsky = (frontsector->floorpic != skyflatnum && frontsector->ceilingpic != skyflatnum);
const boolean inskybox = (skyboxmo[0] && cv_skybox.value && newview->sky); // dont mess with skyVisible within skybox rendering!
// if we cant see the goddamn skyplane, well there wont be any skybox
// we could kill skyVisible instead, but i want to keep the performance improvements it yields
// so we do this absolute trash
if ((tophigh
&& (frontsector->floorpic != skyflatnum && frontsector->ceilingpic != skyflatnum)) // try to guess if its a "window"
&& ((!backsector) // single sided
|| ((backsector && (worldhigh != worldtop || worldhighslope != worldtopslope))
&& (backsector->floorheight >= frontsector->ceilingheight || backsector->ceilingheight <= frontsector->floorheight)))) // check if there is a "thok" sector behind it
skyVisible = true;
// this is an attempt to fix issues with textureless single sided lines drawing nothing where they should just draw sky instead
if (tophigh && !backsector && frontsector->ceilingpic == skyflatnum)
// single sided line
if (!backsector)
{
// account for slopes to try and get rid of sharp edges from the black void
if (frontsector->f_slope || (backsector && backsector->f_slope))
// this is an attempt to fix issues with textureless single sided lines drawing nothing where they should just draw sky instead
// there is a sky flat on the ceiling
// so we can assume this is supposed to draw the sky
if (frontsector->ceilingpic == skyflatnum)
{
topstep = -FixedMul(rw_scalestep, worldbottomslope);
topfrac = (centeryfrac>>4) - FixedMul(worldbottomslope, rw_scale);
// just draw sky from top to bottom!
if (frontsector->f_slope)
{
topstep = -FixedMul(rw_scalestep, worldbottomslope);
topfrac = (centeryfrac >> 4) - FixedMul(worldbottomslope, rw_scale);
}
else
{
topstep = -FixedMul(rw_scalestep, worldbottom);
topfrac = (centeryfrac >> 4) - FixedMul(worldbottom, rw_scale);
}
}
else
else if (nofrontsky && !inskybox)
{
topstep = -FixedMul(rw_scalestep, worldbottom);
topfrac = (centeryfrac>>4) - FixedMul(worldbottom, rw_scale);
// completely empty wall without sky flats, just assume skybox is visible then
skyVisible = true;
}
}
else
set_topstep_normal();
else if (nofrontsky && !inskybox) // if there was a skyflat, drawplane would already set skyvisible
{
// "thok walls" are double sided
// so we need to check a few things here
// to be rather conservative
// as skyrendering is pretty costly!
// ideally we´d just dont care and always draw the skytexture
// or skybox at any time, like gl does
// wonder if there would be a fast way to draw atleast just the texture?
// gotta shift those here for proper comparisons
const INT32 whigh = worldhigh >> 4;
const INT32 whslope = worldhighslope >> 4;
// check if there is a window to force skybox to draw
if ((whigh <= worldtop && whslope <= worldtopslope) && (backsector->ceilingpic == skyflatnum)) // backsector has a skyflat?
skyVisible = true;
// otherwise check for thokwalls
else if ((whigh != worldtop || whslope != worldtopslope) && // FIXME: i forgor what this was for lol
(backsector->floorheight >= frontsector->ceilingheight || // thok walls usually are set up like that...
frontsector->floorheight >= backsector->ceilingheight)) // floor higher than the other sides ceiling
skyVisible = true;
}
}
else
set_topstep_normal();
bottomstep = -FixedMul(rw_scalestep, worldbottom);
bottomfrac = (centeryfrac>>4) - FixedMul(worldbottom, rw_scale);
bottomfrac = (centeryfrac >> 4) - FixedMul(worldbottom, rw_scale);
if (frontsector->c_slope)
{
fixed_t topfracend = (centeryfrac>>4) - FixedMul(worldtopslope, ds_p->scale2);
fixed_t topfracend = (centeryfrac >> 4) - FixedMul(worldtopslope, ds_p->scale2);
topstep = (topfracend-topfrac)/(range);
}
if (frontsector->f_slope)
{
fixed_t bottomfracend = (centeryfrac>>4) - FixedMul(worldbottomslope, ds_p->scale2);
fixed_t bottomfracend = (centeryfrac >> 4) - FixedMul(worldbottomslope, ds_p->scale2);
bottomstep = (bottomfracend-bottomfrac)/(range);
}
}
@@ -2706,12 +2721,13 @@ void R_StoreWallRange(INT32 start, INT32 stop)
if (leftheight < worldbottom && rightheight < worldbottomslope)
continue;
if (leftheight > worldtop && rightheight > worldtopslope && i+1 < dc.numlights && frontsector->lightlist[i+1].height > frontsector->ceilingheight)
if ((leftheight > worldtop) && (rightheight > worldtopslope) &&
(i+1 < dc.numlights) && (frontsector->lightlist[i+1].height > frontsector->ceilingheight))
continue;
}
rlight->height = (centeryfrac>>4) - FixedMul(leftheight, rw_scale);
rlight->heightstep = (centeryfrac>>4) - FixedMul(rightheight, ds_p->scale2);
rlight->height = (centeryfrac >> 4) - FixedMul(leftheight, rw_scale);
rlight->heightstep = (centeryfrac >> 4) - FixedMul(rightheight, ds_p->scale2);
rlight->heightstep = (rlight->heightstep-rlight->height)/(range);
rlight->flags = static_cast<ffloortype_e>(light->flags);
@@ -2730,10 +2746,9 @@ void R_StoreWallRange(INT32 start, INT32 stop)
leftheight >>= 4;
rightheight >>= 4;
rlight->botheight = (centeryfrac>>4) - FixedMul(leftheight, rw_scale);
rlight->botheightstep = (centeryfrac>>4) - FixedMul(rightheight, ds_p->scale2);
rlight->botheight = (centeryfrac >> 4) - FixedMul(leftheight, rw_scale);
rlight->botheightstep = (centeryfrac >> 4) - FixedMul(rightheight, ds_p->scale2);
rlight->botheightstep = (rlight->botheightstep-rlight->botheight)/(range);
}
rlight->lightlevel = *light->lightlevel;
@@ -2754,13 +2769,14 @@ void R_StoreWallRange(INT32 start, INT32 stop)
if (linedef->special == HORIZONSPECIAL) // Horizon lines extend FOFs in contact with them too.
{
visffloor[i].f_step = 0;
visffloor[i].f_frac = (centeryfrac>>4);
visffloor[i].f_frac = (centeryfrac >> 4);
topfrac++; // Prevent 1px HOM
}
else
{
visffloor[i].f_frac = (centeryfrac>>4) - FixedMul(visffloor[i].f_pos, rw_scale);
visffloor[i].f_step = ((centeryfrac>>4) - FixedMul(visffloor[i].f_pos_slope, ds_p->scale2) - visffloor[i].f_frac)/(range);
visffloor[i].f_frac = (centeryfrac >> 4) - FixedMul(visffloor[i].f_pos, rw_scale);
visffloor[i].f_step = (centeryfrac >> 4) - FixedMul(visffloor[i].f_pos_slope, ds_p->scale2);
visffloor[i].f_step = (visffloor[i].f_step - visffloor[i].f_frac)/(range);
}
}
}
@@ -2774,9 +2790,8 @@ void R_StoreWallRange(INT32 start, INT32 stop)
if (toptexture)
{
fixed_t topfracend = (centeryfrac>>4) - FixedMul(worldhighslope, ds_p->scale2);
pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw_scale);
fixed_t topfracend = (centeryfrac >> 4) - FixedMul(worldhighslope, ds_p->scale2);
pixhigh = (centeryfrac >> 4) - FixedMul(worldhigh, rw_scale);
pixhighstep = (topfracend-pixhigh)/(range);
// If the lowest part of a ceiling stretching down covers the entire screen
@@ -2786,9 +2801,8 @@ void R_StoreWallRange(INT32 start, INT32 stop)
if (bottomtexture)
{
fixed_t bottomfracend = (centeryfrac>>4) - FixedMul(worldlowslope, ds_p->scale2);
pixlow = (centeryfrac>>4) - FixedMul (worldlow, rw_scale);
fixed_t bottomfracend = (centeryfrac >> 4) - FixedMul(worldlowslope, ds_p->scale2);
pixlow = (centeryfrac >> 4) - FixedMul(worldlow, rw_scale);
pixlowstep = (bottomfracend-pixlow)/(range);
// If the highest part of a floor stretching up covers the entire screen
-1
View File
@@ -817,7 +817,6 @@ void R_AddSkins(UINT16 wadnum, boolean local)
}
#undef lnumskins
//sortSkinGrid();
return;
}
+1 -1
View File
@@ -90,7 +90,7 @@ extern side_t *sides;
extern fixed_t viewx, viewy, viewz;
extern angle_t viewangle, aimingangle, viewroll;
extern UINT8 viewssnum; // splitscreen view number
extern boolean viewsky, skyVisible;
extern boolean skyVisible;
extern boolean skyVisiblePerPlayer[MAXSPLITSCREENPLAYERS]; // saved values of skyVisible of each splitscreen player
extern sector_t *viewsector;
extern player_t *viewplayer;
+92 -61
View File
@@ -87,6 +87,8 @@ static drawseg_xrange_item_t *drawsegs_xrange;
static size_t drawsegs_xrange_size = 0;
static INT32 drawsegs_xrange_count = 0;
#define CLIP_UNDEF -2
//
// Sprite rotation 0 is facing the viewer,
// rotation 1 is one angle turn CLOCKWISE around the axis.
@@ -1241,9 +1243,9 @@ static void R_ProjectSprite(mobj_t *thing)
return;
const boolean mirrored = thing->mirrored;
const boolean vflip = (thing->eflags & MFE_VERTICALFLIP);
const boolean hflip = (!(thing->frame & FF_HORIZONTALFLIP) != !mirrored);
const boolean papersprite = (thing->frame & FF_PAPERSPRITE);
const boolean vflip = R_ThingVerticallyFlipped(thing);
const boolean hflip = (!R_ThingHorizontallyFlipped(thing) != !mirrored);
const boolean papersprite = R_ThingIsPaperSprite(thing);
// transform the origin point
tr_x = interp.x - viewx;
@@ -1276,7 +1278,7 @@ static void R_ProjectSprite(mobj_t *thing)
#ifdef ROTSPRITE
// determine here if sprite should rotate for optimization
const boolean sliprollrotate = (cv_sliptideroll.value && (thing->player && thing->player->sliproll));
const boolean shouldrotate = (interp.sloperoll || interp.slopepitch || interp.roll || interp.pitch || thing->rollangle || sliprollrotate);
const boolean shouldrotate = (interp.sloperoll || interp.slopepitch || interp.roll || interp.pitch || thing->rollangle || thing->temprollangle || sliprollrotate);
#endif
sprskin = K_GetMobjSkin(thing);
@@ -1376,16 +1378,18 @@ static void R_ProjectSprite(mobj_t *thing)
#ifdef ROTSPRITE
if (shouldrotate)
{
const fixed_t thingrollangle = (thing->rollangle - thing->temprollangle);
if (papersprite)
{
if (ang >= ANGLE_180)
{
// Makes Software act much more sane like OpenGL
rollangle = InvAngle(thing->rollangle);
rollangle = InvAngle(thingrollangle);
}
else
{
rollangle = thing->rollangle;
rollangle = thingrollangle;
}
}
else
@@ -1393,7 +1397,7 @@ static void R_ProjectSprite(mobj_t *thing)
// this is very messy, but it on-the-fly calculates rotations for all the
// pitch and roll variables
pitchnroll = R_RotationAngle(ang, camang, &interp);
rollangle = thing->rollangle;
rollangle = thingrollangle;
}
if (rollangle || pitchnroll || sliprollrotate)
@@ -2219,6 +2223,7 @@ static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 e
best = ds;
}
}
if (best)
{
best->next->prev = best->prev;
@@ -2627,7 +2632,7 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port
for (x = x1; x <= x2; x++)
{
spr->clipbot[x] = spr->cliptop[x] = -2;
spr->clipbot[x] = spr->cliptop[x] = CLIP_UNDEF;
}
// Scan drawsegs from end to start for obscuring segs.
@@ -2656,29 +2661,26 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port
ds = curr->user;
if (ds->portalpass != 66) // unused?
if (ds->portalpass > 0 && ds->portalpass <= portalrender)
continue; // is a portal
if (ds->scale1 > ds->scale2)
{
if (ds->portalpass > 0 && ds->portalpass <= portalrender)
continue; // is a portal
lowscale = ds->scale2;
scale = ds->scale1;
}
else
{
lowscale = ds->scale1;
scale = ds->scale2;
}
if (ds->scale1 > ds->scale2)
{
lowscale = ds->scale2;
scale = ds->scale1;
}
else
{
lowscale = ds->scale1;
scale = ds->scale2;
}
if (scale < spr->sortscale ||
(lowscale < spr->sortscale &&
!R_PointOnSegSide(spr->gx, spr->gy, ds->curline)))
{
// seg is behind sprite
continue;
}
if (scale < spr->sortscale ||
(lowscale < spr->sortscale &&
!R_PointOnSegSide(spr->gx, spr->gy, ds->curline)))
{
// seg is behind sprite
continue;
}
r1 = ds->x1 < x1 ? x1 : ds->x1;
@@ -2697,14 +2699,14 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port
{
// bottom sil
for (x = r1; x <= r2; x++)
if (spr->clipbot[x] == -2)
if (spr->clipbot[x] == CLIP_UNDEF)
spr->clipbot[x] = ds->sprbottomclip[x];
}
else if (silhouette == SIL_TOP)
{
// top sil
for (x = r1; x <= r2; x++)
if (spr->cliptop[x] == -2)
if (spr->cliptop[x] == CLIP_UNDEF)
spr->cliptop[x] = ds->sprtopclip[x];
}
else if (silhouette == (SIL_TOP|SIL_BOTTOM))
@@ -2712,9 +2714,9 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port
// both
for (x = r1; x <= r2; x++)
{
if (spr->clipbot[x] == -2)
if (spr->clipbot[x] == CLIP_UNDEF)
spr->clipbot[x] = ds->sprbottomclip[x];
if (spr->cliptop[x] == -2)
if (spr->cliptop[x] == CLIP_UNDEF)
spr->cliptop[x] = ds->sprtopclip[x];
}
}
@@ -2733,13 +2735,13 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port
if (mh <= 0 || (phs != -1 && viewz > sectors[phs].floorheight))
{ // clip bottom
for (x = x1; x <= x2; x++)
if (spr->clipbot[x] == -2 || h < spr->clipbot[x])
if (spr->clipbot[x] == CLIP_UNDEF || h < spr->clipbot[x])
spr->clipbot[x] = (INT16)h;
}
else // clip top
{
for (x = x1; x <= x2; x++)
if (spr->cliptop[x] == -2 || h > spr->cliptop[x])
if (spr->cliptop[x] == CLIP_UNDEF || h > spr->cliptop[x])
spr->cliptop[x] = (INT16)h;
}
}
@@ -2751,13 +2753,13 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port
if (phs != -1 && viewz >= sectors[phs].ceilingheight)
{ // clip bottom
for (x = x1; x <= x2; x++)
if (spr->clipbot[x] == -2 || h < spr->clipbot[x])
if (spr->clipbot[x] == CLIP_UNDEF || h < spr->clipbot[x])
spr->clipbot[x] = (INT16)h;
}
else // clip top
{
for (x = x1; x <= x2; x++)
if (spr->cliptop[x] == -2 || h > spr->cliptop[x])
if (spr->cliptop[x] == CLIP_UNDEF || h > spr->cliptop[x])
spr->cliptop[x] = (INT16)h;
}
}
@@ -2767,10 +2769,10 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port
{
for (x = x1; x <= x2; x++)
{
if (spr->cliptop[x] == -2 || spr->szt > spr->cliptop[x])
if (spr->cliptop[x] == CLIP_UNDEF || spr->szt > spr->cliptop[x])
spr->cliptop[x] = spr->szt;
if (spr->clipbot[x] == -2 || spr->sz < spr->clipbot[x])
if (spr->clipbot[x] == CLIP_UNDEF || spr->sz < spr->clipbot[x])
spr->clipbot[x] = spr->sz;
}
}
@@ -2778,7 +2780,7 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port
{
for (x = x1; x <= x2; x++)
{
if (spr->cliptop[x] == -2 || spr->szt > spr->cliptop[x])
if (spr->cliptop[x] == CLIP_UNDEF || spr->szt > spr->cliptop[x])
spr->cliptop[x] = spr->szt;
}
}
@@ -2786,7 +2788,7 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port
{
for (x = x1; x <= x2; x++)
{
if (spr->clipbot[x] == -2 || spr->sz < spr->clipbot[x])
if (spr->clipbot[x] == CLIP_UNDEF || spr->sz < spr->clipbot[x])
spr->clipbot[x] = spr->sz;
}
}
@@ -2796,21 +2798,13 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port
// check for unclipped columns
for (x = x1; x <= x2; x++)
{
if (spr->clipbot[x] == -2)
if (spr->clipbot[x] == CLIP_UNDEF)
spr->clipbot[x] = (INT16)viewheight;
if (spr->cliptop[x] == -2)
if (spr->cliptop[x] == CLIP_UNDEF)
spr->cliptop[x] = -1;
}
// Check if it'll be visible
// Not done for floorsprites.
if (cv_spriteclip.value)
{
if (!R_CheckSpriteVisible(spr, x1, x2))
spr->cut = static_cast<spritecut_e>(spr->cut | SC_NOTVISIBLE);
}
if (portal)
{
INT32 start_index = std::max(portal->start, x1);
@@ -2821,6 +2815,7 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port
spr->clipbot[x] = -1;
spr->cliptop[x] = -1;
}
for (x = start_index; x <= end_index; x++)
{
if (spr->clipbot[x] > portal->floorclip[x - portal->start])
@@ -2828,12 +2823,21 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port
if (spr->cliptop[x] < portal->ceilingclip[x - portal->start])
spr->cliptop[x] = portal->ceilingclip[x - portal->start];
}
for (x = end_index + 1; x <= x2; x++)
{
spr->clipbot[x] = -1;
spr->cliptop[x] = -1;
}
}
// Check if it'll be visible
// Not done for floorsprites.
if (cv_spriteclip.value)
{
if (!R_CheckSpriteVisible(spr, x1, x2))
spr->cut = static_cast<spritecut_e>(spr->cut | SC_NOTVISIBLE);
}
}
void R_ClipSprites(drawseg_t* dsstart, portal_t* portal)
@@ -2906,8 +2910,9 @@ void R_ClipSprites(drawseg_t* dsstart, portal_t* portal)
{
vissprite_t *spr = R_GetVisSprite(clippedvissprites);
if (cv_spriteclip.value
&& (spr->szt > vid.height || spr->sz < 0))
if (cv_spriteclip.value &&
(spr->szt > vid.height || spr->sz < 0) &&
!spr->scalestep)
{
spr->cut = static_cast<spritecut_e>(spr->cut | SC_NOTVISIBLE);
continue;
@@ -2939,16 +2944,16 @@ void R_ClipSprites(drawseg_t* dsstart, portal_t* portal)
/* Check if thing may be drawn from our current view. */
boolean R_ThingVisible(mobj_t *thing)
{
if (UNLIKELY((thing->sprite == SPR_NULL) || (thing->flags2 & MF2_DONTDRAW)))
if ((thing->sprite == SPR_NULL) || (thing->flags2 & MF2_DONTDRAW))
return false;
if (UNLIKELY(splitscreen))
if (splitscreen)
{
if ((viewssnum == 0 && (thing->eflags & MFE_DRAWONLYFORP1))
|| (viewssnum == 1 && (thing->eflags & MFE_DRAWONLYFORP2))
|| (viewssnum == 2 && (thing->eflags & MFE_DRAWONLYFORP2))
|| (viewssnum == 3 && (thing->eflags & MFE_DRAWONLYFORP4)))
return true;
if (((thing->eflags & MFE_DRAWONLYFORP1) && viewssnum != 0)
|| ((thing->eflags & MFE_DRAWONLYFORP2) && viewssnum != 1)
|| ((thing->eflags & MFE_DRAWONLYFORP3) && viewssnum != 2)
|| ((thing->eflags & MFE_DRAWONLYFORP4) && viewssnum != 3))
return false;
}
return true;
@@ -3020,11 +3025,37 @@ boolean R_CheckMobjInterpDist(mobj_t *thing)
return R_CheckInterpDist(thing);
}
boolean R_ThingIsFullBright(mobj_t *thing)
boolean R_ThingHorizontallyFlipped(mobj_t *thing)
{
return (thing->frame & FF_HORIZONTALFLIP);
}
boolean R_ThingVerticallyFlipped(mobj_t *thing)
{
return (thing->eflags & MFE_VERTICALFLIP); //(thing->frame & FF_VERTICALFLIP);
}
boolean R_ThingIsPaperSprite(mobj_t *thing)
{
return (thing->frame & FF_PAPERSPRITE);
}
template<typename T>
static boolean R_ThingIsFullBrightT(T *thing)
{
return ((thing->frame & FF_BRIGHTMASK) == FF_FULLBRIGHT);
}
boolean R_PrecipThingIsFullBright(precipmobj_t *thing)
{
return R_ThingIsFullBrightT(thing);
}
boolean R_ThingIsFullBright(mobj_t *thing)
{
return R_ThingIsFullBrightT(thing);
}
boolean R_ThingIsSemiBright(mobj_t *thing)
{
return ((thing->frame & FF_BRIGHTMASK) == FF_SEMIBRIGHT);
+5
View File
@@ -88,6 +88,11 @@ boolean R_CheckPrecipMobjInterpDist(precipmobj_t *thing);
boolean R_CheckMobjInterpDist(mobj_t *thing);
fixed_t R_DoPlayerFade(mobj_t *thing);
boolean R_ThingHorizontallyFlipped(mobj_t *thing);
boolean R_ThingVerticallyFlipped(mobj_t *thing);
boolean R_ThingIsPaperSprite(mobj_t *thing);
boolean R_PrecipThingIsFullBright(precipmobj_t *thing);
boolean R_ThingIsFullBright(mobj_t *thing);
boolean R_ThingIsSemiBright(mobj_t *thing);
boolean R_ThingIsFullDark(mobj_t *thing);
+25 -15
View File
@@ -1297,9 +1297,7 @@ static boolean ReadMusicDefFields(UINT16 wadnum, int line, char *stoken, musicde
if (!value)
{
CONS_Alert(CONS_WARNING,
"MUSICDEF: Field '%s' is missing name. (file %s, line %d)\n",
stoken, wadfiles[wadnum]->filename, line);
CONS_Alert(CONS_WARNING, "MUSICDEF: Field '%s' is missing name. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line);
(void)strtok(NULL, " ");
return true;
}
@@ -1332,9 +1330,7 @@ static boolean ReadMusicDefFields(UINT16 wadnum, int line, char *stoken, musicde
if (!value)
{
CONS_Alert(CONS_WARNING,
"MUSICDEF: Field '%s' is missing value. (file %s, line %d)\n",
stoken, wadfiles[wadnum]->filename, line);
CONS_Alert(CONS_WARNING, "MUSICDEF: Field '%s' is missing value. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line);
(void)strtok(NULL, " ");
return true;
}
@@ -1344,9 +1340,7 @@ static boolean ReadMusicDefFields(UINT16 wadnum, int line, char *stoken, musicde
if (!def)
{
CONS_Alert(CONS_ERROR,
"MUSICDEF: No music definition before field '%s'. (file %s, line %d)\n",
stoken, wadfiles[wadnum]->filename, line);
CONS_Alert(CONS_ERROR, "MUSICDEF: No music definition before field '%s'. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line);
return false;
}
@@ -1358,11 +1352,19 @@ static boolean ReadMusicDefFields(UINT16 wadnum, int line, char *stoken, musicde
textline = value;
// turn _ into spaces.
#define ADDDEF(field)\
STRBUFCPY(def->field, textline);\
for (textline = def->field; *textline; textline++)\
if (*textline == '_') *textline = ' ';
// turn _ into spaces while also removing trailing whitespaces.
#define ADDDEF(field) \
int err = 0; \
STRBUFCPY(def->field, textline); \
size_t len = strlen(def->field); \
while (len > 0 && (def->field[len-1] == ' ')) { \
def->field[len-1] = 0; \
len--; \
} \
for (textline = def->field; *textline; textline++) { \
if (err == 0 && *textline == ' ') {err = 1; CONS_Alert(CONS_WARNING, "MUSICDEF: Erroneous whitespace detected in field '%s': '%s'.\n(file %s, line %d) Musicdef might not work correctly!\n", stoken, value, wadfiles[wadnum]->filename, line);} \
if (*textline == '_') *textline = ' '; \
}
if (fasticmp(stoken, "usage"))
{
@@ -1374,7 +1376,6 @@ static boolean ReadMusicDefFields(UINT16 wadnum, int line, char *stoken, musicde
}
else if (fasticmp(stoken, "title"))
{
def->use_info = true;
ADDDEF(title);
}
else if (fasticmp(stoken, "alttitle"))
@@ -2039,6 +2040,10 @@ static boolean S_SkipIntroMusic(void)
if (!cv_skipintromusic.value)
return false;
// dont skip if we disabled music, weird? but this would skip sounds that play on map start as well otherwise
if (music_disabled)
return false;
// check if menu music is playing, otherwise it may continue playing
if (fasticmp(music.name, "titles"))
return false;
@@ -2050,6 +2055,11 @@ static boolean S_SkipIntroMusic(void)
return false;
}
// without sound there wont be any intro playing
if (sound_disabled)
return true;
// yes i sometimes play with only music but no sound
return true;
}
-1
View File
@@ -186,7 +186,6 @@ typedef struct musicdef_s
char title[256];
char alttitle[256];
char authors[256];
boolean use_info;
size_t num;
} musicdef_t;
-7
View File
@@ -1,7 +0,0 @@
/* Include the SDL main definition header */
#include "SDL_main.h"
void XBoxStartup()
{
SDL_main(0, NULL); /// \todo ?
}
-39
View File
@@ -1,39 +0,0 @@
# Quick Pandora target to make a compliant SRB2 PND file.
PNDNAME=SRB2.pnd
PNDDIR=$(BIN)/pnd
ICON=sdl/SRB2Pandora/icon.png
PXML=sdl/SRB2Pandora/PXML.xml
SED=sed
CAT=cat
CP=cp
XARGS=xargs
FOR=for
WGET=wget -P $(PNDDIR) -c -nc
SHXARGS:=$(XARGS)
SHSED:=$(SED)
ifndef ECHO
CP:=@$(CP)
CAT:=@$(CAT)
SED:=@$(SED)
XARGS:=@$(XARGS)
FOR:=@(FOR)
endif
$(BIN)/$(PNDNAME): $(BIN)/$(EXENAME)
@echo Linking $(PNDNAME)...
$(MKDIR) $(PNDDIR)
$(CP) $(BIN)/$(EXENAME) $(PNDDIR)
$(CP) $(ICON) $(PNDDIR)
$(CP) $(PXML) $(PNDDIR)
ifdef WITHDATA
$(FOR) datafile in $(shell echo $(D_FILES) | $(SHSED) 's/\.srb/\.wad/' | $(SHXARGS) -n 1 basename); do \
$(WGET) http://alam.srb2.org/SRB2/2.0.6-Final/Resources/$$datafile; \
done
endif
$(MKISOFS) -l -r -o $@ $(PNDDIR)
$(CAT) $(PXML) >> $@
$(REMOVE) -r $(PNDDIR)
-17
View File
@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<PXML xmlns="http://openpandora.org/namespaces/PXML">
<application id="srb2.pandora.v20" appdata="srb2">
<title lang="en_US">Sonic Robo Blast 2</title>
<title lang="ja_JA">ソニック・ロボ・ブラスト・2</title>
<description lang="en_US">A 3D Sonic fangame with a huge fanbase developing custom content, including characters, levels, and even large-scale modifications</description>
<version major="2" minor="0" release="6" build="1" />
<exec command="lsdlsrb2" background="true" standalone="true" x11="ignore"/>
<author name="Sonic Team Junior" website="http://www.srb2.org/" email="stjr@srb2.org"/>
<icon src="icon.png"/>
<categories>
<category name="Game">
<subcategory name="ActionGame" />
</category>
</categories>
</application>
</PXML>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

-1035
View File
File diff suppressed because it is too large. Load diff
-62
View File
@@ -1,62 +0,0 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "Srb2SDL"=.\Srb2SDL.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name libpng
End Project Dependency
Begin Project Dependency
Project_Dep_Name zlib
End Project Dependency
}}}
###############################################################################
Project: "libpng"="..\..\libs\libpng-src\projects\visualc6\libpng.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name zlib
End Project Dependency
}}}
###############################################################################
Project: "zlib"=..\..\libs\zlib\projects\visualc6\zlib.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################
Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

-15
View File
@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup>
<ClCompile>
<!-- x86/x64 defines: has specific libraries that ARM does not -->
<PreprocessorDefinitions Condition="'$(Platform)' == 'Win32' OR '$(Platform)' == 'x64'">HAVE_ZLIB;HAVE_LIBGME;USE_WGL_SWAP;HAVE_SDL;HWRENDER;HAVE_FILTER;HAVE_MIXER;SDLMAIN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<!-- ARM defines -->
<PreprocessorDefinitions Condition="'$(Platform)' != 'Win32' AND '$(Platform)' != 'x64'">USE_WGL_SWAP;HAVE_SDL;HWRENDER;HAVE_FILTER;HAVE_MIXER;SDLMAIN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup />
</Project>
+60 -22
View File
@@ -83,6 +83,12 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T);
#if defined (__unix__) || defined(__APPLE__) || (defined (UNIXCOMMON) && !defined (__HAIKU__))
#if defined (__linux__)
#include <sys/vfs.h>
#elif defined(__APPLE__)
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <mach/mach.h>
#else
#include <sys/param.h>
#include <sys/mount.h>
@@ -172,8 +178,7 @@ const char *wadSearchPaths[] = {
/** \brief WAD file to look for
*/
#define WADKEYWORD1 "srb2.srb"
#define WADKEYWORD2 "srb2.wad"
#define WADKEYWORD "srb2.srb"
/** \brief holds wad path
*/
static char returnWadPath[256];
@@ -555,12 +560,12 @@ void I_OutputMsg(const char *fmt, ...)
{
size_t len;
char *txt;
va_list argptr;
va_list argptr;
if (!fmt)
return;
va_start(argptr,fmt);
va_start(argptr, fmt);
len = vsnprintf(NULL, 0, fmt, argptr);
va_end(argptr);
if (len == 0)
@@ -571,7 +576,7 @@ void I_OutputMsg(const char *fmt, ...)
if (!txt)
I_Error("I_OutputMsg: Out of memory!\n");
va_start(argptr,fmt);
va_start(argptr, fmt);
vsprintf(txt, fmt, argptr);
va_end(argptr);
@@ -691,7 +696,7 @@ void I_OutputMsg(const char *fmt, ...)
//
// I_GetKey
//
INT32 I_GetKey (void)
INT32 I_GetKey(void)
{
// Warning: I_GetKey empties the event queue till next keypress
event_t *ev;
@@ -1700,7 +1705,7 @@ static void I_PrintSignal(INT32 signal_num, boolean core_dumped, char *signal_ms
sprintf(signal_name, "%s", signame);
}
static int I_OpenURL(const char *url)
int I_OpenURL(const char *url)
{
#if SDL_VERSION_ATLEAST(2,0,14)
return SDL_OpenURL(va("%s", url));
@@ -1736,7 +1741,13 @@ static void I_ShowErrorBox(const char *title, const char *msg)
SDL_ShowMessageBox(&messageboxdata, &buttonid);
if (buttonid == 1)
I_OpenURL("https://github.com/Indev450/SRB2Kart-Saturn/issues");
{
int url = I_OpenURL(SATURNISSUEPAGE);
// SDL_OpenURL unsupported or failed
if (url == -1)
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Failed to Open Web Page", "Please open the following page in your web browser:\n" SATURNISSUEPAGE, NULL);
}
}
static void I_ShowSimpleErrorBox(const char *title, char *msg)
@@ -2253,7 +2264,6 @@ void I_ShutdownSystem(void)
logstream = NULL;
}
#endif
}
void I_GetDiskFreeSpace(INT64 *freespace)
@@ -2425,7 +2435,7 @@ static boolean isWadPathOk(const char *path)
if (!wad3path)
return false;
sprintf(wad3path, pandf, path, WADKEYWORD1);
sprintf(wad3path, pandf, path, WADKEYWORD);
if (FIL_ReadFileOK(wad3path))
{
@@ -2465,10 +2475,10 @@ static void pathonly(char *s)
*/
static const char *searchWad(const char *searchDir)
{
static char tempsw[255] = "";
static char tempsw[256] = "";
filestatus_t fstemp;
strcpy(tempsw, WADKEYWORD1);
strcpy(tempsw, WADKEYWORD);
fstemp = filesearch(tempsw, searchDir, NULL, true, 20);
if (fstemp == FS_FOUND)
{
@@ -2629,13 +2639,13 @@ size_t I_GetFreeMem(size_t *total)
*total = 32 << 20;
return 32 << 20;
#elif defined (_WIN32)
MEMORYSTATUS info;
MEMORYSTATUSEX info;
info.dwLength = sizeof (MEMORYSTATUS);
GlobalMemoryStatus( &info );
info.dwLength = sizeof (MEMORYSTATUSEX);
GlobalMemoryStatusEx( &info );
if (total)
*total = (size_t)info.dwTotalPhys;
return (size_t)info.dwAvailPhys;
*total = (size_t)info.ullTotalPhys;
return (size_t)info.ullAvailPhys;
#elif defined (__OS2__)
UINT32 pr_arena;
@@ -2668,7 +2678,7 @@ size_t I_GetFreeMem(size_t *total)
{
// Error
if (total)
*total = 0L;
*total = 0;
return 0;
}
@@ -2677,12 +2687,12 @@ size_t I_GetFreeMem(size_t *total)
{
// Error
if (total)
*total = 0L;
*total = 0;
return 0;
}
memTag += sizeof (MEMTOTAL);
totalKBytes = (size_t)atoi(memTag);
totalKBytes = strtoul(memTag, NULL, 10);
if ((memTag = strstr(buf, MEMAVAILABLE)) == NULL)
{
@@ -2696,7 +2706,7 @@ size_t I_GetFreeMem(size_t *total)
{
// Error
if (total)
*total = 0L;
*total = 0;
return 0;
}
freeKBytes = MemAvailable;
@@ -2704,12 +2714,40 @@ size_t I_GetFreeMem(size_t *total)
else
{
memTag += sizeof (MEMAVAILABLE);
freeKBytes = atoi(memTag);
freeKBytes = strtoul(memTag, NULL, 10);
}
if (total)
*total = totalKBytes << 10;
return freeKBytes << 10;
#elif defined(__APPLE__)
/* macOS */
mach_port_t host = mach_host_self();
kern_return_t kr;
mach_msg_type_number_t count;
vm_size_t v_page_size;
struct vm_statistics64 vm_stats;
uint64_t total_mem, free_mem;
size_t size;
size = sizeof(total_mem);
if (sysctlbyname("hw.memsize", &total_mem, &size, NULL, 0) < 0)
total_mem = 0;
kr = host_page_size(host, &v_page_size);
if (kr != KERN_SUCCESS)
v_page_size = 4096;
count = HOST_VM_INFO64_COUNT;
kr = host_statistics64(host, HOST_VM_INFO64, (host_info64_t)&vm_stats, &count);
if (kr == KERN_SUCCESS)
free_mem = (uint64_t)(vm_stats.free_count + vm_stats.inactive_count) * v_page_size;
else
free_mem = 0;
if (total)
*total = (size_t)total_mem;
return (size_t)free_mem;
#else
// Guess 48 MB.
if (total)
+3
View File
@@ -1816,15 +1816,18 @@ void I_StartupGraphics(void)
framebuffer = SDL_TRUE;
}
// Choose Software renderer
if (M_CheckParm("-software"))
rendermode = render_soft;
#ifdef HWRENDER
// Choose OpenGL renderer
else if (M_CheckParm("-opengl"))
rendermode = render_opengl;
msaa = 0; boolean msaa_set = false;
a2c = false; boolean a2c_set = false;
// MSAA antialiasing
if (M_CheckParm("-msaa") && M_IsNextParm())
{
const char* str = M_GetNextParm();
+923 -930
View File
File diff suppressed because it is too large. Load diff
+2
View File
@@ -59,6 +59,8 @@ typedef enum
#define NUMSFXFREESLOTS 1600 // Matches SOC Editor.
#define NUMSKINSFXSLOTS (MAXSKINS*NUMSKINSOUNDS)
#define MAXSOUNDNAME 7
//
// SoundFX struct.
//
+3 -1
View File
@@ -14,6 +14,7 @@
/// Does palette indicators as well (red pain/berserk, bright pickup)
#include "doomdef.h"
#include "d_main.h"
#include "g_game.h"
#include "g_input.h"
#include "k_director.h"
@@ -172,7 +173,8 @@ INT32 st_palette = 0;
void ST_ResetPaletteStuff(void)
{
st_palette = 0;
V_SetPalette(0);
if (loaded_config)
V_SetPalette(0);
}
static void ST_doPaletteStuff(void)
+16 -3
View File
@@ -676,6 +676,7 @@ static void CV_palette_OnChange(void)
{
if (!loaded_config)
return;
// reload palette
// recalculate Color Cube
V_ReloadPalette();
@@ -1563,8 +1564,8 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
{ // mpc 12-04-2018
const UINT8 *fadetable = ((UINT8 *)transtables + ((alphalevel-1)<<FF_TRANSSHIFT) + (c*256));
#define clip(x,y) (x>y) ? y : x
w = clip(w,vid.width);
h = clip(h,vid.height);
w = clip(w, vid.width);
h = clip(h, vid.height);
#undef clip
for (v = 0; v < h; v++, dest += vid.width)
{
@@ -2718,6 +2719,7 @@ void V_DrawSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *st
INT32 charflags = 0;
const UINT8 *colormap = NULL;
INT32 spacewidth = 2, charwidth = 0;
INT32 lowercase = (option & V_ALLOWLOWERCASE);
option &= ~V_FLIP; // which is also shared with V_ALLOWLOWERCASE...
@@ -2738,6 +2740,7 @@ void V_DrawSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *st
scrwidth *= vid.dup;
charflags = (option & V_CHARCOLORMASK);
colormap = V_GetStringColormap(charflags);
switch (option & V_SPACINGMASK)
{
@@ -2762,7 +2765,11 @@ void V_DrawSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *st
{
// manually set flags override color codes
if (!(option & V_CHARCOLORMASK))
{
charflags = ((*ch & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK;
colormap = V_GetStringColormap(charflags);
}
continue;
}
@@ -2806,7 +2813,6 @@ void V_DrawSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *st
continue;
}
colormap = V_GetStringColormap(charflags);
V_DrawFixedPatch(cx + (center<<FRACBITS), cy, FRACUNIT/2, option, hu_font[c], colormap);
cx += w<<FRACBITS;
}
@@ -2818,6 +2824,13 @@ void V_DrawCenteredSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, const
V_DrawSmallStringAtFixed(x, y, option, string);
}
void V_DrawRightAlignedSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string)
{
x -= V_SmallStringWidth(string, option)<<FRACBITS;
V_DrawSmallStringAtFixed(x, y, option, string);
}
// Draws a thin string at a fixed_t location.
void V_DrawThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string)
{
fixed_t cx = x, cy = y;
+1
View File
@@ -252,6 +252,7 @@ void V_DrawStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string)
void V_DrawSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string);
void V_DrawCenteredSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string);
void V_DrawRightAlignedSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string);
void V_DrawThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string);
+87 -29
View File
@@ -123,6 +123,9 @@ static const char pat_end[] = {0x50, 0x4b, 0x05, 0x06, 0x00};
UINT16 numwadfiles = 0; // number of active wadfiles
wadfile_t *wadfiles[MAX_WADFILES] = {}; // 0 to numwadfiles-1 are valid
// use strnlen as some lump names may not be null terminated
#define CHECKMAPMARKER(name) (memcmp(name, "MAP", 3) == 0 && strnlen(name, 8) == 5)
// W_Shutdown
// Closes all of the WAD files before quitting
// If not done on a Mac then open wad files
@@ -2392,7 +2395,7 @@ static int W_NameStartsWith(const char *name, lumpchecklist_t *checklist)
}
// Checks if file contains at least one lump which name starts with one of strings in checklist
static int W_CheckWADContains(FILE *fp, lumpchecklist_t *checklist)
static int W_CheckWADContainsEx(FILE *fp, lumpchecklist_t *checklist, boolean checkmap)
{
size_t i, j;
// if we're here it's a WAD file
@@ -2433,13 +2436,29 @@ static int W_CheckWADContains(FILE *fp, lumpchecklist_t *checklist)
if (!strncmp(lumpinfo.name, sprnames[j], 4)) // Sprites
continue;
if (W_NameStartsWith(lumpinfo.name, checklist))
if (checkmap)
{
if (CHECKMAPMARKER(lumpinfo.name))
return true;
}
else if (W_NameStartsWith(lumpinfo.name, checklist))
return true;
}
return false;
}
static int W_CheckPK3Contains(FILE *fp, lumpchecklist_t *checklist)
static int W_CheckWADContains(FILE *fp, lumpchecklist_t *checklist)
{
return W_CheckWADContainsEx(fp, checklist, false);
}
static int W_CheckWADContainsMap(FILE *fp)
{
return W_CheckWADContainsEx(fp, NULL, true);
}
static int W_CheckPK3ContainsEx(FILE *fp, lumpchecklist_t *checklist, boolean checkmap)
{
zend_t zend;
zlentry_t zlentry;
@@ -2513,13 +2532,23 @@ static int W_CheckPK3Contains(FILE *fp, lumpchecklist_t *checklist)
memset(lumpname, '\0', 9); // Making sure they're initialized to 0. Is it necessary?
strncpy(lumpname, trimname, min(8, dotpos - trimname));
if (W_NameStartsWith(lumpname, checklist))
if (checkmap)
{
if (CHECKMAPMARKER(lumpname))
return true;
}
else if (W_NameStartsWith(lumpname, checklist))
{
return true;
}
}
if (W_NameStartsWith(fullname, checklist))
if (checkmap)
{
if (CHECKMAPMARKER(fullname))
return true;
}
else if (W_NameStartsWith(fullname, checklist))
{
return true;
}
@@ -2561,12 +2590,24 @@ static int W_CheckPK3Contains(FILE *fp, lumpchecklist_t *checklist)
}
}
static int W_CheckFileContains(const char *filename, lumpchecklist_t *checklist)
static int W_CheckPK3Contains(FILE *fp, lumpchecklist_t *checklist)
{
return W_CheckPK3ContainsEx(fp, checklist, false);
}
static int W_CheckPK3ContainsMap(FILE *fp)
{
return W_CheckPK3ContainsEx(fp, NULL, true);
}
static int W_CheckFileContainsEx(const char *filename, lumpchecklist_t *checklist, boolean checkmap)
{
FILE *handle;
int contains = false;
if (!checklist)
// if we just check for maps this will be NULL
// hacky but i dont care
if (!checklist && !checkmap)
I_Error("No checklist for %s\n", filename);
// open wad file
@@ -2577,27 +2618,41 @@ static int W_CheckFileContains(const char *filename, lumpchecklist_t *checklist)
if (type == RET_PK3)
{
contains = W_CheckPK3Contains(handle, checklist);
if (checkmap)
contains = W_CheckPK3ContainsMap(handle);
else
contains = W_CheckPK3Contains(handle, checklist);
}
else if (type == RET_WAD)
{
contains = W_CheckWADContains(handle, checklist);
if (checkmap)
contains = W_CheckWADContainsMap(handle);
else
contains = W_CheckWADContains(handle, checklist);
}
fclose(handle);
return contains;
}
static int W_CheckFileContains(const char *filename, lumpchecklist_t *checklist)
{
return W_CheckFileContainsEx(filename, checklist, false);
}
static int W_CheckFileContainsMap(const char *filename)
{
return W_CheckFileContainsEx(filename, NULL, true);
}
// kinda stupid but we cant just check for any lump containing "MAP"
// we have to explicitly check if its MAP and 5 characters long
// the more correct way would be checking inside wad files nested within pk3´s
// and check the presence of actual map data like SSECTORS or something
// but man i cannot be assed to rework shit for that
int W_CheckAutoLoadContainsMap(const char *filename)
{
// for now this checks for map marker
static lumpchecklist_t autoloadblacklist[] =
{
{"MAP", 3},
{NULL, 0},
};
return W_CheckFileContains(filename, autoloadblacklist);
return W_CheckFileContainsMap(filename);
}
int W_CheckPostLoadList(const char *filename)
@@ -2676,8 +2731,9 @@ virtres_t* vres_GetMap(lumpnum_t lumpnum)
vlumps[i].size = vsizecache[realentry];
const char *name = (fileinfo + realentry)->name;
I_Assert(name != NULL);
if (strnlen(name, 8) == 5 && memcmp(name, "MAP", 3) == 0)
if (!name || CHECKMAPMARKER(name))
{
numlumps--; // We skip map marker, so 1 of entries becomes empty
continue; // This will skip i++ so we will write to same entry
@@ -2686,9 +2742,7 @@ virtres_t* vres_GetMap(lumpnum_t lumpnum)
// Play it safe with the name in this case.
memcpy(vlumps[i].name, name, 8);
vlumps[i].name[8] = '\0';
vlumps[i].data = (UINT8 *)(
Z_Malloc(vlumps[i].size, PU_LEVEL, NULL) // This is memory inefficient, sorry about that.
);
vlumps[i].data = (UINT8 *)(Z_Malloc(vlumps[i].size, PU_LEVEL, NULL)); // This is memory inefficient, sorry about that.
memcpy(vlumps[i].data, wadData + LONG((fileinfo + realentry)->filepos), vlumps[i].size);
i++;
}
@@ -2698,15 +2752,20 @@ virtres_t* vres_GetMap(lumpnum_t lumpnum)
}
else
{
// Count number of lumps until the end of resource OR up until next "MAPXX" lump.
// Count number of lumps until the end of resource OR up until next 0-length lump OR up until next "MAPXX" lump.
lumpnum_t lumppos = lumpnum + 1;
for (i = LUMPNUM(lumppos); i < wadfiles[WADFILENUM(lumpnum)]->numlumps; i++, lumppos++, numlumps++)
{
const char *name = W_CheckNameForNum(lumppos);
if (name == NULL)
continue;
if (W_LumpLength(lumppos) == 0)
{
break;
}
if (memcmp(name, "MAP", 3) == 0 || W_LumpLength(lumppos) == 0)
const char *name = W_CheckNameForNum(lumppos);
I_Assert(name != NULL);
// if no name then theres no lump
if (!name || CHECKMAPMARKER(name))
{
break;
}
@@ -2721,10 +2780,9 @@ virtres_t* vres_GetMap(lumpnum_t lumpnum)
{
// Check if it is map marker. It is not always first lump sadly, so we need to expect it anywhere
const char *name = W_CheckNameForNum(lumpnum);
if (name == NULL)
continue;
I_Assert(name != NULL);
if (strlen(name) == 5 && memcmp(name, "MAP", 3) == 0)
if (!name || CHECKMAPMARKER(name))
{
--i; // Decrement so on next iteration we write on same i, so we don't leave corrupted vlumps entry
numlumps--; // Just so we don't try to access the leftover vlumps entry
+10
View File
@@ -114,6 +114,7 @@ void Z_Init(void)
head.next = head.prev = &head;
memfree = I_GetFreeMem(&total)>>20;
CONS_Printf("System memory: %sMB - Free: %sMB\n", sizeu1(total>>20), sizeu2(memfree));
// Note: This allocates memory. Watch out.
@@ -745,6 +746,7 @@ static void Command_Memfree_f(void)
CONS_Printf(M_GetText("HUD graphics : %7s KB\n"), sizeu1(Z_TagUsage(PU_HUDGFX)>>10));
CONS_Printf(M_GetText("Locked cache : %7s KB\n"), sizeu1(Z_TagUsage(PU_CACHE)>>10));
CONS_Printf(M_GetText("Level : %7s KB\n"), sizeu1(Z_TagUsage(PU_LEVEL)>>10));
CONS_Printf(M_GetText("Level (pooled) : %7s KB\n"), sizeu1(Z_LevelPoolUsage()>>10));
CONS_Printf(M_GetText("Special thinker : %7s KB\n"), sizeu1(Z_TagUsage(PU_LEVSPEC)>>10));
CONS_Printf(M_GetText("All purgable : %7s KB\n"),
sizeu1(Z_TagsUsage(PU_PURGELEVEL, INT32_MAX)>>10));
@@ -804,6 +806,14 @@ char *Z_StrDup(const char *s)
return strcpy((char*)ZZ_Alloc(strlen(s) + 1), s);
}
size_t Z_LevelPoolUsage(void)
{
return g_level_large_pool.allocated_bytes()
+ g_level_med_pool.allocated_bytes()
+ g_level_small_pool.allocated_bytes()
+ g_level_tiny_pool.allocated_bytes();
}
void* Z_LevelPoolMalloc(size_t size)
{
void* p = nullptr;
+1
View File
@@ -167,6 +167,7 @@ char *Z_StrDup(const char *in);
//
// Specialty allocation functions
//
size_t Z_LevelPoolUsage(void);
void *Z_LevelPoolMalloc(size_t size);
void *Z_LevelPoolCalloc(size_t size);
void Z_LevelPoolFree(void *p, size_t size);