Compare commits

..
234 Commits
Author SHA1 Message Date
Alug 0ac0f2bae2 forgor to remove this 2024-10-26 00:51:24 +02:00
Alug cee28c6166 refactor a bunch of crap and fix skyportals 2024-10-25 22:58:10 +02:00
Alug a6be267325 Add visplane portal creation functionality and use it to replace the skybox rendering.
https://git.do.srb2.org/STJr/SRB2/-/commit/264386f84257a47fe5480bb6300df02d039a2491
2024-10-25 22:58:05 +02:00
Alug 426740e0ac port srb2 software portal refactor 2024-10-25 22:57:43 +02:00
Alug 78c0f64135 dont pass skybox to r_setupframe
why was this even done?
neither srb2 nor v2/rr ever did this?
2024-10-25 22:57:38 +02:00
indev b6e766ee44 Fix A_Lua not removing error handler from lua stack 2024-10-25 23:15:52 +03:00
Alug 5437040b78 move the return ealier in V_DoPostProcessor 2024-10-25 20:21:10 +02:00
Alug c786569981 Merge branch 'refactorpostimg' into Saturn-Next 2024-10-25 20:12:56 +02:00
Alug 7064b14539 Merge branch 'autoloadagain' into Saturn-Next 2024-10-25 20:12:53 +02:00
Alug f275ae98f5 this is needed for postimg stuff in first person
lol
also adds break in splitscreen lööp
2024-10-25 20:12:14 +02:00
Alug ef07d89e29 Revert "update lzf compression to 1.6"
This reverts commit 48e71afec1.
2024-10-25 19:50:16 +02:00
Alug b9bbd45e15 Revert "shut up mingw"
This reverts commit 75637e361c.
2024-10-25 19:50:10 +02:00
Alug 2bda27b80d Revert "those should be size_t"
This reverts commit b357c09171.
2024-10-25 19:49:26 +02:00
Alug 6ebf90cc50 Merge branch 'Saturn-Next' into autoloadagain 2024-10-25 03:28:43 +02:00
Alug ea00bebb04 Merge branch 'Saturn-Next' into refactorpostimg 2024-10-25 03:28:20 +02:00
Alug b862d835a5 save one calc lol 2024-10-25 03:27:51 +02:00
Alug d6602747ae oops forgor lol 2024-10-25 03:26:22 +02:00
Alug 9f79429d03 slight cleanup + make static + smol optimize ogl sprite drawers 2024-10-25 03:26:19 +02:00
Alug 5ff0c09868 just check for noencore bool in hwr_processseg instead of checked line flags everytime 2024-10-23 21:33:31 +02:00
Alug ad1c3e63a4 why not reuse those? 2024-10-23 21:33:28 +02:00
Alug 24dd6ba675 cleanup HWR_ProcessSeg
stuff was quite the mess
2024-10-23 21:33:21 +02:00
Alug 85f036a45b dont always calc this twice 2024-10-23 21:33:14 +02:00
Alug 6f8342b9a8 remove cv_splitwallfix
tbh i dont think anyone even knows about this, never heard any complains, never had any issues, neither visually or performancewise.
its just clutter at this point
2024-10-23 21:33:04 +02:00
Alug c5c6f6b820 this does nothing 2024-10-23 21:30:21 +02:00
Alug 3d472c34a1 no need to check stuff in already postload marked addons 2024-10-23 15:48:44 +02:00
Alug 63ca366bd8 dont play rain sounds when weather is disabled 2024-10-23 13:00:36 +02:00
Alug e9e888ab7f remove debug print 2024-10-23 02:41:28 +02:00
indev 5ea55b3e3a Add W_CheckFileContains for W_CheckPostLoadList 2024-10-23 02:41:25 +02:00
Alug 8b1797927a attempt to check for things in file for postload detection 2024-10-23 02:41:23 +02:00
Alug 05a98964fb split auto and postload, let autoload run on gamestart again
prep for smth
2024-10-23 02:41:20 +02:00
Alug 8cbf798de8 redo rain sound overflow fix
https://git.do.srb2.org/KartKrew/RingRacers/-/commit/3eac1fed0f44a8285a9f6b82a12e86997bbb0d34
2024-10-23 02:37:32 +02:00
Alug 9314a24cb2 use highly optmized (but slightly inaccurate) version of R_PointOnSide for rendering 2024-10-23 02:37:08 +02:00
Alug 19b1683e61 make those not look terrible thx 2024-10-22 01:18:13 +02:00
Alug d029107e75 refactor postimg stuff so it can be combined with each other better
thx much indev! <3
everything now works with encore!
software now also supports screen effects in splitscreen!
2024-10-22 01:17:57 +02:00
Alug bc97e0b703 actually remove "renderflags" lol 2024-10-21 22:53:44 +02:00
Alug f47c663f79 remove renderflags
those literally did nothing
2024-10-21 22:47:32 +02:00
Alug 6f9d41eadb fix R_ThingVisible
those are "eflags" in kart smh
2024-10-21 22:46:59 +02:00
Alug 1b512edc56 add proper null check here too 2024-10-21 21:28:08 +02:00
Alug 884a6da2bd dont use cv_sloperolldist in splitscreen + save some assignments and one fixedhypot call
also use tabs lul
2024-10-21 21:07:32 +02:00
Alug 7a3d958fc1 tab pls 2024-10-21 18:43:08 +02:00
Alug 7223581539 Clarify we're calculating a cross product 2024-10-21 18:10:29 +02:00
Alug 664bd2de3f dont draw fadescreen when minimap iss active 2024-10-21 17:47:44 +02:00
indev 63568e3861 Fix off-by-one error for using '?' as map name 2024-10-21 18:43:37 +03:00
indev f149d058a1 Fix off-by-one error in lib_setSfxInfo 2024-10-21 18:06:35 +03:00
Alug 970251ced3 also check here ig? 2024-10-21 17:01:27 +02:00
Alug dba7a7dc3c prevent map command crash from maps with invalid or non existing mapinfo 2024-10-21 15:37:44 +02:00
Alug 393c0be407 Revert "attempt to optimize some p_maputl stuff"
This reverts commit 81d415c5ba.
2024-10-21 14:19:35 +02:00
Alug 5e9ea2429b replace those two P_MobjWasRemoved with simple null check insteead
since those may actually segfault if null anyways
2024-10-21 06:23:14 +02:00
Alug 81a14995da trailing space hell 2024-10-21 06:14:24 +02:00
Alug 4267ac9a8d remove more P_MobjWasRemoved checks
same as before, those may be not synchsafe
2024-10-21 06:04:47 +02:00
Alug bcf72cc0e8 revert some P_MobjWasRemoved checks i forgor about
those may NOT be vanilla netsafe
2024-10-21 06:04:17 +02:00
Alug 54d9a98090 rotsprite stuff also should be SHORT 2024-10-20 19:11:54 +02:00
Alug 81d415c5ba attempt to optimize some p_maputl stuff 2024-10-20 16:25:12 +02:00
Alug de1b801bda try to take some registers for span drawers too 2024-10-20 16:24:02 +02:00
Alug 2c665fef6f remove this again 2024-10-20 15:21:42 +02:00
Alug c6fbf405bf optimize R_PointOnSegSide
its only used for 2 rendering functions, so being potentially inaccurate is not that dangerous and the speedup in some instances might be worth the tradeoff
2024-10-20 15:16:37 +02:00
Alug 7076c35521 HWR_RenderPlane can be static 2024-10-20 14:57:28 +02:00
Alug 86ed1b709e fix some rendering issues and crashes in software renderer
- Increase MINZ from 4 fracunits to 16
- R_StoreWallRange: do not render textures with holes
- fix off-by-one error in R_ProjectSprite
- Avoid rendering unused left/right edges of screen while rolling
- Clamp patch column post drawing bounds
- Vissprites: set dc.texheight
- Add null check for column in R_DrawMaskedColumn
2024-10-20 14:57:22 +02:00
Alug d30c96e8cb fix a maybe-uninitialized warning 2024-10-20 00:22:06 +02:00
Alug 0af52ba3ae dont need to always check this 16 times if we already know theres more than one player ingame 2024-10-19 21:15:11 +02:00
Alug fbe97556de change versionstring
also remove the fbo one, its honestly not necessary anymore
2024-10-18 20:36:16 +02:00
Alug 7a6f43bece dont show encore toggle text in record attack menu
dont think you can even record attack in encore hmm
2024-10-18 20:34:22 +02:00
Alug afca521fe5 dont run director if theres only one player ingame
idk if this is good lol
2024-10-18 19:53:44 +02:00
Alug d3e2875c94 those can be registered in lööp 2024-10-16 13:14:31 +02:00
Alug 1daac9a124 revert all the cam things for now here
Dont wanna deal with this shit for 7.1 anymore
2024-10-14 22:15:27 +02:00
Alug 38f3e48aed only do this in software renderer
doesent work even with pal rendering in ogl
2024-10-13 23:07:37 +02:00
indev 4cf4d49f48 Fix error handler staying on lua stack after lua commands being called 2024-10-13 15:37:39 +03:00
indev a19c4dc5e5 Fix game crashing when using P_DoPlayerExit on player without mobj 2024-10-13 15:37:39 +03:00
Alug d37505ff06 this should be SHORT 2024-10-13 02:59:10 +02:00
Alug 7f6ce1f299 this uhhh actually makes things crash lol 2024-10-13 02:47:57 +02:00
Alug 262a84aac6 fix ogl shearing
no clue wtf kart was doing here lmao
2024-10-13 02:42:37 +02:00
Alug 3f12ebb2bd only interp cam during pause for replay freecam to not jitter during pause 2024-10-13 01:11:59 +02:00
Alug b58fcf331c ignore keepmusic when called from P_RestoreMusic
most of the sound handling just calls this and this may just stop the music entirely on some occasions so just ignore keepmusic for that
2024-10-13 00:40:51 +02:00
Alug fe51278295 Merge branch 'newmusicstuff' into Saturn-Next 2024-10-13 00:04:59 +02:00
Alug c3fb84981e Merge branch 'pakcheck' into Saturn-Next 2024-10-13 00:02:32 +02:00
Alug 919aad4f30 Merge branch 'vres-skip-map-marker' into Saturn-Next 2024-10-12 23:57:27 +02:00
Alug 818e6046b7 Merge branch 'Saturn-Next' into vres-skip-map-marker 2024-10-12 23:30:03 +02:00
Alug f01d2a0ba6 print saturnpak print into debfile instead of console 2024-10-12 23:29:11 +02:00
Alug 8df0a2d059 Merge branch 'Saturn-Next' into pakcheck 2024-10-12 23:28:05 +02:00
Alug d7ed91af1d Refactor TTY input handling
https://git.do.srb2.org/STJr/SRB2/-/merge_requests/2451#b2f76b3273f1780347c35ec752bcde560c5f73a5
2024-10-12 23:26:14 +02:00
Alug 081dcc021b fix tty converting everything to lowercase 2024-10-12 23:21:11 +02:00
Alug 70ebd0d475 Merge remote-tracking branch 'origin/unified-text-input' into Saturn-Next 2024-10-12 23:19:38 +02:00
Alug 02bbb38606 Fix insane TTY input latency
https://git.do.srb2.org/STJr/SRB2/-/merge_requests/2360
2024-10-12 23:16:42 +02:00
indev d00014ea59 If corrupted save received, leave netgame 2024-10-12 22:10:58 +02:00
indev 210d6ac8ac Add few checks to prevent game crashing if netgame archive becomes corrupted 2024-10-12 22:10:48 +02:00
indev 55248e7fcf Attempt to fix a lua panic when unarchiveing extvars (print error to console instead. Not sure if it would be safe for game to read from save afterwards though) 2024-10-12 22:09:51 +02:00
Alug 23b36b5074 oops 2024-10-12 21:29:49 +02:00
Alug 2e7f0721b9 make s_sound a little prettier 2024-10-12 21:24:43 +02:00
Alug 4927e55c7e fix some warnings when compiling with older sdl version 2024-10-12 21:24:04 +02:00
Alug c51d33fa6e save 1 G_BuildMapTitle call kek 2024-10-12 20:19:53 +02:00
Alug 8630d8cd47 clean bird music stuff again
we dont need to return everywhere but instead stuff can be mostly just set to 0
this also somewhat ensures stuff works after toggling without having to restart the game or map
2024-10-12 19:55:02 +02:00
Alug 659243baa1 always assign stutter_threshold 2024-10-12 19:44:21 +02:00
Alug b6a84c1646 readd music_resync_powerups_only 2024-10-12 19:40:12 +02:00
Alug c33afa4a3b shut up mingw 2024-10-11 19:09:49 +02:00
Alug 1428c3c2bf fix spec cam bug + more cleanup 2024-10-11 21:00:13 +02:00
Alug aa0cbfda74 Revert "rendertimefrac_unpaused should be fracunit on netlag"
This reverts commit 6722b43244.
2024-10-09 15:33:19 +02:00
Alug 9d13ff3c9f proper inline P_MobjWasRemoved 2024-10-07 23:01:52 +02:00
Alug e47c13b7ac proper inline M_Memcpy 2024-10-07 23:01:45 +02:00
Alug 3f5b96bd45 this shouldnt be here lol 2024-10-07 13:15:08 +02:00
Alug 63c1372c34 keep debug print for now 2024-10-07 12:57:55 +02:00
Alug 8b915f9ac1 make this less ugly 2024-10-07 12:53:31 +02:00
Alug f3a18a0655 false 2024-10-07 12:48:36 +02:00
Alug e8351d44b6 add crap to menu 2024-10-07 12:45:03 +02:00
Alug 297af069cb doubt anyone wants this
also psure this will cause some weird issues somewhere idk
2024-10-07 12:41:59 +02:00
Alug baa5d6630d Merge branch 'Saturn-Next' into newmusicstuff 2024-10-07 12:39:41 +02:00
Alug 0c30730ef6 Merge branch 'Saturn-Next' into pakcheck 2024-10-06 18:52:24 +02:00
Alug c82148fafc prevent this from become super large somehow lol
just like cap it at 19 it works just fine
2024-10-06 18:50:32 +02:00
Alug d1346dee53 shouldnt that be a bool? 2024-10-06 18:31:54 +02:00
Alug 6722b43244 rendertimefrac_unpaused should be fracunit on netlag
makes this a little more sane tbh
2024-10-06 18:31:51 +02:00
Alug cfdbf1f4ad hopefully fix awayview cam interp crap 2024-10-06 14:53:10 +02:00
Alug 48a00ba911 this needs to be set twice
Zzz...
2024-10-06 14:52:54 +02:00
Alug 4b1102357a only do this in replays
otherwise shit will jitter during netlag
2024-10-06 14:46:11 +02:00
Alug e3b0204b2c fix main menu interpolation
apparently in main menu, opening the menu pauses the game so rendertimefrac was FRACUNIT and didnt interpolate
2024-10-06 14:46:06 +02:00
Alug a2799ddcca Interpolate view, even when paused
https://github.com/KartKrewDev/RingRacers/commit/3320faec8cebecb124882d38c7ec0ad37b79340a#diff-607b68058edc6124b3061267d902aabeddb6ba338c6483df0af8b1a7cf796a01R43
2024-10-06 14:46:03 +02:00
Alug 76198f61de add missing break 2024-10-06 14:45:50 +02:00
Alug ff2006ad74 smol fix 2024-10-06 12:40:01 +02:00
Alug 55c9c7297f throw this into own function too 2024-10-06 12:39:56 +02:00
Alug 4b083ee72e make function for quakes, scale with mobjscale 2024-10-06 12:39:54 +02:00
Alug 6574ec2fb9 attempt to cleanup R_SetupFrame 2024-10-06 12:39:48 +02:00
Alug f54bb349b5 add G_FixCamera 2024-10-06 12:39:44 +02:00
Alug 6f1252e27d set timeinmap for demo rewind
idk maybe this helps with that feature desynching all the time lol
2024-10-06 12:39:26 +02:00
Alug 7d65b5369f add some brackets lul 2024-10-06 12:34:51 +02:00
Alug 4877c81728 comment this out for now so v7 clients dont use vanilla resynch system
keep sending PT_WILLRESENDGAMESTATE packets to everyone for now
saturnpak will still mark the right clients so they will use the right consistency check without having to desynch first
2024-10-06 12:32:57 +02:00
Alug 5cb207edfa add debfile prints whenever gamestate counter changes 2024-10-06 12:14:32 +02:00
Alug fc39a0dedf make the debug print a little better 2024-10-06 12:12:59 +02:00
Alug 0b3e7240a8 use saturn packet to determine if client can receive gamestate
before the server always assumed every client cant receive the gamestate using the vanilla consistency check for everyone.
aswell as before the first resynch it tried to send the gamestate resend packets to everyone
2024-10-06 12:07:17 +02:00
Alug f32c346534 this needs gamestate check
sometimes the title music kept playing
2024-10-05 06:56:31 +02:00
Alug 3165004d0e add comment to try and explain this crap 2024-10-03 18:15:19 +02:00
Alug ec3b1cf130 make this more readable 2024-10-03 17:55:08 +02:00
Alug a0437713bf smol dupe 2024-10-02 14:40:03 +02:00
Alug 96f7ff550c prevent this from overflowing
ye well idk anymore.
2024-10-02 14:22:48 +02:00
Alug 837216d78e we dont need any of this in ogl 2024-10-02 14:22:39 +02:00
Alug dfb6006f9c fix up old fps counter 2024-10-02 12:14:40 +02:00
indev fb0765a5f3 Fix selection in replay save prompt 2024-10-01 20:55:27 +03:00
indev 2e8769496f Use textinput_t for replay save prompt too 2024-10-01 20:39:04 +03:00
Alug bdb39fcd8d dont leak pls 2024-10-01 17:57:45 +02:00
Alug 31516c7987 fix G_BuildMapTitle leaks 2024-10-01 17:56:15 +02:00
Alug b985ce06a2 lol 2024-10-01 16:03:56 +02:00
Alug 12d6546062 dumb special case for wandering balls Zzz... 2024-10-01 16:03:00 +02:00
indev fb71da3627 Remove debug print 2024-10-01 16:50:44 +03:00
indev a90ffff320 Fix (hopefully) all other menu types that use IT_CV_STRING 2024-10-01 16:49:59 +03:00
Alug 9abf2bca75 fix some stuff 2024-10-01 15:46:22 +02:00
indev 3db6770dfd Fix IT_CV_STRING crashing game in M_DrawGenericMenu 2024-10-01 16:24:14 +03:00
Alug 3a951576ee use stricmp for this 2024-10-01 15:22:29 +02:00
Alug 6b0d67ac36 more 2024-10-01 15:22:25 +02:00
Alug d06b8ac398 cleanup + comments 2024-10-01 15:22:22 +02:00
Alug 67435ebf9e work around encore music again
S_InitMapMusic would play before the level actually started thus playing a smol bit of non encore music in encore
2024-10-01 15:22:19 +02:00
Alug 2ee29630fb fix encore music again lol 2024-10-01 15:22:16 +02:00
Alug 7fa21e9aea work around custom vote theme music + rename a bunch of stuff
please help me
2024-10-01 15:22:08 +02:00
Alug b4b206f575 encoremusic... 2024-10-01 15:22:04 +02:00
Alug f363663b3e fix up everything and make stuff work
i hope lmao
2024-10-01 15:22:01 +02:00
Alug 42d957e21b change how keepmusic works
compare map and encore instead of the music itself
2024-10-01 15:21:57 +02:00
Alug 07f9756bc8 forgor about encore music 2024-10-01 15:21:54 +02:00
Alug e958e43b49 update comments a little 2024-10-01 15:21:51 +02:00
Alug 0d150e4b08 add some basics of what i wanna have for music stuff
- basic keepmusic implementation (currently checks for if the song changes instead of the map, idk if i keep this, since this allows certain maps to change the music on start, ex abstract avenue or wandering balls)
- Toggle to ignore any kind of music change during the level (includes intermission music, depends on how custom intermission music works)
-toggle to start map music instantly on levelload and skip the intro fanfare (also skips any linedef executed sound so some map intros dont interfere with this)
2024-10-01 15:21:47 +02:00
Alug 0deff73a46 make a function for the music level start stuff 2024-10-01 15:21:43 +02:00
Alug b24caf397a add "map ?" shortcut for random map 2024-10-01 14:49:46 +02:00
Alug f051e33a0c cv_showdirectorhud didnt save Zzz... 2024-09-30 23:00:39 +02:00
indev ff2b28ac73 Use m_textinput for chat too 2024-09-30 12:13:25 +03:00
indev e2367d26d1 Use same keyboardlayout code as in chat for textinput, also add a null terminator after ctrl-v just in case string is not always zeroed out already 2024-09-30 12:08:21 +03:00
indev e1a65add5d Put all text input logic into separate file and use it for all text input fields 2024-09-30 10:35:27 +03:00
Alug 913426bfdb let SOC also use PRECIP_BLANK/ weather = 4
no idea why it couldnt doesent make any sense
2024-09-29 22:28:35 +02:00
Alug d7b0726e42 no need to even traverse part of the blockmap when PRECIP_STORM_NORAIN and PRECIP_BLANK 2024-09-29 22:28:31 +02:00
Alug cadb67e6c9 move this stuff
so dont need check for renderisnewtic multiple  times and dont need to check for menu and dpad stuff every single frame
2024-09-29 15:15:53 +02:00
Alug 564838a439 only draw lua hud stuff when patch exists 2024-09-29 15:15:49 +02:00
Alug 4554bcc565 reset rumble on some conditions 2024-09-28 03:29:12 +02:00
Alug fd48335688 Replace portalline boolean with g_portal pointer to current portal Beta 2024-09-28 03:29:09 +02:00
Alug 222f56d1b2 smol director stuffs 2024-09-28 01:03:44 +02:00
Alug b71870f57b this needs no dedi check actually 2024-09-28 01:03:41 +02:00
Alug 01c9632025 set those in P_SpawnGhostMobj too 2024-09-28 01:03:39 +02:00
Alug 1533e13d68 let player pointer be const in P_IsLocalPlayer and P_IsDisplayPlayer 2024-09-28 01:03:34 +02:00
Alug 89965ad718 forgor remove this 2024-09-28 01:03:31 +02:00
Alug eb74f3525a consolidate this 2024-09-28 01:03:29 +02:00
Alug 536f88dee0 this does nothing 2024-09-28 01:03:26 +02:00
Alug 2622ba286e z 2024-09-28 01:03:18 +02:00
Alug a1d490cb49 R_DrawMaskedColumn: do not draw zero length column 2024-09-28 01:03:15 +02:00
Alug b357c09171 those should be size_t 2024-09-28 01:03:11 +02:00
Alug 48e71afec1 update lzf compression to 1.6 2024-09-28 01:03:08 +02:00
Alug 1c6fce9339 fix encore minimap 2024-09-27 15:05:38 +02:00
Alug 96551d3b75 use qs22j here again
it is really faster
thought it wasnt in this case
2024-09-27 15:05:34 +02:00
Alug 7a832df4d3 cleanup + reformatting 2024-09-27 15:05:31 +02:00
Alug c3b6121968 forgor this 2024-09-27 15:04:15 +02:00
Alug b3b2b65c5f reformat this 2024-09-27 15:04:12 +02:00
Alug 7a3ccec38d ; 2024-09-26 18:18:42 +02:00
Alug d8da0a11a2 gamestate resend counter was never proper reset for nodes
means it would carry over to the next person occupieing that node and made them have less chances to get the gamestate resent
2024-09-25 19:31:25 +02:00
Alug d5c3332635 those can be static 2024-09-24 22:23:29 +02:00
Alug 0137f2254d add toggle for water ripples Zzz... 2024-09-24 22:18:27 +02:00
Alug da769ce524 only allow director toggling with button when you spec someone 2024-09-24 16:57:25 +02:00
Alug 2e99636bb0 make director text disappear after 13 seconds, and in replays after 4 2024-09-24 15:25:56 +02:00
indev ff7f68f5b4 Expose demo.freecam as replayfreecam 2024-09-24 16:05:22 +03:00
Alug 14eec0c902 dont show director text when in replay freecam 2024-09-24 15:03:31 +02:00
Alug b064c534d8 hide viewpoint text when in replay freecam 2024-09-24 15:03:28 +02:00
Alug e7c0f322ee dont show driftgauge when in replay freecam 2024-09-24 15:03:14 +02:00
Alug 725754c427 dont run director when you use spectator freecam 2024-09-24 15:03:07 +02:00
Alug 9a6c0a0280 check vres data before freeing it 2024-09-23 23:13:08 +02:00
Alug 26d8c05ce7 forgor some casting 2024-09-23 23:13:05 +02:00
indev 91a9f20af7 Skip map marker in vres_GetMap 2024-09-24 00:08:48 +03:00
indev 90745d91aa Add showdownloadprompt cvar, so addon download prompt can be disabled 2024-09-23 23:39:25 +03:00
Alug 0dbae34998 completely forgor to revert this lol 2024-09-23 15:53:05 +02:00
Alug eec93b8013 Revert "beta hud driftgauge"
This reverts commit 26e8c2ca2b.
2024-09-23 01:35:14 +02:00
Alug cfe3f01b32 Revert "extra check"
This reverts commit 0bb1efcd50.
2024-09-23 01:35:11 +02:00
Alug 43452e1af4 dont actually call Nullprecipthinker 2024-09-23 01:03:59 +02:00
Alug a4706e0785 read precip row in perfstats 2 2024-09-23 01:03:24 +02:00
Alug c921ab463c dont count precip towards thinkers in perfstats 2024-09-23 01:03:20 +02:00
Alug 892816dadf fix precip performance issuess on certain maps 2024-09-23 01:03:17 +02:00
Alug e7e1fd711e dont check consistency/attempt to resend the gamestate while a client is currently getting the save resend
perhaps that makes mass synchs less bad
2024-09-22 22:16:21 +02:00
Alug ba5459eeb6 Revert "clean up leveload a bit"
This reverts commit c14af4a136.
2024-09-22 17:52:26 +02:00
Alug 0bd9c696df try to prevent unknown packet type spam when client attempt to connect while levelloading 2024-09-22 16:53:31 +02:00
Alug c14af4a136 clean up leveload a bit 2024-09-22 16:53:25 +02:00
Alug 8dfa841a7b Load palette before map data 2024-09-22 16:52:07 +02:00
Alug a6de843c75 cleanup r_draw8 2024-09-22 16:52:04 +02:00
Alug 0bb1efcd50 extra check 2024-09-22 04:14:31 +02:00
Alug 26e8c2ca2b beta hud driftgauge
eh needs some stuff for menu still
also should replace driftgauge gfx sometime
2024-09-22 04:13:53 +02:00
Alug 12ffca7374 precalc automap and minimap stuff on mapload instead of every frame 2024-09-22 04:13:02 +02:00
Alug 6ecf65d83a Merge remote-tracking branch 'origin/Saturn-Next' into Saturn-Next 2024-09-21 16:03:17 +02:00
Alug 231c173545 move this so speccing resets your laptime 2024-09-21 16:03:13 +02:00
Alug f12b7fd772 move this 2024-09-19 12:41:40 +02:00
Alug 14ea041c72 always reset cam subsector regardless of splitscreen 2024-09-18 12:11:14 +02:00
Alug 6fb804292c Prevent integer div by 0 in curl progress callback 2024-09-18 01:07:43 +02:00
Alug f77f7361a9 this also does nothing 2024-09-18 01:06:54 +02:00
Alug d6d19d5dab smol cleanup 2024-09-18 01:02:42 +02:00
Alug 8074bfacb6 this does nothing 2024-09-18 00:58:37 +02:00
Alug f5f7b99479 Fix crash if a packet fails to reach the client
https://git.do.srb2.org/STJr/SRB2/-/merge_requests/2480 but keeps the returns;
2024-09-17 21:02:05 +02:00
Alug f0a8c27829 Fix crash when trying to send to an unreachable client
https://git.do.srb2.org/STJr/SRB2/-/merge_requests/2232
2024-09-17 20:58:23 +02:00
Alug 30024f2341 this is the correct value 2024-09-17 19:47:30 +02:00
Alug ff0dcafeea make ticcmds on gamestateresend
resynch will still stop making em
should hopefully fix some weird issues where you might end up somewhere weird if the resend takes a little longer
2024-09-17 16:47:34 +02:00
Alug 8580451bce properly reset all splitscreen cameras on resynch
also fix some casting
2024-09-17 16:47:31 +02:00
Alug d867868854 Revert "dont run playerjoin hook on resynch"
This reverts commit 5f7bf4164d.
2024-09-17 16:43:25 +02:00
indev b1644d4817 Ignore case here 2024-09-17 17:23:16 +03:00
indev a9a3a04379 Add proper skin search in skin command 2024-09-17 17:16:35 +03:00
Alug 7ac9f0cbef dont rerun mapload hook on resynch 2024-09-16 00:54:29 +02:00
Alug 5f7bf4164d dont run playerjoin hook on resynch 2024-09-16 00:54:26 +02:00
Alug 43690c9b2c fix sound bug lol 2024-09-16 00:08:21 +02:00
Alug 02c14bfa5c Merge branch 'Saturn' into Saturn-Next 2024-09-16 00:08:11 +02:00
86 changed files with 4766 additions and 4002 deletions

No files matched your search

+1
View File
@@ -28,6 +28,7 @@ LOCAL_SRC_FILES := am_map.c \
m_cheat.c \
m_fixed.c \
m_menu.c \
m_textinput.c \
m_misc.c \
m_queue.c \
m_random.c \
+553 -551
View File
File diff suppressed because it is too large. Load diff
+8 -6
View File
@@ -213,9 +213,9 @@ DOSATURNSYNCH=1
ifndef NOSATURNJOIN
DOSATURNJOIN=1
endif
#ifndef NOSATURNPAK
#DOSATURNPAK=1
#endif
ifndef NOSATURNPAK
DOSATURNPAK=1
endif
endif
endif
@@ -404,9 +404,9 @@ OPTS+=-DDOSATURNSYNCH
ifndef NOSATURNJOIN
OPTS+=-DDOSATURNJOIN
endif
#ifndef NOSATURNPAK
#OPTS+=-DDOSATURNPAK
#endif
ifndef NOSATURNPAK
OPTS+=-DDOSATURNPAK
endif
endif
endif
@@ -529,6 +529,7 @@ OBJS:=$(i_main_o) \
$(OBJDIR)/m_fixed.o \
$(OBJDIR)/m_menu.o \
$(OBJDIR)/m_misc.o \
$(OBJDIR)/m_textinput.o \
$(OBJDIR)/m_perfstats.o \
$(OBJDIR)/m_random.o \
$(OBJDIR)/m_queue.o \
@@ -562,6 +563,7 @@ OBJS:=$(i_main_o) \
$(OBJDIR)/r_splats.o \
$(OBJDIR)/r_patch.o \
$(OBJDIR)/r_things.o \
$(OBJDIR)/r_portal.o \
$(OBJDIR)/screen.o \
$(OBJDIR)/v_video.o \
$(OBJDIR)/s_sound.o \
+7 -17
View File
@@ -260,25 +260,15 @@ static inline void AM_restoreScaleAndLoc(void)
*/
static void AM_findMinMaxBoundaries(void)
{
size_t i;
fixed_t a;
fixed_t b;
fixed_t a, b;
min_x = min_y = +INT32_MAX;
max_x = max_y = -INT32_MAX;
min_x = minimapinfo.min_x << MAPBITS;
max_x = minimapinfo.max_x << MAPBITS;
min_y = minimapinfo.min_y << MAPBITS;
max_y = minimapinfo.max_y << MAPBITS;
for (i = 0; i < numvertexes; i++)
{
if (vertexes[i].x < min_x)
min_x = vertexes[i].x;
else if (vertexes[i].x > max_x)
max_x = vertexes[i].x;
if (vertexes[i].y < min_y)
min_y = vertexes[i].y;
else if (vertexes[i].y > max_y)
max_y = vertexes[i].y;
}
max_w = minimapinfo.map_w << MAPBITS;
max_h = minimapinfo.map_h << MAPBITS;
max_w = (max_x >>= FRACTOMAPBITS) - (min_x >>= FRACTOMAPBITS);
max_h = (max_y >>= FRACTOMAPBITS) - (min_y >>= FRACTOMAPBITS);
+48 -348
View File
@@ -32,6 +32,7 @@
#include "i_threads.h"
#include "d_main.h"
#include "m_menu.h"
#include "m_textinput.h"
#include "filesrch.h"
#ifdef HWRENDER
@@ -97,9 +98,7 @@ static char inputlines[32][CON_MAXPROMPTCHARS]; // hold last 32 prompt lines
static INT32 inputline; // current input line number
static INT32 inputhist; // line number of history input line to restore
static size_t input_cur; // position of cursor in line
static size_t input_sel; // position of selection marker (I.E.: anything between this and input_cur is "selected")
static size_t input_len; // length of current line, used to bound cursor and such
static textinput_t input;
// notice: input does NOT include the "$" at the start of the line. - 11/3/16
// protos.
@@ -458,7 +457,8 @@ static void CON_InputInit(void)
// prepare the first prompt line
memset(inputlines, 0, sizeof (inputlines));
inputline = 0;
input_cur = input_sel = input_len = 0;
M_TextInputInit(&input, inputlines[inputline], CON_MAXPROMPTCHARS);
Unlock_state();
}
@@ -802,178 +802,6 @@ void CON_Ticker(void)
Unlock_state();
}
//
// ----
//
// Shortcuts for adding and deleting characters, strings, and sections
// Necessary due to moving cursor
//
static void CON_InputClear(void)
{
Lock_state();
memset(inputlines[inputline], 0, CON_MAXPROMPTCHARS);
input_cur = input_sel = input_len = 0;
Unlock_state();
}
static void CON_InputSetString(const char *c)
{
Lock_state();
memset(inputlines[inputline], 0, CON_MAXPROMPTCHARS);
strcpy(inputlines[inputline], c);
input_cur = input_sel = input_len = strlen(c);
Unlock_state();
}
static void CON_InputAddString(const char *c)
{
size_t csize = strlen(c);
Lock_state();
if (input_len + csize > CON_MAXPROMPTCHARS-1)
{
Unlock_state();
return;
}
if (input_cur != input_len)
memmove(&inputlines[inputline][input_cur+csize], &inputlines[inputline][input_cur], input_len-input_cur);
memcpy(&inputlines[inputline][input_cur], c, csize);
input_len += csize;
input_sel = (input_cur += csize);
Unlock_state();
}
static void CON_InputDel(size_t start, size_t end)
{
size_t len;
Lock_state();
len = (end - start);
if (end != input_len)
memmove(&inputlines[inputline][start], &inputlines[inputline][end], input_len-end);
memset(&inputlines[inputline][input_len - len], 0, len);
input_len -= len;
if (input_sel >= end)
input_sel -= len;
else if (input_sel > start)
input_sel = start;
if (input_cur >= end)
input_cur -= len;
else if (input_cur > start)
input_cur = start;
Unlock_state();
}
static void CON_InputDelSelection(void)
{
size_t start, end;
Lock_state();
if (input_cur > input_sel)
{
start = input_sel;
end = input_cur;
}
else
{
start = input_cur;
end = input_sel;
}
CON_InputDel(start, end);
input_sel = input_cur = start;
Unlock_state();
}
static void CON_ToWordEnd(boolean move_sel)
{
Lock_state();
// Skip spaces
while (input_cur < input_len && isspace(inputlines[inputline][input_cur]))
++input_cur;
// Skip word
while (input_cur < input_len && !isspace(inputlines[inputline][input_cur]))
++input_cur;
if (move_sel) input_sel = input_cur;
Unlock_state();
}
static void CON_ToWordBegin(boolean move_sel)
{
Lock_state();
// Hack, always move back 1 character if possible so if we press ctrl-left at a word beginning
// we move to previous word
if (input_cur) --input_cur;
// Skip spaces
while (input_cur && isspace(inputlines[inputline][input_cur]))
--input_cur;
// Skip word
while (input_cur && !isspace(inputlines[inputline][input_cur]))
--input_cur;
// Unless we reached beginning of line, we're pointing at a space before word, so move cursor
// forward to fix that
if (input_cur) ++input_cur;
if (move_sel) input_sel = input_cur;
Unlock_state();
}
static void CON_InputAddChar(char c)
{
if (input_len >= CON_MAXPROMPTCHARS-1)
return;
Lock_state();
if (input_cur != input_len)
memmove(&inputlines[inputline][input_cur+1], &inputlines[inputline][input_cur], input_len-input_cur);
inputlines[inputline][input_cur++] = c;
inputlines[inputline][++input_len] = 0;
input_sel = input_cur;
Unlock_state();
}
static void CON_InputDelChar(void)
{
if (!input_cur)
return;
Lock_state();
if (input_cur != input_len)
memmove(&inputlines[inputline][input_cur-1], &inputlines[inputline][input_cur], input_len-input_cur);
inputlines[inputline][--input_len] = 0;
input_sel = --input_cur;
Unlock_state();
}
//
// ----
//
@@ -1054,6 +882,10 @@ boolean CON_Responder(event_t *ev)
}
}
Lock_state();
M_TextInputHandle(&input, key);
Unlock_state();
// Always eat ctrl/shift/alt if console open, so the menu doesn't get ideas
if (key == KEY_LSHIFT || key == KEY_RSHIFT
|| key == KEY_LCTRL || key == KEY_RCTRL
@@ -1066,12 +898,11 @@ boolean CON_Responder(event_t *ev)
// show all cvars/commands that match what we have inputted
if (key == KEY_TAB)
{
if (!completion[0])
{
if (!input_len || input_len >= 40 || strchr(inputlines[inputline], ' '))
if (!input.length || input.length >= 40 || strchr(input.buffer, ' '))
return true;
strcpy(completion, inputlines[inputline]);
strcpy(completion, input.buffer);
comskips = varskips = 0;
}
@@ -1092,74 +923,9 @@ boolean CON_Responder(event_t *ev)
return true;
}
if (key == 'x' || key == 'X')
{
if (input_sel > input_cur)
I_ClipboardCopy(&inputlines[inputline][input_cur], input_sel-input_cur);
else
I_ClipboardCopy(&inputlines[inputline][input_sel], input_cur-input_sel);
CON_InputDelSelection();
// Those are already handled in M_TextInputHandle, but they do extra logic... Maybe textinput_t should have some sort of callbacks?
if (key == 'x' || key == 'X' || key == 'v' || key == 'V')
completion[0] = 0;
return true;
}
else if (key == 'c' || key == 'C')
{
if (input_sel > input_cur)
I_ClipboardCopy(&inputlines[inputline][input_cur], input_sel-input_cur);
else
I_ClipboardCopy(&inputlines[inputline][input_sel], input_cur-input_sel);
return true;
}
else if (key == 'v' || key == 'V')
{
const char *paste = I_ClipboardPaste();
if (input_sel != input_cur)
CON_InputDelSelection();
if (paste != NULL)
CON_InputAddString(paste);
completion[0] = 0;
return true;
}
else if (key == 'w' || key == 'W')
{
size_t word_start, word_end, i;
word_end = i = input_cur;
// Unless we're pointing at the beginning of line, decrement i so we only start
// removing symbols that come before the cursor
if (i) --i;
// We might be pointing to spaces, skip them first
while (i && isspace(inputlines[inputline][i]))
--i;
// Now skip the "word"
while (i && !isspace(inputlines[inputline][i]))
--i;
// Unless we reached beginning of line, i is pointing at first space that was found
// before word start, and we don't want to remove it
if (i) ++i;
word_start = i;
if (word_start != word_end)
CON_InputDel(word_start, word_end);
return true;
}
else if (key == KEY_RIGHTARROW)
CON_ToWordEnd(!shiftdown);
else if (key == KEY_LEFTARROW)
CON_ToWordBegin(!shiftdown);
// Select all
if (key == 'a' || key == 'A')
{
input_sel = 0;
input_cur = input_len;
return true;
}
// ...why shouldn't it eat the key? if it doesn't, it just means you
// can control Sonic from the console, which is silly
@@ -1174,9 +940,9 @@ boolean CON_Responder(event_t *ev)
// remember typing for several completions (a-la-4dos)
if (!completion[0])
{
if (!input_len || input_len >= 40 || strchr(inputlines[inputline], ' '))
if (!input.length || input.length >= 40 || strchr(input.buffer, ' '))
return true;
strcpy(completion, inputlines[inputline]);
strcpy(completion, input.buffer);
comskips = varskips = 0;
}
else
@@ -1207,7 +973,11 @@ boolean CON_Responder(event_t *ev)
cmd = CV_CompleteVar(completion, varskips);
if (cmd)
CON_InputSetString(va("%s ", cmd));
{
Lock_state();
M_TextInputSetString(&input, va("%s ", cmd));
Unlock_state();
}
else
{
if (comskips > 0)
@@ -1233,37 +1003,6 @@ boolean CON_Responder(event_t *ev)
return true;
}
if (key == KEY_LEFTARROW)
{
if (input_cur != 0)
--input_cur;
if (!shiftdown)
input_sel = input_cur;
return true;
}
else if (key == KEY_RIGHTARROW)
{
if (input_cur < input_len)
++input_cur;
if (!shiftdown)
input_sel = input_cur;
return true;
}
else if (key == KEY_HOME)
{
input_cur = 0;
if (!shiftdown)
input_sel = input_cur;
return true;
}
else if (key == KEY_END)
{
input_cur = input_len;
if (!shiftdown)
input_sel = input_cur;
return true;
}
// At this point we're messing with input
// Clear completion
completion[0] = 0;
@@ -1271,45 +1010,29 @@ boolean CON_Responder(event_t *ev)
// command enter
if (key == KEY_ENTER)
{
if (!input_len)
if (!input.length)
return true;
// push the command
COM_BufAddText(inputlines[inputline]);
COM_BufAddText(input.buffer);
COM_BufAddText("\n");
CONS_Printf("\x86""%c""\x80""%s\n", CON_PROMPTCHAR, inputlines[inputline]);
Lock_state();
// Only add command to history if it differs from previous one
if (strcmp(inputlines[inputline], inputlines[(inputline-1) & 31]))
if (strcmp(input.buffer, inputlines[(inputline-1) & 31]))
{
inputline = (inputline+1) & 31;
M_TextInputInit(&input, inputlines[inputline], CON_MAXPROMPTCHARS);
}
inputhist = inputline;
CON_InputClear();
M_TextInputClear(&input);
return true;
}
Unlock_state();
// backspace and delete command prompt
if (input_sel != input_cur)
{
if (key == KEY_BACKSPACE || key == KEY_DEL)
{
CON_InputDelSelection();
return true;
}
}
else if (key == KEY_BACKSPACE)
{
CON_InputDelChar();
return true;
}
else if (key == KEY_DEL)
{
if (input_cur == input_len)
return true;
++input_cur;
CON_InputDelChar();
return true;
}
@@ -1326,7 +1049,9 @@ boolean CON_Responder(event_t *ev)
if (inputhist == inputline)
inputhist = (inputline + 1) & 31;
CON_InputSetString(inputlines[inputhist]);
Lock_state();
M_TextInputSetString(&input, inputlines[inputhist]);
Unlock_state();
return true;
}
@@ -1340,41 +1065,16 @@ boolean CON_Responder(event_t *ev)
while (inputhist != inputline && !inputlines[inputhist][0]);
// back to currentline
Lock_state();
if (inputhist == inputline)
CON_InputClear();
M_TextInputClear(&input);
else
CON_InputSetString(inputlines[inputhist]);
M_TextInputSetString(&input, inputlines[inputhist]);
Unlock_state();
return true;
}
// allow people to use keypad in console (good for typing IP addresses) - Calum
if (key >= KEY_KEYPAD7 && key <= KEY_KPADDEL)
{
char keypad_translation[] = {'7','8','9','-',
'4','5','6','+',
'1','2','3',
'0','.'};
key = keypad_translation[key - KEY_KEYPAD7];
}
else if (key == KEY_KPADSLASH)
key = '/';
// same capslock code as hu_stuff.c's HU_responder. Check there for details.
key = CON_ShiftChar(key);
// enter a char into the command prompt
if (key < 32 || key > 127)
return true;
// add key to cmd line here
if (key >= 'A' && key <= 'Z' && !(shiftdown ^ capslock)) //this is only really necessary for dedicated servers
key = key + 'a' - 'A';
if (input_sel != input_cur)
CON_InputDelSelection();
CON_InputAddChar(key);
return true;
}
@@ -1656,16 +1356,16 @@ static void CON_DrawInput(void)
clen = con_width-13;
if (input_len <= clen)
if (input.length <= clen)
{
c = 0;
clen = input_len;
clen = input.length;
}
else // input line scrolls left if it gets too long
{
clen -= 2; // There will always be some extra truncation -- but where is what we'll find out
if (input_cur <= clen/2)
if (input.cursor <= clen/2)
{
// Close enough to right edge to show all
c = 0;
@@ -1676,15 +1376,15 @@ static void CON_DrawInput(void)
{
// Cursor in the middle (or right side) of input
// Move over for the ellipsis
c = input_cur - (clen/2) + 2;
c = input.cursor - (clen/2) + 2;
x += charwidth*2;
lellip = 1;
if (c + clen >= input_len)
if (c + clen >= input.length)
{
// Cursor in the right side of input
// We were too far over, so move back
c = input_len - clen;
c = input.length - clen;
}
else
{
@@ -1698,7 +1398,7 @@ static void CON_DrawInput(void)
if (lellip)
{
x -= charwidth*3;
if (input_sel < c)
if (input.select < c)
V_DrawFill(x, y, charwidth*3, (10 * con_scalefactor), 107 | V_NOSCALESTART);
for (i = 0; i < 3; ++i, x += charwidth)
V_DrawCharacter(x, y, '.' | cv_constextsize.value | V_GRAYMAP | V_NOSCALESTART, !cv_allcaps.value);
@@ -1708,7 +1408,7 @@ static void CON_DrawInput(void)
for (cend = c + clen; c < cend; ++c, x += charwidth)
{
if ((input_sel > c && input_cur <= c) || (input_sel <= c && input_cur > c))
if ((input.select > c && input.cursor <= c) || (input.select <= c && input.cursor > c))
{
V_DrawFill(x, y, charwidth, (10 * con_scalefactor), 107 | V_NOSCALESTART);
V_DrawCharacter(x, y, p[c] | cv_constextsize.value | V_YELLOWMAP | V_NOSCALESTART, !cv_allcaps.value);
@@ -1716,14 +1416,14 @@ static void CON_DrawInput(void)
else
V_DrawCharacter(x, y, p[c] | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
if (c == input_cur && con_tick >= 4)
if (c == input.cursor && con_tick >= 4)
V_DrawCharacter(x, y + (con_scalefactor*2), '_' | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
}
if (cend == input_cur && con_tick >= 4)
if (cend == input.cursor && con_tick >= 4)
V_DrawCharacter(x, y + (con_scalefactor*2), '_' | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
if (rellip)
{
if (input_sel > cend)
if (input.select > cend)
V_DrawFill(x, y, charwidth*3, (10 * con_scalefactor), 107 | V_NOSCALESTART);
for (i = 0; i < 3; ++i, x += charwidth)
V_DrawCharacter(x, y, '.' | cv_constextsize.value | V_GRAYMAP | V_NOSCALESTART, !cv_allcaps.value);
+108 -77
View File
@@ -136,7 +136,7 @@ static UINT8 gamestate_resend_counter[MAXNETNODES];
#endif
// kart, true when a player is connecting or disconnecting so that the gameplay has stopped in its tracks
UINT8 hu_stopped = 0;
boolean hu_stopped = false;
// Client specific
static ticcmd_t localcmds;
@@ -1790,6 +1790,18 @@ static boolean SV_SendServerConfig(INT32 node)
#ifdef JOININGAME
#define SAVEGAMESIZE (768*1024)
#ifdef SATURNSYNCH
static boolean SV_ResendingSavegameToAnyone(void)
{
INT32 i;
for (i = 0; i < MAXNETNODES; i++)
if (resendingsavegame[i])
return true;
return false;
}
#endif
static void SV_SendSaveGame(INT32 node, boolean resending)
{
size_t length, compressedlen;
@@ -1993,13 +2005,16 @@ static void CL_ReloadReceivedSavegame(void)
neededtic = gametic;
maketic = neededtic;
// set camera angle to somewhat match where your player is turning
// we dont have P_ForceLocalAngle so were setting it manually here
for (i = 0; i <= splitscreen; i++)
{
localangle[i] = players[displayplayers[i]].cmd.angleturn<<16;
localangle[i] = (angle_t)(players[displayplayers[i]].cmd.angleturn<<16);
}
camera->subsector = R_PointInSubsector(camera->x, camera->y);
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
camera[i].subsector = R_PointInSubsector(camera[i].x, camera[i].y);
}
cl_redownloadinggamestate = false;
@@ -2182,6 +2197,33 @@ void CL_TimeoutServerList(void)
}
#endif // ifndef NONET
static void CL_ConfirmConnect(void)
{
if (totalfilesrequestednum > 0)
{
#ifdef HAVE_CURL
if (http_source[0] == '\0' || curl_failedwebdownload)
#endif
{
if (CL_SendRequestFile())
{
cl_mode = CL_DOWNLOADFILES;
}
else
{
cl_mode = CL_LEGACYREQUESTFAILED;
}
}
#ifdef HAVE_CURL
else
cl_mode = CL_PREPAREHTTPFILES;
#endif
}
else
cl_mode = CL_LOADFILES;
}
static void M_ConfirmConnect(event_t *ev)
{
#ifndef NONET
@@ -2189,28 +2231,7 @@ static void M_ConfirmConnect(event_t *ev)
{
if (ev->data1 == ' ' || ev->data1 == 'y' || ev->data1 == KEY_ENTER || ev->data1 == gamecontrol[gc_accelerate][0] || ev->data1 == gamecontrol[gc_accelerate][1])
{
if (totalfilesrequestednum > 0)
{
#ifdef HAVE_CURL
if (http_source[0] == '\0' || curl_failedwebdownload)
#endif
{
if (CL_SendRequestFile())
{
cl_mode = CL_DOWNLOADFILES;
}
else
{
cl_mode = CL_LEGACYREQUESTFAILED;
}
}
#ifdef HAVE_CURL
else
cl_mode = CL_PREPAREHTTPFILES;
#endif
}
else
cl_mode = CL_LOADFILES;
CL_ConfirmConnect();
M_ClearMenus(true);
}
@@ -2340,24 +2361,30 @@ static boolean CL_FinishedFileList(void)
downloadsize = Z_StrDup(va("%uK",totalfilesrequestedsize>>10));
#endif
if (serverisfull)
M_StartMessage(va(M_GetText(
"This server is full!\n"
"Download of %s additional content is required to join.\n"
"\n"
"You may download, load server addons, and wait for a slot.\n"
"\n"
"Press ACCEL to continue or BRAKE to cancel.\n\n"
), downloadsize), M_ConfirmConnect, MM_EVENTHANDLER);
if (cv_showdownloadprompt.value)
{
if (serverisfull)
M_StartMessage(va(M_GetText(
"This server is full!\n"
"Download of %s additional content is required to join.\n"
"\n"
"You may download, load server addons, and wait for a slot.\n"
"\n"
"Press ACCEL to continue or BRAKE to cancel.\n\n"
), downloadsize), M_ConfirmConnect, MM_EVENTHANDLER);
else
M_StartMessage(va(M_GetText(
"Download of %s additional content is required to join.\n"
"\n"
"Press ACCEL to continue or BRAKE to cancel.\n\n"
), downloadsize), M_ConfirmConnect, MM_EVENTHANDLER);
cl_mode = CL_CONFIRMCONNECT;
}
else
M_StartMessage(va(M_GetText(
"Download of %s additional content is required to join.\n"
"\n"
"Press ACCEL to continue or BRAKE to cancel.\n\n"
), downloadsize), M_ConfirmConnect, MM_EVENTHANDLER);
CL_ConfirmConnect();
Z_Free(downloadsize);
cl_mode = CL_CONFIRMCONNECT;
}
#ifdef HAVE_CURL
else
@@ -3367,6 +3394,7 @@ void CL_Reset(void)
curl_running = false;
http_source[0] = '\0';
#endif
G_ResetAllDeviceRumbles();
// D_StartTitle should get done now, but the calling function will handle it
}
@@ -4219,6 +4247,7 @@ static void ResetNode(INT32 node)
resendingsavegame[node] = false;
can_receive_gamestate[node] = false;
savegameresendcooldown[node] = 0;
gamestate_resend_counter[node] = 0;
#endif
//
}
@@ -4435,7 +4464,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
if (server && multiplayer && motd[0] != '\0')
COM_BufAddText(va("sayto %d %s\n", newplayernum, motd));
D_AddAutoloadFiles();
D_AddPostloadFiles();
LUAh_PlayerJoin(newplayernum);
@@ -5354,15 +5383,21 @@ static void HandlePacketFromPlayer(SINT8 node)
}
#ifdef SATURNSYNCH
// this decreases by one point at twice the cooldown time (ex cooldown of 2 seconds means, this counter decreases by one every 4 seconds), pretty much there to prevent a resynch loop
if ((gamestate_resend_counter[node] != 0) && (I_GetTime() % ((max(cv_resynchcooldown.value, 1) * TICRATE) *2) == 0))
{
gamestate_resend_counter[node]--;
DEBFILE(va("gamestate counter %d for node %d\n", gamestate_resend_counter[node], netconsole));
}
// Check player consistancy during the level
if (((!can_receive_gamestate[node]) && realstart <= gametic && realstart > gametic - TICQUEUE+1 && gamestate == GS_LEVEL
&& consistancy[realstart%TICQUEUE] != SHORT(netbuffer->u.clientpak.consistancy)) || (can_receive_gamestate[node] && realstart <= gametic && realstart + TICQUEUE - 1 > gametic && gamestate == GS_LEVEL
&& consistancy[realstart%TICQUEUE] != SHORT(netbuffer->u.clientpak.consistancy)
&& !resendingsavegame[node] && savegameresendcooldown[node] <= I_GetTime()))
&& !resendingsavegame[node] && savegameresendcooldown[node] <= I_GetTime()
&& !SV_ResendingSavegameToAnyone()))
{
//#ifndef SATURNPAK // lug: keep this behaviour for v7.1 atleast
// we need to send this so the client can tell us if it can receive the savegame
netbuffer->packettype = PT_WILLRESENDGAMESTATE;
HSendPacket(node, true, 0, 0);
@@ -5374,13 +5409,28 @@ static void HandlePacketFromPlayer(SINT8 node)
SV_RequireResynch(node);
resendingsavegame[node] = false;
}
/*#else
if (can_receive_gamestate[node])
{
// Tell the client we are about to resend them the gamestate
netbuffer->packettype = PT_WILLRESENDGAMESTATE;
HSendPacket(node, true, 0, 0);
if ((!can_receive_gamestate[node] && cv_resynchattempts.value && resynch_score[node] <= (unsigned)cv_resynchattempts.value*250) || (can_receive_gamestate[node] && (gamestate_resend_counter[node] < cv_gamestateattempts.value)))
resendingsavegame[node] = true;
}
else
{
SV_RequireResynch(node);
resendingsavegame[node] = false;
}
#endif*/
if ((!can_receive_gamestate[node] && (cv_resynchattempts.value && resynch_score[node] <= (unsigned)cv_resynchattempts.value*250)) || (can_receive_gamestate[node] && (gamestate_resend_counter[node] < cv_gamestateattempts.value)))
{
if (can_receive_gamestate[node] && resendingsavegame[node])
{
gamestate_resend_counter[node]++;
DEBFILE(va("gamestate counter %d for player %d\n", gamestate_resend_counter[node], netconsole));
DEBFILE(va("gamestate counter %d for node %d\n", gamestate_resend_counter[node], netconsole));
}
if (cv_blamecfail.value)
@@ -5403,6 +5453,8 @@ static void HandlePacketFromPlayer(SINT8 node)
DEBFILE(va("player %d kicked (synch failure) [%u] %d!=%d\n",
netconsole, realstart, consistancy[realstart%TICQUEUE],
SHORT(netbuffer->u.clientpak.consistancy)));
gamestate_resend_counter[node] = 0;
DEBFILE(va("gamestate counter %d for node %d\n", gamestate_resend_counter[node], netconsole));
break;
}
}
@@ -5414,7 +5466,7 @@ static void HandlePacketFromPlayer(SINT8 node)
if (realstart <= gametic && realstart > gametic - TICQUEUE+1 && gamestate == GS_LEVEL
&& consistancy[realstart%TICQUEUE] != SHORT(netbuffer->u.clientpak.consistancy))
{
SV_RequireResynch(node);
SV_RequireResynch(node);
if (cv_resynchattempts.value && resynch_score[node] <= (unsigned)cv_resynchattempts.value*250)
{
@@ -5552,31 +5604,6 @@ static void HandlePacketFromPlayer(SINT8 node)
else
buf[1] = KICK_MSG_PLAYER_QUIT;
SendNetXCmd(XD_KICK, &buf, 2);
//nodetoplayer[node] = -1;
/*if (nodetoplayer2[node] != -1 && nodetoplayer2[node] >= 0
&& playeringame[(UINT8)nodetoplayer2[node]])
{
buf[0] = nodetoplayer2[node];
SendNetXCmd(XD_KICK, &buf, 2);
nodetoplayer2[node] = -1;
}
if (nodetoplayer3[node] != -1 && nodetoplayer3[node] >= 0
&& playeringame[(UINT8)nodetoplayer3[node]])
{
buf[0] = nodetoplayer3[node];
SendNetXCmd(XD_KICK, &buf, 2);
nodetoplayer3[node] = -1;
}
if (nodetoplayer4[node] != -1 && nodetoplayer4[node] >= 0
&& playeringame[(UINT8)nodetoplayer4[node]])
{
buf[0] = nodetoplayer4[node];
SendNetXCmd(XD_KICK, &buf, 2);
nodetoplayer4[node] = -1;
}*/
}
Net_CloseConnection(node);
nodeingame[node] = false;
@@ -5765,8 +5792,9 @@ static void HandlePacketFromPlayer(SINT8 node)
#endif
#ifdef SATURNPAK
case PT_ISSATURN:
//CONS_Printf("hi im on saturn%d\n", node);
DEBFILE(va("hi im on saturn! node = %d\n", node));
is_client_saturn[node] = true;
can_receive_gamestate[node] = true;
break;
#endif
default:
@@ -5790,9 +5818,12 @@ static void GetPackets(void)
{
node = (SINT8)doomcom->remotenode;
if (netbuffer->packettype == PT_CLIENTJOIN && server && !levelloading)
if (netbuffer->packettype == PT_CLIENTJOIN && server)
{
HandleConnect(node);
if (!levelloading) // Otherwise just ignore
{
HandleConnect(node);
}
continue;
}
if (node == servernode && client && cl_mode != CL_SEARCHING)
@@ -6350,7 +6381,7 @@ boolean TryRunTics(tic_t realtics)
if (demo.playback)
{
neededtic = gametic + realtics * (gamestate == GS_LEVEL ? cv_playbackspeed.value : 1);
neededtic = gametic + realtics;
// start a game after a demo
maketic += realtics;
firstticstosend = maketic;
@@ -6599,7 +6630,7 @@ void NetKeepAlive(void)
#ifdef MASTERSERVER
MasterClient_Ticker();
#endif
#ifdef HOLEPUNCH
if (netgame && serverrunning)
{
@@ -6710,7 +6741,7 @@ void NetUpdate(void)
CL_SendClientCmd(); // send it
GetPackets(); // get packet from client or from server
// client send the command after a receive of the server
// the server send before because in single player is beter
+1 -1
View File
@@ -656,7 +656,7 @@ extern UINT8 hu_resynching;
#ifdef SATURNSYNCH
extern UINT8 hu_redownloadinggamestate;
#endif
extern UINT8 hu_stopped; // kart, true when the game is stopped for players due to a disconnecting or connecting player
extern boolean hu_stopped; // kart, true when the game is stopped for players due to a disconnecting or connecting player
typedef struct rewind_s {
UINT8 savebuffer[(768*1024)];
+70 -100
View File
@@ -99,7 +99,6 @@ UINT8 window_notinfocus = false;
// DEMO LOOP
//
//static INT32 demosequence;
static const char *pagename = "MAP1PIC";
static char *startupwadfiles[MAX_WADFILES];
static char *startuppwads[MAX_WADFILES];
@@ -116,7 +115,6 @@ boolean devparm = false; // started game with -devparm
boolean singletics = false; // timedemo
boolean lastdraw = false;
postimg_t postimgtype[MAXSPLITSCREENPLAYERS];
INT32 postimgparam[MAXSPLITSCREENPLAYERS];
// These variables are only true if
@@ -513,15 +511,12 @@ static boolean D_Display(void)
if (rendermode == render_soft)
{
if (!splitscreen)
R_ApplyViewMorph();
if (!splitscreen)
R_ApplyViewMorph();
for (i = 0; i <= splitscreen; i++)
{
if (!postimgtype[i])
continue;
V_DoPostProcessor(i, postimgtype[i], postimgparam[i]);
V_DoPostProcessor(i, &players[displayplayers[i]], postimgparam[i]);
}
}
@@ -568,7 +563,7 @@ static boolean D_Display(void)
V_DrawScaledPatch(viewwindowx + (BASEVIDWIDTH - SHORT(patch->width))/2, py, V_SNAPTOTOP, patch);
}
if (demo.rewinding)
if (rendermode == render_soft && demo.rewinding)
V_DrawFadeScreen(TC_RAINBOW, (leveltime & 0x20) ? SKINCOLOR_PASTEL : SKINCOLOR_MOONSLAM);
// vid size change is now finished if it was on...
@@ -654,7 +649,7 @@ static boolean D_Display(void)
// =========================================================================
tic_t rendergametic;
static int menuInputDelayTimer = 0;
static SINT8 menuInputDelayTimer = 0;
void D_SRB2Loop(void)
{
@@ -780,6 +775,38 @@ void D_SRB2Loop(void)
doDisplay = true;
}
#define DPADSCROLLINPUT(INPUT)\
{\
myev.data1 = INPUT;\
M_Responder(&myev);\
}
// this is absolutely awful and i hate it lmao
if (menuactive && (DPADUPSCROLL || DPADDOWNSCROLL || DPADLEFTSCROLL || DPADRIGHTSCROLL))
{
event_t myev;
myev.type = ev_keydown;
if (menuInputDelayTimer < 19)
menuInputDelayTimer++;
if (menuInputDelayTimer == 19) // TICRATE * ( (k+2) (1 - [wz + h + j - q]^2 - [(gk + 2g + k + 1)(h + j) + h - z]^2 - [16(k + 1)^3(k + 2)(n + 1)^2 + 1 - f^2]^2 calculated by my butt
{
if (DPADUPSCROLL)
DPADSCROLLINPUT(KEY_UPARROW)
else if (DPADDOWNSCROLL)
DPADSCROLLINPUT(KEY_DOWNARROW)
else if (DPADLEFTSCROLL)
DPADSCROLLINPUT(KEY_LEFTARROW)
else if (DPADRIGHTSCROLL)
DPADSCROLLINPUT(KEY_RIGHTARROW)
}
}
else
menuInputDelayTimer = 0;
#undef DPADSCROLLINPUT
D_DeviceLEDTick();
}
if (interp)
@@ -794,11 +821,14 @@ void D_SRB2Loop(void)
{
rendertimefrac = FRACUNIT;
}
rendertimefrac_unpaused = g_time.timefrac;
}
else
{
renderdeltatics = realtics * FRACUNIT;
rendertimefrac = FRACUNIT;
rendertimefrac_unpaused = FRACUNIT;
}
if ((interp || doDisplay) && !frameskip)
@@ -828,47 +858,6 @@ void D_SRB2Loop(void)
}
#endif
// this is absolutely awful and i hate it lmao
if (menuactive && (DPADUPSCROLL || DPADDOWNSCROLL || DPADLEFTSCROLL || DPADRIGHTSCROLL))
{
event_t myev;
myev.type = ev_keydown;
if (renderisnewtic)
{
menuInputDelayTimer++;
if (menuInputDelayTimer >= 19) // TICRATE * ( (k+2) (1 - [wz + h + j - q]^2 - [(gk + 2g + k + 1)(h + j) + h - z]^2 - [16(k + 1)^3(k + 2)(n + 1)^2 + 1 - f^2]^2 calculated by my butt
{
if (DPADUPSCROLL)
{
myev.data1 = KEY_UPARROW;
M_Responder(&myev);
}
else if (DPADDOWNSCROLL)
{
myev.data1 = KEY_DOWNARROW;
M_Responder(&myev);
}
else if (DPADLEFTSCROLL)
{
myev.data1 = KEY_LEFTARROW;
M_Responder(&myev);
}
else if (DPADRIGHTSCROLL)
{
myev.data1 = KEY_RIGHTARROW;
M_Responder(&myev);
}
}
}
}
else
menuInputDelayTimer = 0;
if (!dedicated && renderisnewtic) // idk does this need dedi check??
D_DeviceLEDTick();
// Fully completed frame made.
finishprecise = I_GetPreciseTime();
@@ -1078,8 +1067,7 @@ static void D_FindAddonsToAutoload(void)
const char *autoloadpath;
boolean postload;
INT32 i, len;
boolean hasprefix = false;
INT32 i;
char wadsToAutoload[256] = "";
// does it exist tho
@@ -1101,7 +1089,8 @@ static void D_FindAddonsToAutoload(void)
|| (wadsToAutoload[0] == '#'))
continue;
// this marks it so that it loads after loading server addons
else if (fastncmp(wadsToAutoload, "postload ", 9)) {
else if (fastncmp(wadsToAutoload, "postload ", 9))
{
strremove(wadsToAutoload, "postload ");
postload = true;
}
@@ -1113,34 +1102,10 @@ static void D_FindAddonsToAutoload(void)
wadsToAutoload[i] = '\0';
}
len = strlen(wadsToAutoload);
hasprefix = false;
for (i = 0; i < len; ++i)
if (!postload && W_CheckPostLoadList(wadsToAutoload))
{
if (wadsToAutoload[i] == '_')
{
hasprefix = true;
break;
}
}
// Lets just hope no one adds bonuschars in autoload
if (hasprefix)
{
// We searching for c in prefix, which stands for "character" and doesn't work well with
// autoload atm, only fine for postload
for (i = 0; i < len; ++i)
{
if (wadsToAutoload[i] == '_') break; // Prefix end
if (wadsToAutoload[i] == 'c' || wadsToAutoload[i] == 'C')
{
CONS_Alert(CONS_WARNING, "forcing postload for %s as local skin\n", wadsToAutoload);
postload = true;
break; // Found it
}
}
CONS_Printf("forcing postload for file %s\n", wadsToAutoload);
postload = true;
}
// LOAD IT
@@ -1158,30 +1123,30 @@ static void D_FindAddonsToAutoload(void)
fclose(autoloadconfigfile);
}
void D_AddAutoloadFiles(void)
static void D_AddAutoloadFiles(void)
{
if (wasautoloaded && postautoloaded)
if (wasautoloaded)
return;
if (!wasautoloaded && !modeattacking)
{
CONS_Printf("D_AutoloadFile(): Loading autoloaded addons...\n");
if (W_AddAutoloadedLocalFiles(autoloadwadfiles) == 0)
CONS_Printf("D_AutoloadFile(): Are you sure you put in valid files or what?\n");
D_CleanFile(autoloadwadfiles);
CONS_Printf("D_AutoloadFile(): Loading autoloaded addons...\n");
if (W_AddAutoloadedLocalFiles(autoloadwadfiles) == 0)
CONS_Printf("D_AutoloadFile(): Are you sure you put in valid files or what?\n");
D_CleanFile(autoloadwadfiles);
wasautoloaded = true;
}
wasautoloaded = true;
}
if ((!postautoloaded) && netgame)
{
CONS_Printf("D_AutoloadFile(): Loading postloaded addons...\n");
if (W_AddAutoloadedLocalFiles(autoloadwadfilespost) == 0)
CONS_Printf("D_AutoloadFile(): Are you sure you put in valid files or what?\n");
D_CleanFile(autoloadwadfilespost);
void D_AddPostloadFiles(void)
{
if (postautoloaded || !netgame)
return;
postautoloaded = true;
}
CONS_Printf("D_AddPostloadFiles(): Loading postloaded addons...\n");
if (W_AddAutoloadedLocalFiles(autoloadwadfilespost) == 0)
CONS_Printf("D_AddPostloadFiles(): Are you sure you put in valid files or what?\n");
D_CleanFile(autoloadwadfilespost);
postautoloaded = true;
}
void D_CleanFile(char **filearray)
@@ -1677,6 +1642,10 @@ void D_SRB2Main(void)
#undef PUSHSPEEDO
memcpy(speedo_cons_t, speedo_cons_temp, sizeof(speedo_cons_t));
// Do it before P_InitMapData because PNG patch
// conversion sometimes needs the palette
V_ReloadPalette();
//
// search for maps
//
@@ -1872,6 +1841,8 @@ void D_SRB2Main(void)
CONS_Printf("ST_Init(): Init status bar.\n");
ST_Init();
D_AddAutoloadFiles();
// Set up splitscreen players before joining!
if (!dedicated && (M_CheckParm("-splitscreen") && M_IsNextParm()))
{
@@ -2073,7 +2044,6 @@ void D_SRB2Main(void)
if (dedicated && server)
{
pagename = "TITLESKY";
levelstarttic = gametic;
G_SetGamestate(GS_LEVEL);
if (!P_SetupLevel(false, false))
+3 -3
View File
@@ -45,12 +45,12 @@ extern boolean statdp; // stat display for extended player setup
extern boolean nametaggfx; // Nametag stuffs
extern boolean driftgaugegfx;
void D_AddAutoloadFiles(void);
// autoload stuff
extern boolean autoloading;
extern boolean autoloaded;
extern boolean postautoloaded;
extern boolean wasautoloaded;
void D_AddPostloadFiles(void);
extern char *autoloadwadfilespost[MAX_WADFILES];
extern char *autoloadwadfiles[MAX_WADFILES];
+4 -4
View File
@@ -1446,13 +1446,13 @@ void Command_Ping_f(void)
}
}
if (f_width < 10) f_width = 1;
if (f_width < 10) f_width = 1;
else if (f_width < 100) f_width = 2;
else f_width = 3;
else f_width = 3;
if (ms_width < 10) ms_width = 1;
if (ms_width < 10) ms_width = 1;
else if (ms_width < 100) ms_width = 2;
else ms_width = 3;
else ms_width = 3;
qsort(pingv, pingc, sizeof (struct pingcell), &pingcellcmp);
+80 -33
View File
@@ -493,6 +493,8 @@ consvar_t cv_showlapemblem = {"showlapemblem", "On", CV_SAVE, CV_OnOff, NULL, 0,
consvar_t cv_showviewpointtext = {"showviewpointtext", "On", CV_SAVE, CV_OnOff, 0, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_showdownloadprompt = {"showdownloadprompt", "On", CV_SAVE, CV_OnOff, 0, 0, NULL, NULL, 0, 0, NULL};
// Intermission time Tails 04-19-2002
static CV_PossibleValue_t inttime_cons_t[] = {{0, "MIN"}, {3600, "MAX"}, {0, NULL}};
consvar_t cv_inttime = {"inttime", "20", CV_NETVAR, inttime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -567,7 +569,7 @@ consvar_t cv_ps_descriptor = {"ps_descriptor", "Average", 0, ps_descriptor_cons_
consvar_t cv_director = {"director", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_kartdebugdirector = {"debugdirector", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_showdirectorhud = {"showdirectorhud", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_showdirectorhud = {"showdirectorhud", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_showtrackaddon = {"showtrackaddon", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -976,7 +978,6 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_audbuffersize);
// m_menu.c
//CV_RegisterVar(&cv_compactscoreboard);
CV_RegisterVar(&cv_chatheight);
CV_RegisterVar(&cv_chatwidth);
CV_RegisterVar(&cv_chattime);
@@ -994,6 +995,7 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_showtrackaddon);
CV_RegisterVar(&cv_showviewpointtext);
CV_RegisterVar(&cv_showdownloadprompt);
CV_RegisterVar(&cv_director);
CV_RegisterVar(&cv_kartdebugdirector);
@@ -1087,20 +1089,12 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_controlperkey);
CV_RegisterVar(&cv_turnsmooth);
CV_RegisterVar(&cv_rumble[0]);
CV_RegisterVar(&cv_rumble[1]);
CV_RegisterVar(&cv_rumble[2]);
CV_RegisterVar(&cv_rumble[3]);
CV_RegisterVar(&cv_gamepadled[0]);
CV_RegisterVar(&cv_gamepadled[1]);
CV_RegisterVar(&cv_gamepadled[2]);
CV_RegisterVar(&cv_gamepadled[3]);
CV_RegisterVar(&cv_ledpowerup[0]);
CV_RegisterVar(&cv_ledpowerup[1]);
CV_RegisterVar(&cv_ledpowerup[2]);
CV_RegisterVar(&cv_ledpowerup[3]);
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
CV_RegisterVar(&cv_rumble[i]);
CV_RegisterVar(&cv_gamepadled[i]);
CV_RegisterVar(&cv_ledpowerup[i]);
}
CV_RegisterVar(&cv_usemouse);
CV_RegisterVar(&cv_usemouse2);
@@ -1204,26 +1198,16 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_speed);
CV_RegisterVar(&cv_opflags);
CV_RegisterVar(&cv_mapthingnum);
//CV_RegisterVar(&cv_grid);
//CV_RegisterVar(&cv_snapto);
// add cheat commands
COM_AddCommand("noclip", Command_CheatNoClip_f);
COM_AddCommand("god", Command_CheatGod_f);
COM_AddCommand("notarget", Command_CheatNoTarget_f);
/*COM_AddCommand("getallemeralds", Command_Getallemeralds_f);
COM_AddCommand("resetemeralds", Command_Resetemeralds_f);
COM_AddCommand("setrings", Command_Setrings_f);
COM_AddCommand("setlives", Command_Setlives_f);
COM_AddCommand("setcontinues", Command_Setcontinues_f);*/
COM_AddCommand("devmode", Command_Devmode_f);
COM_AddCommand("savecheckpoint", Command_Savecheckpoint_f);
COM_AddCommand("scale", Command_Scale_f);
COM_AddCommand("gravflip", Command_Gravflip_f);
COM_AddCommand("hurtme", Command_Hurtme_f);
/*COM_AddCommand("jumptoaxis", Command_JumpToAxis_f);
COM_AddCommand("charability", Command_Charability_f);
COM_AddCommand("charspeed", Command_Charspeed_f);*/
COM_AddCommand("teleport", Command_Teleport_f);
COM_AddCommand("rteleport", Command_RTeleport_f);
COM_AddCommand("skynum", Command_Skynum_f);
@@ -1255,19 +1239,69 @@ void D_RegisterClientCommands(void)
*/
static void Skin_FindRealNameSkin(consvar_t *cvar)
{
// Not the best way to implements this but it will do.
INT32 matches[MAXSKINS] = {0}; // Skin numbers of matching skins
INT32 matches_pos[MAXSKINS] = {0}; // Index of matching substring
INT32 nummatches = 0;
int i;
INT32 i;
const char *value = cvar->string;
for (i = 0; i < numskins; i++)
{
if (strncmp(value, skins[i].realname, sizeof skins[i].realname) == 0)
{
// Change the cvar to be the value of the name.
CV_StealthSet(cvar, skins[i].name);
// Perfect match with some skin name, no need to find matching realname
if (strncasecmp(value, skins[i].name, sizeof skins[i].name) == 0)
return;
const char *match = strcasestr(skins[i].realname, value);
if (match != NULL)
{
matches[nummatches] = i;
matches_pos[nummatches] = match - skins[i].realname;
++nummatches;
}
}
if (nummatches == 1)
{
// Change the cvar to be the value of the name.
CV_StealthSet(cvar, skins[matches[0]].name);
}
else if (nummatches > 1)
{
size_t query_length = strlen(value);
char start[SKINNAMESIZE+1] = {0}; // Start of name, printed with normal color
char match[SKINNAMESIZE+1] = {0}; // Matching part of name, highlighted in red
const char *end = NULL; // End of the name, printed with normal color. Can be just a pointer into realname part
CONS_Printf("\x86Multiple matches found:\n");
for (i = 0; i < nummatches; ++i)
{
const char *realname = skins[matches[i]].realname;
if (matches_pos[i] == 0)
start[0] = 0;
else
{
memcpy(start, realname, matches_pos[i]);
start[matches_pos[i]] = 0;
}
memcpy(match, realname+matches_pos[i], query_length);
match[matches_pos[i] + query_length] = 0;
end = realname + matches_pos[i] + query_length;
CONS_Printf("%s\x85%s\x80%s (%s)\n", start, match, end, skins[matches[i]].name);
}
CONS_Printf("\x86Try be more specific\n");
}
else
{
CONS_Printf("\x86Skin not found\n");
}
}
@@ -2949,6 +2983,14 @@ static void Command_Map_f(void)
// G_TOLFlag handles both multiplayer gametype and ignores it for !multiplayer
else
{
if (!mapheaderinfo[newmapnum-1] || mapheaderinfo[newmapnum-1] == NULL)
{
CONS_Alert(CONS_WARNING, M_GetText("Invalid mapheaderinfo for Course %s (%s)\n"), realmapname, G_BuildMapName(newmapnum));
Z_Free(realmapname);
Z_Free(mapname);
return;
}
if (!(mapheaderinfo[newmapnum-1]->typeoflevel & G_TOLFlag(newgametype)))
{
CONS_Alert(CONS_WARNING, M_GetText("Course %s (%s) doesn't support %s mode!\n(Use -force to override)\n"), realmapname, G_BuildMapName(newmapnum),
@@ -3175,6 +3217,8 @@ static void Got_Pause(UINT8 **cp, INT32 playernum)
else
S_ResumeAudio();
}
G_ResetAllDeviceRumbles();
}
static void Command_ReplayMarker(void)
@@ -3192,7 +3236,10 @@ static void Command_ReplayMarker(void)
demo.savemode = DSM_WILLAUTOSAVE;
if (adjustedleveltime < 0)
adjustedleveltime = 0;
snprintf(demo.titlename, 64, "%s [%i:%02d/%.5s]", G_BuildMapTitle(gamemap), G_TicsToMinutes(adjustedleveltime, false), G_TicsToSeconds(adjustedleveltime), modeattacking ? "Record Attack" : connectedservername);
char *title = G_BuildMapTitle(gamemap);
snprintf(demo.titlename, 64, "%s [%i:%02d/%.5s]", title, G_TicsToMinutes(adjustedleveltime, false), G_TicsToSeconds(adjustedleveltime), modeattacking ? "Record Attack" : connectedservername);
if (title)
Z_Free(title);
CONS_Printf("Replay will be saved!\n");
}
}
+1
View File
@@ -166,6 +166,7 @@ extern consvar_t cv_minihead;
extern consvar_t cv_showlapemblem;
extern consvar_t cv_showviewpointtext;
extern consvar_t cv_showdownloadprompt;
extern consvar_t cv_luaimmersion;
extern consvar_t cv_fakelocalskin;
extern consvar_t cv_showlocalskinmenus;
+34 -6
View File
@@ -65,10 +65,10 @@ static boolean SV_SendFile(INT32 node, const char *filename, UINT8 fileid);
#ifdef HAVE_CURL
size_t curlwrite_data(void *ptr, size_t size, size_t nmemb, FILE *stream);
#if defined(CURL_AT_LEAST_VERSION) && CURL_AT_LEAST_VERSION(7, 35, 0)
int curlprogress_callbackx(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow);
static int curlprogress_callbackx(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow);
#define XFERINFOFUNCTION
#else
int curlprogress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);
static int curlprogress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);
#endif
#endif
@@ -1203,25 +1203,53 @@ size_t curlwrite_data(void *ptr, size_t size, size_t nmemb, FILE *stream)
}
#ifdef XFERINFOFUNCTION
int curlprogress_callbackx(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
static int curlprogress_callbackx(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
{
time_t curtime;
(void)clientp;
(void)ultotal;
(void)ulnow; // Function prototype requires these but we won't use, so just discard
curtime = time(NULL);
curl_dlnow = dlnow;
curl_dltotal = dltotal;
getbytes = curl_dlnow / (time(NULL) - curl_starttime); // To-do: Make this more accurate???
if (curtime > curl_starttime)
{
getbytes = curl_dlnow / (curtime - curl_starttime); // To-do: Make this more accurate???
}
else
{
getbytes = 0;
}
return 0;
}
#else
int curlprogress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)
static int curlprogress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)
{
time_t curtime;
(void)clientp;
(void)ultotal;
(void)ulnow; // Function prototype requires these but we won't use, so just discard
curtime = time(NULL);
curl_dlnow = dlnow;
curl_dltotal = dltotal;
getbytes = curl_dlnow / (time(NULL) - curl_starttime); // To-do: Make this more accurate???
if (curtime > curl_starttime)
{
getbytes = curl_dlnow / (curtime - curl_starttime); // To-do: Make this more accurate???
}
else
{
getbytes = 0;
}
return 0;
}
#endif
+2
View File
@@ -413,6 +413,8 @@ typedef struct player_s
// See pflags_t, above.
pflags_t pflags;
UINT16 postimgflags;
// playing animation.
panim_t panim;
+5
View File
@@ -9216,6 +9216,11 @@ int LUA_EnumLib(lua_State *L)
lua_glib_push_bool_getter(L, &demo.playback);
lua_call(L, 2, 0);
lua_pushcfunction(L, lua_glib_new_getter);
lua_pushliteral(L, "replayfreecam");
lua_glib_push_bool_getter(L, &demo.freecam);
lua_call(L, 2, 0);
if (!mathlib)
{
lua_pushcfunction(L, lua_glib_new_getter);
+11 -11
View File
@@ -127,13 +127,8 @@ extern char logfilename[1024];
#else
#define VERSION 1 // Game version
#define SUBVERSION 6 // more precise version number
#ifndef USE_FBO_OGL
#define VERSIONSTRING "Saturn v7"
#define VERSIONSTRINGW L"Saturn v7"
#else
#define VERSIONSTRING "Saturn v7 - FBO "
#define VERSIONSTRINGW L"Saturn v7 - FBO"
#endif
#define VERSIONSTRING "Saturn v7.1"
#define VERSIONSTRINGW L"Saturn v7.1"
// Hey! If you change this, add 1 to the MODVERSION below! Otherwise we can't force updates!
// And change CMakeLists.txt (not src/, but in root), for CMake users!
// AND appveyor.yml, for the build bots!
@@ -474,7 +469,12 @@ void M_StartupLocale(void);
// M_GetText function that just returns the string.
#define M_GetText(x) (x)
#endif
void *M_Memcpy(void* dest, const void* src, size_t n);
FUNCINLINE static ATTRINLINE void *M_Memcpy(void *dest, const void *src, size_t n)
{
return memcpy(dest, src, n);
}
char *va(const char *format, ...) FUNCPRINTF;
char *M_GetToken(const char *inputString);
char *sizeu1(size_t num);
@@ -585,9 +585,9 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// Server detection for if a connecting client is on Saturn.
/// For stuff like extra synching, etc.
//#ifdef DOSATURNPAK
//#define SATURNPAK
//#endif
#ifdef DOSATURNPAK
#define SATURNPAK
#endif
//-- <( ̄︶ ̄)> __
#endif
+1 -2
View File
@@ -112,7 +112,6 @@ extern UINT8 window_notinfocus; // are we in focus? (backend independant -- hand
extern boolean nodrawers;
extern boolean noblit;
extern boolean lastdraw;
extern postimg_t postimgtype[MAXSPLITSCREENPLAYERS];
extern INT32 postimgparam[MAXSPLITSCREENPLAYERS];
extern INT32 viewwindowx, viewwindowy;
@@ -192,7 +191,7 @@ extern struct quake
// camera offsets and duration
fixed_t x,y,z;
angle_t roll;
UINT16 time;
tic_t time;
// location, radius, and intensity...
mappoint_t *epicenter;
+6 -8
View File
@@ -344,14 +344,12 @@ typedef union FColorRGBA RGBA_t;
typedef enum
{
postimg_none,
postimg_water,
postimg_motion,
postimg_flip,
postimg_heat,
postimg_mirror,
postimg_mirrorflip
} postimg_t;
POSTIMG_WATER = 1, // Underwater screen effect.
POSTIMG_MOTION = 1<<1, // Unused motion blur effect.
POSTIMG_FLIP = 1<<2, // Flipcam screen effect.
POSTIMG_HEAT = 1<<3, // Heatwave screen effect.
POSTIMG_MIRROR = 1<<4, // encore screen effect.
} postimgflag_t;
typedef UINT32 lumpnum_t; // 16 : 16 unsigned long (wad num: lump num)
#define LUMPERROR UINT32_MAX
+5 -5
View File
@@ -170,8 +170,8 @@ static void F_SkyScroll(INT32 scrollspeed)
w = (vid.width / vid.dupx)<<FRACBITS;
// The scroll offset MUST be clamped before shifting by FRACBITS, or else it'll overflow in about 3 minutes
animtimer = ((((finalecount * scrollspeed) % (SHORT(pat->width)*16))<<FRACBITS) + (R_GetHudUncap() * scrollspeed))/16;
anim2 = (SHORT(pat2->width)<<FRACBITS) - ((((finalecount * scrollspeed) % (SHORT(pat2->width)*16))<<FRACBITS) + (R_GetHudUncap() * scrollspeed))/16;
animtimer = ((((finalecount * scrollspeed) % (SHORT(pat->width)*16))<<FRACBITS) + (R_GetMenuUncap() * scrollspeed))/16;
anim2 = (SHORT(pat2->width)<<FRACBITS) - ((((finalecount * scrollspeed) % (SHORT(pat2->width)*16))<<FRACBITS) + (R_GetMenuUncap() * scrollspeed))/16;
// SRB2Kart: F_DrawPatchCol is over-engineered; recoded to be less shitty and error-prone
if (rendermode != render_none)
@@ -996,7 +996,7 @@ void F_TitleScreenDrawer(void)
if (finalecount >= 20)
V_DrawSmallScaledPatch(84, 87, 0, ttkart);
else if (finalecount >= 10)
V_DrawSciencePatch((84<<FRACBITS) - 18*(((20 - finalecount)<<FRACBITS) - R_GetHudUncap()), 87<<FRACBITS, 0, ttkart, FRACUNIT/2);
V_DrawSciencePatch((84<<FRACBITS) - 18*(((20 - finalecount)<<FRACBITS) - R_GetMenuUncap()), 87<<FRACBITS, 0, ttkart, FRACUNIT/2);
}
else if (finalecount < 52)
{
@@ -1012,8 +1012,8 @@ void F_TitleScreenDrawer(void)
F_SkyScroll(titlescrollspeed);
V_DrawSciencePatch(0, -40*FixedDiv(((finalecount % 70)<<FRACBITS) + R_GetHudUncap(), 70<<FRACBITS), V_SNAPTOTOP|V_SNAPTOLEFT, ttcheckers, FRACUNIT);
V_DrawSciencePatch(280<<FRACBITS, -(40<<FRACBITS) + 40*FixedDiv(((finalecount % 70)<<FRACBITS) + R_GetHudUncap(), 70<<FRACBITS), V_SNAPTOTOP|V_SNAPTORIGHT, ttcheckers, FRACUNIT);
V_DrawSciencePatch(0, -40*FixedDiv(((finalecount % 70)<<FRACBITS) + R_GetMenuUncap(), 70<<FRACBITS), V_SNAPTOTOP|V_SNAPTOLEFT, ttcheckers, FRACUNIT);
V_DrawSciencePatch(280<<FRACBITS, -(40<<FRACBITS) + 40*FixedDiv(((finalecount % 70)<<FRACBITS) + R_GetMenuUncap(), 70<<FRACBITS), V_SNAPTOTOP|V_SNAPTORIGHT, ttcheckers, FRACUNIT);
if (transval)
V_DrawFadeScreen(120, 10 - transval);
+74 -196
View File
@@ -357,10 +357,6 @@ consvar_t cv_demochangemap = {"netdemo_savemapchange", "Disabled", CV_SAVE, demo
static UINT8 *savebuffer;
// Analog Control
static void UserAnalog_OnChange(void);
static void UserAnalog2_OnChange(void);
static void UserAnalog3_OnChange(void);
static void UserAnalog4_OnChange(void);
static void Analog_OnChange(void);
static void Analog2_OnChange(void);
static void Analog3_OnChange(void);
@@ -446,10 +442,10 @@ consvar_t cv_analog = {"analog", "Off", CV_CALL, CV_OnOff, Analog_OnChange, 0, N
consvar_t cv_analog2 = {"analog2", "Off", CV_CALL, CV_OnOff, Analog2_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_analog3 = {"analog3", "Off", CV_CALL, CV_OnOff, Analog3_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_analog4 = {"analog4", "Off", CV_CALL, CV_OnOff, Analog4_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_useranalog = {"useranalog", "Off", CV_SAVE|CV_CALL, CV_OnOff, UserAnalog_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_useranalog2 = {"useranalog2", "Off", CV_SAVE|CV_CALL, CV_OnOff, UserAnalog2_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_useranalog3 = {"useranalog3", "Off", CV_SAVE|CV_CALL, CV_OnOff, UserAnalog3_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_useranalog4 = {"useranalog4", "Off", CV_SAVE|CV_CALL, CV_OnOff, UserAnalog4_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_useranalog = {"useranalog", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_useranalog2 = {"useranalog2", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_useranalog3 = {"useranalog3", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_useranalog4 = {"useranalog4", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_turnaxis = {"joyaxis_turn", "Left X", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_moveaxis = {"joyaxis_move", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -511,8 +507,8 @@ static CV_PossibleValue_t driftsparkpulse_t[] = {{0, "MIN"}, {FRACUNIT*3, "MAX"}
consvar_t cv_driftsparkpulse = {"driftsparkpulse", "1.4", CV_FLOAT | CV_SAVE, driftsparkpulse_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t stretchfactor_t[] = {
{0, "Off"}, {FRACUNIT/8, "0.125"}, {FRACUNIT/4, "0.250"},
{3*FRACUNIT/8, "0.375"}, {FRACUNIT/2, "0.500"}, {5*FRACUNIT/8, "0.625"},
{0, "Off"}, {FRACUNIT/8, "0.125"}, {FRACUNIT/4, "0.250"},
{3*FRACUNIT/8, "0.375"}, {FRACUNIT/2, "0.500"}, {5*FRACUNIT/8, "0.625"},
{3*FRACUNIT/4, "0.750"}, {7*FRACUNIT/8, "0.875"}, {FRACUNIT, "Max"}, {0, NULL}};
consvar_t cv_gravstretch = {"gravstretch", "0", CV_SAVE, stretchfactor_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -596,15 +592,6 @@ void G_ClearRecords(void)
}
}
// For easy retrieval of records
/*UINT32 G_GetBestScore(INT16 map)
{
if (!mainrecords[map-1])
return 0;
return mainrecords[map-1]->score;
}*/
tic_t G_GetBestTime(INT16 map)
{
if (!mainrecords[map-1] || mainrecords[map-1]->time <= 0)
@@ -980,7 +967,7 @@ static INT32 Joy3Axis(axis_input_e axissel)
}
if (flp) retaxis = -retaxis; //flip it around
return retaxis;
}
else
{
@@ -1000,7 +987,7 @@ static INT32 Joy3Axis(axis_input_e axissel)
}
if (flp) retaxis = -retaxis; //flip it around
return retaxis;
}
}
@@ -1075,7 +1062,7 @@ static INT32 Joy4Axis(axis_input_e axissel)
}
if (flp) retaxis = -retaxis; //flip it around
return retaxis;
}
else
{
@@ -1095,7 +1082,7 @@ static INT32 Joy4Axis(axis_input_e axissel)
}
if (flp) retaxis = -retaxis; //flip it around
return retaxis;
}
}
@@ -1197,11 +1184,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
// why build a ticcmd if we're paused?
// Or, for that matter, if we're being reborn.
// Kart, don't build a ticcmd if someone is resynching or the server is stopped too so we don't fly off course in bad conditions
if (paused || P_AutoPause() || (gamestate == GS_LEVEL && player->playerstate == PST_REBORN) || hu_resynching
#ifdef SATURNSYNCH
|| hu_redownloadinggamestate
#endif
)
if (paused || P_AutoPause() || (gamestate == GS_LEVEL && player->playerstate == PST_REBORN) || hu_resynching)
{
cmd->angleturn = (INT16)(lang >> 16);
cmd->aiming = G_ClipAimingPitch(&laim);
@@ -1513,61 +1496,11 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
}
// User has designated that they want
// analog ON, so tell the game to stop
// fudging with it.
static void UserAnalog_OnChange(void)
{
/*if (cv_useranalog.value)
CV_SetValue(&cv_analog, 1);
else
CV_SetValue(&cv_analog, 0);*/
}
static void UserAnalog2_OnChange(void)
{
if (botingame)
return;
/*if (cv_useranalog2.value)
CV_SetValue(&cv_analog2, 1);
else
CV_SetValue(&cv_analog2, 0);*/
}
static void UserAnalog3_OnChange(void)
{
if (botingame)
return;
/*if (cv_useranalog3.value)
CV_SetValue(&cv_analog3, 1);
else
CV_SetValue(&cv_analog3, 0);*/
}
static void UserAnalog4_OnChange(void)
{
if (botingame)
return;
/*if (cv_useranalog4.value)
CV_SetValue(&cv_analog4, 1);
else
CV_SetValue(&cv_analog4, 0);*/
}
static void Analog_OnChange(void)
{
if (!cv_cam_dist.string)
return;
// cameras are not initialized at this point
/*
if (!cv_chasecam.value && cv_analog.value) {
CV_SetValue(&cv_analog, 0);
return;
}
*/
SendWeaponPref();
}
@@ -1576,15 +1509,6 @@ static void Analog2_OnChange(void)
if (!(splitscreen || botingame) || !cv_cam2_dist.string)
return;
// cameras are not initialized at this point
/*
if (!cv_chasecam2.value && cv_analog2.value) {
CV_SetValue(&cv_analog2, 0);
return;
}
*/
SendWeaponPref2();
}
@@ -1593,15 +1517,6 @@ static void Analog3_OnChange(void)
if (splitscreen < 2 || !cv_cam3_dist.string)
return;
// cameras are not initialized at this point
/*
if (!cv_chasecam3.value && cv_analog3.value) {
CV_SetValue(&cv_analog3, 0);
return;
}
*/
SendWeaponPref3();
}
@@ -1610,15 +1525,6 @@ static void Analog4_OnChange(void)
if (splitscreen < 3 || !cv_cam4_dist.string)
return;
// cameras are not initialized at this point
/*
if (!cv_chasecam4.value && cv_analog4.value) {
CV_SetValue(&cv_analog4, 0);
return;
}
*/
SendWeaponPref4();
}
@@ -1694,6 +1600,8 @@ void G_DoLoadLevel(boolean resetplayer)
// clear hud messages remains (usually from game startup)
CON_ClearHUD();
G_ResetAllDeviceRumbles();
}
static INT32 pausedelay = 0;
@@ -1952,7 +1860,6 @@ boolean G_Responder(event_t *ev)
|| ev->data1 == gamecontrol[gc_director][1])
{
K_ToggleDirector();
directortoggletimer = 0;
}
return true;
@@ -2084,6 +1991,29 @@ INT32 G_CountPlayersPotentiallyViewable(boolean active)
return total;
}
//
// G_FixCamera
// Reset camera position, angle and interpolation on a view
// after changing state.
//
static void G_FixCamera(UINT8 view)
{
player_t *player = &players[displayplayers[view - 1]];
// The order of displayplayers can change, which would
// invalidate localangle.
localangle[view - 1] = player->cmd.angleturn;
P_ResetCamera(player, &camera[view - 1]);
// Make sure the viewport doesn't interpolate at all into
// its new position -- just snap instantly into place.
// Why does it need to be done twice?
R_ResetViewInterpolation(view);
R_ResetViewInterpolation(view);
}
//
// G_ResetView
// Correct a viewpoint to playernum or the next available, wraps forward.
@@ -2096,7 +2026,6 @@ void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive)
UINT8 viewd;
INT32 *displayplayerp;
camera_t *camerap;
INT32 olddisplayplayer;
INT32 playersviewable;
@@ -2133,31 +2062,20 @@ void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive)
/* Focus our target view first so that we don't take its player. */
(*displayplayerp) = playernum;
if ((*displayplayerp) != olddisplayplayer)
{
camerap = &camera[viewnum-1];
P_ResetCamera(&players[(*displayplayerp)], camerap);
// Make sure the viewport doesn't interpolate at all into
// its new position -- just snap instantly into place.
R_ResetViewInterpolation(viewnum);
}
/* If a viewpoint changes, reset the camera to clear uninitialized memory. */
if (viewnum > splits)
{
for (viewd = splits+1; viewd < viewnum; ++viewd)
for (viewd = splits+1; viewd <= viewnum; ++viewd)
{
displayplayerp = (&displayplayers[viewd-1]);
camerap = &camera[viewd];
(*displayplayerp) = G_FindView(0, viewd, onlyactive, false);
P_ResetCamera(&players[(*displayplayerp)], camerap);
// Make sure the viewport doesn't interpolate at all into
// its new position -- just snap instantly into place.
R_ResetViewInterpolation(viewd);
G_FixCamera(viewd);
}
}
else
{
if ((*displayplayerp) != olddisplayplayer)
{
G_FixCamera(viewnum);
}
}
@@ -2239,13 +2157,6 @@ void G_Ticker(boolean run)
if (!(netgame || multiplayer) && G_GetRetryFlag())
{
G_ClearRetryFlag();
// Costs a life to retry ... unless the player in question is dead already.
/*if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE)
players[consoleplayer].lives -= 1;
G_DoReborn(consoleplayer);*/
D_MapChange(gamemap, gametype, cv_kartencore.value, true, 1, false, false);
}
@@ -2558,21 +2469,6 @@ void G_PlayerReborn(INT32 player)
bot = players[player].bot;
pity = players[player].pity;
if (leveltime <= starttime) // man i really hope this crap works kek but need to reset this somehow at mapstart
{
for (i = 0; i < LAP__MAX; i++)
{
laptime[i] = 0;
}
}
else
{
for (i = 0; i < LAP__MAX; i++)
{
laptime[i] = players[player].laptime[i];
}
}
// SRB2kart
if (leveltime <= starttime || spectator == true)
{
@@ -2593,6 +2489,11 @@ void G_PlayerReborn(INT32 player)
starpostnum = 0;
respawnflip = 0;
starpostangle = 0;
for (i = 0; i < LAP__MAX; i++)
{
laptime[i] = 0;
}
}
else
{
@@ -2621,6 +2522,11 @@ void G_PlayerReborn(INT32 player)
bumper = players[player].kartstuff[k_bumper];
comebackpoints = players[player].kartstuff[k_comebackpoints];
wanted = players[player].kartstuff[k_wanted];
for (i = 0; i < LAP__MAX; i++)
{
laptime[i] = players[player].laptime[i];
}
}
spectatorreentry = players[player].spectatorreentry;
@@ -3139,6 +3045,8 @@ void G_AddPlayer(INT32 playernum)
void G_ExitLevel(void)
{
G_ResetAllDeviceRumbles();
if (gamestate == GS_LEVEL)
{
gameaction = ga_completed;
@@ -3167,13 +3075,6 @@ const char *Gametype_Names[NUMGAMETYPES] =
{
"Race", // GT_RACE
"Battle" // GT_MATCH
/*"Co-op", // GT_COOP
"Competition", // GT_COMPETITION
"Team Match", // GT_TEAMMATCH
"Tag", // GT_TAG
"Hide and Seek", // GT_HIDEANDSEEK
"CTF" // GT_CTF*/
};
//
@@ -3235,12 +3136,7 @@ boolean G_GametypeHasTeams(void)
//
boolean G_GametypeHasSpectators(void)
{
// SRB2Kart: We don't have any exceptions to not being able to spectate yet. Maybe when SP & bots roll around.
#if 0
return (gametype != GT_COOP && gametype != GT_COMPETITION && gametype != GT_RACE);
#else
return (netgame || (multiplayer && demo.playback)); //true
#endif
}
//
@@ -4275,14 +4171,11 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
Z_Free(savebuffer);
save_p = savebuffer = NULL;
// gameaction = ga_nothing;
// G_SetGamestate(GS_LEVEL);
displayplayers[0] = consoleplayer;
multiplayer = false;
splitscreen = 0;
SplitScreen_OnChange(); // not needed?
// G_DeferedInitNew(sk_medium, G_BuildMapName(1), 0, 0, 1);
if (setsizeneeded)
R_ExecuteSetViewSize();
@@ -4487,6 +4380,7 @@ void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, bool
else
{
LUAh_MapChange(gamemap);
S_CheckMap();
G_DoLoadLevel(resetplayer);
}
@@ -4648,8 +4542,7 @@ INT32 G_FindMap(const char *mapname, char **foundmapnamep,
break;
}
}
else
if (apromapnum == 0 || wanttable)
else if (apromapnum == 0 || wanttable)
{
/* LEVEL 1--match keywords verbatim */
if (( aprop = strcasestr(realmapname, mapname) ))
@@ -4740,6 +4633,8 @@ INT32 G_FindMapByNameOrCode(const char *mapname, char **realmapnamep)
{
if (mapname[0] == '*') // current map
return gamemap;
else if (mapname[0] == '?' && mapheaderinfo[gamemap-1])
return G_RandMap(G_TOLFlag(gametype), gamemap-1, false, 0, false, NULL)+1;
else if (mapname[0] == '+' && mapheaderinfo[gamemap-1]) // next map
{
newmapnum = mapheaderinfo[gamemap-1]->nextlevel;
@@ -6491,8 +6386,18 @@ void G_BeginRecording(void)
// Full replay title
demo_p += 64;
{
char demotitlename[65];
char *title = G_BuildMapTitle(gamemap);
snprintf(demo.titlename, 64, "%s - %s", title, modeattacking ? "Time Attack" : connectedservername);
// Print to a separate temp buffer instead of demo.titlename, so we can use it in M_TextInputSetString
snprintf(demotitlename, 64, "%s - %s", title, modeattacking ? "Time Attack" : connectedservername);
// Init just in case it isn't initialized already
M_TextInputInit(&demo.titlenameinput, demo.titlename, sizeof(demo.titlename));
// This will indirectly assign to demo.titlename too
M_TextInputSetString(&demo.titlenameinput, demotitlename);
Z_Free(title);
}
@@ -7862,9 +7767,6 @@ void G_AddGhost(char *defdemoname)
case ATTACKING_RECORD: // 1
p += 8; // demo time, lap
break;
/*case ATTACKING_NIGHTS: // 2
p += 8; // demo time left, score
break;*/
default: // 3
break;
}
@@ -8485,7 +8387,6 @@ void G_SaveDemo(void)
boolean G_DemoTitleResponder(event_t *ev)
{
size_t len;
INT32 ch;
if (ev->type != ev_keydown)
@@ -8506,28 +8407,7 @@ boolean G_DemoTitleResponder(event_t *ev)
return true;
}
if ((ch >= HU_FONTSTART && ch <= HU_FONTEND && hu_font[ch-HU_FONTSTART])
|| ch == ' ') // Allow spaces, of course
{
len = strlen(demo.titlename);
if (len < 64)
{
demo.titlename[len+1] = 0;
demo.titlename[len] = cv_keyboardlayout.value == 3 ? CON_ShitAndAltGrChar(ch) : CON_ShiftChar(ch);
}
}
else if (ch == KEY_BACKSPACE)
{
if (shiftdown)
memset(demo.titlename, 0, sizeof(demo.titlename));
else
{
len = strlen(demo.titlename);
if (len > 0)
demo.titlename[len-1] = 0;
}
}
M_TextInputHandle(&demo.titlenameinput, ch);
return true;
}
@@ -8540,7 +8420,6 @@ boolean G_DemoTitleResponder(event_t *ev)
void G_SetGamestate(gamestate_t newstate)
{
gamestate = newstate;
#ifdef HAVE_DISCORDRPC
DRPC_UpdatePresence();
#endif
@@ -8613,4 +8492,3 @@ INT32 G_TicsToMilliseconds(tic_t tics)
{
return (INT32)((tics%TICRATE) * (1000.00f/TICRATE));
}
+4 -10
View File
@@ -17,6 +17,7 @@
#include "doomdef.h"
#include "doomstat.h"
#include "d_event.h"
#include "m_textinput.h"
extern char gamedatafilename[64];
extern char timeattackfolder[64];
@@ -44,6 +45,7 @@ extern consvar_t cv_recordmultiplayerdemos, cv_netdemosyncquality, cv_maxdemosiz
// Publicly-accessible demo vars
struct demovars_s {
char titlename[65];
textinput_t titlenameinput;
boolean recording, playback, timing;
UINT16 version; // Current file format of the demo being played
boolean title; // Title Screen demo can be cancelled by any key
@@ -417,19 +419,9 @@ void G_SetGamestate(gamestate_t newstate);
// Gamedata record shit
void G_AllocMainRecordData(INT16 i);
//void G_AllocNightsRecordData(INT16 i);
void G_ClearRecords(void);
//UINT32 G_GetBestScore(INT16 map);
tic_t G_GetBestTime(INT16 map);
//tic_t G_GetBestLap(INT16 map);
//UINT16 G_GetBestRings(INT16 map);
//UINT32 G_GetBestNightsScore(INT16 map, UINT8 mare);
//tic_t G_GetBestNightsTime(INT16 map, UINT8 mare);
//UINT8 G_GetBestNightsGrade(INT16 map, UINT8 mare);
//void G_AddTempNightsRecords(UINT32 pscore, tic_t ptime, UINT8 mare);
//void G_SetNightsRecords(void);
FUNCMATH INT32 G_TicsToHours(tic_t tics);
FUNCMATH INT32 G_TicsToMinutes(tic_t tics, boolean full);
@@ -437,6 +429,8 @@ FUNCMATH INT32 G_TicsToSeconds(tic_t tics);
FUNCMATH INT32 G_TicsToCentiseconds(tic_t tics);
FUNCMATH INT32 G_TicsToMilliseconds(tic_t tics);
boolean K_DirectorIsPlayerAlone(void); // idk where else to put this lol
// Don't split up TOL handling
INT16 G_TOLFlag(INT32 pgametype);
+15
View File
@@ -1013,6 +1013,21 @@ static void G_ResetPlayerDeviceRumble(INT32 player)
I_GamepadRumble(device_id, 0, 0, 0);
}
void G_ResetAllDeviceRumbles(void)
{
int i;
int devices;
devices = I_NumJoys();
for (i = 0; i < devices; i++)
{
INT32 device_id = G_GetDeviceForPlayer(i);
I_GamepadRumble(device_id, 0, 0, 0);
}
}
void G_PlayerDeviceRumble(INT32 player, UINT16 low_strength, UINT16 high_strength, UINT32 duration)
{
INT32 device_id;
+1
View File
@@ -138,6 +138,7 @@ UINT16 G_GetSkinColor(INT32 player);
INT32 G_GetDeviceForPlayer(INT32 player);
void G_SetPlayerGamepadIndicatorColor(INT32 player, UINT16 color);
void G_PlayerDeviceRumble(INT32 player, UINT16 low_strength, UINT16 high_strength, UINT32 duration);
void G_ResetAllDeviceRumbles(void);
// remaps the input event to a game control.
void G_MapEventsToControls(event_t *ev);
+1 -1
View File
@@ -156,7 +156,7 @@ typedef struct
boolean mirrorflip; // Encore Mode with Flipcam
#endif
boolean shearing; // 14042019
angle_t viewaiming; // 17052019
float viewaiming; // 17052019
} FTransform;
// Transformed vector, as passed to HWR API
-1
View File
@@ -32,7 +32,6 @@ typedef struct gr_vissprite_s
float scale;
float spritexscale, spriteyscale;
float spritexoffset, spriteyoffset;
UINT32 renderflags;
GLPatch_t *gpatch;
boolean flip;
UINT8 translucency; //alpha level 0-255
+272 -326
View File
File diff suppressed because it is too large. Load diff
+1 -8
View File
@@ -116,7 +116,7 @@ void HWR_MakeScreenFinalTexture(void);
void HWR_DrawScreenFinalTexture(INT32 width, INT32 height);
// hw_main.c: Planes
void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap);
//void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap);
void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap);
void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, FBITFIELD blendmode, UINT8 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap);
@@ -131,12 +131,6 @@ void HWR_AddTransparentWall(FOutVector *wallVerts, FSurfaceInfo * pSurf, INT32 t
void HWR_DrawSkyWall(FOutVector *wallVerts, FSurfaceInfo *Surf);
void HWR_DrawSkyBackground(float fpov);
// hw_main.c: Sprites
void HWR_AddSprites(sector_t *sec);
void HWR_ProjectSprite(mobj_t *thing);
//void HWR_ProjectPrecipitationSprite(precipmobj_t *thing);
void HWR_DrawSprites(void);
// hw_bsp.c
void HWR_CreatePlanePolygons(INT32 bspnum);
extern boolean gr_maphasportals;
@@ -152,7 +146,6 @@ extern consvar_t cv_grshaders;
#ifdef USE_FBO_OGL
extern consvar_t cv_grframebuffer;
#endif
extern consvar_t cv_splitwallfix;
extern consvar_t cv_grshearing;
extern consvar_t cv_grfov;
extern consvar_t cv_grmdls;
+1 -1
View File
@@ -2984,7 +2984,7 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform)
// https://zdoom.org/wiki/Y-shearing
if (shearing)
{
float dy = FIXED_TO_FLOAT(AIMINGTODY((stransform->viewaiming)) * 2)* ((float)vid.width / vid.height) / ((float)BASEVIDWIDTH / BASEVIDHEIGHT); //screen_width/BASEVIDWIDTH;
float dy = stransform->viewaiming * 2;
if (stransform->flip || stransform->mirrorflip)
dy *= -1.0f;
pglTranslatef(0.0f, -dy/BASEVIDHEIGHT, 0.0f);
+148 -275
View File
@@ -49,6 +49,8 @@
#include "s_sound.h" // song credits
#include "k_kart.h"
#include "m_textinput.h"
#ifdef HWRENDER
#include "hardware/hw_main.h"
#endif
@@ -86,8 +88,8 @@ patch_t *frameslash; // framerate stuff. Used in screen.c
static player_t *plr;
boolean chat_on; // entering a chat message?
static char w_chat[HU_MAXMSGLEN + 1];
static size_t c_input = 0; // let's try to make the chat input less shitty.
static char w_chat_buf[HU_MAXMSGLEN + 1];
static textinput_t w_chat;
static boolean headsupactive = false;
boolean hu_showscores; // draw rankings
static char hu_tick;
@@ -1143,71 +1145,6 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
#endif
}
// Handles key input and string input
//
static inline boolean HU_keyInChatString(char *s, char ch)
{
size_t l;
if ((ch >= HU_FONTSTART && ch <= HU_FONTEND && hu_font[ch-HU_FONTSTART])
|| ch == ' ') // Allow spaces, of course
{
l = strlen(s);
if (l < HU_MAXMSGLEN - 1)
{
if (c_input >= strlen(s)) // don't do anything complicated
{
s[l++] = ch;
s[l]=0;
}
else
{
// move everything past c_input for new characters:
size_t m = HU_MAXMSGLEN-1;
while (m>=c_input)
{
if (s[m])
s[m+1] = (s[m]);
if (m == 0) // prevent overflow
break;
m--;
}
s[c_input] = ch; // and replace this.
}
c_input++;
return true;
}
return false;
}
else if (ch == KEY_BACKSPACE)
{
size_t i = c_input;
if (c_input <= 0)
return false;
if (!s[i-1])
return false;
if (i >= strlen(s)-1)
{
s[strlen(s)-1] = 0;
c_input--;
return false;
}
for (; (i < HU_MAXMSGLEN); i++)
{
s[i-1] = s[i];
}
c_input--;
}
else if (ch != KEY_ENTER)
return false; // did not eat key
return true; // ate the key
}
#endif
//
@@ -1280,9 +1217,9 @@ static boolean HU_clearChatSpaces(void)
char c; // current character we're iterating.
boolean nothingbutspaces = true;
for (; i < strlen(w_chat); i++) // iterate through message and eradicate all spaces that don't belong.
for (; i < strlen(w_chat_buf); i++) // iterate through message and eradicate all spaces that don't belong.
{
c = w_chat[i];
c = w_chat_buf[i];
if (!c)
break; // if there's nothing, it's safe to assume our message has ended, so let's not waste any more time here.
@@ -1294,128 +1231,110 @@ static boolean HU_clearChatSpaces(void)
return nothingbutspaces;
}
//
//
static void HU_queueChatChar(INT32 c)
static void HU_SendChatMessage(void)
{
// send automaticly the message (no more chat char)
if (c == KEY_ENTER)
char buf[2 + HU_MAXMSGLEN + 1];
char *msg = &buf[2];
size_t ci = 2;
INT32 target = 0;
char c;
if (HU_clearChatSpaces()) // Avoids being able to send empty messages, or something.
return; // If this returns true, that means our message was NOTHING but spaces, so don't send it period.
do {
c = w_chat_buf[-2+ci++];
if (!c || (c >= ' ' && !(c & 0x80))) // copy printable characters and terminating '\0' only.
buf[ci-1]=c;
} while (c);
M_TextInputClear(&w_chat);
// last minute mute check
if (CHAT_MUTE)
{
char buf[2 + HU_MAXMSGLEN + 1];
char *msg = &buf[2];
size_t i;
size_t ci = 2;
INT32 target = 0;
HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"), false);
return;
}
if (HU_clearChatSpaces()) // Avoids being able to send empty messages, or something.
return; // If this returns true, that means our message was NOTHING but spaces, so don't send it period.
if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm
{
INT32 spc = 1; // used if nodenum[1] is a space.
char *nodenum = (char*) malloc(3);
const char *newmsg;
do {
c = w_chat[-2+ci++];
if (!c || (c >= ' ' && !(c & 0x80))) // copy printable characters and terminating '\0' only.
buf[ci-1]=c;
} while (c);
i = 0;
for (;(i<HU_MAXMSGLEN);i++)
w_chat[i] = 0; // reset this.
// what we're gonna do now is check if the node exists
// with that logic, characters 4 and 5 are our numbers:
c_input = 0;
for (;(i<HU_MAXMSGLEN);i++)
w_chat[i] = 0; // reset this.
c_input = 0;
// last minute mute check
if (CHAT_MUTE)
// teamtalk can't send PMs, just don't send it, else everyone would be able to see it, and no one wants to see your sex RP sicko.
if (teamtalk)
{
HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"), false);
HU_AddChatText(va("%sCannot send sayto in Say-Team.", "\x85"), false);
return;
}
if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm
memcpy(nodenum, msg+3, 2);
nodenum[2] = '\0';
// check for undesirable characters in our "number"
if (((nodenum[0] < '0') || (nodenum[0] > '9')) || ((nodenum[1] < '0') || (nodenum[1] > '9')))
{
INT32 spc = 1; // used if nodenum[1] is a space.
char *nodenum = (char*) malloc(3);
const char *newmsg;
// what we're gonna do now is check if the node exists
// with that logic, characters 4 and 5 are our numbers:
// teamtalk can't send PMs, just don't send it, else everyone would be able to see it, and no one wants to see your sex RP sicko.
if (teamtalk)
{
HU_AddChatText(va("%sCannot send sayto in Say-Team.", "\x85"), false);
return;
}
memcpy(nodenum, msg+3, 2);
nodenum[2] = '\0';
// check for undesirable characters in our "number"
if (((nodenum[0] < '0') || (nodenum[0] > '9')) || ((nodenum[1] < '0') || (nodenum[1] > '9')))
{
// check if nodenum[1] is a space
if (nodenum[1] == ' ')
spc = 0;
// let it slide
else
{
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<node> \'.", false);
free(nodenum);
return;
}
}
// I'm very bad at C, I swear I am, additional checks eww!
if (spc != 0)
{
if (msg[5] != ' ')
{
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<node> \'.", false);
free(nodenum);
return;
}
}
target = atoi((const char*) nodenum); // turn that into a number
free(nodenum);
//CONS_Printf("%d\n", target);
// check for target player, if it doesn't exist then we can't send the message!
if (target < MAXPLAYERS && playeringame[target]) // player exists
target++; // even though playernums are from 0 to 31, target is 1 to 32, so up that by 1 to have it work!
// check if nodenum[1] is a space
if (nodenum[1] == ' ')
spc = 0;
// let it slide
else
{
HU_AddChatText(va("\x82NOTICE: \x80Player %d does not exist.", target), false); // same
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<node> \'.", false);
free(nodenum);
return;
}
// we need to get rid of the /pm<node>
newmsg = msg+5+spc;
strlcpy(msg, newmsg, HU_MAXMSGLEN + 1);
}
if (ci > 3) // don't send target+flags+empty message.
// I'm very bad at C, I swear I am, additional checks eww!
if (spc != 0)
{
if (teamtalk)
buf[0] = -1; // target
else
buf[0] = target;
buf[1] = 0; // flags
SendNetXCmd(XD_SAY, buf, 2 + strlen(&buf[2]) + 1);
if (msg[5] != ' ')
{
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<node> \'.", false);
free(nodenum);
return;
}
}
return;
target = atoi((const char*) nodenum); // turn that into a number
free(nodenum);
//CONS_Printf("%d\n", target);
// check for target player, if it doesn't exist then we can't send the message!
if (target < MAXPLAYERS && playeringame[target]) // player exists
target++; // even though playernums are from 0 to 31, target is 1 to 32, so up that by 1 to have it work!
else
{
HU_AddChatText(va("\x82NOTICE: \x80Player %d does not exist.", target), false); // same
return;
}
// we need to get rid of the /pm<node>
newmsg = msg+5+spc;
strlcpy(msg, newmsg, HU_MAXMSGLEN + 1);
}
if (ci > 3) // don't send target+flags+empty message.
{
if (teamtalk)
buf[0] = -1; // target
else
buf[0] = target;
buf[1] = 0; // flags
SendNetXCmd(XD_SAY, buf, 2 + strlen(&buf[2]) + 1);
}
}
#endif
void HU_clearChatChars(void)
{
size_t i = 0;
for (;i<HU_MAXMSGLEN;i++)
w_chat[i] = 0; // reset this.
M_TextInputClear(&w_chat);
chat_on = false;
c_input = 0;
}
#ifndef NONET
@@ -1463,7 +1382,8 @@ boolean HU_Responder(event_t *ev)
&& netgame && !OLD_MUTE) // check for old chat mute, still let the players open the chat incase they want to scroll otherwise.
{
chat_on = true;
w_chat[0] = 0;
w_chat_buf[0] = 0;
M_TextInputInit(&w_chat, w_chat_buf, sizeof w_chat_buf);
teamtalk = false;
chat_scrollmedown = true;
typelines = 1;
@@ -1473,7 +1393,8 @@ boolean HU_Responder(event_t *ev)
&& netgame && !OLD_MUTE)
{
chat_on = true;
w_chat[0] = 0;
w_chat_buf[0] = 0;
M_TextInputInit(&w_chat, w_chat_buf, sizeof w_chat_buf);
teamtalk = G_GametypeHasTeams(); // Don't teamtalk if we don't have teams.
chat_scrollmedown = true;
typelines = 1;
@@ -1498,62 +1419,13 @@ boolean HU_Responder(event_t *ev)
&& ev->data1 != gamecontrol[gc_talkkey][1]))
return false;
c = cv_keyboardlayout.value == 3 ? CON_ShitAndAltGrChar(c) : CON_ShiftChar(c);
M_TextInputHandle(&w_chat, c);
// pasting. pasting is cool. chat is a bit limited, though :(
if (((c == 'v' || c == 'V') && ctrldown) && !CHAT_MUTE)
{
const char *paste = I_ClipboardPaste();
size_t chatlen;
size_t pastelen;
// create a dummy string real quickly
if (paste == NULL)
return true;
chatlen = strlen(w_chat);
pastelen = strlen(paste);
if (chatlen+pastelen > HU_MAXMSGLEN)
return true; // we can't paste this!!
if (c_input >= strlen(w_chat)) // add it at the end of the string.
{
memcpy(&w_chat[chatlen], paste, pastelen); // copy all of that.
c_input += pastelen;
/*size_t i = 0;
for (;i<pastelen;i++)
{
HU_queueChatChar(paste[i]); // queue it so that it's actually sent. (this chat write thing is REALLY messy.)
}*/
return true;
}
else // otherwise, we need to shift everything and make space, etc etc
{
size_t i = HU_MAXMSGLEN-1;
while (i >= c_input)
{
if (w_chat[i])
w_chat[i+pastelen] = w_chat[i];
if (i == 0) // prevent overflow
break;
i--;
}
memcpy(&w_chat[c_input], paste, pastelen); // copy all of that.
c_input += pastelen;
return true;
}
}
if (!CHAT_MUTE && HU_keyInChatString(w_chat,c))
{
HU_queueChatChar(c);
}
if (c == KEY_ENTER)
{
chat_on = false;
c_input = 0; // reset input cursor
chat_scrollmedown = true; // you hit enter, so you might wanna autoscroll to see what you just sent. :)
HU_SendChatMessage();
}
else if (c == KEY_ESCAPE
|| ((c == gamecontrol[gc_talkkey][0] || c == gamecontrol[gc_talkkey][1]
@@ -1561,7 +1433,6 @@ boolean HU_Responder(event_t *ev)
&& c >= KEY_MOUSE1)) // If it's not a keyboard key, then the chat button is used as a toggle.
{
chat_on = false;
c_input = 0; // reset input cursor
}
else if ((c == KEY_UPARROW || c == KEY_MOUSEWHEELUP) && chat_scroll > 0 && !OLDCHAT) // CHAT SCROLLING YAYS!
{
@@ -1575,10 +1446,6 @@ boolean HU_Responder(event_t *ev)
justscrolleddown = true;
chat_scrolltime = 4;
}
else if (c == KEY_LEFTARROW && c_input != 0 && !OLDCHAT) // i said go back
c_input--;
else if (c == KEY_RIGHTARROW && c_input < strlen(w_chat) && !OLDCHAT) // don't need to check for admin or w/e here since the chat won't ever contain anything if it's muted.
c_input++;
return true;
}
#endif
@@ -1932,8 +1799,9 @@ static void HU_DrawChat(void)
INT32 charwidth = 4, charheight = 6;
INT32 boxw = cv_chatwidth.value;
INT32 t = 0, c = 0, y = chaty - (typelines*charheight);
UINT32 i = 0, saylen = strlen(w_chat); // You learn new things everyday!
UINT32 i = 0, saylen = strlen(w_chat_buf); // You learn new things everyday!
INT32 cflag = 0;
size_t select_start = 0, select_end = 0;
const char *ntalk = "Say: ", *ttalk = "Team: ";
const char *talk = ntalk;
const char *mute = "Chat has been muted.";
@@ -1995,13 +1863,19 @@ static void HU_DrawChat(void)
i = 0;
typelines = 1;
if ((strlen(w_chat) == 0 || c_input == 0) && hu_tick < 4)
V_DrawChatCharacter(chatx + 2 + c, y+1, '_' |V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, !cv_allcaps.value, NULL);
if ((w_chat.cursor == 0 || w_chat.length == 0) && hu_tick < 4)
V_DrawChatCharacter(chatx+2+c+charwidth*w_chat.cursor, y+1, '_'|V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, !cv_allcaps.value, NULL);
while (w_chat[i])
if (w_chat.select != w_chat.cursor)
{
select_start = min(w_chat.select, w_chat.cursor);
select_end = max(w_chat.select, w_chat.cursor);
}
while (w_chat_buf[i])
{
boolean skippedline = false;
if (c_input == (i+1))
if (w_chat.cursor == (i+1))
{
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);
@@ -2016,10 +1890,14 @@ static void HU_DrawChat(void)
}
//Hurdler: isn't it better like that?
if (w_chat[i] < HU_FONTSTART)
++i;
else
V_DrawChatCharacter(chatx + c + 2, y, w_chat[i++] | V_SNAPTOBOTTOM|V_SNAPTOLEFT | t, !cv_allcaps.value, NULL);
if (w_chat_buf[i] >= HU_FONTSTART)
V_DrawChatCharacter(chatx + c + 2, y, w_chat_buf[i] | V_SNAPTOBOTTOM|V_SNAPTOLEFT | t, !cv_allcaps.value, NULL);
// Draw selection
if (i >= select_start && i < select_end)
V_DrawFill(chatx + c + 2, y-1, charwidth, charheight, 103|V_TRANSLUCENT|V_SNAPTOBOTTOM|V_SNAPTOLEFT|t);
++i;
c += charwidth;
if (c > boxw-(charwidth*2) && !skippedline)
@@ -2031,7 +1909,7 @@ static void HU_DrawChat(void)
}
// handle /pm list. It's messy, horrible and I don't care.
if (strnicmp(w_chat, "/pm", 3) == 0 && vid.width >= 400 && !teamtalk) // 320x200 unsupported kthxbai
if (strnicmp(w_chat_buf, "/pm", 3) == 0 && vid.width >= 400 && !teamtalk) // 320x200 unsupported kthxbai
{
INT32 count = 0;
INT32 p_dispy = chaty - charheight -1;
@@ -2051,38 +1929,38 @@ static void HU_DrawChat(void)
{
// filter: (code needs optimization pls help I'm bad with C)
if (w_chat[3])
if (w_chat_buf[3])
{
char *nodenum;
UINT32 n;
// right, that's half important: (w_chat[4] may be a space since /pm0 msg is perfectly acceptable!)
if ( ( ((w_chat[3] != 0) && ((w_chat[3] < '0') || (w_chat[3] > '9'))) || ((w_chat[4] != 0) && (((w_chat[4] < '0') || (w_chat[4] > '9'))))) && (w_chat[4] != ' '))
// right, that's half important: (w_chat_buf[4] may be a space since /pm0 msg is perfectly acceptable!)
if ( ( ((w_chat_buf[3] != 0) && ((w_chat_buf[3] < '0') || (w_chat_buf[3] > '9'))) || ((w_chat_buf[4] != 0) && (((w_chat_buf[4] < '0') || (w_chat_buf[4] > '9'))))) && (w_chat_buf[4] != ' '))
break;
nodenum = (char*) malloc(3);
memcpy(nodenum, w_chat+3, 2);
memcpy(nodenum, w_chat_buf+3, 2);
nodenum[2] = '\0';
n = atoi((const char*) nodenum); // turn that into a number
free(nodenum);
// special cases:
if ((n == 0) && !(w_chat[4] == '0'))
if ((n == 0) && !(w_chat_buf[4] == '0'))
{
if (!(i<10))
continue;
}
else if ((n == 1) && !(w_chat[3] == '0'))
else if ((n == 1) && !(w_chat_buf[3] == '0'))
{
if (!((i == 1) || ((i >= 10) && (i <= 19))))
continue;
}
else if ((n == 2) && !(w_chat[3] == '0'))
else if ((n == 2) && !(w_chat_buf[3] == '0'))
{
if (!((i == 2) || ((i >= 20) && (i <= 29))))
continue;
}
else if ((n == 3) && !(w_chat[3] == '0'))
else if ((n == 3) && !(w_chat_buf[3] == '0'))
{
if (!((i == 3) || ((i >= 30) && (i <= 31))))
continue;
@@ -2121,6 +1999,7 @@ static void HU_DrawChat_Old(void)
size_t i = 0;
const char *ntalk = "Say: ", *ttalk = "Say-Team: ";
const char *talk = ntalk;
size_t select_start = 0, select_end = 0;
INT32 charwidth = 8 * con_scalefactor; //SHORT(hu_font['A'-HU_FONTSTART]->width) * con_scalefactor;
INT32 charheight = 8 * con_scalefactor; //SHORT(hu_font['A'-HU_FONTSTART]->height) * con_scalefactor;
if (teamtalk)
@@ -2149,14 +2028,19 @@ static void HU_DrawChat_Old(void)
c += charwidth;
}
if ((strlen(w_chat) == 0 || c_input == 0) && hu_tick < 4)
V_DrawCharacter(HU_INPUTX+c, y+2*con_scalefactor, '_' |cv_constextsize.value | V_NOSCALESTART|t, !cv_allcaps.value);
if ((w_chat.cursor == 0 || w_chat.length == 0) && hu_tick < 4)
V_DrawCharacter(HU_INPUTX+c+charwidth*w_chat.cursor, y+2*con_scalefactor, '_'|cv_constextsize.value|V_NOSCALESTART|t, !cv_allcaps.value);
if (w_chat.select != w_chat.cursor)
{
select_start = min(w_chat.select, w_chat.cursor);
select_end = max(w_chat.select, w_chat.cursor);
}
i = 0;
while (w_chat[i])
while (w_chat_buf[i])
{
if (c_input == (i+1) && hu_tick < 4)
if (w_chat.cursor == (i+1) && hu_tick < 4)
{
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);
@@ -2164,17 +2048,18 @@ static void HU_DrawChat_Old(void)
}
//Hurdler: isn't it better like that?
if (w_chat[i] < HU_FONTSTART)
{
++i;
//charwidth = 4 * con_scalefactor;
}
else
if (w_chat_buf[i] >= HU_FONTSTART)
{
//charwidth = SHORT(hu_font[w_chat[i]-HU_FONTSTART]->width) * con_scalefactor;
V_DrawCharacter(HU_INPUTX + c, y, w_chat[i++] | cv_constextsize.value | V_NOSCALESTART | t, !cv_allcaps.value);
V_DrawCharacter(HU_INPUTX + c, y, w_chat_buf[i] | cv_constextsize.value | V_NOSCALESTART | t, !cv_allcaps.value);
}
// Draw selection
if (i >= select_start && i < select_end)
V_DrawFill(HU_INPUTX + c, y, charwidth, charheight, 103|V_TRANSLUCENT|cv_constextsize.value|V_NOSCALESTART|t);
++i;
c += charwidth;
if (c >= vid.width)
{
@@ -2732,7 +2617,8 @@ static void HU_DrawRankings(void)
boolean completed[MAXPLAYERS];
UINT32 whiteplayer = MAXPLAYERS;
V_DrawFadeScreen(0xFF00, 16); // A little more readable, and prevents cheating the fades under other circumstances.
if (!automapactive)
V_DrawFadeScreen(0xFF00, 16); // A little more readable, and prevents cheating the fades under other circumstances.
if (cons_menuhighlight.value)
hilicol = cons_menuhighlight.value;
@@ -2748,10 +2634,14 @@ static void HU_DrawRankings(void)
//V_DrawString(4, 188, hilicol|V_SNAPTOBOTTOM|V_SNAPTOLEFT, gametype_cons_t[gametype].strvalue);
// draw the current map in the lower right if theres none just say its unknown
if (!G_BuildMapTitle(gamemap))
char *maptitle = G_BuildMapTitle(gamemap);
if (!maptitle)
V_DrawString(4, 188, hilicol|V_SNAPTOBOTTOM|V_SNAPTOLEFT, "UNKNOWN");
else
V_DrawString(4, 188, hilicol|V_SNAPTOBOTTOM|V_SNAPTOLEFT, G_BuildMapTitle(gamemap));
{
V_DrawString(4, 188, hilicol|V_SNAPTOBOTTOM|V_SNAPTOLEFT, maptitle);
Z_Free(maptitle);
}
if (G_GametypeHasTeams())
{
@@ -2801,18 +2691,6 @@ static void HU_DrawRankings(void)
V_DrawCenteredString(256, 16, hilicol, va("%d", cv_pointlimit.value));
}
}
/*else if (gametype == GT_COOP)
{
INT32 totalscore = 0;
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i])
totalscore += players[i].score;
}
V_DrawCenteredString(256, 8, 0, "TOTAL SCORE");
V_DrawCenteredString(256, 16, 0, va("%u", totalscore));
}*/
else
{
if (circuitmap)
@@ -2885,12 +2763,7 @@ static void HU_DrawRankings(void)
#endif
}
/*if (G_GametypeHasTeams())
HU_DrawTeamTabRankings(tab, whiteplayer); //separate function for Spazzo's silly request -- gotta fix this up later
else if (scorelines > 10)*/
HU_DrawTabRankings(((scorelines > 8) ? 32 : 40), 33, tab, scorelines, whiteplayer, hilicol);
/*else
HU_DrawDualTabRankings(32, 32, tab, scorelines, whiteplayer);*/
// draw spectators in a ticker across the bottom
if (netgame && G_GametypeHasSpectators())
+22 -3
View File
@@ -100,6 +100,14 @@
#undef ETIMEDOUT
#endif
#define ETIMEDOUT WSAETIMEDOUT
#ifdef EHOSTUNREACH
#undef EHOSTUNREACH
#endif
#define EHOSTUNREACH WSAEHOSTUNREACH
#ifdef ENETUNREACH
#undef ENETUNREACH
#endif
#define ENETUNREACH WSAENETUNREACH
#ifndef IOC_VENDOR
#define IOC_VENDOR 0x18000000
#endif
@@ -816,6 +824,8 @@ static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, mysockaddr_t *sockaddr
return sendto(socket, (char *)&doomcom->data, doomcom->datalength, 0, &sockaddr->any, d);
}
#define ALLOWEDERROR(x) ((x) == ECONNREFUSED || (x) == EWOULDBLOCK || (x) == EHOSTUNREACH || (x) == ENETUNREACH)
static void SOCK_Send(void)
{
ssize_t c = ERRSOCKET;
@@ -831,7 +841,11 @@ static void SOCK_Send(void)
for (j = 0; j < broadcastaddresses; j++)
{
if (myfamily[i] == broadcastaddress[j].any.sa_family)
SOCK_SendToAddr(mysockets[i], &broadcastaddress[j]);
{
c = SOCK_SendToAddr(mysockets[i], &broadcastaddress[j]);
if (c == ERRSOCKET && !ALLOWEDERROR(errno))
break;
}
}
}
return;
@@ -841,7 +855,11 @@ static void SOCK_Send(void)
for (i = 0; i < mysocketses; i++)
{
if (myfamily[i] == clientaddress[doomcom->remotenode].any.sa_family)
SOCK_SendToAddr(mysockets[i], &clientaddress[doomcom->remotenode]);
{
c = SOCK_SendToAddr(mysockets[i], &clientaddress[doomcom->remotenode]);
if (c == ERRSOCKET && !ALLOWEDERROR(errno))
break;
}
}
return;
}
@@ -853,11 +871,12 @@ static void SOCK_Send(void)
if (c == ERRSOCKET)
{
int e = errno; // save error code so it can't be modified later
if (e != ECONNREFUSED && e != EWOULDBLOCK)
if (!ALLOWEDERROR(e))
I_Error("SOCK_Send, error sending to node %d (%s) #%u: %s", doomcom->remotenode,
SOCK_GetNodeAddress(doomcom->remotenode), e, strerror(e));
}
}
#undef ALLOWEDERROR
#endif
#ifndef NONET
+33 -2
View File
@@ -17,12 +17,13 @@
#include "k_director.h"
#include "d_netcmd.h"
#include "p_local.h"
#include "st_stuff.h"
#define SWITCHTIME TICRATE * 5 // cooldown between unforced switches
#define BOREDOMTIME 3 * TICRATE / 2 // how long until players considered far apart?
#define TRANSFERTIME TICRATE // how long to delay reaction shots?
#define BREAKAWAYDIST 2000 // how *far* until players considered far apart?
#define WALKBACKDIST 600 // how close should a trailing player be before we switch?
#define WALKBACKDIST 400 // how close should a trailing player be before we switch?
#define PINCHDIST 20000 // how close should the leader be to be considered "end of race"?
struct directorinfo
@@ -37,6 +38,25 @@ struct directorinfo
INT32 boredom[MAXPLAYERS]; // how long has a given position had no credible attackers?
} directorinfo;
boolean K_DirectorIsPlayerAlone(void)
{
UINT8 pingame = 0;
// Gotta check how many players are active at this moment.
for (UINT8 i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
continue;
pingame++;
if (pingame >= 2) // we dont need to check further
break;
}
return (pingame <= 1);
}
static inline boolean race_rules(void)
{
return gametype == GT_RACE;
@@ -49,7 +69,7 @@ static fixed_t ScaleFromMap(fixed_t n, fixed_t scale)
static boolean K_DirectorIsEnabled(void)
{
return cv_director.value && !splitscreen && (gamestate == GS_LEVEL && (!playeringame[consoleplayer] || players[consoleplayer].spectator || (demo.playback && (!demo.title || !modeattacking))));
return cv_director.value && !splitscreen && (gamestate == GS_LEVEL && (((stplyr && !stplyr->spectator) && (!playeringame[consoleplayer] || players[consoleplayer].spectator)) || (demo.playback && !demo.freecam && (!demo.title || !modeattacking))) && !K_DirectorIsPlayerAlone());
}
void K_InitDirector(void)
@@ -376,6 +396,12 @@ void K_UpdateDirector(void)
break;
}
// if this is a splitscreen player, try next pair
if (P_IsDisplayPlayer(&players[target]))
{
continue;
}
// if we're certain the back half of the pair is actually in this position, try to switch
if (!players[target].kartstuff[k_positiondelay])
{
@@ -394,10 +420,15 @@ void K_UpdateDirector(void)
void K_ToggleDirector(void)
{
if (!directortextactive)
return;
if (!K_DirectorIsEnabled())
{
directorinfo.cooldown = 0; // switch immediately
}
directortoggletimer = 0;
COM_ImmedExecute("add director 1");
}
+114 -171
View File
@@ -725,34 +725,34 @@ void K_RegisterKartStuff(void)
CV_RegisterVar(&cv_showinput);
CV_RegisterVar(&cv_showlaptimes);
CV_RegisterVar(&cv_newspeedometer);
CV_RegisterVar(&cv_battlespeedo);
CV_RegisterVar(&cv_saltyhop);
CV_RegisterVar(&cv_saltyhopsfx);
CV_RegisterVar(&cv_saltysquish);
//Colourized HUD
CV_RegisterVar(&cv_colorizedhud);
CV_RegisterVar(&cv_colorizedhudcolor);
CV_RegisterVar(&cv_colorizeditembox);
CV_RegisterVar(&cv_darkitembox);
CV_RegisterVar(&cv_biglaps);
CV_RegisterVar(&cv_highresportrait);
CV_RegisterVar(&cv_slamsound);
CV_RegisterVar(&cv_minihead);
CV_RegisterVar(&cv_showminimapnames);
CV_RegisterVar(&cv_showlapemblem);
CV_RegisterVar(&cv_stagetitle);
CV_RegisterVar(&cv_stagetitle);
CV_RegisterVar(&cv_lessflicker);
CV_RegisterVar(&cv_mouseturn);
}
@@ -2686,8 +2686,7 @@ void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor) // A b
if (P_IsLocalPlayer(player))
{
quake.intensity = 64*FRACUNIT;
quake.time = 5;
P_StartQuake(5, 64<<FRACBITS, 0);
}
player->kartstuff[k_instashield] = 15;
@@ -3198,7 +3197,7 @@ static void K_StretchPlayerGravity(player_t *p)
I_Assert(p != NULL);
I_Assert(p->mo != NULL);
I_Assert(!P_MobjWasRemoved(p->mo));
if (p->mo->slamsoundtimer)
p->mo->slamsoundtimer--;
@@ -3234,7 +3233,7 @@ static void K_StretchPlayerGravity(player_t *p)
slamDiv = 0;
else
slamDiv = FixedDiv(p->mo->stretchslam, stretchScaleFactor);
p->mo->spritexscale = (dxs+(((slamDiv*2)/3)*2));
p->mo->spriteyscale = (dys-(slamDiv));
if (p->mo->stretchslam > 0)
@@ -3244,7 +3243,7 @@ static void K_StretchPlayerGravity(player_t *p)
}
}
static void K_QuiteSaltyHop(player_t *p)
static void K_QuiteSaltyHop(player_t *p)
{
// what the fuck is this haya
fixed_t mos = FRACUNIT; // doesnt work correctly if it isnt :/
@@ -3266,7 +3265,7 @@ static void K_QuiteSaltyHop(player_t *p)
p->mo->salty_zoffset = 0;
p->mo->salty_momz = 0;
p->mo->init_salty = true;
}
}
else if ((p->mo->salty_jump)) {
if (p->mo->eflags & MFE_JUSTHITFLOOR) {
p->mo->salty_zoffset = 0;
@@ -3300,7 +3299,7 @@ static void K_QuiteSaltyHop(player_t *p)
p->mo->salty_jump = true;
p->mo->salty_zoffset = 0;
p->mo->salty_momz = 6*mos;
if (cv_saltyhopsfx.value)
if (cv_saltyhopsfx.value)
S_StartSound(p->mo, sfx_s25a);
}
}
@@ -3309,56 +3308,55 @@ static void K_QuiteSaltyHop(player_t *p)
void K_RollMobjBySlopes(mobj_t* mo, boolean usedistance)
{
I_Assert(mo->subsector != NULL);
I_Assert(mo->subsector->sector != NULL);
I_Assert(mo->subsector != NULL);
I_Assert(mo->subsector->sector != NULL);
angle_t an;
boolean flip = mo->eflags & MFE_VERTICALFLIP;
fixed_t m_dist = R_PointToDist(mo->x, mo->y);
fixed_t rolldist = cv_sloperolldist.value * mapobjectscale;
angle_t an;
const boolean flip = mo->eflags & MFE_VERTICALFLIP;
const fixed_t m_dist = usedistance ? R_PointToDist(mo->x, mo->y) : 0;
const fixed_t rolldist = cv_sloperolldist.value * mapobjectscale;
// lifted from hw_md2
if (mo->standingslope)
{
fixed_t tempz = mo->standingslope->normal.z;
fixed_t tempy = mo->standingslope->normal.y;
fixed_t tempx = mo->standingslope->normal.x;
fixed_t tempangle = -(R_PointToAngle2(
0, 0, FixedSqrt(FixedMul(tempy, tempy) + FixedMul(tempz, tempz)), tempx));
// lifted from hw_md2
if (mo->standingslope)
{
fixed_t tempz = mo->standingslope->normal.z;
fixed_t tempy = mo->standingslope->normal.y;
fixed_t tempx = mo->standingslope->normal.x;
fixed_t tempangle = -(R_PointToAngle2(0, 0, FixedSqrt(FixedMul(tempy, tempy) + FixedMul(tempz, tempz)), tempx));
// admittedly this is a very hacky way to do the pitch and roll easing
// admittedly this is a very hacky way to do the pitch and roll easing
// pitch
if ((!usedistance) || (m_dist <= (rolldist)))
{
an = (INT32)((angle_t)tempangle - mo->pitch_sprite) / SLOPEROLL_DIV;
// pitch
if ((!usedistance) || (m_dist <= (rolldist)))
{
an = (INT32)((angle_t)tempangle - mo->pitch_sprite) / SLOPEROLL_DIV;
mo->pitch_sprite = an ? mo->pitch_sprite + an : (angle_t)tempangle;
}
else
mo->pitch_sprite = FixedAngle(0);
mo->pitch_sprite = an ? mo->pitch_sprite + an : (angle_t)tempangle;
}
else
mo->pitch_sprite = FixedAngle(0);
mo->slopepitch = flip ? InvAngle(mo->pitch_sprite) : mo->pitch_sprite;
mo->slopepitch = flip ? InvAngle(mo->pitch_sprite) : mo->pitch_sprite;
// roll
tempangle = (R_PointToAngle2(0, 0, tempz, tempy));
// roll
tempangle = (R_PointToAngle2(0, 0, tempz, tempy));
if ((!usedistance) || (m_dist <= (rolldist)))
{
an = (INT32)((angle_t)tempangle - mo->roll_sprite) / SLOPEROLL_DIV;
if (!usedistance || (m_dist <= (rolldist)))
{
an = (INT32)((angle_t)tempangle - mo->roll_sprite) / SLOPEROLL_DIV;
mo->roll_sprite = an ? mo->roll_sprite + an : (angle_t)tempangle;
}
else
mo->roll_sprite = FixedAngle(0);
mo->roll_sprite = an ? mo->roll_sprite + an : (angle_t)tempangle;
}
else
mo->roll_sprite = FixedAngle(0);
mo->sloperoll = flip ? InvAngle(mo->roll_sprite) : mo->roll_sprite;
}
else if (P_IsObjectOnGround(mo))
{
mo->sloperoll = FixedAngle(0);
mo->slopepitch = FixedAngle(0);
}
mo->sloperoll = flip ? InvAngle(mo->roll_sprite) : mo->roll_sprite;
}
else if (P_IsObjectOnGround(mo))
{
mo->sloperoll = FixedAngle(0);
mo->slopepitch = FixedAngle(0);
}
}
void K_SpawnBoostTrail(player_t *player)
@@ -4461,7 +4459,6 @@ void K_RepairOrbitChain(mobj_t *orbit)
if (orbit->target && orbit->target->player)
{
player_t *player = orbit->target->player;
INT32 num = 0;
mobj_t *cur = orbit->target->hnext;
@@ -5360,12 +5357,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
// Handle invincibility sfx
K_UpdateInvincibilitySounds(player); // Also thanks, VAda!
// Plays the music after the starting countdown.
if (P_IsLocalPlayer(player) && leveltime == (starttime + (TICRATE/2)))
{
S_ChangeMusic(mapmusname, mapmusflags, true);
S_ShowMusicCredit();
}
// Plays the music during and after the starting countdown.
if (P_IsLocalPlayer(player))
S_StartMapMusic(false);
}
void K_KartPlayerAfterThink(player_t *player)
@@ -6508,14 +6502,10 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
player->mo->spriteyscale = player->mo->realyscale;
}
boolean usedist = false;
if (cv_sloperolldist.value > 0)
usedist = true;
if ((cv_spriteroll.value) && (cv_sloperoll.value))
if (cv_spriteroll.value && cv_sloperoll.value)
{
if ((!player->mo->salty_jump)) // seeing a character rotate mid-hop looks really janky
K_RollMobjBySlopes(player->mo, usedist);
K_RollMobjBySlopes(player->mo, (cv_sloperolldist.value && !splitscreen));
}
else
{
@@ -6553,10 +6543,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
if ((leveltime == starttime-(3*TICRATE)) || (leveltime == starttime-(2*TICRATE)) || (leveltime == starttime-TICRATE))
S_StartSound(NULL, sfx_s3ka7);
if (leveltime == starttime)
{
S_StartSound(NULL, sfx_s3kad);
S_StopMusic(); // The GO! sound stops the level start ambience
}
}
// Start charging once you're given the opportunity.
@@ -7118,7 +7105,7 @@ void K_LoadKartHUDGraphics(void)
kp_karmasticker = W_CachePatchName("K_STKARM", PU_HUDGFX);
kp_splitkarmabomb = W_CachePatchName("K_SPTKRM", PU_HUDGFX);
kp_timeoutsticker = W_CachePatchName("K_STTOUT", PU_HUDGFX);
if (xtra_speedo) // snowy speedometer
{
skp_smallsticker = W_CachePatchName("SP_SMSTC", PU_HUDGFX);
@@ -7133,8 +7120,8 @@ void K_LoadKartHUDGraphics(void)
{
skp_smallsticker3 = W_CachePatchName("SP_SM3TC", PU_HUDGFX);
}
if (achi_speedo)
if (achi_speedo)
{
skp_smallstickerachi = W_CachePatchName("SP_AMSTC", PU_HUDGFX);
skp_speedpatchesachi[0] = W_CachePatchName("K_TRNULL", PU_HUDGFX); // lolxd
@@ -7144,7 +7131,7 @@ void K_LoadKartHUDGraphics(void)
skp_speedpatchesachi[4] = W_CachePatchName("SP_APERC", PU_HUDGFX);
}
if (big_lap){
if (big_lap){
kp_lapstickerbig = W_CachePatchName("K_STLAPB", PU_HUDGFX);
kp_lapstickerbig2 = W_CachePatchName("K_STLA2B", PU_HUDGFX);
}
@@ -7166,8 +7153,8 @@ void K_LoadKartHUDGraphics(void)
kp_itembgclr[3] = W_CachePatchName("K_ISBCD", PU_HUDGFX);
kp_itemmulstickerclr[1] = W_CachePatchName("K_ISMULC", PU_HUDGFX);
kp_itemmulstickerclr[0] = W_CachePatchName("K_ITMULC", PU_HUDGFX);
if (big_lap_color){
if (big_lap_color){
kp_lapstickerbigclr = W_CachePatchName("K_SCLAPB", PU_HUDGFX);
kp_lapstickerbig2clr = W_CachePatchName("K_SCLA2B", PU_HUDGFX);
}
@@ -7177,8 +7164,8 @@ void K_LoadKartHUDGraphics(void)
if (xtra_speedo3 && xtra_speedo_clr3) // 80x11 patch scaled to size
skp_smallstickerclr3 = W_CachePatchName("SC_SM3TC", PU_HUDGFX);
if (achi_speedo && achi_speedo_clr)
if (achi_speedo && achi_speedo_clr)
{
skp_smallstickerachiclr = W_CachePatchName("SC_AMSTC", PU_HUDGFX);
skp_speedpatchesachiclr[0] = W_CachePatchName("K_TRNULL", PU_HUDGFX); // lolxd
@@ -7209,13 +7196,13 @@ void K_LoadKartHUDGraphics(void)
// Nametags
if (nametaggfx)
{
nametagpic = W_CachePatchName("NTLINE", PU_HUDGFX);
nametagline = W_CachePatchName("NTLINEV", PU_HUDGFX);
nametagspeed = W_CachePatchName("NTSP", PU_HUDGFX);
nametagweight = W_CachePatchName("NTWH", PU_HUDGFX);
}
if (driftgaugegfx){
driftgauge = W_CachePatchName("K_DGAU", PU_HUDGFX);
driftgaugecolor = W_CachePatchName("K_DCAU", PU_HUDGFX);
@@ -7782,7 +7769,7 @@ static void K_drawKartStats(void)
flags = V_SNAPTOBOTTOM|V_SNAPTOLEFT;
UINT8 splitnum = 0;
for (; splitnum < MAXSPLITSCREENPLAYERS; ++splitnum)
{
if (stplyr == &players[displayplayers[splitnum]])
@@ -7791,7 +7778,7 @@ static void K_drawKartStats(void)
if (!LUA_HudEnabled(hud_statdisplay))
return;
//Internal offset for speedometer
if (cv_kartspeedometer.value)
{
@@ -8355,7 +8342,7 @@ static void K_DrawKartPositionNum(INT32 num)
scale *= 2;
overtake = true; // this is used for splitscreen stuff in conjunction with flipdraw.
}
if (splitscreen || (cv_showinput.value && !splitscreen))
scale /= 2;
@@ -8647,7 +8634,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
p = &players[tab[i].num];
if (cv_highresportrait.value)
V_DrawSmallMappedPatch(x, y-4, 0, R_GetSkinFaceWant(p), colormap);
else
else
V_DrawMappedPatch(x, y-4, 0, R_GetSkinFaceRank(p), colormap);
}
/*if (G_BattleGametype() && players[tab[i].num].kartstuff[k_bumper] > 0) -- not enough space for this
@@ -8789,7 +8776,7 @@ static void K_drawKartSpeedometer(void)
//KartZ speedo
fixed_t fuspeed = 0;
INT32 spdpatch = 0;
INT32 speedtype = 0;
INT32 splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTOLEFT);
@@ -8817,7 +8804,7 @@ static void K_drawKartSpeedometer(void)
}
// man.
if ((cv_newspeedometer.value == 1) || (cv_newspeedometer.value == 2 && !xtra_speedo) || (cv_newspeedometer.value == 3 && !achi_speedo) || (cv_newspeedometer.value == 4 && !kartzspeedo) || (cv_newspeedometer.value == 5 && !xtra_speedo3))
if ((cv_newspeedometer.value == 1) || (cv_newspeedometer.value == 2 && !xtra_speedo) || (cv_newspeedometer.value == 3 && !achi_speedo) || (cv_newspeedometer.value == 4 && !kartzspeedo) || (cv_newspeedometer.value == 5 && !xtra_speedo3))
{
switch (speedtype) {
case 1:
@@ -8866,8 +8853,8 @@ static void K_drawKartSpeedometer(void)
V_DrawScaledPatch(SPDM_X + 1, SPDM_Y + 4, (V_HUDTRANS|splitflags), (skp_smallstickerachi));
V_DrawRankNum(SPDM_X + 26, SPDM_Y + 4, V_HUDTRANS|splitflags, convSpeed, 3, NULL);
V_DrawScaledPatch(SPDM_X + 31, SPDM_Y + 4, V_HUDTRANS|splitflags, skp_speedpatchesachi[cv_kartspeedometer.value]);
}
}
}
}
else if (cv_newspeedometer.value == 5 && xtra_speedo3) // why bother if we dont?
{
if (K_UseColorHud() && xtra_speedo_clr3) //Colourized hud
@@ -8881,19 +8868,19 @@ static void K_drawKartSpeedometer(void)
V_DrawRankNum(SPDM_X + 26, SPDM_Y + 4, V_HUDTRANS|splitflags, convSpeed, 3, NULL);
V_DrawScaledPatch(SPDM_X + 31, SPDM_Y + 4, V_HUDTRANS|splitflags, skp_speedpatches[cv_kartspeedometer.value]);
}
// Kart Z speedo bullshit...
// Draw the Speed counter.
else if (cv_newspeedometer.value == 4 && kartzspeedo)
{
fuspeed = FixedDiv(stplyr->speed, mapobjectscale)/FRACUNIT;
#define NUM_INTERVALS 22
const int speedIntervals[NUM_INTERVALS] = {2, 5, 7, 10, 12, 15, 17, 20, 22, 25, 27, 30, 32, 35, 37, 40, 42, 45, 47, 50, 52, 55};
for (int i = 0; i < NUM_INTERVALS; ++i)
for (int i = 0; i < NUM_INTERVALS; ++i)
{
if (fuspeed < speedIntervals[i])
if (fuspeed < speedIntervals[i])
{
spdpatch = i;
break;
@@ -9083,9 +9070,9 @@ static boolean K_GetScreenCoords(vector2_t *vec, player_t *player, mobj_t *targe
// project the angle to get our final X coordinate
x = FixedMul(FINETANGENT(((x+ANGLE_90)>>ANGLETOFINESHIFT) & 4095), fov);
if (splitscreen == 1) // divide by 320/200 (1.6) on 2P splitscreen
x = (x/2) + (x/8);
x = (x/2) + (x/8);
x = x + xres;
// now clip in screen-space
if (!dontclip && (x < 0 || x > xres*2 || y < 0 || y > yres*2))
return false;
@@ -9148,7 +9135,7 @@ static void K_drawNameTags(void)
fixed_t maxdistance = (10*cv_nametagdist.value)* mapobjectscale;
flipped = 0;
fixed_t z;
if (i > PLAYERSMASK)
continue;
if (!players[i].mo || P_MobjWasRemoved(players[i].mo) || players[i].spectator || !playeringame[i])
@@ -9187,7 +9174,7 @@ static void K_drawNameTags(void)
trans = V_40TRANS;
else if (distance > (maxdistance*3/5))
trans = V_20TRANS;
else
else
trans = 0;
break;
case 3:
@@ -9370,6 +9357,9 @@ static void K_drawDriftGauge(void)
0, 31, 47, 63, 79, 95, 111, 119, 127, 143, 159, 175, 183, 191, 199, 207, 223, 247
};
if (demo.playback && demo.freecam)
return;
if (!stplyr->mo || (!splitscreen && !camera->chase))
return;
@@ -9384,7 +9374,7 @@ skipcrap:
if (!K_GetScreenCoords(&pos, stplyr, stplyr->mo, FixedMul(cv_driftgaugeofs.value, cv_driftgaugeofs.value > 0 ? stplyr->mo->scale : mapobjectscale), false))
return;
basex = pos.x>>FRACBITS;
basex = pos.x>>FRACBITS;
basey = pos.y>>FRACBITS;
fixed_t barx;
@@ -9622,7 +9612,7 @@ static void K_drawKartPlayerCheck(void)
}
}
static void K_drawKartMinimapHead(mobj_t *mo, INT32 x, INT32 y, INT32 flags, patch_t *AutomapPic)
static void K_drawKartMinimapHead(mobj_t *mo, INT32 x, INT32 y, INT32 flags)
{
// amnum xpos & ypos are the icon's speed around the HUD.
// The number being divided by is for how fast it moves.
@@ -9637,60 +9627,17 @@ static void K_drawKartMinimapHead(mobj_t *mo, INT32 x, INT32 y, INT32 flags, pat
fixed_t amnumxpos, amnumypos;
INT32 amxpos, amypos;
node_t *bsp = &nodes[numnodes-1];
fixed_t maxx, minx, maxy, miny;
fixed_t mapwidth, mapheight;
fixed_t xoffset, yoffset;
fixed_t xscale, yscale, zoom;
if (mo->skin)
skin = ((skin_t*)((mo->localskin) ? mo->localskin : mo->skin))-((skinlocal) ? localskins : skins);
skin = ((skin_t*)(mo->localskin ? mo->localskin : mo->skin))-(skinlocal ? localskins : skins);
maxx = maxy = INT32_MAX;
minx = miny = INT32_MIN;
minx = bsp->bbox[0][BOXLEFT];
maxx = bsp->bbox[0][BOXRIGHT];
miny = bsp->bbox[0][BOXBOTTOM];
maxy = bsp->bbox[0][BOXTOP];
if (bsp->bbox[1][BOXLEFT] < minx)
minx = bsp->bbox[1][BOXLEFT];
if (bsp->bbox[1][BOXRIGHT] > maxx)
maxx = bsp->bbox[1][BOXRIGHT];
if (bsp->bbox[1][BOXBOTTOM] < miny)
miny = bsp->bbox[1][BOXBOTTOM];
if (bsp->bbox[1][BOXTOP] > maxy)
maxy = bsp->bbox[1][BOXTOP];
// You might be wondering why these are being bitshift here
// it's because mapwidth and height would otherwise overflow for maps larger than half the size possible...
// map boundaries and sizes will ALWAYS be whole numbers thankfully
// later calculations take into consideration that these are actually not in terms of FRACUNIT though
minx >>= FRACBITS;
maxx >>= FRACBITS;
miny >>= FRACBITS;
maxy >>= FRACBITS;
mapwidth = maxx - minx;
mapheight = maxy - miny;
// These should always be small enough to be bitshift back right now
xoffset = (minx + mapwidth/2)<<FRACBITS;
yoffset = (miny + mapheight/2)<<FRACBITS;
xscale = FixedDiv(AutomapPic->width, mapwidth);
yscale = FixedDiv(AutomapPic->height, mapheight);
zoom = FixedMul(min(xscale, yscale), FRACUNIT-FRACUNIT/20);
amnumxpos = (FixedMul(lerp(mo->old_x, mo->x), zoom) - FixedMul(xoffset, zoom));
amnumypos = -(FixedMul(lerp(mo->old_y, mo->y), zoom) - FixedMul(yoffset, zoom));
amnumxpos = (FixedMul(lerp(mo->old_x, mo->x), minimapinfo.zoom) - minimapinfo.offs_x);
amnumypos = -(FixedMul(lerp(mo->old_y, mo->y), minimapinfo.zoom) - minimapinfo.offs_y);
if (encoremode)
amnumxpos = -amnumxpos;
amxpos = amnumxpos + ((x + AutomapPic->width/2 - (((skinlocal) ? localfacemmapprefix : facemmapprefix)[skin]->width/2))<<FRACBITS);
amypos = amnumypos + ((y + AutomapPic->height/2 - (((skinlocal) ? localfacemmapprefix : facemmapprefix)[skin]->height/2))<<FRACBITS);
amxpos = amnumxpos + ((x + (SHORT(minimapinfo.minimap_pic->width)-SHORT((skinlocal ? localfacemmapprefix : facemmapprefix)[skin]->width))/2)<<FRACBITS);
amypos = amnumypos + ((y + (SHORT(minimapinfo.minimap_pic->height)-SHORT((skinlocal ? localfacemmapprefix : facemmapprefix)[skin]->height))/2)<<FRACBITS);
if (!mo->color) // 'default' color
V_DrawSciencePatch(amxpos, amypos, flags, ( (skinlocal) ? localfacemmapprefix : facemmapprefix )[skin], FRACUNIT);
@@ -9701,12 +9648,12 @@ static void K_drawKartMinimapHead(mobj_t *mo, INT32 x, INT32 y, INT32 flags, pat
colormap = R_GetTranslationColormap(TC_RAINBOW, mo->color, GTC_CACHE);
else
colormap = R_GetLocalTranslationColormap(mo->skin, mo->localskin, mo->color, GTC_CACHE, skinlocal);
if (cv_minihead.value)
V_DrawFixedPatch(amxpos + (2*FRACUNIT), amypos + (2*FRACUNIT), FRACUNIT/2, flags, ((skinlocal) ? localfacemmapprefix : facemmapprefix)[skin], colormap);
else
V_DrawFixedPatch(amxpos, amypos, FRACUNIT, flags, ((skinlocal) ? localfacemmapprefix : facemmapprefix)[skin], colormap);
if (cv_showminimapnames.value && !(modeattacking || gamestate == GS_TIMEATTACK))
{
const char *player_name = va("%c%s", V_GetSkincolorChar(mo->color), player_names[mo->player - players]);
@@ -9728,8 +9675,6 @@ static void K_drawKartMinimapHead(mobj_t *mo, INT32 x, INT32 y, INT32 flags, pat
static void K_drawKartMinimap(void)
{
INT32 lumpnum;
patch_t *AutomapPic;
INT32 i = 0;
INT32 x, y;
INT32 minimaptrans, splitflags;
@@ -9744,17 +9689,15 @@ static void K_drawKartMinimap(void)
if (stplyr != &players[displayplayers[0]])
return;
lumpnum = W_CheckNumForName(va("%sR", G_BuildMapName(gamemap)));
if (lumpnum != -1)
AutomapPic = W_CachePatchName(va("%sR", G_BuildMapName(gamemap)), PU_HUDGFX);
else
if (minimapinfo.minimap_pic == NULL)
{
return; // no pic, just get outta here
}
drawinfo_t info;
K_getMinimapDrawinfo(&info);
x = info.x - (AutomapPic->width/2);
y = info.y - (AutomapPic->height/2);
x = info.x - (SHORT(minimapinfo.minimap_pic->width)/2);
y = info.y - (SHORT(minimapinfo.minimap_pic->height)/2);
splitflags = info.flags;
@@ -9775,9 +9718,9 @@ static void K_drawKartMinimap(void)
splitflags |= minimaptrans;
if (encoremode)
V_DrawScaledPatch(x+(AutomapPic->width), y, splitflags|V_FLIP, AutomapPic);
V_DrawScaledPatch(x+SHORT(minimapinfo.minimap_pic->width), y, splitflags|V_FLIP, minimapinfo.minimap_pic);
else
V_DrawScaledPatch(x, y, splitflags, AutomapPic);
V_DrawScaledPatch(x, y, splitflags, minimapinfo.minimap_pic);
if (!(splitscreen == 2))
{
@@ -9787,10 +9730,10 @@ static void K_drawKartMinimap(void)
// let offsets transfer to the heads, too!
if (encoremode)
x += SHORT(AutomapPic->leftoffset);
x += SHORT(minimapinfo.minimap_pic->leftoffset);
else
x -= SHORT(AutomapPic->leftoffset);
y -= SHORT(AutomapPic->topoffset);
x -= SHORT(minimapinfo.minimap_pic->leftoffset);
y -= SHORT(minimapinfo.minimap_pic->topoffset);
// initialize
for (i = 0; i < 4; i++)
@@ -9802,7 +9745,7 @@ static void K_drawKartMinimap(void)
demoghost *g = ghosts;
while (g)
{
K_drawKartMinimapHead(g->mo, x, y, splitflags, AutomapPic);
K_drawKartMinimapHead(g->mo, x, y, splitflags);
g = g->next;
}
@@ -9843,7 +9786,7 @@ static void K_drawKartMinimap(void)
continue;
}
K_drawKartMinimapHead(players[i].mo, x, y, splitflags, AutomapPic);
K_drawKartMinimapHead(players[i].mo, x, y, splitflags);
}
}
@@ -9855,7 +9798,7 @@ static void K_drawKartMinimap(void)
{
if (i == -1)
continue; // this doesn't interest us
K_drawKartMinimapHead(players[localplayers[i]].mo, x, y, splitflags, AutomapPic);
K_drawKartMinimapHead(players[localplayers[i]].mo, x, y, splitflags);
}
}
@@ -10556,7 +10499,7 @@ void K_drawKartHUD(void)
// Draw the item window
if (LUA_HudEnabled(hud_item) && !freecam)
K_drawKartItem();
K_drawKartItem();
if (cv_driftgauge.value && !modeattacking)
{
+3 -5
View File
@@ -1553,8 +1553,9 @@ static int lib_pSetSkyboxMobj(lua_State *L)
// Shhh, neither does P_StartQuake.
static int lib_pStartQuake(lua_State *L)
{
tic_t q_time = (tic_t)luaL_checkinteger(L, 2);
fixed_t q_intensity = luaL_checkinteger(L, 1);
UINT16 q_time = (UINT16)luaL_checkinteger(L, 2);
fixed_t q_radius = luaL_optinteger(L, 4, 512<<FRACBITS);
static mappoint_t q_epicenter = {0,0,0};
NOHUD
@@ -1606,11 +1607,8 @@ static int lib_pStartQuake(lua_State *L)
}
else
quake.epicenter = NULL;
quake.radius = luaL_optinteger(L, 4, 512*FRACUNIT);
// These things are actually used in 2.1.
quake.intensity = q_intensity;
quake.time = q_time;
P_StartQuake(q_time, q_intensity, q_radius);
return 0;
}
+6 -1
View File
@@ -81,6 +81,9 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum)
lua_pushstring(gL, buf);
}
LUA_Call(gL, (int)argc, 0, 1); // argc is 1-based, so this will cover the player we passed too.
lua_pop(gL, 1); // Pop LUA_GetErrorMessage (lua_pcall doesn't pop it)
return;
deny:
@@ -143,7 +146,7 @@ void COM_Lua_f(void)
if (netgame && !( flags & COM_LOCAL ))/* don't send local commands */
{ // Send the command through the network
UINT8 argc;
lua_pop(gL, 1); // pop command info table
lua_pop(gL, 2); // pop command info table and LUA_GetErrorMessage
if (flags & COM_ADMIN && !server && !IsPlayerAdmin(playernum)) // flag 1: only server/admin can use this command.
{
@@ -182,6 +185,8 @@ void COM_Lua_f(void)
for (i = 1; i < COM_Argc(); i++)
lua_pushstring(gL, COM_Argv(i));
LUA_Call(gL, (int)COM_Argc(), 0, 1); // COM_Argc is 1-based, so this will cover the player we passed too.
lua_pop(gL, 1); // Pop LUA_GetErrorMessage (lua_pcall doesn't pop it)
}
// Wrapper for COM_AddCommand
+6
View File
@@ -632,12 +632,18 @@ void LUA_HUD_DrawList(huddrawlist_h list)
switch (item->type)
{
case DI_Draw:
if (!item->patch || item->patch == NULL)
return;
V_DrawFixedPatch(LERPS(x), LERPS(y), FRACUNIT, item->flags, item->patch, item->colormap);
break;
case DI_DrawScaled:
if (!item->patch || item->patch == NULL)
return;
V_DrawFixedPatch(LERPS(x), LERPS(y), LERP(scale), item->flags, item->patch, item->colormap);
break;
case DI_DrawStretched:
if (!item->patch || item->patch == NULL)
return;
V_DrawStretchyFixedPatch(LERPS(x), LERPS(y), LERP(hscale), LERP(vscale), item->flags, item->patch, item->colormap);
break;
case DI_DrawNum:
+3 -1
View File
@@ -111,6 +111,8 @@ static void A_Lua(mobj_t *actor)
lua_pushinteger(gL, var2);
LUA_Call(gL, 3, 0, 1);
lua_pop(gL, 1); // pop error handler
if (found)
{
--superstack;
@@ -940,7 +942,7 @@ static int lib_setSfxInfo(lua_State *L)
if (lua_isnumber(L, 2))
{
int j = lua_tointeger(L, 2) - 1;
int j = lua_tointeger(L, 2);
// Read and Write enums were combined, need to do this switch now
switch (j)
+1 -1
View File
@@ -281,7 +281,7 @@ static int lib_iterateSectorThinglist(lua_State *L)
if (!lua_isnil(L, 1))
{
thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
if (P_MobjWasRemoved(thing))
if (!thing)
return luaL_error(L, "current entry in thinglist was removed; avoid calling P_RemoveMobj on entries!");
thing = thing->snext;
}
+40 -4
View File
@@ -22,6 +22,8 @@
#include "p_saveg.h"
#include "p_local.h"
#include "p_slopes.h" // for P_SlopeById
#include "s_sound.h"
#include "m_menu.h"
#ifdef LUA_ALLOW_BYTECODE
#include "d_netfil.h" // for LUA_DumpFile
#endif
@@ -1333,6 +1335,12 @@ static UINT8 UnArchiveValue(int TABLESINDEX)
break;
case ARCH_TEND:
return 1;
default:
CONS_Alert(CONS_ERROR, "Unknown value type unarchived, save is corrupted!\n");
G_SetExitGameFlag();
S_StartSound(NULL, sfx_syfail); // he he he
M_StartMessage(M_GetText("Corrupted save received\nPress ESC\n"), NULL, MM_NOTHING);
return 1;
}
return 0;
}
@@ -1460,7 +1468,13 @@ static void UnArchiveExtVars(void *pointer)
for (i = 0; i < field_count; i++)
{
READSTRING(save_p, field);
UnArchiveValue(TABLESINDEX);
if (UnArchiveValue(TABLESINDEX) == 1)
{
CONS_Alert(CONS_ERROR, "Unexpected end marker when reading ExtVars (field '%s')\n", field);
break;
}
lua_setfield(gL, -2, field);
}
@@ -1524,12 +1538,29 @@ static void UnArchiveTables(void)
for (i = 1; i <= n; i++)
{
lua_rawgeti(gL, TABLESINDEX, i);
if (!lua_istable(gL, -1))
{
CONS_Alert(CONS_ERROR, "Value in tables list #%d is not a table! (corrupted save?)\n", i);
continue;
}
while (true)
{
if (UnArchiveValue(TABLESINDEX) == 1) // read key
break;
if (UnArchiveValue(TABLESINDEX) == 2) // read value
UINT8 ret = UnArchiveValue(TABLESINDEX);
if (ret == 1)
{
CONS_Alert(CONS_ERROR, "Unexpected end of save reached (Corrupted save?)\n");
lua_pop(gL, 1); // Pop key
break;
}
else if (ret == 2) // read value
n++;
if (lua_isnil(gL, -2)) // if key is nil (if a function etc was accidentally saved)
{
CONS_Alert(CONS_ERROR, "A nil key in table %d was found! (Invalid key type or corrupted save?)\n", i);
@@ -1589,8 +1620,13 @@ void LUA_Step(void)
{
if (!gL)
return;
lua_settop(gL, 0);
lua_gc(gL, LUA_GCSTEP, 1);
if (lua_gettop(gL) != 0)
{
CONS_Alert(CONS_WARNING, "Eek, there is garbage on lua stack!\n");
lua_settop(gL, 0);
lua_gc(gL, LUA_GCSTEP, 1);
}
}
void LUA_Archive(void)
+222 -245
View File
@@ -30,6 +30,7 @@
#include "g_game.h"
#include "g_input.h"
#include "m_argv.h"
#include "m_textinput.h"
// Data.
#include "sounds.h"
@@ -159,6 +160,9 @@ boolean fromlevelselect = false;
boolean menu_text_input = false;
char menu_text_input_buf[MAXSTRINGLENGTH];
static textinput_t menuinput;
static INT32 coolalphatimer = 9;
typedef enum
@@ -245,6 +249,7 @@ menu_t SR_MainDef, SR_UnlockChecklistDef;
// Misc. Main Menu
static void M_Options(INT32 choice);
static void M_Multiplayer(INT32 choice);
static void M_LocalSkinMenu(INT32 choice);
static void M_LocalSkinChange(INT32 choice);
static void M_Manual(INT32 choice);
@@ -591,7 +596,7 @@ static menuitem_t MainMenu[] =
{
{IT_SUBMENU|IT_STRING, NULL, "Extras", &SR_MainDef, 76},
{IT_CALL |IT_STRING, NULL, "Time Attack", M_TimeAttack, 84},
{IT_SUBMENU|IT_STRING, NULL, "Multiplayer", &MP_MainDef, 92},
{IT_CALL |IT_STRING, NULL, "Multiplayer", M_Multiplayer, 92},
{IT_CALL |IT_STRING, NULL, "Options", M_Options, 100},
{IT_CALL |IT_STRING, NULL, "Addons", M_Addons, 108},
{IT_CALL |IT_STRING, NULL, "Quit Game", M_QuitSRB2, 116},
@@ -1493,8 +1498,6 @@ static menuitem_t OP_ExpOptionsMenu[] =
{IT_STRING | IT_CVAR, NULL, "FBO Downsampling support", &cv_grframebuffer, 110},
#endif
{IT_STRING | IT_CVAR, NULL, "Palette Depth", &cv_grpalettedepth, 130},
{IT_STRING | IT_CVAR, NULL, "Splitwall/Slope texture fix", &cv_splitwallfix, 150},
#endif
};
@@ -1512,7 +1515,6 @@ static const char* OP_ExpTooltips[] =
"Allows the game to downsample from a higher resolution than your display\nin OpenGL renderer mode. Requires a GPU with atleast OpenGL 3.0 support.",
#endif
"Change the depth of the Palette in Palette rendering mode\n 16 bits is like software looks ingame\nwhile 24 bits is how software looks in screenshots.",
"Fixes issues that resulted in Textures sticking from the ground sometimes.\n This may be CPU heavy and result in worse performance in some cases.",
#endif
};
@@ -1530,7 +1532,6 @@ enum
op_exp_fbo,
#endif
op_exp_paldepth,
op_exp_spltwal,
#endif
};
@@ -1598,7 +1599,20 @@ static menuitem_t OP_SoundOptionsMenu[] =
//{IT_STRING|IT_CALL, NULL, "Restart Audio System", M_RestartAudio, 50},
#ifdef NO_MIDI
{IT_STRING|IT_CVAR, NULL, "Reverse L/R Channels", &stereoreverse, 50},
{IT_STRING|IT_CVAR, NULL, "Surround Sound", &surround, 60},
{IT_STRING|IT_CVAR, NULL, "Chat Notifications", &cv_chatnotifications, 65},
{IT_STRING|IT_CVAR, NULL, "Character voices", &cv_kartvoices, 75},
{IT_STRING|IT_CVAR, NULL, "Hit Em Delay", &cv_karthitemdialog, 85},
{IT_STRING|IT_CVAR, NULL, "Powerup Warning", &cv_kartinvinsfx, 95},
{IT_KEYHANDLER|IT_STRING, NULL, "Sound Test", M_HandleSoundTest, 105},
{IT_STRING|IT_CALL, NULL, "Music Test", M_MusicTest, 115},
{IT_STRING|IT_CVAR, NULL, "Play Music While Unfocused", &cv_playmusicifunfocused, 125},
{IT_STRING|IT_CVAR, NULL, "Play SFX While Unfocused", &cv_playsoundifunfocused, 135},
{IT_STRING|IT_SUBMENU, NULL, "Advanced Settings...", &OP_SoundAdvancedDef, 145}
#else
{IT_STRING|IT_CVAR, NULL, "Reverse L/R Channels", &stereoreverse, 60},
{IT_STRING|IT_CVAR, NULL, "Chat Notifications", &cv_chatnotifications, 75},
{IT_STRING|IT_CVAR, NULL, "Character voices", &cv_kartvoices, 85},
@@ -1611,21 +1625,6 @@ static menuitem_t OP_SoundOptionsMenu[] =
{IT_STRING|IT_CVAR, NULL, "Play Music While Unfocused", &cv_playmusicifunfocused, 135},
{IT_STRING|IT_CVAR, NULL, "Play SFX While Unfocused", &cv_playsoundifunfocused, 145},
{IT_STRING|IT_SUBMENU, NULL, "Advanced Settings...", &OP_SoundAdvancedDef, 155}
#else
{IT_STRING|IT_CVAR, NULL, "Reverse L/R Channels", &stereoreverse, 60},
{IT_STRING|IT_CVAR, NULL, "Surround Sound", &surround, 70},
{IT_STRING|IT_CVAR, NULL, "Chat Notifications", &cv_chatnotifications, 85},
{IT_STRING|IT_CVAR, NULL, "Character voices", &cv_kartvoices, 95},
{IT_STRING|IT_CVAR, NULL, "Hit Em Delay", &cv_karthitemdialog, 105},
{IT_STRING|IT_CVAR, NULL, "Powerup Warning", &cv_kartinvinsfx, 115},
{IT_KEYHANDLER|IT_STRING, NULL, "Sound Test", M_HandleSoundTest, 125},
{IT_STRING|IT_CALL, NULL, "Music Test", M_MusicTest, 135},
{IT_STRING|IT_CVAR, NULL, "Play Music While Unfocused", &cv_playmusicifunfocused, 145},
{IT_STRING|IT_CVAR, NULL, "Play SFX While Unfocused", &cv_playsoundifunfocused, 155},
{IT_STRING|IT_SUBMENU, NULL, "Advanced Settings...", &OP_SoundAdvancedDef, 165}
#endif
};
@@ -1640,7 +1639,6 @@ static const char* OP_SoundTooltips[] =
"Volume of Midi Music.",
#endif
"Reverse left and right channels of audio.",
"Surround Sound.",
"Chat notification sound.",
"Frequency of character voice lines.",
"Play 'Hit Em' character line after other player's hurt line.",
@@ -1656,21 +1654,25 @@ static const char* OP_SoundTooltips[] =
static menuitem_t OP_SoundAdvancedMenu[] =
{
#ifdef HAVE_OPENMPT
{IT_HEADER, NULL, "Tracker Module Options", NULL, 10},
{IT_HEADER, NULL, "Tracker Module Options", NULL, 0},
{IT_STRING | IT_CVAR, NULL, "Instrument Filter", &cv_modfilter, 22},
{IT_STRING | IT_CVAR, NULL, "Amiga Resampler", &cv_amigafilter, 42},
{IT_STRING | IT_CVAR, NULL, "Instrument Filter", &cv_modfilter, 20},
{IT_STRING | IT_CVAR, NULL, "Amiga Resampler", &cv_amigafilter, 30},
#if OPENMPT_API_VERSION_MAJOR < 1 && OPENMPT_API_VERSION_MINOR > 4
{IT_STRING | IT_CVAR, NULL, "Amiga Type", &cv_amigatype, 62},
{IT_STRING | IT_CVAR, NULL, "Amiga Type", &cv_amigatype, 40},
#endif
{IT_STRING | IT_CVAR, NULL, "Stereo Seperation", &cv_stereosep, 82},
{IT_STRING | IT_CVAR, NULL, "Stereo Seperation", &cv_stereosep, 50},
#endif
{IT_HEADER, NULL, "Misc", NULL, 105},
{IT_STRING | IT_CVAR, NULL, "Grow Music", &cv_growmusic, 117},
{IT_STRING | IT_CVAR, NULL, "Invulnerability Music", &cv_supermusic, 127},
{IT_HEADER, NULL, "Misc", NULL, 70},
{IT_STRING | IT_CVAR, NULL, "Audio Buffer Size", &cv_audbuffersize, 147},
{IT_STRING | IT_CVAR, NULL, "Grow Music", &cv_growmusic, 90},
{IT_STRING | IT_CVAR, NULL, "Invulnerability Music", &cv_supermusic, 100},
{IT_STRING | IT_CVAR, NULL, "Keep Map Music", &cv_keepmusic, 120},
{IT_STRING | IT_CVAR, NULL, "Skip Intro Music", &cv_skipintromusic, 130},
{IT_STRING | IT_CVAR, NULL, "Audio Buffer Size", &cv_audbuffersize, 150},
};
static const char* OP_SoundAdvancedTooltips[] =
@@ -1688,6 +1690,8 @@ static const char* OP_SoundAdvancedTooltips[] =
NULL,
"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?",
"Size of the Audio Buffer\nreducing it will result in less sound latency\nbut may cause issues such as crackling or distorted Sound.",
};
@@ -2580,6 +2584,7 @@ static menuitem_t OP_AdvancedBirdMenu[] =
{IT_STRING | IT_CVAR, NULL, "Fade Back In While Respawning", &cv_respawnfademusicback, 40},
{IT_STRING | IT_CVAR, NULL, "Resync Threshold", &cv_music_resync_threshold, 60},
{IT_STRING | IT_CVAR, NULL, "Resync Special Music Only", &cv_music_resync_powerups_only, 70},
};
static const char* OP_AdvancedBirdTooltips[] =
@@ -3327,8 +3332,6 @@ static void Newgametype_OnChange(void)
}
CV_SetValue(&cv_nextmap, M_FindFirstMap(value));
//CV_AddValue(&cv_nextmap, -1);
//CV_AddValue(&cv_nextmap, 1);
}
}
}
@@ -3504,46 +3507,15 @@ static void M_ChangeCvar(INT32 choice)
static boolean M_ChangeStringCvar(INT32 choice)
{
consvar_t *cv = (consvar_t *)currentMenu->menuitems[itemOn].itemaction;
char buf[MAXSTRINGLENGTH];
size_t len;
choice = M_ShiftChar(choice);
switch (choice)
if (M_TextInputHandle(&menuinput, choice))
{
case KEY_BACKSPACE:
len = strlen(cv->string);
if (len > 0)
{
S_StartSound(NULL,sfx_menu1); // Tails
M_Memcpy(buf, cv->string, len);
buf[len-1] = 0;
CV_Set(cv, buf);
}
return true;
case KEY_DEL:
if (cv->string[0])
{
S_StartSound(NULL,sfx_menu1); // Tails
CV_Set(cv, "");
}
return true;
default:
if ((cv_keyboardlayout.value != 3 && choice >= 32 && choice <= 127) || (cv_keyboardlayout.value == 3 && choice >= 32 && choice <= 141))
{
len = strlen(cv->string);
if (len < MAXSTRINGLENGTH - 1)
{
S_StartSound(NULL,sfx_menu1); // Tails
M_Memcpy(buf, cv->string, len);
buf[len++] = (char)choice;
buf[len] = 0;
CV_Set(cv, buf);
}
return true;
}
break;
S_StartSound(NULL,sfx_menu1); // Tails
CV_Set(cv, menuinput.buffer);
return true;
}
return false;
}
@@ -3560,6 +3532,21 @@ static void M_ResetCvars(void)
}
}
// If current menu item is IT_CV_STRING, setup menuinput
static void M_CheckStringItem(void)
{
if (itemOn < currentMenu->numitems && (currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_STRING)
{
consvar_t *cv = (consvar_t *)currentMenu->menuitems[itemOn].itemaction;
// Just in case
memset(menu_text_input_buf, 0, sizeof menu_text_input_buf);
M_TextInputInit(&menuinput, menu_text_input_buf, sizeof menu_text_input_buf);
M_TextInputSetString(&menuinput, cv->string);
}
}
static void M_NextOpt(void)
{
INT16 oldItemOn = itemOn; // prevent infinite loop
@@ -3571,6 +3558,8 @@ static void M_NextOpt(void)
else
itemOn++;
} while (oldItemOn != itemOn && (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_SPACE);
M_CheckStringItem();
}
static void M_PrevOpt(void)
@@ -3584,6 +3573,8 @@ static void M_PrevOpt(void)
else
itemOn--;
} while (oldItemOn != itemOn && (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_SPACE);
M_CheckStringItem();
}
// lock out further input in a tic when important buttons are pressed
@@ -3944,7 +3935,6 @@ boolean M_Responder(event_t *ev)
if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_STRING)
{
menu_text_input = true;
ch = M_ShiftChar(ch);
if (M_ChangeStringCvar(ch))
return true;
else
@@ -4295,7 +4285,9 @@ void M_Drawer(void)
{
// now that's more readable with a faded background (yeah like Quake...)
if (ShouldDrawMenuBG())
{
V_DrawFadeScreen(0xFF00, 16);
}
if (currentMenu->drawroutine)
{
@@ -4603,6 +4595,8 @@ void M_SetupNextMenu(menu_t *menudef)
}
}
}
M_CheckStringItem();
}
//
@@ -4726,7 +4720,6 @@ void M_Init(void)
#ifdef USE_FBO_OGL
OP_ExpOptionsMenu[op_exp_fbo].status = IT_DISABLED;
#endif
OP_ExpOptionsMenu[op_exp_spltwal].status = IT_DISABLED;
}
if (rendermode == render_opengl)
@@ -4942,6 +4935,33 @@ void M_DrawTextBoxFlags(INT32 x, INT32 y, INT32 width, INT32 boxlines, INT32 fla
V_DrawFill(x+5, y+5, width*8+6, boxlines*8+6, 239|flags);
}
void M_DrawTextInput(INT32 x, INT32 y, textinput_t *input, INT32 flags)
{
INT32 skullx = x;
V_DrawString(x, y, V_ALLOWLOWERCASE|flags, input->buffer);
// draw text cursor for name
if (input->length)
skullx = x+V_SubStringWidth(input->buffer, input->cursor, V_ALLOWLOWERCASE);
if (skullAnimCounter < 4) // blink cursor
V_DrawCharacter(skullx, y+3, '_'|flags, false);
// draw selection
if (input->select != input->cursor)
{
size_t start = min(input->select, input->cursor);
size_t end = max(input->select, input->cursor);
size_t len = end - start;
INT32 startx = V_SubStringWidth(input->buffer, start, V_ALLOWLOWERCASE);
V_DrawFill(x+startx, y, V_SubStringWidth(input->buffer+start, len, V_ALLOWLOWERCASE), 8, 103|V_TRANSLUCENT|flags);
}
}
// horizontally centered text
static void M_CentreText(INT32 y, const char *string)
{
@@ -5143,10 +5163,12 @@ static void M_DrawGenericMenu(void)
break;
case IT_CV_STRING:
M_DrawTextBox(x, y + 4, MAXSTRINGLENGTH, 1);
V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, cv->string);
if (skullAnimCounter < 4 && i == itemOn)
V_DrawCharacter(x + 8 + V_StringWidth(cv->string, 0), y + 12,
'_' | 0x80, false);
if (itemOn == i)
M_DrawTextInput(x + 8, y + 12, &menuinput, 0);
else
V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, cv->string);
y += 16;
break;
default:
@@ -5330,10 +5352,12 @@ static void M_DrawGenericScrollMenu(void)
if (y + 12 > (currentMenu->y + 2*scrollareaheight))
break;
M_DrawTextBox(x, y + 4, MAXSTRINGLENGTH, 1);
V_DrawString(x + 8, y + 12, lowercase, cv->string);
if (skullAnimCounter < 4 && i == itemOn)
V_DrawCharacter(x + 8 + V_StringWidth(cv->string, 0), y + 12,
'_' | 0x80, false);
if (itemOn == i)
M_DrawTextInput(x + 8, y + 12, &menuinput, 0);
else
V_DrawString(x + 8, y + 12, lowercase, cv->string);
break;
default:
V_DrawRightAlignedString(BASEVIDWIDTH - x, y,
@@ -5469,10 +5493,12 @@ static void M_DrawCenteredMenu(void)
break;
case IT_CV_STRING:
M_DrawTextBox(x, y + 4, MAXSTRINGLENGTH, 1);
V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, cv->string);
if (skullAnimCounter < 4 && i == itemOn)
V_DrawCharacter(x + 8 + V_StringWidth(cv->string, 0), y + 12,
'_' | 0x80, false);
if (itemOn == i)
M_DrawTextInput(x + 8, y + 12, &menuinput, 0);
else
V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, cv->string);
y += 16;
break;
default:
@@ -5608,27 +5634,13 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt)
switch (levellistmode)
{
case LLM_CREATESERVER:
// Should the map be hidden?
//if (mapheaderinfo[mapnum]->menuflags & LF2_HIDEINMENU && mapnum+1 != gamemap)
//return false;
// Should the map be hidden? <-- well imma wanna toggle it, its just annoying being unable to select hell maps in mapselect
if ((mapheaderinfo[mapnum]->menuflags & LF2_HIDEINMENU && mapnum+1 != gamemap) && (gt == GT_RACE && (mapheaderinfo[mapnum]->typeoflevel & TOL_RACE))) // map hell
{
if (cv_showallmaps.value)
return true;
else
return false;
}
return cv_showallmaps.value;
// same goes here, just show every map if i want to
if (M_MapLocked(mapnum+1)) // not unlocked
{
if (cv_showallmaps.value)
return true;
else
return false;
}
return cv_showallmaps.value;
if ((gt == GT_MATCH || gt == GT_TEAMMATCH) && (mapheaderinfo[mapnum]->typeoflevel & TOL_MATCH))
return true;
@@ -5638,18 +5650,7 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt)
return false;
/*case LLM_LEVELSELECT:
if (mapheaderinfo[mapnum]->levelselect != maplistoption)
return false;
if (M_MapLocked(mapnum+1))
return false; // not unlocked
return true;*/
case LLM_RECORDATTACK:
/*if (!(mapheaderinfo[mapnum]->menuflags & LF2_RECORDATTACK))
return false;*/
if (!(mapheaderinfo[mapnum]->typeoflevel & TOL_RACE))
return false;
@@ -5662,12 +5663,6 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt)
if (mapheaderinfo[mapnum]->menuflags & LF2_HIDEINMENU)
return false; // map hell
/*if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED)
return true;
if (!mapvisited[mapnum])
return false;*/
return true;
default:
return false;
@@ -6679,11 +6674,11 @@ I_mutex replayquerymutex;
#define MAXREPLAYQUERY 40
char replayqueryinput[MAXREPLAYQUERY+1]; // The input typed
size_t replayquerypos = 0; // Position in input window
static char replayqueryinput_buffer[MAXREPLAYQUERY+1]; // The input typed
static textinput_t replayqueryinput;
size_t replayqueryfound = 0; // Number of checked replay entries
size_t replayquerycheck = 0; // Index of next replay entry to check in demolist_all
static size_t replayqueryfound = 0; // Number of checked replay entries
static size_t replayquerycheck = 0; // Index of next replay entry to check in demolist_all
#define DF_ENCORE 0x40
static INT16 replayScrollTitle = 0;
@@ -6738,8 +6733,8 @@ static void LoadReplayNames(void)
static void ResetReplayQuery(void)
{
memset(replayqueryinput, 0, MAXREPLAYQUERY);
replayquerypos = 0;
memset(replayqueryinput_buffer, 0, MAXREPLAYQUERY);
M_TextInputInit(&replayqueryinput, replayqueryinput_buffer, MAXREPLAYQUERY);
replayqueryfound = 0;
replayquerycheck = 0;
@@ -6763,7 +6758,7 @@ static void M_HutCheckReplays(size_t maxnum)
return;
// If we don't have any query, just copy all demos and consider them checked
if (replayquerypos == 0)
if (replayqueryinput.length == 0)
{
// Mark as done
replayqueryfound = replayquerycheck = sizedirmenu;
@@ -6787,7 +6782,7 @@ static void M_HutCheckReplays(size_t maxnum)
case MD_NOTLOADED:
case MD_OUTDATED:
case MD_LOADED:
if (demolist_all[replayquerycheck].title[0] && strcasestr(demolist_all[replayquerycheck].title, replayqueryinput) != NULL)
if (demolist_all[replayquerycheck].title[0] && strcasestr(demolist_all[replayquerycheck].title, replayqueryinput.buffer) != NULL)
AddCheckedReplay(); // It matches, add it!
else
replayquerycheck++; // Doesn't match, moving on...
@@ -6886,41 +6881,23 @@ void M_ReplayHut(INT32 choice)
static boolean M_HandleReplayHutQuery(INT32 choice)
{
switch (choice)
// Yea gonna copy buffer and check if it changed, thats better than checking for specific keys i think
char tmp[MAXREPLAYQUERY+1];
memcpy(tmp, replayqueryinput_buffer, MAXREPLAYQUERY+1);
if (M_TextInputHandle(&replayqueryinput, choice))
{
case KEY_BACKSPACE:
if (replayquerypos == 0)
break;
S_StartSound(NULL,sfx_menu1);
replayquerypos--;
replayqueryinput[replayquerypos] = 0;
S_StartSound(NULL,sfx_menu1);
// Restart search only if we actually modified input and not just moved in it
if (memcmp(tmp, replayqueryinput_buffer, MAXREPLAYQUERY+1))
{
preparefilemenu(false, true);
dir_on[menudepthleft] = 0;
PrepReplayList(false);
}
return true;
default:
if (choice < 32 || choice > 127)
break;
if (replayquerypos < MAXREPLAYQUERY)
{
S_StartSound(NULL,sfx_menu1);
replayqueryinput[replayquerypos] = choice;
replayqueryinput[replayquerypos+1] = 0;
++replayquerypos;
preparefilemenu(false, true);
dir_on[menudepthleft] = 0;
PrepReplayList(false);
}
return true;
return true;
}
return false;
@@ -7351,15 +7328,11 @@ static void M_DrawReplayHut(void)
// Draw search query
M_DrawTextBoxFlags(x, 200 - 22, MAXREPLAYQUERY, 1, V_SNAPTOBOTTOM);
if (replayquerypos)
V_DrawString(x + 8, 200 - 14, V_ALLOWLOWERCASE|V_SNAPTOBOTTOM, replayqueryinput);
if (replayqueryinput.length)
M_DrawTextInput(x + 8, 200 - 14, &replayqueryinput, V_SNAPTOBOTTOM);
else
V_DrawString(x + 8, 200 - 14, V_ALLOWLOWERCASE|V_SNAPTOBOTTOM, "\x86Type to search...");
// draw text cursor for name
if (replayquerypos && skullAnimCounter < 4) // blink cursor
V_DrawCharacter(x + 8 + V_StringWidth(replayqueryinput, V_ALLOWLOWERCASE), 200 - 14, '_'|V_SNAPTOBOTTOM, false);
if (replaynamesloaded && replayquerycheck < sizedirmenu)
V_DrawString(x + 8, 200 - 30, V_ALLOWLOWERCASE|V_SNAPTOBOTTOM, va("Searching %u/%u...", (unsigned)replayquerycheck, (unsigned)sizedirmenu));
}
@@ -8937,9 +8910,11 @@ void M_DrawTimeAttackMenu(void)
if (currentMenu->menuitems[i].status & IT_CV_STRING)
{
M_DrawTextBox(x + 32, y - 8, MAXPLAYERNAME, 1);
V_DrawString(x + 40, y, V_ALLOWLOWERCASE, cv->string);
if (itemOn == i && skullAnimCounter < 4) // blink cursor
V_DrawCharacter(x + 40 + V_StringWidth(cv->string, V_ALLOWLOWERCASE), y, '_',false);
if (itemOn != i)
V_DrawString(x + 40, y, V_ALLOWLOWERCASE, cv->string);
else
M_DrawTextInput(x + 40, y, &menuinput, 0);
}
else
{
@@ -10011,16 +9986,19 @@ static void M_DrawLevelSelectOnly(boolean leftfade, boolean rightfade)
patch_t *PictureOfLevel;
INT32 x, y, w, i, oldval, trans, dupadjust = ((vid.width/vid.dupx) - BASEVIDWIDTH)>>1;
char encoretoggle[32] = {0};
const char *item1 = gamecontrol[gc_fire][0] != 0 ? G_KeynumToString(gamecontrol[gc_fire][0]) : NULL;
const char *item2 = gamecontrol[gc_fire][1] != 0 ? G_KeynumToString(gamecontrol[gc_fire][1]) : NULL;
if (levellistmode != LLM_RECORDATTACK) // so it doesent show in record attack menu
{
char encoretoggle[32] = {0};
const char *item1 = gamecontrol[gc_fire][0] != 0 ? G_KeynumToString(gamecontrol[gc_fire][0]) : NULL;
const char *item2 = gamecontrol[gc_fire][1] != 0 ? G_KeynumToString(gamecontrol[gc_fire][1]) : NULL;
if (item1 != NULL && item2 != NULL)
snprintf(encoretoggle, 32, "%s/%s: Toggle Encore", item1, item2);
else
snprintf(encoretoggle, 32, "%s: Toggle Encore", item1 != NULL ? item1 : item2 != NULL ? item2 : "Item");
if (item1 != NULL && item2 != NULL)
snprintf(encoretoggle, 32, "%s/%s: Toggle Encore", item1, item2);
else
snprintf(encoretoggle, 32, "%s: Toggle Encore", item1 != NULL ? item1 : item2 != NULL ? item2 : "Item");
V_DrawThinString(1, BASEVIDHEIGHT-8-1, V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_TRANSLUCENT|V_ALLOWLOWERCASE, encoretoggle);
V_DrawThinString(1, BASEVIDHEIGHT-8-1, V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_TRANSLUCENT|V_ALLOWLOWERCASE, encoretoggle);
}
// A 160x100 image of the level as entry MAPxxP
if (cv_nextmap.value)
@@ -10216,7 +10194,19 @@ static void M_StartServerMenu(INT32 choice)
// ==============
static char setupm_ip[28];
static textinput_t setupm_input_ip;
#endif
void M_Multiplayer(INT32 choice)
{
(void)choice;
#ifndef NONET
memset(setupm_ip, 0, 28);
M_TextInputInit(&setupm_input_ip, setupm_ip, 28);
#endif
M_SetupNextMenu(&MP_MainDef);
}
static UINT8 setupm_pselect = 1;
// Draw the funky Connect IP menu. Tails 11-19-2002
@@ -10250,12 +10240,10 @@ Update the maxplayers label...
V_DrawFill(x+5, y+4+5, /*16*8 + 6,*/ BASEVIDWIDTH - 2*(x+5), 8+6, 239);
// draw name string
V_DrawString(x+8,y+12, V_ALLOWLOWERCASE, setupm_ip);
// draw text cursor for name
if (itemOn == 9
&& skullAnimCounter < 4) //blink cursor
V_DrawCharacter(x+8+V_StringWidth(setupm_ip, V_ALLOWLOWERCASE),y+12,'_',false);
if (itemOn != 9)
V_DrawString(x+8,y+12, V_ALLOWLOWERCASE, setupm_ip);
else
M_DrawTextInput(x+8, y+12, &setupm_input_ip, 0);
#endif
// character bar, ripped off the color bar :V
@@ -10443,7 +10431,6 @@ static void M_ConnectLastServer(INT32 choice)
// Tails 11-19-2002
static void M_HandleConnectIP(INT32 choice)
{
size_t l;
boolean exitmenu = false; // exit to previous menu and send name change
switch (choice)
@@ -10468,41 +10455,21 @@ static void M_HandleConnectIP(INT32 choice)
exitmenu = true;
break;
case KEY_LEFTARROW:
case KEY_RIGHTARROW:
case KEY_BACKSPACE:
if ((l = strlen(setupm_ip)) != 0)
{
S_StartSound(NULL,sfx_menu1); // Tails
setupm_ip[l-1] = 0;
}
break;
case KEY_DEL:
if (setupm_ip[0])
{
if (M_TextInputHandle(&setupm_input_ip, choice))
S_StartSound(NULL,sfx_menu1); // Tails
setupm_ip[0] = 0;
}
break;
default:
l = strlen(setupm_ip);
if (l >= 28-1)
break;
// Rudimentary number and period enforcing - also allows letters so hostnames can be used instead
if ((choice >= '-' && choice <= ':') || (choice >= 'A' && choice <= 'Z') || (choice >= 'a' && choice <= 'z'))
if ((choice >= '-' && choice <= ':') || (choice >= 'A' && choice <= 'Z') || (choice >= 'a' && choice <= 'z')
|| (choice >= 199 && choice <= 211 && choice != 202 && choice != 206)) //numpad too!
{
S_StartSound(NULL,sfx_menu1); // Tails
setupm_ip[l] = (char)choice;
setupm_ip[l+1] = 0;
}
else if (choice >= 199 && choice <= 211 && choice != 202 && choice != 206) //numpad too!
{
char keypad_translation[] = {'7','8','9','-','4','5','6','+','1','2','3','0','.'};
choice = keypad_translation[choice - 199];
S_StartSound(NULL,sfx_menu1); // Tails
setupm_ip[l] = (char)choice;
setupm_ip[l+1] = 0;
if (M_TextInputHandle(&setupm_input_ip, choice))
S_StartSound(NULL,sfx_menu1); // Tails
}
break;
}
@@ -10527,14 +10494,15 @@ static state_t *multi_state;
// this is set before entering the MultiPlayer setup menu,
// for either player 1 or 2
static char setupm_name[MAXPLAYERNAME+1];
static player_t *setupm_player;
static consvar_t *setupm_cvskin;
static consvar_t *setupm_cvcolor;
static consvar_t *setupm_cvname;
static UINT8 setupm_skinxpos;
static INT32 setupm_fakeskin;
static INT32 setupm_fakecolor;
static char setupm_name[MAXPLAYERNAME+1];
static textinput_t setupm_input;
static player_t *setupm_player;
static consvar_t *setupm_cvskin;
static consvar_t *setupm_cvcolor;
static consvar_t *setupm_cvname;
static UINT8 setupm_skinxpos;
static INT32 setupm_fakeskin;
static INT32 setupm_fakecolor;
//variables used for other skin select menus
static UINT8 setupm_skinypos;
@@ -10610,11 +10578,11 @@ static void M_DrawSetupMultiPlayerMenu(void)
}
M_DrawTextBox(mx + 32, my - 8 + nameboxaddy, MAXPLAYERNAME, 1);
V_DrawString(mx + 40, my + nameboxaddy, V_ALLOWLOWERCASE, setupm_name);
// draw text cursor for name
if (!itemOn && skullAnimCounter < 4) // blink cursor
V_DrawCharacter(mx + 40 + V_StringWidth(setupm_name, V_ALLOWLOWERCASE), my + nameboxaddy, '_', false);
if (itemOn != 0)
V_DrawString(mx + 40, my + nameboxaddy, V_ALLOWLOWERCASE, setupm_input.buffer);
else
M_DrawTextInput(mx + 40, my + nameboxaddy, &setupm_input, 0);
// draw skin string
st = V_StringWidth(skins[setupm_fakeskin].realname, 0);
@@ -11213,7 +11181,6 @@ static void M_DrawSetupMultiPlayerMenu(void)
// Handle 1P/2P MP Setup
static void M_HandleSetupMultiPlayer(INT32 choice)
{
size_t l;
boolean exitmenu = false; // exit to previous menu and send name change
if ((choice == gamecontrol[gc_fire][0] || choice == gamecontrol[gc_fire][1]) && itemOn == 2)
@@ -11335,7 +11302,12 @@ static void M_HandleSetupMultiPlayer(INT32 choice)
break;
case KEY_LEFTARROW:
if (cv_skinselectmenu.value == SKINMENUTYPE_2D && itemOn == 1)
if (itemOn == 0)
{
M_TextInputHandle(&setupm_input, choice);
S_StartSound(NULL,sfx_menu1); // Tails
}
else if (cv_skinselectmenu.value == SKINMENUTYPE_2D && itemOn == 1)
{
if (setupm_skinlockedselect)
{
@@ -11389,7 +11361,12 @@ static void M_HandleSetupMultiPlayer(INT32 choice)
break;
case KEY_RIGHTARROW:
if (cv_skinselectmenu.value == SKINMENUTYPE_2D && itemOn == 1)
if (itemOn == 0)
{
M_TextInputHandle(&setupm_input, choice);
S_StartSound(NULL,sfx_menu1); // Tails
}
else if (cv_skinselectmenu.value == SKINMENUTYPE_2D && itemOn == 1)
{
if (setupm_skinlockedselect)
{
@@ -11420,7 +11397,7 @@ static void M_HandleSetupMultiPlayer(INT32 choice)
}
else if (cv_skinselectmenu.value == SKINMENUTYPE_EXTENDED){
if (setupm_skinselect >= ((setupm_skinypos-1)+SKINGRIDHEIGHT)*8+24 && setupm_skinypos < (ROUNDSKINSUPTO8/8)-SKINGRIDHEIGHT+24)
setupm_skinypos++;
setupm_skinypos++;
}
}
else
@@ -11458,11 +11435,8 @@ static void M_HandleSetupMultiPlayer(INT32 choice)
BREAKWHENLOCKED
if (itemOn == 0)
{
if ((l = strlen(setupm_name))!=0)
{
S_StartSound(NULL,sfx_menu1); // Tails
setupm_name[l-1] =0;
}
M_TextInputHandle(&setupm_input, choice);
S_StartSound(NULL,sfx_menu1); // Tails
}
else if ((cv_skinselectmenu.value == SKINMENUTYPE_GRID || cv_skinselectmenu.value == SKINMENUTYPE_EXTENDED) && itemOn == 1)
{
@@ -11487,10 +11461,10 @@ static void M_HandleSetupMultiPlayer(INT32 choice)
case KEY_DEL:
if (cv_skinselectmenu.value)
BREAKWHENLOCKED
if (itemOn == 0 && (l = strlen(setupm_name))!=0)
if (itemOn == 0)
{
M_TextInputHandle(&setupm_input, choice);
S_StartSound(NULL,sfx_menu1); // Tails
setupm_name[0] = 0;
}
break;
@@ -11527,17 +11501,10 @@ static void M_HandleSetupMultiPlayer(INT32 choice)
break;
default:
if (choice < 32 || choice > 127)
break;
if (itemOn == 0)
{
l = strlen(setupm_name);
if (l < MAXPLAYERNAME)
{
if (M_TextInputHandle(&setupm_input, choice))
S_StartSound(NULL,sfx_menu1); // Tails
setupm_name[l] =(char)choice;
setupm_name[l+1] =0;
}
}
break;
}
@@ -11602,7 +11569,9 @@ static void M_SetupMultiPlayer(INT32 choice)
multi_state = cv_skinselectspin.value == SKINSELECTSPIN_PAIN ? &states[S_KART_PAIN] : &states[mobjinfo[MT_PLAYER].seestate];
multi_tics = multi_state->tics*FRACUNIT;
strcpy(setupm_name, cv_playername.string);
M_TextInputInit(&setupm_input, setupm_name, sizeof(setupm_name));
M_TextInputSetString(&setupm_input, cv_playername.string);
// set for player 1
setupm_player = &players[consoleplayer];
@@ -11644,7 +11613,9 @@ static void M_SetupMultiPlayer2(INT32 choice)
multi_state = cv_skinselectspin.value == SKINSELECTSPIN_PAIN ? &states[S_KART_PAIN] : &states[mobjinfo[MT_PLAYER].seestate];
multi_tics = multi_state->tics*FRACUNIT;
strcpy (setupm_name, cv_playername2.string);
M_TextInputInit(&setupm_input, setupm_name, sizeof(setupm_name));
M_TextInputSetString(&setupm_input, cv_playername2.string);
// set for splitscreen secondary player
setupm_player = &players[displayplayers[1]];
@@ -11685,7 +11656,9 @@ static void M_SetupMultiPlayer3(INT32 choice)
multi_state = cv_skinselectspin.value == SKINSELECTSPIN_PAIN ? &states[S_KART_PAIN] : &states[mobjinfo[MT_PLAYER].seestate];
multi_tics = multi_state->tics;
strcpy(setupm_name, cv_playername3.string);
M_TextInputInit(&setupm_input, setupm_name, sizeof(setupm_name));
M_TextInputSetString(&setupm_input, cv_playername3.string);
// set for splitscreen third player
setupm_player = &players[displayplayers[2]];
@@ -11726,7 +11699,9 @@ static void M_SetupMultiPlayer4(INT32 choice)
multi_state = cv_skinselectspin.value == SKINSELECTSPIN_PAIN ? &states[S_KART_PAIN] : &states[mobjinfo[MT_PLAYER].seestate];
multi_tics = multi_state->tics;
strcpy(setupm_name, cv_playername4.string);
M_TextInputInit(&setupm_input, setupm_name, sizeof(setupm_name));
M_TextInputSetString(&setupm_input, cv_playername4.string);
// set for splitscreen fourth player
setupm_player = &players[displayplayers[3]];
@@ -11753,7 +11728,7 @@ static void M_SetupMultiPlayer4(INT32 choice)
//change the y offsets of the menu depending on cvar settings
SKINSELECTMENUEDIT
sortSkinGrid();
MP_PlayerSetupDef.prevMenu = currentMenu;
@@ -12910,10 +12885,12 @@ static void M_DrawColorMenu(void)
if (y + 12 > (currentMenu->y + 2*scrollareaheight))
break;
M_DrawTextBox(x, y + 4, MAXSTRINGLENGTH, 1);
V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, cv->string);
if (skullAnimCounter < 4 && i == itemOn)
V_DrawCharacter(x + 8 + V_StringWidth(cv->string, 0), y + 12,
'_' | 0x80, false);
if (itemOn == i)
M_DrawTextInput(x + 8, y + 12, &menuinput, 0);
else
V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, cv->string);
y += 16;
break;
default:
+4
View File
@@ -64,6 +64,10 @@ void M_DrawTextBox(INT32 x, INT32 y, INT32 width, INT32 boxlines);
// Same but with extra flags applied
void M_DrawTextBoxFlags(INT32 x, INT32 y, INT32 width, INT32 boxlines, INT32 flags);
// Draw text input
typedef struct textinput_s textinput_t;
void M_DrawTextInput(INT32 x, INT32 y, textinput_t *input, INT32 flags);
// Used in d_netcmd to restart time attack
void M_ModeAttackRetry(INT32 choice);
-5
View File
@@ -1987,11 +1987,6 @@ char *sizeu5(size_t num)
return sizeu5_buf;
}
FUNCINLINE ATTRINLINE void *M_Memcpy(void *dest, const void *src, size_t n)
{
return memcpy(dest, src, n);
}
/** Return the appropriate message for a file error or end of file.
*/
const char *M_FileError(FILE *fp)
+9 -1
View File
@@ -10,6 +10,7 @@
/// \brief Performance measurement tools.
#include "m_perfstats.h"
#include "p_mobj.h"
#include "v_video.h"
#include "i_video.h"
#include "d_netcmd.h"
@@ -58,6 +59,7 @@ static ps_metric_t ps_regularcount = {0};
static ps_metric_t ps_scenerycount = {0};
static ps_metric_t ps_nothinkcount = {0};
static ps_metric_t ps_otherthcount = {0};
static ps_metric_t ps_precipcount = {0};
static ps_metric_t ps_removecount = {0};
ps_metric_t ps_checkposition_calls = {0};
@@ -171,6 +173,7 @@ perfstatrow_t thinkercount_rows[] = {
{" regular", " Regular: ", &ps_regularcount, PS_LEVEL},
{" scenery", " Scenery: ", &ps_scenerycount, PS_LEVEL},
{" nothink", " Nothink: ", &ps_nothinkcount, PS_HIDE_ZERO|PS_LEVEL},
{" precip ", " Precipitation: ", &ps_precipcount, PS_LEVEL},
{" other ", " Other: ", &ps_otherthcount, PS_LEVEL},
{" remove ", " Pending removal:", &ps_removecount, PS_LEVEL},
{0}
@@ -569,11 +572,14 @@ static void PS_CountThinkers(void)
ps_regularcount.value.i = 0;
ps_scenerycount.value.i = 0;
ps_nothinkcount.value.i = 0;
ps_precipcount.value.i = 0;
ps_otherthcount.value.i = 0;
ps_removecount.value.i = 0;
for (thinker = thinkercap.next; thinker != &thinkercap; thinker = thinker->next)
{
ps_thinkercount.value.i++;
if (thinker->function.acp1 != (actionf_p1)P_NullPrecipThinker)
ps_thinkercount.value.i++;
if (thinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
ps_removecount.value.i++;
else if (thinker->function.acp1 == (actionf_p1)P_MobjThinker)
@@ -587,6 +593,8 @@ static void PS_CountThinkers(void)
else
ps_regularcount.value.i++;
}
else if (thinker->function.acp1 == (actionf_p1)P_NullPrecipThinker)
ps_precipcount.value.i++;
else
ps_otherthcount.value.i++;
}
+303
View File
@@ -0,0 +1,303 @@
#include "m_textinput.h"
#include "i_system.h"
#include "keys.h"
#include "console.h"
static void M_TextInputDel(textinput_t *input, size_t start, size_t end)
{
size_t len;
len = (end - start);
if (end != input->length)
memmove(&input->buffer[start], &input->buffer[end], input->length-end);
memset(&input->buffer[input->length - len], 0, len);
input->length -= len;
if (input->select >= end)
input->select -= len;
else if (input->select > start)
input->select = start;
if (input->cursor >= end)
input->cursor -= len;
else if (input->cursor > start)
input->cursor = start;
}
static void M_TextInputDelSelection(textinput_t *input)
{
size_t start, end;
if (input->cursor > input->select)
{
start = input->select;
end = input->cursor;
}
else
{
start = input->cursor;
end = input->select;
}
M_TextInputDel(input, start, end);
input->select = input->cursor = start;
}
static void M_TextInputAddString(textinput_t *input, const char *c)
{
size_t csize = strlen(c);
if (input->length + csize > input->buffer_size-1)
return;
if (input->cursor != input->length)
memmove(&input->buffer[input->cursor+csize], &input->buffer[input->cursor], input->length-input->cursor);
memcpy(&input->buffer[input->cursor], c, csize);
input->length += csize;
input->select = (input->cursor += csize);
input->buffer[input->length] = 0;
}
static void M_TextInputAddChar(textinput_t *input, char c)
{
if (input->length >= input->buffer_size-1)
return;
if (input->cursor != input->length)
memmove(&input->buffer[input->cursor+1], &input->buffer[input->cursor], input->length-input->cursor);
input->buffer[input->cursor++] = c;
input->buffer[++input->length] = 0;
input->select = input->cursor;
}
static void M_TextInputDelChar(textinput_t *input)
{
if (!input->cursor)
return;
if (input->cursor != input->length)
memmove(&input->buffer[input->cursor-1], &input->buffer[input->cursor], input->length-input->cursor);
input->buffer[--input->length] = 0;
input->select = --input->cursor;
}
static void M_TextInputToWordEnd(textinput_t *input, boolean move_sel)
{
// Skip spaces
while (input->cursor < input->length && isspace(input->buffer[input->cursor]))
++input->cursor;
// Skip word
while (input->cursor < input->length && !isspace(input->buffer[input->cursor]))
++input->cursor;
if (move_sel) input->select = input->cursor;
}
static void M_TextInputToWordBegin(textinput_t *input, boolean move_sel)
{
// Hack, always move back 1 character if possible so if we press ctrl-left at a word beginning
// we move to previous word
if (input->cursor) --input->cursor;
// Skip spaces
while (input->cursor && isspace(input->buffer[input->cursor]))
--input->cursor;
// Skip word
while (input->cursor && !isspace(input->buffer[input->cursor]))
--input->cursor;
// Unless we reached beginning of line, we're pointing at a space before word, so move cursor
// forward to fix that
if (input->cursor) ++input->cursor;
if (move_sel) input->select = input->cursor;
}
void M_TextInputInit(textinput_t *input, char *buffer, size_t buffer_size)
{
input->buffer = buffer;
input->buffer_size = buffer_size;
M_TextInputClear(input);
}
void M_TextInputClear(textinput_t *input)
{
input->cursor = 0;
input->select = 0;
input->length = 0;
}
void M_TextInputSetString(textinput_t *input, const char *c)
{
memset(input->buffer, 0, input->buffer_size);
strcpy(input->buffer, c);
input->cursor = input->select = input->length = strlen(c);
}
boolean M_TextInputHandle(textinput_t *input, INT32 key)
{
if (key == KEY_LSHIFT || key == KEY_RSHIFT
|| key == KEY_LCTRL || key == KEY_RCTRL
|| key == KEY_LALT || key == KEY_RALT)
return false;
if ((cv_keyboardlayout.value != 3 && ctrldown) || (cv_keyboardlayout.value == 3 && ctrldown && !altdown))
{
if (key == 'x' || key == 'X')
{
if (input->select > input->cursor)
I_ClipboardCopy(&input->buffer[input->cursor], input->select-input->cursor);
else
I_ClipboardCopy(&input->buffer[input->select], input->cursor-input->select);
M_TextInputDelSelection(input);
return true;
}
else if (key == 'c' || key == 'C')
{
if (input->select > input->cursor)
I_ClipboardCopy(&input->buffer[input->cursor], input->select-input->cursor);
else
I_ClipboardCopy(&input->buffer[input->select], input->cursor-input->select);
return true;
}
else if (key == 'v' || key == 'V')
{
const char *paste = I_ClipboardPaste();
if (input->select != input->cursor)
M_TextInputDelSelection(input);
if (paste != NULL)
M_TextInputAddString(input, paste);
return true;
}
else if (key == 'w' || key == 'W')
{
size_t word_start, word_end, i;
word_end = i = input->cursor;
// Unless we're pointing at the beginning of line, decrement i so we only start
// removing symbols that come before the cursor
if (i) --i;
// We might be pointing to spaces, skip them first
while (i && isspace(input->buffer[i]))
--i;
// Now skip the "word"
while (i && !isspace(input->buffer[i]))
--i;
// Unless we reached beginning of line, i is pointing at first space that was found
// before word start, and we don't want to remove it
if (i) ++i;
word_start = i;
if (word_start != word_end)
M_TextInputDel(input, word_start, word_end);
return true;
}
else if (key == KEY_RIGHTARROW)
M_TextInputToWordEnd(input, !shiftdown);
else if (key == KEY_LEFTARROW)
M_TextInputToWordBegin(input, !shiftdown);
// Select all
if (key == 'a' || key == 'A')
{
input->select = 0;
input->cursor = input->length;
return true;
}
// ...why shouldn't it eat the key? if it doesn't, it just means you
// can control Sonic from the console, which is silly
return true;
}
if (key == KEY_LEFTARROW)
{
if (input->cursor != 0)
--input->cursor;
if (!shiftdown)
input->select = input->cursor;
return true;
}
else if (key == KEY_RIGHTARROW)
{
if (input->cursor < input->length)
++input->cursor;
if (!shiftdown)
input->select = input->cursor;
return true;
}
else if (key == KEY_HOME)
{
input->cursor = 0;
if (!shiftdown)
input->select = input->cursor;
return true;
}
else if (key == KEY_END)
{
input->cursor = input->length;
if (!shiftdown)
input->select = input->cursor;
return true;
}
// backspace and delete command prompt
if (input->select != input->cursor)
{
if (key == KEY_BACKSPACE || key == KEY_DEL)
{
M_TextInputDelSelection(input);
return true;
}
}
else if (key == KEY_BACKSPACE)
{
M_TextInputDelChar(input);
return true;
}
else if (key == KEY_DEL)
{
if (input->cursor == input->length)
return true;
++input->cursor;
M_TextInputDelChar(input);
return true;
}
// allow people to use keypad in console (good for typing IP addresses) - Calum
if (key >= KEY_KEYPAD7 && key <= KEY_KPADDEL)
{
char keypad_translation[] = {'7','8','9','-',
'4','5','6','+',
'1','2','3',
'0','.'};
key = keypad_translation[key - KEY_KEYPAD7];
}
else if (key == KEY_KPADSLASH)
key = '/';
// same capslock code as hu_stuff.c's HU_responder. Check there for details.
key = cv_keyboardlayout.value == 3 ? CON_ShitAndAltGrChar(key) : CON_ShiftChar(key);
// enter a char into the command prompt
if (key < 32 || key > 127)
return false;
if (input->select != input->cursor)
M_TextInputDelSelection(input);
M_TextInputAddChar(input, key);
return true;
}
+23
View File
@@ -0,0 +1,23 @@
#ifndef __M_TEXTINPUT__
#define __M_TEXTINPUT__
#include "doomtype.h"
typedef struct textinput_s {
size_t cursor;
size_t select;
size_t length;
char *buffer;
size_t buffer_size;
} textinput_t;
void M_TextInputInit(textinput_t *input, char *buffer, size_t buffer_size);
void M_TextInputClear(textinput_t *input);
void M_TextInputSetString(textinput_t *input, const char *c);
boolean M_TextInputHandle(textinput_t *input, INT32 key);
#endif
+3 -7
View File
@@ -2400,8 +2400,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
UINT8 shouldForce = LUAh_ShouldDamage(target, inflictor, source, damage);
if (P_MobjWasRemoved(target))
return (shouldForce == 1); // mobj was removed
if (P_MobjWasRemoved(source))
source = NULL;
if (shouldForce == 1)
force = true;
else if (shouldForce == 2)
@@ -2564,8 +2562,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
P_PlayerRingBurst(player, 5);
if (P_IsLocalPlayer(player))
{
quake.intensity = 32*FRACUNIT;
quake.time = 5;
P_StartQuake(5, 32<<FRACBITS, 0);
}
}
else
@@ -2639,6 +2636,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
P_ResetPlayer(target->player);
}
else
{
switch (target->type)
{
case MT_EGGMOBILE2: // egg slimer
@@ -2652,9 +2650,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
P_SetMobjState(target, target->info->painstate);
break;
}
if (P_MobjWasRemoved(target))
return false;
}
if (!P_MobjWasRemoved(target))
{
+22 -3
View File
@@ -164,8 +164,9 @@ void P_InitCameraCmd(void);
boolean P_PlayerInPain(player_t *player);
void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor);
void P_ResetPlayer(player_t *player);
boolean P_IsLocalPlayer(player_t *player);
boolean P_IsDisplayPlayer(player_t *player);
boolean P_IsLocalPlayer(const player_t *player);
boolean P_IsDisplayPlayer(const player_t *player);
boolean P_SpectatorJoinGame(player_t *player);
boolean P_IsObjectInGoop(mobj_t *mo);
@@ -248,7 +249,7 @@ void P_RecalcPrecipInSector(sector_t *sector);
void P_PrecipitationEffects(void);
void P_RemoveMobj(mobj_t *th);
boolean P_MobjWasRemoved(const mobj_t *th);
void P_RemoveSavegameMobj(mobj_t *th);
boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state);
boolean P_SetMobjState(mobj_t *mobj, statenum_t state);
@@ -260,6 +261,12 @@ boolean P_RailThinker(mobj_t *mobj);
void P_PushableThinker(mobj_t *mobj);
void P_SceneryThinker(mobj_t *mobj);
// This does not need to be added to Lua.
// To test it in Lua, check mobj.valid
FUNCINLINE static ATTRINLINE boolean P_MobjWasRemoved(const mobj_t *mobj)
{
return !(mobj && mobj->thinker.function.acp1 == (actionf_p1)P_MobjThinker);
}
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);
@@ -392,6 +399,18 @@ extern fixed_t bmaporgy; // origin of block map
extern mobj_t **blocklinks; // for thing chains
extern precipmobj_t **precipblocklinks; // special blockmap for precip rendering
extern struct minimapinfo
{
patch_t *minimap_pic;
UINT8 mapthingcount;
INT32 min_x, min_y;
INT32 max_x, max_y;
INT32 map_w, map_h;
INT32 minimap_w, minimap_h;
fixed_t offs_x, offs_y;
fixed_t zoom;
} minimapinfo;
//
// P_INTER
//
+170 -167
View File
@@ -408,7 +408,7 @@ void P_ExplodeMissile(mobj_t *mo)
P_RadiusAttack(mo, mo, 96*FRACUNIT);
explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE);
if (!P_MobjWasRemoved(explodemo))
if (explodemo)
{
P_SetScale(explodemo, mo->scale);
explodemo->destscale = mo->destscale;
@@ -417,7 +417,7 @@ void P_ExplodeMissile(mobj_t *mo)
S_StartSound(explodemo, sfx_pop);
}
explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE);
if (!P_MobjWasRemoved(explodemo))
if (explodemo)
{
P_SetScale(explodemo, mo->scale);
explodemo->destscale = mo->destscale;
@@ -426,7 +426,7 @@ void P_ExplodeMissile(mobj_t *mo)
S_StartSound(explodemo, sfx_dmpain);
}
explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE);
if (!P_MobjWasRemoved(explodemo))
if (explodemo)
{
P_SetScale(explodemo, mo->scale);
explodemo->destscale = mo->destscale;
@@ -435,7 +435,7 @@ void P_ExplodeMissile(mobj_t *mo)
S_StartSound(explodemo, sfx_pop);
}
explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE);
if (!P_MobjWasRemoved(explodemo))
if (explodemo)
{
P_SetScale(explodemo, mo->scale);
explodemo->destscale = mo->destscale;
@@ -592,7 +592,8 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t
{
I_Assert(mobj != NULL);
I_Assert(sector != NULL);
if (sector->f_slope) {
if (sector->f_slope)
{
fixed_t testx, testy;
pslope_t *slope = sector->f_slope;
@@ -607,7 +608,8 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t
else
testy = -mobj->radius;
if ((slope->zdelta > 0) ^ !!(lowest)) {
if ((slope->zdelta > 0) ^ !!(lowest))
{
testx = -testx;
testy = -testy;
}
@@ -620,22 +622,21 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t
return P_GetZAt(slope, testx, testy);
// If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point
if (perfect) {
if (perfect)
{
size_t i;
line_t *ld;
fixed_t bbox[4];
fixed_t finalheight;
if (lowest)
finalheight = INT32_MAX;
else
finalheight = INT32_MIN;
finalheight = lowest ? INT32_MAX : INT32_MIN;
bbox[BOXLEFT] = x-mobj->radius;
bbox[BOXRIGHT] = x+mobj->radius;
bbox[BOXTOP] = y+mobj->radius;
bbox[BOXBOTTOM] = y-mobj->radius;
for (i = 0; i < boundsec->linecount; i++) {
for (i = 0; i < boundsec->linecount; i++)
{
ld = boundsec->lines[i];
if (bbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || bbox[BOXLEFT] >= ld->bbox[BOXRIGHT]
@@ -668,7 +669,8 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed
{
I_Assert(mobj != NULL);
I_Assert(sector != NULL);
if (sector->c_slope) {
if (sector->c_slope)
{
fixed_t testx, testy;
pslope_t *slope = sector->c_slope;
@@ -683,7 +685,8 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed
else
testy = -mobj->radius;
if ((slope->zdelta > 0) ^ !!(lowest)) {
if ((slope->zdelta > 0) ^ !!(lowest))
{
testx = -testx;
testy = -testy;
}
@@ -696,22 +699,21 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed
return P_GetZAt(slope, testx, testy);
// If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point
if (perfect) {
if (perfect)
{
size_t i;
line_t *ld;
fixed_t bbox[4];
fixed_t finalheight;
if (lowest)
finalheight = INT32_MAX;
else
finalheight = INT32_MIN;
finalheight = lowest ? INT32_MAX : INT32_MIN;
bbox[BOXLEFT] = x-mobj->radius;
bbox[BOXRIGHT] = x+mobj->radius;
bbox[BOXTOP] = y+mobj->radius;
bbox[BOXBOTTOM] = y-mobj->radius;
for (i = 0; i < boundsec->linecount; i++) {
for (i = 0; i < boundsec->linecount; i++)
{
ld = boundsec->lines[i];
if (bbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || bbox[BOXLEFT] >= ld->bbox[BOXRIGHT]
@@ -746,7 +748,8 @@ fixed_t P_CameraFloorZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fix
I_Assert(mobj != NULL);
I_Assert(sector != NULL);
if (sector->f_slope) {
if (sector->f_slope)
{
fixed_t testx, testy;
pslope_t *slope = sector->f_slope;
@@ -761,7 +764,8 @@ fixed_t P_CameraFloorZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fix
else
testy = -mobj->radius;
if ((slope->zdelta > 0) ^ !!(lowest)) {
if ((slope->zdelta > 0) ^ !!(lowest))
{
testx = -testx;
testy = -testy;
}
@@ -774,22 +778,21 @@ fixed_t P_CameraFloorZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fix
return P_GetZAt(slope, testx, testy);
// If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point
if (perfect) {
if (perfect)
{
size_t i;
line_t *ld;
fixed_t bbox[4];
fixed_t finalheight;
if (lowest)
finalheight = INT32_MAX;
else
finalheight = INT32_MIN;
finalheight = lowest ? INT32_MAX : INT32_MIN;
bbox[BOXLEFT] = x-mobj->radius;
bbox[BOXRIGHT] = x+mobj->radius;
bbox[BOXTOP] = y+mobj->radius;
bbox[BOXBOTTOM] = y-mobj->radius;
for (i = 0; i < boundsec->linecount; i++) {
for (i = 0; i < boundsec->linecount; i++)
{
ld = boundsec->lines[i];
if (bbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || bbox[BOXLEFT] >= ld->bbox[BOXRIGHT]
@@ -823,7 +826,8 @@ fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, f
I_Assert(mobj != NULL);
I_Assert(sector != NULL);
if (sector->c_slope) {
if (sector->c_slope)
{
fixed_t testx, testy;
pslope_t *slope = sector->c_slope;
@@ -838,7 +842,8 @@ fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, f
else
testy = -mobj->radius;
if ((slope->zdelta > 0) ^ !!(lowest)) {
if ((slope->zdelta > 0) ^ !!(lowest))
{
testx = -testx;
testy = -testy;
}
@@ -851,22 +856,21 @@ fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, f
return P_GetZAt(slope, testx, testy);
// If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point
if (perfect) {
if (perfect)
{
size_t i;
line_t *ld;
fixed_t bbox[4];
fixed_t finalheight;
if (lowest)
finalheight = INT32_MAX;
else
finalheight = INT32_MIN;
finalheight = lowest ? INT32_MAX : INT32_MIN;
bbox[BOXLEFT] = x-mobj->radius;
bbox[BOXRIGHT] = x+mobj->radius;
bbox[BOXTOP] = y+mobj->radius;
bbox[BOXBOTTOM] = y-mobj->radius;
for (i = 0; i < boundsec->linecount; i++) {
for (i = 0; i < boundsec->linecount; i++)
{
ld = boundsec->lines[i];
if (bbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || bbox[BOXLEFT] >= ld->bbox[BOXRIGHT]
@@ -3245,7 +3249,7 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled
{
boolean itsatwodlevel = false;
boolean flipcam = (player->pflags & PF_FLIPCAM && !(player->pflags & PF_NIGHTSMODE) && player->mo->eflags & MFE_VERTICALFLIP);
postimg_t postimg = postimg_none;
UINT16 postimgflags = 0;
UINT8 i;
// This can happen when joining
@@ -3267,64 +3271,67 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled
}
}
if (encoremode && !flipcam)
postimg = postimg_mirror;
else if (!encoremode && flipcam)
postimg = postimg_flip;
else if (encoremode && flipcam)
postimg = postimg_mirrorflip;
else if (player->awayviewtics && player->awayviewmobj && !P_MobjWasRemoved(player->awayviewmobj)) // Camera must obviously exist
if (encoremode)
postimgflags |= POSTIMG_MIRROR;
if (flipcam)
postimgflags |= POSTIMG_FLIP;
if (player->awayviewtics && player->awayviewmobj && !P_MobjWasRemoved(player->awayviewmobj)) // Camera must obviously exist
{
camera_t dummycam;
dummycam.subsector = player->awayviewmobj->subsector;
dummycam.x = player->awayviewmobj->x;
dummycam.y = player->awayviewmobj->y;
dummycam.z = player->awayviewmobj->z;
//dummycam.height = 40*FRACUNIT; // alt view height is 20*FRACUNIT
dummycam.height = 0; // Why? Remote viewpoint cameras have no height.
// Are we in water?
if (P_CameraCheckWater(&dummycam))
postimg = postimg_water;
else if (P_CameraCheckHeat(&dummycam))
postimg = postimg_heat;
postimgflags |= POSTIMG_WATER;
if (P_CameraCheckHeat(&dummycam))
postimgflags |= POSTIMG_HEAT;
}
else
{
// Are we in water?
if (P_CameraCheckWater(thiscam))
postimg = postimg_water;
else if (P_CameraCheckHeat(thiscam))
postimg = postimg_heat;
postimgflags |= POSTIMG_WATER;
if (P_CameraCheckHeat(thiscam))
postimgflags |= POSTIMG_HEAT;
}
if (postimg != postimg_none)
for (i = 0; i <= splitscreen; i++)
{
for (i = 0; i <= splitscreen; i++)
{
if (player != &players[displayplayers[i]])
continue;
if (player != &players[displayplayers[i]])
continue;
postimgtype[i] = postimg;
}
players[displayplayers[i]].postimgflags = postimgflags;
break;
}
if (thiscam->momx || thiscam->momy)
{
if (!P_TryCameraMove(thiscam->x + thiscam->momx, thiscam->y + thiscam->momy, thiscam))
{ // Never fails for 2D mode.
if (!P_TryCameraMove(thiscam->x + thiscam->momx, thiscam->y + thiscam->momy, thiscam)) // Never fails for 2D mode.
{
mobj_t dummy;
dummy.thinker.function.acp1 = (actionf_p1)P_MobjThinker;
dummy.subsector = thiscam->subsector;
dummy.x = thiscam->x;
dummy.y = thiscam->y;
dummy.z = thiscam->z;
dummy.height = thiscam->height;
if (player->pflags & PF_TIMEOVER)
player->kartstuff[k_timeovercam] = (2*TICRATE)+1;
if (!resetcalled && !(player->pflags & PF_NOCLIP || leveltime < introtime) && !P_CheckSight(&dummy, player->mo)) // TODO: "P_CheckCameraSight" instead.
P_ResetCamera(player, thiscam);
else
P_SlideCameraMove(thiscam);
if (resetcalled) // Okay this means the camera is fully reset.
return true;
}
@@ -3406,8 +3413,8 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
I_Assert(mobj != NULL);
I_Assert(mobj->player != NULL);
I_Assert(!P_MobjWasRemoved(mobj));
if (P_MobjWasRemoved(mobj))
if (!mobj)
return;
P_MobjCheckWater(mobj);
@@ -6026,41 +6033,36 @@ static void P_KoopaThinker(mobj_t *koopa)
//
void P_RollPitchMobj(mobj_t* mobj)
{
boolean usedist = false;
if (P_MobjWasRemoved(mobj))
return;
if (!mobj || P_MobjWasRemoved(mobj))
return;
if (cv_sloperolldist.value > 0)
usedist = true;
if ((cv_spriteroll.value) && (cv_sloperoll.value == 2))
{
K_RollMobjBySlopes(mobj, usedist);
}
else
{
mobj->sloperoll = FixedAngle(0);
mobj->slopepitch = FixedAngle(0);
}
if (cv_spriteroll.value && cv_sloperoll.value == 2)
{
K_RollMobjBySlopes(mobj, cv_sloperolldist.value && !splitscreen);
}
else
{
mobj->sloperoll = FixedAngle(0);
mobj->slopepitch = FixedAngle(0);
}
}
angle_t P_MobjPitchAndRoll(mobj_t *mobj)
{
spritedef_t *sprdef;
spriteframe_t *sprframe;
angle_t ang = 0;
spritedef_t *sprdef;
spriteframe_t *sprframe;
angle_t ang = 0;
angle_t camang = 0;
angle_t return_angle = 0;
if (!cv_spriteroll.value)
return 0;
if (P_MobjWasRemoved(mobj))
return 0;
if (P_MobjWasRemoved(mobj))
return 0;
size_t rot = mobj->frame & FF_FRAMEMASK;
boolean papersprite = (mobj->frame & FF_PAPERSPRITE);
size_t rot = mobj->frame & FF_FRAMEMASK;
boolean papersprite = (mobj->frame & FF_PAPERSPRITE);
if (mobj->skin && mobj->sprite == SPR_PLAY)
{
@@ -6091,12 +6093,12 @@ angle_t P_MobjPitchAndRoll(mobj_t *mobj)
camang = R_PointToAngle(mobj->x, mobj->y);
}
return_angle = FixedMul(FINECOSINE((ang) >> ANGLETOFINESHIFT), mobj->roll)
return_angle = FixedMul(FINECOSINE((ang) >> ANGLETOFINESHIFT), mobj->roll)
+ FixedMul(FINESINE((ang) >> ANGLETOFINESHIFT), mobj->pitch);
if (cv_sloperoll.value)
{
return_angle += FixedMul(FINECOSINE((camang) >> ANGLETOFINESHIFT), mobj->sloperoll)
return_angle += FixedMul(FINECOSINE((camang) >> ANGLETOFINESHIFT), mobj->sloperoll)
+ FixedMul(FINESINE((camang) >> ANGLETOFINESHIFT), mobj->slopepitch);
}
@@ -6259,8 +6261,8 @@ void P_MobjThinker(mobj_t *mobj)
P_RemoveMobj(mobj);
return;
}
if (mobj->state == &states[S_SHADOW] && cv_sloperoll.value == 2)
if (cv_sloperoll.value == 2 && mobj->state == &states[S_SHADOW])
{
mobj->slopepitch = mobj->target->slopepitch;
mobj->sloperoll = mobj->target->sloperoll;
@@ -6282,6 +6284,7 @@ void P_MobjThinker(mobj_t *mobj)
P_RemoveMobj(mobj);
return;
}
P_RollPitchMobj(mobj);
break;
case MT_SMOLDERING:
@@ -6912,9 +6915,6 @@ void P_MobjThinker(mobj_t *mobj)
// separate thinker
if (mobj->flags & MF_PUSHABLE || (mobj->info->flags & MF_PUSHABLE && mobj->fuse))
{
if (P_MobjWasRemoved(mobj))
return;
P_MobjCheckWater(mobj);
P_PushableThinker(mobj);
@@ -9430,11 +9430,11 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
mobj->destscale = mapobjectscale;
mobj->scalespeed = mapobjectscale/12;
}
// Sprite rendering
mobj->realxscale = mobj->realyscale = mobj->scale;
mobj->realxscale = mobj->realyscale = mobj->scale;
mobj->spritexscale = mobj->realxscale;
mobj->spriteyscale = mobj->realyscale;
mobj->spriteyscale = mobj->realyscale;
mobj->spritexoffset = mobj->spriteyoffset = 0;
// Funni slam sound when landing
@@ -9888,11 +9888,11 @@ mobj_t *P_SpawnShadowMobj(mobj_t * caster)
mobj->destscale = mapobjectscale;
mobj->scalespeed = mapobjectscale/12;
}
// Sprite rendering
mobj->spritexscale = mobj->spriteyscale = mobj->scale;
mobj->spritexscale = mobj->spriteyscale = mobj->scale;
mobj->spritexoffset = mobj->spriteyoffset = 0;
// set subsector and/or block links
P_SetThingPosition(mobj);
I_Assert(mobj->subsector != NULL);
@@ -9990,10 +9990,13 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype
if (mobj->floorz != starting_floorz)
mobj->precipflags |= PCF_FOF;
else if (GETSECSPECIAL(mobj->subsector->sector->special, 1) == 7
|| GETSECSPECIAL(mobj->subsector->sector->special, 1) == 6
|| mobj->subsector->sector->floorpic == skyflatnum)
mobj->precipflags |= PCF_PIT;
else
{
INT32 special = GETSECSPECIAL(mobj->subsector->sector->special, 1);
if (special == 7 || special == 6 || mobj->subsector->sector->floorpic == skyflatnum)
mobj->precipflags |= PCF_PIT;
}
R_ResetPrecipitationMobjInterpolationState(mobj);
@@ -10096,7 +10099,7 @@ void P_RemoveMobj(mobj_t *mobj)
P_SetTarget(&mobj->hprev->hnext, cachenext);
P_SetTarget(&mobj->hprev, NULL);
}
// clear the reference from the mapthing
if (mobj->spawnpoint)
mobj->spawnpoint->mobj = NULL;
@@ -10136,13 +10139,6 @@ void P_RemoveMobj(mobj_t *mobj)
}
}
// This does not need to be added to Lua.
// To test it in Lua, check mobj.valid
FUNCINLINE ATTRINLINE boolean P_MobjWasRemoved(const mobj_t *mobj)
{
return !(mobj && mobj->thinker.function.acp1 == (actionf_p1)P_MobjThinker);
}
void P_FreePrecipMobj(precipmobj_t *mobj)
{
// unlink from sector and block lists
@@ -10205,9 +10201,8 @@ consvar_t cv_suddendeath = {"suddendeath", "Off", CV_NETVAR|CV_CHEAT|CV_NOSHOWHE
void P_SpawnPrecipitation(void)
{
INT32 i, j, k, mrand;
fixed_t basex, basey, x, y, z, height;
fixed_t precipscale = cv_mobjscaleprecip.value ? mapobjectscale : FRACUNIT;
INT32 i, mrand;
fixed_t basex, basey, j, x, y, z;
subsector_t *precipsector = NULL;
precipmobj_t *rainmo = NULL;
@@ -10220,9 +10215,10 @@ void P_SpawnPrecipitation(void)
basex = bmaporgx + (i % bmapwidth) * MAPBLOCKSIZE;
basey = bmaporgy + (i / bmapwidth) * MAPBLOCKSIZE;
for (j = 0; j < FRACUNIT; j += precipscale)
for (j = 0; j < FRACUNIT; j += cv_mobjscaleprecip.value ? mapobjectscale : FRACUNIT)
{
UINT16 numparticles = 0;
INT32 floorz;
INT32 ceilingz;
x = ((cv_lessprecip.value ? basex*1.5 : basex) + ((M_RandomKey(MAPBLOCKUNITS<<3)<<FRACBITS)>>3));
y = ((cv_lessprecip.value ? basey*1.5 : basey) + ((M_RandomKey(MAPBLOCKUNITS<<3)<<FRACBITS)>>3));
@@ -10238,49 +10234,37 @@ void P_SpawnPrecipitation(void)
if (precipsector->sector->ceilingpic != skyflatnum)
continue;
height = precipsector->sector->ceilingheight - precipsector->sector->floorheight;
height = FixedDiv(height, precipscale);
// Exists, but is too small for reasonable precipitation.
if (height < 64<<FRACBITS)
if (!(precipsector->sector->floorheight <= precipsector->sector->ceilingheight - (32<<FRACBITS)))
continue;
// Hack around a quirk of this entire system, where taller sectors look like they get less precipitation.
numparticles = 1 + (height / (MAPBLOCKUNITS<<4<<FRACBITS));
// Don't set z properly yet...
z = precipsector->sector->ceilingheight;
for (k = 0; k < numparticles; k++)
if (curWeather == PRECIP_SNOW)
{
INT32 floorz;
INT32 ceilingz;
rainmo = P_SpawnPrecipMobj(x, y, z, MT_SNOWFLAKE);
mrand = M_RandomByte();
if (mrand < 64)
P_SetPrecipMobjState(rainmo, S_SNOW3);
else if (mrand < 144)
P_SetPrecipMobjState(rainmo, S_SNOW2);
}
else // everything else.
rainmo = P_SpawnPrecipMobj(x, y, z, MT_RAIN);
if (curWeather == PRECIP_SNOW)
{
rainmo = P_SpawnPrecipMobj(x, y, z, MT_SNOWFLAKE);
mrand = M_RandomByte();
if (mrand < 64)
P_SetPrecipMobjState(rainmo, S_SNOW3);
else if (mrand < 144)
P_SetPrecipMobjState(rainmo, S_SNOW2);
}
else // everything else.
rainmo = P_SpawnPrecipMobj(x, y, z, MT_RAIN);
floorz = rainmo->floorz >> FRACBITS;
ceilingz = rainmo->ceilingz >> FRACBITS;
floorz = rainmo->floorz >> FRACBITS;
ceilingz = rainmo->ceilingz >> FRACBITS;
if (floorz < ceilingz)
{
// Randomly assign a height, now that floorz is set.
rainmo->z = M_RandomRange(floorz, ceilingz) << FRACBITS;
}
else
{
// ...except if the floor is above the ceiling.
rainmo->z = ceilingz << FRACBITS;
}
if (floorz < ceilingz)
{
// Randomly assign a height, now that floorz is set.
rainmo->z = M_RandomRange(floorz, ceilingz) << FRACBITS;
}
else
{
// ...except if the floor is above the ceiling.
rainmo->z = ceilingz << FRACBITS;
}
}
}
@@ -10306,7 +10290,7 @@ void P_PrecipitationEffects(void)
INT32 volume;
size_t i;
boolean sounds_rain = true;
boolean rainsfx = true;
boolean sounds_thunder = true;
boolean effects_lightning = true;
boolean lightningStrike = false;
@@ -10339,7 +10323,7 @@ void P_PrecipitationEffects(void)
effects_lightning = false;
break;
case PRECIP_STORM_NORAIN: // no rain, lightning and thunder allowed
sounds_rain = false;
rainsfx = false;
case PRECIP_STORM: // everything.
break;
default:
@@ -10347,6 +10331,8 @@ void P_PrecipitationEffects(void)
return;
}
boolean sounds_rain = ((cv_drawdist_precip.value != 0) && rainsfx && (!leveltime || leveltime % 80 == 1));
// Currently thunderstorming with lightning, and we're sounding the thunder...
// and where there's thunder, there's gotta be lightning!
if (effects_lightning && lightningStrike)
@@ -10366,41 +10352,57 @@ void P_PrecipitationEffects(void)
if (sound_disabled)
return; // Sound off? D'aw, no fun.
if (!sounds_rain && !sounds_thunder)
return; // no need to calculate volume at ALL
if (players[displayplayers[0]].mo->subsector->sector->ceilingpic == skyflatnum)
volume = 255; // Sky above? We get it full blast.
else
{
/* GCC is optimizing away y >= yl, FUCK YOU */
volatile fixed_t x, y, yl, yh, xl, xh;
INT64 x, y, yl, yh, xl, xh;
fixed_t closedist, newdist;
// Essentially check in a 1024 unit radius of the player for an outdoor area.
yl = players[displayplayers[0]].mo->y - 1024*FRACUNIT;
yh = players[displayplayers[0]].mo->y + 1024*FRACUNIT;
xl = players[displayplayers[0]].mo->x - 1024*FRACUNIT;
xh = players[displayplayers[0]].mo->x + 1024*FRACUNIT;
closedist = 2048*FRACUNIT;
#define RADIUSSTEP (64*FRACUNIT)
#define SEARCHRADIUS (16*RADIUSSTEP)
yl = yh = players[displayplayers[0]].mo->y;
yl -= SEARCHRADIUS;
while (yl < INT32_MIN)
yl += RADIUSSTEP;
yh += SEARCHRADIUS;
while (yh > INT32_MAX)
yh -= RADIUSSTEP;
for (y = yl; y >= yl && y <= yh; y += FRACUNIT*64)
for (x = xl; x >= xl && x <= xh; x += FRACUNIT*64)
xl = xh = players[displayplayers[0]].mo->x;
xl -= SEARCHRADIUS;
while (xl < INT32_MIN)
xl += RADIUSSTEP;
xh += SEARCHRADIUS;
while (xh > INT32_MAX)
xh -= RADIUSSTEP;
closedist = SEARCHRADIUS*2;
#undef SEARCHRADIUS
for (y = yl; y <= yh; y += RADIUSSTEP)
for (x = xl; x <= xh; x += RADIUSSTEP)
{
if (R_PointInSubsector(x, y)->sector->ceilingpic != skyflatnum) // Found the outdoors!
if (R_PointInSubsector((fixed_t)x, (fixed_t)y)->sector->ceilingpic != skyflatnum) // Found the outdoors!
continue;
newdist = S_CalculateSoundDistance(players[displayplayers[0]].mo->x, players[displayplayers[0]].mo->y, 0, x, y, 0);
newdist = S_CalculateSoundDistance(players[displayplayers[0]].mo->x, players[displayplayers[0]].mo->y, 0, (fixed_t)x, (fixed_t)y, 0);
if (newdist < closedist)
closedist = newdist;
}
volume = 255 - (closedist>>(FRACBITS+2));
}
#undef RADIUSSTEP
if (volume < 0)
volume = 0;
else if (volume > 255)
volume = 255;
volume = CLAMP(volume, 0, 255);
if (sounds_rain && (!leveltime || leveltime % 80 == 1))
if (sounds_rain)
S_StartSoundAtVolume(players[displayplayers[0]].mo, sfx_rainin, volume);
if (!sounds_thunder)
@@ -11268,7 +11270,8 @@ void P_SpawnMapThing(mapthing_t *mthing)
mobj = P_SpawnMobj(x, y, z, i);
if (!mobj || P_MobjWasRemoved(mobj)) {
if (!mobj || P_MobjWasRemoved(mobj))
{
CONS_Alert(CONS_ERROR, "Failed to spawn map thing #%d at %d, %d. This will crash vanilla clients!\n", mthing->type, x>>FRACBITS, y>>FRACBITS);
return;
}
+10 -11
View File
@@ -261,20 +261,21 @@ typedef enum {
PCF_SPLASH = 1<<4, // Splashed on the ground, return to the ceiling after the animation's over
PCF_THUNK = 1<<5, // Ran the thinker this tic.
} precipflag_t;
// Map Object definition.
typedef struct mobj_s
{
// List: thinker links.
thinker_t thinker;
mobjtype_t type;
const mobjinfo_t *info; // &mobjinfo[mobj->type]
// Info for drawing: position.
fixed_t x, y, z;
fixed_t old_x, old_y, old_z; // position interpolation
fixed_t old_x2, old_y2, old_z2;
mobjtype_t type;
const mobjinfo_t *info; // &mobjinfo[mobj->type]
// More list: links in sector (if needed)
struct mobj_s *bnext;
struct mobj_s **bprev; // killough 8/11/98: change to ptr-to-ptr
@@ -287,8 +288,7 @@ typedef struct mobj_s
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
UINT32 renderflags; // render flags
fixed_t spritexscale, spriteyscale;
fixed_t spritexoffset, spriteyoffset;
fixed_t old_spritexscale, old_spriteyscale;
@@ -420,14 +420,14 @@ typedef struct precipmobj_s
// List: thinker links.
thinker_t thinker;
mobjtype_t type;
const mobjinfo_t *info; // &mobjinfo[mobj->type]
// Info for drawing: position.
fixed_t x, y, z;
fixed_t old_x, old_y, old_z; // position interpolation
fixed_t old_x2, old_y2, old_z2;
mobjtype_t type;
const mobjinfo_t *info; // &mobjinfo[mobj->type]
// More list: links in sector (if needed)
struct precipmobj_s *bnext;
struct precipmobj_s **bprev; // killough 8/11/98: change to ptr-to-ptr
@@ -440,8 +440,7 @@ typedef struct precipmobj_s
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
UINT32 renderflags; // render flags
fixed_t spritexscale, spriteyscale;
fixed_t spritexoffset, spriteyoffset;
fixed_t old_spritexscale, old_spriteyscale;
@@ -450,7 +449,7 @@ typedef struct precipmobj_s
fixed_t realxscale, realyscale; // funn-E streeetch
fixed_t stretchslam; // "squish" effect when you land
//sloperollangle
angle_t sloperoll, slopepitch;
angle_t old_sloperoll, old_slopepitch;
+2 -1
View File
@@ -28,6 +28,7 @@
#include "r_main.h"
#include "r_state.h"
#include "r_defs.h"
#include "qs22j.h"
/*
@@ -580,7 +581,7 @@ static void Polyobj_findExplicit(polyobj_t *po)
// sort the array if necessary
if (numSegItems >= 2)
qsort(segitems, numSegItems, sizeof(segitem_t), Polyobj_segCompare);
qs22j(segitems, numSegItems, sizeof(segitem_t), Polyobj_segCompare);
// second loop: put the sorted segs into the polyobject
for (i = 0; i < numSegItems; ++i)
+15 -25
View File
@@ -3031,11 +3031,17 @@ static inline void P_FinishMobjs(void)
}
}
static inline mobj_t *RelinkMobj(mobj_t **ptr)
{
UINT32 temp = (UINT32)(size_t)*ptr;
*ptr = NULL;
return P_SetTarget(ptr, P_FindNewPosition(temp));
}
static void P_RelinkPointers(void)
{
thinker_t *currentthinker;
mobj_t *mobj;
UINT32 temp;
// use info field (value = oldposition) to relink mobjs
for (currentthinker = thinkercap.next; currentthinker != &thinkercap;
@@ -3051,58 +3057,42 @@ static void P_RelinkPointers(void)
if (mobj->tracer)
{
temp = (UINT32)(size_t)mobj->tracer;
mobj->tracer = NULL;
if (!P_SetTarget(&mobj->tracer, P_FindNewPosition(temp)))
if (!RelinkMobj(&mobj->tracer))
CONS_Debug(DBG_GAMELOGIC, "tracer not found on %d\n", mobj->type);
}
if (mobj->target)
{
temp = (UINT32)(size_t)mobj->target;
mobj->target = NULL;
if (!P_SetTarget(&mobj->target, P_FindNewPosition(temp)))
if (!RelinkMobj(&mobj->target))
CONS_Debug(DBG_GAMELOGIC, "target not found on %d\n", mobj->type);
}
if (mobj->hnext)
{
temp = (UINT32)(size_t)mobj->hnext;
mobj->hnext = NULL;
if (!P_SetTarget(&mobj->hnext, P_FindNewPosition(temp)))
if (!RelinkMobj(&mobj->hnext))
CONS_Debug(DBG_GAMELOGIC, "hnext not found on %d\n", mobj->type);
}
if (mobj->hprev)
{
temp = (UINT32)(size_t)mobj->hprev;
mobj->hprev = NULL;
if (!P_SetTarget(&mobj->hprev, P_FindNewPosition(temp)))
if (!RelinkMobj(&mobj->hprev))
CONS_Debug(DBG_GAMELOGIC, "hprev not found on %d\n", mobj->type);
}
if (mobj->player && mobj->player->capsule)
{
temp = (UINT32)(size_t)mobj->player->capsule;
mobj->player->capsule = NULL;
if (!P_SetTarget(&mobj->player->capsule, P_FindNewPosition(temp)))
if (!RelinkMobj(&mobj->player->capsule))
CONS_Debug(DBG_GAMELOGIC, "capsule not found on %d\n", mobj->type);
}
if (mobj->player && mobj->player->axis1)
{
temp = (UINT32)(size_t)mobj->player->axis1;
mobj->player->axis1 = NULL;
if (!P_SetTarget(&mobj->player->axis1, P_FindNewPosition(temp)))
if (!RelinkMobj(&mobj->player->axis1))
CONS_Debug(DBG_GAMELOGIC, "axis1 not found on %d\n", mobj->type);
}
if (mobj->player && mobj->player->axis2)
{
temp = (UINT32)(size_t)mobj->player->axis2;
mobj->player->axis2 = NULL;
if (!P_SetTarget(&mobj->player->axis2, P_FindNewPosition(temp)))
if (!RelinkMobj(&mobj->player->axis2))
CONS_Debug(DBG_GAMELOGIC, "axis2 not found on %d\n", mobj->type);
}
if (mobj->player && mobj->player->awayviewmobj)
{
temp = (UINT32)(size_t)mobj->player->awayviewmobj;
mobj->player->awayviewmobj = NULL;
if (!P_SetTarget(&mobj->player->awayviewmobj, P_FindNewPosition(temp)))
if (!RelinkMobj(&mobj->player->awayviewmobj))
CONS_Debug(DBG_GAMELOGIC, "awayviewmobj not found on %d\n", mobj->type);
}
}
+62 -11
View File
@@ -2487,6 +2487,61 @@ static boolean P_CanSave(void)
return false; // SRB2Kart: no SP, no saving.
}
struct minimapinfo minimapinfo;
static void P_InitMinimapInfo(void)
{
INT32 lumpnum;
fixed_t a;
fixed_t b;
node_t *bsp = &nodes[numnodes-1];
lumpnum = W_CheckNumForName(va("%sR", G_BuildMapName(gamemap)));
if (lumpnum != -1)
minimapinfo.minimap_pic = W_CachePatchName(va("%sR", G_BuildMapName(gamemap)), PU_HUDGFX);
minimapinfo.mapthingcount = 0;
// TODO iterate over mapthings to look for possible user-defined bounds
minimapinfo.min_x = bsp->bbox[0][BOXLEFT];
minimapinfo.max_x = bsp->bbox[0][BOXRIGHT];
minimapinfo.min_y = bsp->bbox[0][BOXBOTTOM];
minimapinfo.max_y = bsp->bbox[0][BOXTOP];
if (bsp->bbox[1][BOXLEFT] < minimapinfo.min_x)
minimapinfo.min_x = bsp->bbox[1][BOXLEFT];
if (bsp->bbox[1][BOXRIGHT] > minimapinfo.max_x)
minimapinfo.max_x = bsp->bbox[1][BOXRIGHT];
if (bsp->bbox[1][BOXBOTTOM] < minimapinfo.min_y)
minimapinfo.min_y = bsp->bbox[1][BOXBOTTOM];
if (bsp->bbox[1][BOXTOP] > minimapinfo.max_y)
minimapinfo.max_y = bsp->bbox[1][BOXTOP];
// You might be wondering why these are being bitshift here
// it's because mapwidth and height would otherwise overflow for maps larger than half the size possible...
// map boundaries and sizes will ALWAYS be whole numbers thankfully
// later calculations take into consideration that these are actually not in terms of FRACUNIT though
minimapinfo.map_w = (minimapinfo.max_x >>= FRACBITS) - (minimapinfo.min_x >>= FRACBITS);
minimapinfo.map_h = (minimapinfo.max_y >>= FRACBITS) - (minimapinfo.min_y >>= FRACBITS);
minimapinfo.minimap_w = minimapinfo.minimap_h = 100;
a = FixedDiv(minimapinfo.minimap_w<<FRACBITS, minimapinfo.map_w<<4);
b = FixedDiv(minimapinfo.minimap_h<<FRACBITS, minimapinfo.map_h<<4);
if (a < b)
{
minimapinfo.minimap_h = FixedMul(a, minimapinfo.map_h)>>(FRACBITS-4);
minimapinfo.zoom = a;
}
else
{
if (a != b)
{
minimapinfo.minimap_w = FixedMul(b, minimapinfo.map_w)>>(FRACBITS-4);
}
minimapinfo.zoom = b;
}
minimapinfo.zoom >>= (FRACBITS-4);
minimapinfo.zoom -= (minimapinfo.zoom/20);
// These should always be small enough to be bitshift back right now
minimapinfo.offs_x = FixedMul((minimapinfo.min_x + minimapinfo.map_w/2) << FRACBITS, minimapinfo.zoom);
minimapinfo.offs_y = FixedMul((minimapinfo.min_y + minimapinfo.map_h/2) << FRACBITS, minimapinfo.zoom);
}
/** Loads a level from a lump or external wad.
*
* \param skipprecip If true, don't spawn precipitation.
@@ -2532,9 +2587,6 @@ boolean P_SetupLevel(boolean skipprecip, boolean reloadinggamestate)
P_LevelInitStuff(reloadinggamestate);
for (i = 0; i <= splitscreen; i++)
postimgtype[i] = postimg_none;
if (mapheaderinfo[gamemap-1]->forcecharacter[0] != '\0'
&& atoi(mapheaderinfo[gamemap-1]->forcecharacter) != 255)
P_ForceCharacter(mapheaderinfo[gamemap-1]->forcecharacter);
@@ -2628,7 +2680,7 @@ boolean P_SetupLevel(boolean skipprecip, boolean reloadinggamestate)
// As oddly named as this is, this handles music only.
// We should be fine starting it here.
if (!reloadinggamestate)
S_Start();
S_InitMapMusic();
levelfadecol = (encoremode && !ranspecialwipe ? 122 : 120);
@@ -2738,6 +2790,8 @@ boolean P_SetupLevel(boolean skipprecip, boolean reloadinggamestate)
P_SpawnSecretItems(loademblems);
P_InitMinimapInfo();
for (numcoopstarts = 0; numcoopstarts < MAXPLAYERS; numcoopstarts++)
if (!playerstarts[numcoopstarts])
break;
@@ -2935,20 +2989,17 @@ boolean P_SetupLevel(boolean skipprecip, boolean reloadinggamestate)
savedata.lives = 0;
}
// assume the skybox is visible on level load.
skyVisible = true;
memset(skyVisiblePerPlayer, true, sizeof(skyVisiblePerPlayer));
if (loadprecip) // uglier hack
{ // to make a newly loaded level start on the second frame.
INT32 buf = gametic % TICQUEUE;
{
INT32 buf = gametic % TICQUEUE; // to make a newly loaded level start on the second frame.
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i])
G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1);
}
P_PreTicker(2);
LUAh_MapLoad();
if (!reloadinggamestate)
LUAh_MapLoad();
}
if (rendermode != render_none && !reloadinggamestate)
+60 -13
View File
@@ -99,6 +99,8 @@ typedef struct
thinker_t **thinkers;
} thinkerlist_t;
//static boolean fromlapexec = false;
static void P_SearchForDisableLinedefs(void);
static void P_SpawnScrollers(void);
static void P_SpawnFriction(void);
@@ -1340,6 +1342,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
fixed_t dist = P_AproxDistance(triggerline->dx, triggerline->dy)>>FRACBITS;
size_t i, linecnt, sectori;
INT16 specialtype = triggerline->special;
//fromlapexec = false;
/////////////////////////////////////////////////
// Distance-checking/sector trigger conditions //
@@ -1461,6 +1464,8 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
if (lap != (sides[triggerline->sidenum[0]].textureoffset >> FRACBITS))
return false;
}
//fromlapexec = true;
}
// If we were not triggered by a sector type especially for the purpose,
// a Linedef Executor linedef trigger is not handling sector triggers properly, return.
@@ -2113,12 +2118,12 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
return;
if (bot)
P_Teleport(bot, dest->x, dest->y, dest->z, (line->flags & ML_NOCLIMB) ? mo->angle : dest->angle, (line->flags & ML_BLOCKMONSTERS) == 0, (line->flags & ML_EFFECT4) == ML_EFFECT4);
P_Teleport(bot, dest->x, dest->y, dest->z, (line->flags & ML_NOCLIMB) ? mo->angle : dest->angle, (line->flags & ML_BLOCKMONSTERS) == 0, (line->flags & ML_EFFECT4) == ML_EFFECT4);
if (line->flags & ML_BLOCKMONSTERS)
P_Teleport(mo, dest->x, dest->y, dest->z, (line->flags & ML_NOCLIMB) ? mo->angle : dest->angle, false, (line->flags & ML_EFFECT4) == ML_EFFECT4);
P_Teleport(mo, dest->x, dest->y, dest->z, (line->flags & ML_NOCLIMB) ? mo->angle : dest->angle, false, (line->flags & ML_EFFECT4) == ML_EFFECT4);
else
{
P_Teleport(mo, dest->x, dest->y, dest->z, (line->flags & ML_NOCLIMB) ? mo->angle : dest->angle, true, (line->flags & ML_EFFECT4) == ML_EFFECT4);
P_Teleport(mo, dest->x, dest->y, dest->z, (line->flags & ML_NOCLIMB) ? mo->angle : dest->angle, true, (line->flags & ML_EFFECT4) == ML_EFFECT4);
// Play the 'bowrwoosh!' sound
S_StartSound(dest, sfx_mixup);
}
@@ -2127,6 +2132,12 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
break;
case 413: // Change music
if (keepmusic && (leveltime <= MUSICSTARTTIME)) //why check for starttime? cause encore music Zzz...
return;
//if (cv_ignoremusicchanges.value && (leveltime >= MUSICSTARTTIME) && !fromlapexec) // keep lap music intanct tho
//return;
// console player only unless NOCLIMB is set
if ((line->flags & ML_NOCLIMB) || (mo && mo->player && P_IsLocalPlayer(mo->player)))
{
@@ -2179,9 +2190,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
mapmusflags |= MUSIC_FORCERESET;
mapmusposition = position;
if (cv_birdmusic.value)
mapmusresume = 0;
mapmusresume = 0;
S_ChangeMusicEx(mapmusname, mapmusflags, !(line->flags & ML_EFFECT4), position,
!(line->flags & ML_EFFECT2) ? prefadems : 0,
@@ -2209,6 +2218,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
{
INT32 sfxnum;
//dont play any funky sound intros that may interfere with the music
if (skipintromus && (leveltime < MUSICSTARTTIME))
return;
sfxnum = sides[line->sidenum[0]].toptexture; //P_AproxDistance(line->dx, line->dy)>>FRACBITS;
if (sfxnum == sfx_None)
@@ -2485,6 +2498,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
case 422: // Cut away to another view
{
mobj_t *altview;
INT32 i;
if (!mo || !mo->player) // only players have views
return;
@@ -2499,6 +2513,18 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
P_SetTarget(&mo->player->awayviewmobj, altview);
mo->player->awayviewtics = P_AproxDistance(line->dx, line->dy)>>FRACBITS;
if (gamestate == GS_LEVEL)
{
for (i = 0; i <= splitscreen; i++)
{
if (displayplayers[i] == (mo->player - players))
{
R_ResetViewInterpolation(i + 1);
R_ResetViewInterpolation(i + 1);
}
}
}
if (line->flags & ML_NOCLIMB) // lets you specify a vertical angle
{
INT32 aim;
@@ -2836,17 +2862,19 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
case 444: // Earthquake camera
{
quake.intensity = sides[line->sidenum[0]].textureoffset;
quake.radius = sides[line->sidenum[0]].rowoffset;
quake.time = P_AproxDistance(line->dx, line->dy)>>FRACBITS;
fixed_t intensity = sides[line->sidenum[0]].textureoffset;
fixed_t radius = sides[line->sidenum[0]].rowoffset;
tic_t time = P_AproxDistance(line->dx, line->dy)>>FRACBITS;
quake.epicenter = NULL; /// \todo
// reasonable defaults.
if (!quake.intensity)
quake.intensity = 8<<FRACBITS;
if (!quake.radius)
quake.radius = 512<<FRACBITS;
if (intensity <= 0)
intensity = 8<<FRACBITS;
if (radius <= 0)
radius = 512<<FRACBITS;
P_StartQuake(time, intensity, radius);
break;
}
@@ -5308,6 +5336,8 @@ void P_SpawnSpecials(INT32 fromnetsave, boolean reloadinggamestate)
curWeather = PRECIP_STORM_NORAIN;
else if (mapheaderinfo[gamemap-1]->weather == 6) // storm w/o lightning
curWeather = PRECIP_STORM_NOSTRIKES;
else if (mapheaderinfo[gamemap-1]->weather == 4) // blank
curWeather = PRECIP_BLANK;
else
curWeather = PRECIP_NONE;
@@ -7544,6 +7574,23 @@ static void P_SpawnPushers(void)
}
}
void P_StartQuake(tic_t time, fixed_t intensity, fixed_t radius)
{
if (time <= 0 || intensity <= 0)
{
// Invalid parameters
return;
}
quake.time = time;
quake.intensity = FixedMul(intensity, mapobjectscale);
if (radius > 0)
{
quake.radius = FixedMul(radius, mapobjectscale);
}
}
static void P_SearchForDisableLinedefs(void)
{
size_t i;
+2
View File
@@ -454,4 +454,6 @@ void P_CalcHeight(player_t *player);
sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo);
void P_StartQuake(tic_t time, fixed_t intensity, fixed_t radius);
#endif
+1
View File
@@ -166,6 +166,7 @@ boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle
P_ResetCamera(thing->player, &camera[i]);
R_ResetViewInterpolation(i + 1);
break;
}
// don't run in place after a teleport
+46 -32
View File
@@ -287,7 +287,7 @@ mobj_t *P_SetTarget(mobj_t **mop, mobj_t *targ)
{
if (*mop) // If there was a target already, decrease its refcount
(*mop)->thinker.references--;
if ((*mop = targ) != NULL) // Set new target and if non-NULL, increase its counter
if ((*mop = targ) != NULL) // Set new target and if non-NULL, increase its counter
targ->thinker.references++;
return targ;
}
@@ -318,8 +318,12 @@ static inline void P_RunThinkers(void)
{
for (currentthinker = thinkercap.next; currentthinker != &thinkercap; currentthinker = currentthinker->next)
{
if (currentthinker->function.acp1)
currentthinker->function.acp1(currentthinker);
if (currentthinker->function.acp1 == (actionf_p1)P_NullPrecipThinker)
continue;
#ifdef PARANOIA
I_Assert(currentthinker->function.acp1 != NULL)
#endif
currentthinker->function.acp1(currentthinker);
}
}
@@ -393,6 +397,36 @@ void P_RunChaseCameras(void)
}
}
static inline void P_RunQuakes(void)
{
fixed_t ir;
if (quake.time <= 0)
{
quake.x = quake.y = quake.z = quake.roll = 0;
return;
}
ir = quake.intensity>>1;
/// \todo Calculate distance from epicenter if set and modulate the intensity accordingly based on radius.
quake.x = M_RandomRange(-ir,ir);
quake.y = M_RandomRange(-ir,ir);
quake.z = M_RandomRange(-ir,ir);
ir >>= 2;
ir = M_RandomRange(-ir,ir);
if (ir < 0)
ir = ANGLE_MAX - FixedAngle(-ir);
else
ir = FixedAngle(ir);
quake.roll = ir;
--quake.time;
}
//
// P_Ticker
//
@@ -425,6 +459,8 @@ void P_Ticker(boolean run)
if (demo.rewinding && leveltime > 0)
{
leveltime = (leveltime-1) & ~3;
if (timeinmap > 0)
timeinmap = (timeinmap-1) & ~3;
G_PreviewRewind(leveltime);
}
else if (demo.freecam && democam.cam) // special case: allow freecam to MOVE during pause!
@@ -433,9 +469,6 @@ void P_Ticker(boolean run)
return;
}
for (i = 0; i <= splitscreen; i++)
postimgtype[i] = postimg_none;
P_MapStart();
if (run)
@@ -583,24 +616,7 @@ void P_Ticker(boolean run)
K_CalculateBattleWanted();
}
if (quake.time)
{
fixed_t ir = quake.intensity>>1;
/// \todo Calculate distance from epicenter if set and modulate the intensity accordingly based on radius.
quake.x = M_RandomRange(-ir,ir);
quake.y = M_RandomRange(-ir,ir);
quake.z = M_RandomRange(-ir,ir);
ir >>= 2;
ir = M_RandomRange(-ir,ir);
if (ir < 0)
ir = ANGLE_MAX - FixedAngle(-ir);
else
ir = FixedAngle(ir);
quake.roll = ir;
--quake.time;
}
else
quake.x = quake.y = quake.z = quake.roll = 0;
P_RunQuakes();
if (metalplayback)
G_ReadMetalTic(metalplayback);
@@ -663,14 +679,17 @@ void P_Ticker(boolean run)
for (i = 0; i <= splitscreen; i++)
{
player_t *player = &players[displayplayers[i]];
boolean isSkyVisibleForPlayer = skyVisiblePerPlayer[i];
if (!player->mo)
continue;
if (isSkyVisibleForPlayer && skyboxmo[0] && cv_skybox.value)
const boolean skybox = (skyboxmo[0] && cv_skybox.value);
if (skybox)
{
R_SkyboxFrame(player);
}
R_SetupFrame(player, (skyboxmo[0] && cv_skybox.value));
R_SetupFrame(player);
}
}
}
@@ -679,8 +698,6 @@ void P_Ticker(boolean run)
if (demo.playback)
G_StoreRewindInfo();
// Z_CheckMemCleanup();
}
// Abbreviated ticker for pre-loading, calls thinkers and assorted things
@@ -689,9 +706,6 @@ void P_PreTicker(INT32 frames)
INT32 i;
ticcmd_t temptic;
for (i = 0; i <= splitscreen; i++)
postimgtype[i] = postimg_none;
hook_defrosting = frames;
while (hook_defrosting)
+36 -43
View File
@@ -742,9 +742,8 @@ void P_RestoreMusic(player_t *player)
if (P_EndingMusic(player))
return;
// Event - Level Start
if (leveltime < (starttime + (TICRATE/2)))
S_ChangeMusicInternal((encoremode ? "estart" : "kstart"), false); //S_StopMusic();
if (leveltime < MUSICSTARTTIME)
S_StartMapMusic(true);
else // see also where time overs are handled - search for "lives = 2" in this file
{
INT32 wantedmus = 0; // 0 is level music, 1 is invincibility, 2 is grow
@@ -800,19 +799,13 @@ void P_RestoreMusic(player_t *player)
if (G_RaceGametype() && player->laps >= (UINT8)(cv_numlaps.value - 1))
S_SpeedMusic(1.2f);
#endif
if (cv_birdmusic.value)
{
if (mapmusresume && cv_resume.value)
position = mapmusresume;
else
position = mapmusposition;
S_ChangeMusicEx(mapmusname, mapmusflags, true, position, 0, S_GetRestoreMusicFadeIn());
S_ClearRestoreMusicFadeInCvar();
}
if (mapmusresume && cv_resume.value) // mapmusresume will be 0 anyways when birdmusic stuff is disabled
position = mapmusresume;
else
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
position = mapmusposition;
S_ChangeMusicEx(mapmusname, mapmusflags, true, position, 0, S_GetRestoreMusicFadeIn());
S_ClearRestoreMusicFadeInCvar();
mapmusresume = 0;
}
}
@@ -1041,7 +1034,7 @@ fixed_t P_GetPlayerSpinHeight(player_t *player)
// Returns true if player is
// on the local machine.
//
boolean P_IsLocalPlayer(player_t *player)
boolean P_IsLocalPlayer(const player_t *player)
{
UINT8 i;
@@ -1065,7 +1058,7 @@ boolean P_IsLocalPlayer(player_t *player)
// Returns true if player is
// currently being watched.
//
boolean P_IsDisplayPlayer(player_t *player)
boolean P_IsDisplayPlayer(const player_t *player)
{
UINT8 i;
@@ -1179,6 +1172,7 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj)
ghost = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_GHOST);
P_SetScale(ghost, mobj->scale);
ghost->scalespeed = mobj->scalespeed;
ghost->destscale = mobj->scale;
if (mobj->eflags & MFE_VERTICALFLIP)
@@ -1230,6 +1224,7 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj)
ghost->old_roll = mobj->old_roll2;
ghost->old_sloperoll = mobj->old_sloperoll2;
ghost->old_slopepitch = mobj->old_slopepitch2;
ghost->old_scale = mobj->old_scale2;
return ghost;
}
@@ -1254,7 +1249,7 @@ void P_DoPlayerExit(player_t *player)
player->exiting = raceexittime+2;
K_KartUpdatePosition(player);
if (cv_kartvoices.value)
if (!P_MobjWasRemoved(player->mo) && cv_kartvoices.value)
{
if (P_IsLocalPlayer(player))
{
@@ -4111,8 +4106,8 @@ boolean P_SpectatorJoinGame(player_t *player)
static void P_CalcPostImg(player_t *player)
{
sector_t *sector = player->mo->subsector->sector;
postimg_t *type = NULL;
INT32 *param;
INT16 typeflag = 0;
//INT32 *param;
fixed_t pviewheight;
UINT8 i;
@@ -4127,20 +4122,19 @@ static void P_CalcPostImg(player_t *player)
pviewheight = player->awayviewmobj->z + 20*FRACUNIT;
}
for (i = 0; i <= splitscreen; i++)
/*for (i = 0; i <= splitscreen; i++)
{
if (player == &players[displayplayers[i]])
{
type = &postimgtype[i];
param = &postimgparam[i];
break;
}
}
}*/
// see if we are in heat (no, not THAT kind of heat...)
if (P_FindSpecialLineFromTag(13, sector->tag, -1) != -1)
*type = postimg_heat;
typeflag |= POSTIMG_HEAT;
else if (sector->ffloors)
{
ffloor_t *rover;
@@ -4159,7 +4153,7 @@ static void P_CalcPostImg(player_t *player)
continue;
if (P_FindSpecialLineFromTag(13, rover->master->frontsector->tag, -1) != -1)
*type = postimg_heat;
typeflag |= POSTIMG_HEAT;
}
}
@@ -4181,36 +4175,35 @@ static void P_CalcPostImg(player_t *player)
if (pviewheight >= topheight || pviewheight <= bottomheight)
continue;
*type = postimg_water;
typeflag |= POSTIMG_WATER;
}
}
if (!encoremode) // srb2kart
{
if (player->mo->eflags & MFE_VERTICALFLIP)
*type = postimg_flip;
}
else
{
if (player->mo->eflags & MFE_VERTICALFLIP)
*type = postimg_mirrorflip;
else
*type = postimg_mirror;
}
if (encoremode) // srb2kart
typeflag |= POSTIMG_MIRROR;
if (player->mo->eflags & MFE_VERTICALFLIP)
typeflag |= POSTIMG_FLIP;
#if 1
(void)param;
#else
// Motion blur
if (player->speed > (35<<FRACBITS))
// unused
/*if (player->speed > (35<<FRACBITS))
{
*type = postimg_motion;
typeflag |= POSTIMG_MOTION;
*param = (player->speed - 32)/4;
if (*param > 5)
*param = 5;
}*/
for (i = 0; i <= splitscreen; i++)
{
if (player != &players[displayplayers[i]])
continue;
players[displayplayers[i]].postimgflags = typeflag;
break;
}
#endif
}
void P_DoTimeOver(player_t *player)
+138 -138
View File
@@ -18,13 +18,15 @@
#include <stdint.h>
#include "qs22j.h"
#define INSORTTHRESH 5 // if n < this use insertion sort
// MUST be >= 2
#define MIDTHRESH 20 // < this use middle as pivot
#define MEDOF3THRESH 50 // < this use median-of-3 as pivot
// larger subfiles use med-of-3-medians
#define INSORTTHRESH 5 // if n < this use insertion sort
// MUST be >= 2
#define MIDTHRESH 20 // < this use middle as pivot
#define MEDOF3THRESH 50 // < this use median-of-3 as pivot
// larger subfiles use med-of-3-medians
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
typedef int32_t WORD;
typedef int64_t DWORD;
@@ -37,242 +39,240 @@ typedef void *pref_typ;
#define ASWAP(a, b, t) ((void)(t = a, a = b, b = t))
#define SWAP(a, b) if (swap_type) swapf(a, b, size);\
else do {pref_typ t; ASWAP(*(pref_typ*)(a), *(pref_typ*)(b), t);} while (0)
else do {pref_typ t; ASWAP(*(pref_typ*)(a), *(pref_typ*)(b), t);} while (0)
#define COMP(a, b) ((*compar)((void *)(a), (void *)(b)))
#define COMP(a, b) ((*compar)((void *)(a), (void *)(b)))
static inline void swapbytes(void *a0, void *b0, size_t n)
{
char *a = a0, *b = b0, t;
do {ASWAP(*a, *b, t); a++; b++;} while (--n);
char *a = a0, *b = b0, t;
do {ASWAP(*a, *b, t); a++; b++;} while (--n);
}
static inline void swapdword(void *a0, void *b0, size_t n)
{
DWORD *a = a0, *b = b0, t;
ASWAP(*a, *b, t);
(void)n;
(void)n;
DWORD *a = a0, *b = b0, t;
ASWAP(*a, *b, t);
}
static inline void swapdwords(void *a0, void *b0, size_t n)
{
DWORD *a = a0, *b = b0, t;
do {ASWAP(*a, *b, t); a++; b++;} while (n -= sizeof(DWORD));
DWORD *a = a0, *b = b0, t;
do {ASWAP(*a, *b, t); a++; b++;} while (n -= sizeof(DWORD));
}
static inline void swapword(void *a0, void *b0, size_t n)
{
WORD *a = a0, *b = b0, t;
ASWAP(*a, *b, t);
(void)n;
(void)n;
WORD *a = a0, *b = b0, t;
ASWAP(*a, *b, t);
}
static inline void swapwords(void *a0, void *b0, size_t n)
{
WORD *a = a0, *b = b0, t;
do {ASWAP(*a, *b, t); a++; b++;} while (n -= sizeof(WORD));
WORD *a = a0, *b = b0, t;
do {ASWAP(*a, *b, t); a++; b++;} while (n -= sizeof(WORD));
}
typedef void (*swapf_typ)(void *, void *, size_t);
static inline char *med3(char *a, char *b, char *c, int (*compar)(const void *, const void *))
{
return COMP(a, b) < 0 ?
(COMP(b, c) < 0 ? b : COMP(a, c) < 0 ? c : a) :
(COMP(b, c) > 0 ? b : COMP(a, c) > 0 ? c : a);
return COMP(a, b) < 0 ?
(COMP(b, c) < 0 ? b : COMP(a, c) < 0 ? c : a) :
(COMP(b, c) > 0 ? b : COMP(a, c) > 0 ? c : a);
}
void qs22j(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *))
{
char *stack[2*8*sizeof(size_t)], **sp = stack; // stack and stack pointer
char *left = base; // set up char * base pointer
char *limit = left + nmemb * size; // pointer past end of array
char *i, *ii, *j, *jj; // scan pointers
int ki = 0, kj = 0;
int swap_type = 1;
swapf_typ swapf, vecswapf;
char *stack[2*8*sizeof(size_t)], **sp = stack; // stack and stack pointer
char *left = base; // set up char * base pointer
char *limit = left + nmemb * size; // pointer past end of array
char *i, *ii, *j, *jj; // scan pointers
int ki = 0, kj = 0;
int swap_type = 1;
swapf_typ swapf, vecswapf;
vecswapf = swapf = swapbytes;
if ((ptr_to_int(left) | size) % sizeof(WORD))
vecswapf = swapf = swapbytes;
if ((ptr_to_int(left) | size) % sizeof(WORD))
{
; // unaligned or not multple of WORD size; swap bytes
}
; // unaligned or not multple of WORD size; swap bytes
}
else if (size == sizeof(DWORD))
{
swapf = swapdword;
vecswapf = swapdwords;
if (size == sizeof(pref_typ))
swap_type = 0;
}
swapf = swapdword;
vecswapf = swapdwords;
if (size == sizeof(pref_typ))
swap_type = 0;
}
else if (size == sizeof(WORD))
{
swapf = swapword;
vecswapf = swapwords;
if (size == sizeof(pref_typ))
swap_type = 0;
swapf = swapword;
vecswapf = swapwords;
if (size == sizeof(pref_typ))
swap_type = 0;
}
else if ((size % sizeof(DWORD)) == 0)
{
swapf = vecswapf = swapdwords;
}
swapf = vecswapf = swapdwords;
}
else if ((size % sizeof(WORD)) == 0)
{
swapf = vecswapf = swapwords;
}
for (;;)
swapf = vecswapf = swapwords;
}
for (;;)
{
nmemb = (limit - left) / size;
for (i = left + size; i < limit && COMP(i - size, i) <= 0; i += size)
;
nmemb = (limit - left) / size;
for (i = left + size; i < limit && COMP(i - size, i) <= 0; i += size)
;
if (i == limit) // if already in order
goto pop;
if (i == limit) // if already in order
goto pop;
if (nmemb >= INSORTTHRESH) // otherwise use insertion sort
if (nmemb >= INSORTTHRESH) // otherwise use insertion sort
{
char *right = limit - size;
// best so far? fewer compares, a few more swaps
char *p = left + (nmemb / 2) * size;
if (nmemb >= MIDTHRESH)
char *right = limit - size;
// best so far? fewer compares, a few more swaps
char *p = left + (nmemb / 2) * size;
if (nmemb >= MIDTHRESH)
{
char *pleft = left + size;
char *pright = right - size;
char *pleft = left + size;
char *pright = right - size;
if (nmemb >= MEDOF3THRESH)
if (nmemb >= MEDOF3THRESH)
{
size_t k = (nmemb / 8) * size;
pleft = med3(pleft, left + k, left + k * 2, compar);
p = med3(p - k, p, p + k, compar);
pright = med3(right - k * 2, right - k, pright, compar);
}
size_t k = (nmemb / 8) * size;
pleft = med3(pleft, left + k, left + k * 2, compar);
p = med3(p - k, p, p + k, compar);
pright = med3(right - k * 2, right - k, pright, compar);
}
p = med3(pleft, p, pright, compar);
}
p = med3(pleft, p, pright, compar);
}
i = ii = left; // i scans left to right
j = jj = right; // j scans right to left
i = ii = left; // i scans left to right
j = jj = right; // j scans right to left
for (;;)
{
while (i <= j)
{
if (i != p && ((ki = COMP(i, p)) >= 0))
{
if (ki)
break;
if (ki)
break;
if (ii == p)
{
p = i;
p = i;
}
else if (i != ii)
{
SWAP(i, ii);
SWAP(i, ii);
}
ii += size;
}
i += size;
}
ii += size;
}
i += size;
}
while (i < j)
while (i < j)
{
if (j != p && ((kj = COMP(j, p)) <= 0))
if (j != p && ((kj = COMP(j, p)) <= 0))
{
if (kj)
break;
if (kj)
break;
if (jj == p)
if (jj == p)
{
p = j;
p = j;
}
else if (j != jj)
else if (j != jj)
{
SWAP(j, jj);
SWAP(j, jj);
}
jj -= size;
}
j -= size;
}
jj -= size;
}
j -= size;
}
if (i >= j)
break;
if (i >= j)
break;
SWAP(i, j);
i += size;
j -= size;
}
SWAP(i, j);
i += size;
j -= size;
}
if (p < i)
i -= size;
if (p < i)
i -= size;
if (p != i)
{
SWAP(p, i);
}
ptrdiff_t lessthan = i - ii;
size_t k = min(lessthan, ii - left);
ptrdiff_t lessthan = i - ii;
size_t k = min(lessthan, ii - left);
if (k)
vecswapf(left, i - k, k);
if (k)
vecswapf(left, i - k, k);
ptrdiff_t morethan = jj - i;
k = min(morethan, right - jj);
ptrdiff_t morethan = jj - i;
k = min(morethan, right - jj);
if (k)
vecswapf(i + size, limit - k, k);
if (k)
vecswapf(i + size, limit - k, k);
if (lessthan > morethan)
if (lessthan > morethan)
{
if (lessthan > 1)
if (lessthan > 1)
{
sp[0] = left;
sp[1] = left + lessthan;
sp += 2; // increment stack pointer
}
sp[0] = left;
sp[1] = left + lessthan;
sp += 2; // increment stack pointer
}
if (morethan <= 1)
goto pop;
if (morethan <= 1)
goto pop;
left = limit - morethan;
left = limit - morethan;
}
else
{
if (morethan > 1)
if (morethan > 1)
{
sp[0] = limit - morethan;
sp[1] = limit;
sp += 2; // increment stack pointer
}
sp[0] = limit - morethan;
sp[1] = limit;
sp += 2; // increment stack pointer
}
if (lessthan <= 1)
goto pop;
if (lessthan <= 1)
goto pop;
limit = left + lessthan;
}
}
limit = left + lessthan;
}
}
else // else subfile is small, use insertion sort
{
for (i = left + size; i < limit; i += size)
for (i = left + size; i < limit; i += size)
{
for (j = i; j != left && COMP(j - size, j) > 0; j -= size)
for (j = i; j != left && COMP(j - size, j) > 0; j -= size)
{
SWAP(j - size, j);
}
}
SWAP(j - size, j);
}
}
pop:
if (sp != stack) // if any entries on stack
if (sp != stack) // if any entries on stack
{
sp -= 2; // pop the left and limit
left = sp[0];
limit = sp[1];
}
else // else stack empty, done
break;
sp -= 2; // pop the left and limit
left = sp[0];
limit = sp[1];
}
else // else stack empty, done
break;
}
}
}
+16 -2
View File
@@ -1,7 +1,21 @@
// License: 0BSD
//
// Copyright 2022 Raymond Gardner
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
#ifndef __QS22J__
#define __QS22J__
void qs22j(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
#endif
+7 -6
View File
@@ -15,6 +15,7 @@
#include "g_game.h"
#include "r_local.h"
#include "r_state.h"
#include "r_portal.h" // Add seg portals
#include "r_splats.h"
#include "p_local.h" // camera
@@ -28,11 +29,11 @@ side_t *sidedef;
line_t *linedef;
sector_t *frontsector;
sector_t *backsector;
boolean portalline; // is curline a portal seg?
// very ugly realloc() of drawsegs at run-time, I upped it to 512
// instead of 256.. and someone managed to send me a level with
// 896 drawsegs! So too bad here's a limit removal a-la-Boom
drawseg_t *curdrawsegs = NULL; /**< This is used to handle multiple lists for masked drawsegs. */
drawseg_t *drawsegs = NULL;
drawseg_t *ds_p = NULL;
@@ -417,7 +418,7 @@ static void R_AddLine(seg_t *line)
angle_t angle1, angle2, span, tspan;
static sector_t tempsec;
portalline = false;
g_portal = NULL;
if (line->polyseg && !(line->polyseg->flags & POF_RENDERSIDES))
return;
@@ -486,7 +487,7 @@ static void R_AddLine(seg_t *line)
line2 = P_FindSpecialLineFromTag(40, line->linedef->tag, line2);
if (line2 >= 0) // found it!
{
R_AddPortal(line->linedef-lines, line2, x1, x2); // Remember the lines for later rendering
Portal_Add2Lines(line->linedef-lines, line2, x1, x2); // Remember the lines for later rendering
//return; // Don't fill in that space now!
goto clipsolid;
}
@@ -1319,7 +1320,8 @@ void R_RenderBSPNode(INT32 bspnum)
bsp = &nodes[bspnum];
// Decide which side the view point is on.
side = R_PointOnSide(viewx, viewy, bsp);
side = R_PointOnSideRender(viewx, viewy, bsp);
// Recursively divide front space.
R_RenderBSPNode(bsp->children[side]);
@@ -1333,8 +1335,7 @@ void R_RenderBSPNode(INT32 bspnum)
// PORTAL CULLING
if (portalcullsector)
{
sector_t *sect = subsectors[bspnum & ~NF_SUBSECTOR].sector;
if (sect != portalcullsector)
if (subsectors[bspnum & ~NF_SUBSECTOR].sector != portalcullsector)
return;
portalcullsector = NULL;
}
+5 -2
View File
@@ -18,17 +18,21 @@
#pragma interface
#endif
#include "r_main.h"
extern seg_t *curline;
extern side_t *sidedef;
extern line_t *linedef;
extern sector_t *frontsector;
extern sector_t *backsector;
extern boolean portalline; // is curline a portal seg?
typedef struct portal_s portal_t;
extern portal_t *g_portal; // is curline a portal seg?
// drawsegs are allocated on the fly... see r_segs.c
extern INT32 checkcoord[12][4];
extern drawseg_t *curdrawsegs;
extern drawseg_t *drawsegs;
extern drawseg_t *ds_p;
extern INT32 doorclosed;
@@ -39,7 +43,6 @@ void R_ClearClipSegs(void);
void R_PortalClearClipSegs(INT32 start, INT32 end);
void R_ClearDrawSegs(void);
void R_RenderBSPNode(INT32 bspnum);
void R_AddPortal(INT32 line1, INT32 line2, INT32 x1, INT32 x2);
// determines when a given sector shouldn't abide by the encoremap's palette.
// no longer a static since this is used for encore in hw_main.c as well now:
-8
View File
@@ -687,14 +687,6 @@ typedef struct
#pragma pack()
#endif
typedef enum // trimmed since its only real use here is for xscale/yscale
{
RF_HORIZONTALFLIP = 0x0001, // Flip sprite horizontally
RF_VERTICALFLIP = 0x0002, // Flip sprite vertically
RF_ABSOLUTEOFFSETS = 0x0004, // Sprite uses the object's offsets absolutely, instead of relatively
RF_FLIPOFFSETS = 0x0008, // Relative object offsets are flipped with the sprite
} renderflags_t;
typedef enum
{
SRF_SINGLE = 0, // 0-angle for all rotations
+1
View File
@@ -78,6 +78,7 @@ fixed_t dc_iscale, dc_texturemid;
UINT8 dc_hires; // under MSVC boolean is a byte, while on other systems, it a bit,
// soo lets make it a byte on all system for the ASM code
UINT8 *dc_source;
INT32 dc_sourcelength;
// -----------------------
// translucency stuff here
+1
View File
@@ -62,6 +62,7 @@ extern lighttable_t *ds_colormap;
extern fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep;
extern INT32 ds_waterofs, ds_bgofs;
extern UINT8 *ds_source; // start of a 64*64 tile image
extern INT32 dc_sourcelength;
extern UINT8 *ds_transmap;
extern INT32 ds_bgofs;
+288 -267
View File
File diff suppressed because it is too large. Load diff
+129 -306
View File
@@ -31,6 +31,7 @@
#include "p_spec.h" // skyboxmo
#include "z_zone.h"
#include "m_random.h" // quake camera shake
#include "r_portal.h"
#include "doomstat.h" // MAXSPLITSCREENPLAYERS
#include "r_fps.h" // Frame interpolation/uncapped
#include "tables.h"
@@ -61,38 +62,11 @@ fixed_t viewx, viewy, viewz;
angle_t viewangle, aimingangle, viewroll;
UINT8 viewssnum;
fixed_t viewcos, viewsin;
boolean skyVisible;
boolean skyVisiblePerPlayer[MAXSPLITSCREENPLAYERS]; // saved values of skyVisible for each splitscreen player
sector_t *viewsector;
player_t *viewplayer;
// PORTALS!
// You can thank and/or curse JTE for these.
UINT8 portalrender;
sector_t *portalcullsector;
typedef struct portal_pair
{
INT32 line1;
INT32 line2;
UINT8 pass;
struct portal_pair *next;
fixed_t viewx;
fixed_t viewy;
fixed_t viewz;
angle_t viewangle;
INT32 start;
INT32 end;
INT16 *ceilingclip;
INT16 *floorclip;
fixed_t *frontscale;
} portal_pair;
portal_pair *portal_base, *portal_cap;
line_t *portalclipline;
INT32 portalclipstart, portalclipend;
fixed_t rendertimefrac;
fixed_t rendertimefrac_unpaused;
fixed_t renderdeltatics;
boolean renderisnewtic;
@@ -173,10 +147,6 @@ static CV_PossibleValue_t maxportals_cons_t[] = {{0, "MIN"}, {12, "MAX"}, {0, NU
static CV_PossibleValue_t homremoval_cons_t[] = {{0, "No"}, {1, "Yes"}, {2, "Flash"}, {0, NULL}};
static void Fov_OnChange(void);
static void ChaseCam_OnChange(void);
static void ChaseCam2_OnChange(void);
static void ChaseCam3_OnChange(void);
static void ChaseCam4_OnChange(void);
static void FlipCam_OnChange(void);
static void FlipCam2_OnChange(void);
static void FlipCam3_OnChange(void);
@@ -189,10 +159,10 @@ void SendWeaponPref4(void);
static void Precipstuff_OnChange(void);
consvar_t cv_tailspickup = {"tailspickup", "On", CV_NETVAR|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chasecam = {"chasecam", "On", CV_CALL, CV_OnOff, ChaseCam_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chasecam2 = {"chasecam2", "On", CV_CALL, CV_OnOff, ChaseCam2_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chasecam3 = {"chasecam3", "On", CV_CALL, CV_OnOff, ChaseCam3_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chasecam4 = {"chasecam4", "On", CV_CALL, CV_OnOff, ChaseCam4_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chasecam = {"chasecam", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chasecam2 = {"chasecam2", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chasecam3 = {"chasecam3", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chasecam4 = {"chasecam4", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_flipcam = {"flipcam", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_flipcam2 = {"flipcam2", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam2_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_flipcam3 = {"flipcam3", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam3_OnChange, 0, NULL, NULL, 0, 0, NULL};
@@ -217,6 +187,8 @@ consvar_t cv_mobjscaleprecip = {"scaleprecipmobjscale", "Off", CV_SAVE|CV_CALL|C
consvar_t cv_grmaxinterpdist = {"gr_maxinterpdist", "Infinite", CV_SAVE, maxinterpdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ripplewater = {"waterripples", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
// cap fov, fov too high tears software apart.
consvar_t cv_fov = {"fov", "90", CV_FLOAT|CV_CALL|CV_SAVE, fov_cons_t, Fov_OnChange, 0, NULL, NULL, 0, 0, NULL};
@@ -272,47 +244,9 @@ void SplitScreen_OnChange(void)
}
static void Fov_OnChange(void)
{
// Shouldn't be needed with render parity?
//if ((netgame || multiplayer) && !cv_debug && cv_fov.value != 90*FRACUNIT)
// CV_Set(&cv_fov, cv_fov.defaultvalue);
R_SetViewSize();
}
static void ChaseCam_OnChange(void)
{
/*if (!cv_chasecam.value || !cv_useranalog.value)
CV_SetValue(&cv_analog, 0);
else
CV_SetValue(&cv_analog, 1);*/
}
static void ChaseCam2_OnChange(void)
{
if (botingame)
return;
/*if (!cv_chasecam2.value || !cv_useranalog2.value)
CV_SetValue(&cv_analog2, 0);
else
CV_SetValue(&cv_analog2, 1);*/
}
static void ChaseCam3_OnChange(void)
{
/*if (!cv_chasecam3.value || !cv_useranalog3.value)
CV_SetValue(&cv_analog3, 0);
else
CV_SetValue(&cv_analog3, 1);*/
}
static void ChaseCam4_OnChange(void)
{
/*if (!cv_chasecam4.value || !cv_useranalog4.value)
CV_SetValue(&cv_analog4, 0);
else
CV_SetValue(&cv_analog4, 1);*/
}
static void FlipCam_OnChange(void)
{
SendWeaponPref();
@@ -382,29 +316,6 @@ PUREFUNC INT32 R_PointOnSide(fixed_t x, fixed_t y, const node_t *restrict node)
(~mask & (FixedMul(y, node->dx>>FRACBITS) >= FixedMul(node->dy>>FRACBITS, x)));
}
// killough 5/2/98: reformatted
PUREFUNC INT32 R_PointOnSegSide(fixed_t x, fixed_t y, const seg_t *line)
{
fixed_t lx = line->v1->x;
fixed_t ly = line->v1->y;
fixed_t ldx = line->v2->x - lx;
fixed_t ldy = line->v2->y - ly;
if (!ldx)
return x <= lx ? ldy > 0 : ldy < 0;
if (!ldy)
return y <= ly ? ldx < 0 : ldx > 0;
x -= lx;
y -= ly;
// Try to quickly decide by looking at sign bits.
if ((ldy ^ ldx ^ x ^ y) < 0)
return (ldy ^ x) < 0; // (left is negative)
return FixedMul(y, ldx>>FRACBITS) >= FixedMul(ldy>>FRACBITS, x);
}
//
// R_PointToAngle
// To get a global angle from cartesian coordinates,
@@ -516,6 +427,11 @@ INT32 R_GetHudUncap(void)
return cv_uncappedhud.value ? rendertimefrac & FRACMASK : 0;
}
INT32 R_GetMenuUncap(void)
{
return cv_uncappedhud.value ? rendertimefrac_unpaused & FRACMASK : 0;
}
//
// R_ScaleFromGlobalAngle
// Returns the texture mapping scale for the current line (horizontal span)
@@ -1037,6 +953,16 @@ void R_ExecuteSetViewSize(void)
R_InitTextureMapping();
// why did we calc all the software crap?
#ifdef HWRENDER
if (rendermode == render_opengl)
{
HWR_SetViewSize();
am_recalc = true;
return;
}
#endif
// thing clipping
for (i = 0; i < viewwidth; i++)
screenheightarray[i] = (INT16)viewheight;
@@ -1045,27 +971,24 @@ void R_ExecuteSetViewSize(void)
R_SetSkyScale();
// planes
if (rendermode == render_soft)
// this is only used for planes rendering in software mode
j = viewheight*16;
for (i = 0; i < j; i++)
{
// this is only used for planes rendering in software mode
j = viewheight*16;
for (i = 0; i < j; i++)
{
dy = (i - viewheight*8)<<FRACBITS;
dy = FixedMul(abs(dy), fovtan);
yslopetab[i] = FixedDiv(centerx*FRACUNIT, dy);
}
if (ds_su)
Z_Free(ds_su);
if (ds_sv)
Z_Free(ds_sv);
if (ds_sz)
Z_Free(ds_sz);
ds_su = ds_sv = ds_sz = NULL;
ds_sup = ds_svp = ds_szp = NULL;
dy = (i - viewheight*8)<<FRACBITS;
dy = FixedMul(abs(dy), fovtan);
yslopetab[i] = FixedDiv(centerx*FRACUNIT, dy);
}
if (ds_su)
Z_Free(ds_su);
if (ds_sv)
Z_Free(ds_sv);
if (ds_sz)
Z_Free(ds_sz);
ds_su = ds_sv = ds_sz = NULL;
ds_sup = ds_svp = ds_szp = NULL;
memset(scalelight, 0xFF, sizeof(scalelight));
@@ -1087,12 +1010,6 @@ void R_ExecuteSetViewSize(void)
}
}
// continue to do the software setviewsize as long as we use the reference software view
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_SetViewSize();
#endif
am_recalc = true;
}
@@ -1407,13 +1324,10 @@ void R_SkyboxFrame(player_t *player)
else
newview->sector = R_PointInSubsector(newview->x, newview->y)->sector;
// newview->sin = FINESINE(viewangle>>ANGLETOFINESHIFT);
// newview->cos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
R_InterpolateView(R_UsingFrameInterpolation() ? rendertimefrac : FRACUNIT, false);
R_InterpolateView(R_UsingFrameInterpolation() ? (demo.playback && demo.freecam) ? rendertimefrac_unpaused : rendertimefrac : FRACUNIT, false);
}
void R_SetupFrame(player_t *player, boolean skybox)
void R_SetupFrame(player_t *player)
{
camera_t *thiscam;
boolean chasecam = false;
@@ -1476,26 +1390,24 @@ void R_SetupFrame(player_t *player, boolean skybox)
else if (thiscam && !chasecam)
thiscam->chase = false;
newview->sky = !skybox;
if (player->awayviewtics)
newview->sky = false;
if (player->awayviewtics) // cut-away view stuff
{
// cut-away view stuff
viewmobj = player->awayviewmobj; // should be a MT_ALTVIEWMAN
I_Assert(viewmobj != NULL);
newview->z = viewmobj->z + 20*FRACUNIT;
newview->aim = player->awayviewaiming;
newview->angle = viewmobj->angle;
}
else if (!player->spectator && (thiscam && chasecam))
// use outside cam view
else if (!player->spectator && (thiscam && chasecam)) // use outside cam view
{
viewmobj = NULL;
newview->z = thiscam->z + (thiscam->height>>1);
newview->aim = thiscam->aiming;
newview->angle = thiscam->angle;
}
else
// use the player's eyes view
else // use the player's eyes view
{
newview->z = player->viewz;
@@ -1557,121 +1469,52 @@ void R_SetupFrame(player_t *player, boolean skybox)
newview->sector = R_PointInSubsector(newview->x, newview->y)->sector;
}
// newview->sin = FINESINE(viewangle>>ANGLETOFINESHIFT);
// newview->cos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
R_InterpolateView(R_UsingFrameInterpolation() ? rendertimefrac : FRACUNIT, false);
R_InterpolateView(R_UsingFrameInterpolation() ? (demo.playback && demo.freecam) ? rendertimefrac_unpaused : rendertimefrac : FRACUNIT, false);
}
#define ANGLED_PORTALS
static void R_PortalFrame(line_t *start, line_t *dest, portal_pair *portal)
static void R_PortalFrame(portal_t *portal)
{
vertex_t dest_c, start_c;
#ifdef ANGLED_PORTALS
// delta angle
angle_t dangle = R_PointToAngle2(0,0,dest->dx,dest->dy) - R_PointToAngle2(start->dx,start->dy,0,0);
#endif
//R_SetupFrame(player, false);
viewx = portal->viewx;
viewy = portal->viewy;
viewz = portal->viewz;
viewangle = portal->viewangle;
// newview->sin = FINESINE(newview->angle>>ANGLETOFINESHIFT);
// newview->cos = FINECOSINE(newview->angle>>ANGLETOFINESHIFT);
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
portalcullsector = dest->frontsector;
viewsector = dest->frontsector;
portalclipline = dest;
portalclipstart = portal->start;
portalclipend = portal->end;
// Offset the portal view by the linedef centers
// looking glass center
start_c.x = (start->v1->x + start->v2->x) / 2;
start_c.y = (start->v1->y + start->v2->y) / 2;
// other side center
dest_c.x = (dest->v1->x + dest->v2->x) / 2;
dest_c.y = (dest->v1->y + dest->v2->y) / 2;
// Heights!
viewz += dest->frontsector->floorheight - start->frontsector->floorheight;
// calculate the difference in position and rotation!
#ifdef ANGLED_PORTALS
if (dangle == 0)
#endif
{ // the entrance goes straight opposite the exit, so we just need to mess with the offset.
viewx += dest_c.x - start_c.x;
viewy += dest_c.y - start_c.y;
return;
}
#ifdef ANGLED_PORTALS
viewangle += dangle;
// newview->sin = FINESINE(newview->angle>>ANGLETOFINESHIFT);
// newview->cos = FINECOSINE(newview->angle>>ANGLETOFINESHIFT);
//CONS_Printf("dangle == %u\n", AngleFixed(dangle)>>FRACBITS);
// ????
if (portal->clipline != -1)
{
fixed_t disttopoint;
angle_t angtopoint;
disttopoint = R_PointToDist2(start_c.x, start_c.y, newview->x, newview->y);
angtopoint = R_PointToAngle2(start_c.x, start_c.y, newview->x, newview->y);
angtopoint += dangle;
viewx = dest_c.x+FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
viewy = dest_c.y+FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
}
#endif
}
void R_AddPortal(INT32 line1, INT32 line2, INT32 x1, INT32 x2)
{
portal_pair *portal = Z_Malloc(sizeof(portal_pair), PU_LEVEL, NULL);
INT16 *ceilingclipsave = Z_Malloc(sizeof(INT16)*(x2-x1), PU_LEVEL, NULL);
INT16 *floorclipsave = Z_Malloc(sizeof(INT16)*(x2-x1), PU_LEVEL, NULL);
fixed_t *frontscalesave = Z_Malloc(sizeof(fixed_t)*(x2-x1), PU_LEVEL, NULL);
portal->line1 = line1;
portal->line2 = line2;
portal->pass = portalrender+1;
portal->next = NULL;
R_PortalStoreClipValues(x1, x2, ceilingclipsave, floorclipsave, frontscalesave);
portal->ceilingclip = ceilingclipsave;
portal->floorclip = floorclipsave;
portal->frontscale = frontscalesave;
portal->start = x1;
portal->end = x2;
portalline = true; // this tells R_StoreWallRange that curline is a portal seg
portal->viewx = viewx;
portal->viewy = viewy;
portal->viewz = viewz;
portal->viewangle = viewangle;
if (!portal_base)
{
portal_base = portal;
portal_cap = portal;
portalclipline = &lines[portal->clipline];
portalcullsector = portalclipline->frontsector;
viewsector = portalclipline->frontsector;
}
else
{
portal_cap->next = portal;
portal_cap = portal;
portalclipline = NULL;
portalcullsector = NULL;
viewsector = R_PointInSubsector(viewx, viewy)->sector;
}
}
static void Mask_Pre (maskcount_t* m)
{
m->drawsegs[0] = ds_p - drawsegs;
m->vissprites[0] = visspritecount;
m->viewx = viewx;
m->viewy = viewy;
m->viewz = viewz;
m->viewsector = viewsector;
}
static void Mask_Post (maskcount_t* m)
{
m->drawsegs[1] = ds_p - drawsegs;
m->vissprites[1] = visspritecount;
}
// ================
// R_RenderView
// ================
@@ -1684,9 +1527,8 @@ void R_AddPortal(INT32 line1, INT32 line2, INT32 x1, INT32 x2)
void R_RenderPlayerView(player_t *player)
{
portal_pair *portal;
const boolean skybox = (skyboxmo[0] && cv_skybox.value);
UINT8 i;
INT32 nummasks = 1;
maskcount_t* masks = malloc(sizeof(maskcount_t));
// if this is display player 1
if (cv_homremoval.value && player == &players[displayplayers[0]])
@@ -1711,44 +1553,7 @@ void R_RenderPlayerView(player_t *player)
}
}
// load previous saved value of skyVisible for the player
for (i = 0; i <= splitscreen; i++)
{
if (player != &players[displayplayers[i]])
continue;
skyVisible = skyVisiblePerPlayer[i];
break;
}
portalrender = 0;
portal_base = portal_cap = NULL;
PS_START_TIMING(ps_skyboxtime);
if (skybox && skyVisible)
{
R_SkyboxFrame(player);
R_ClearClipSegs();
R_ClearDrawSegs();
R_ClearPlanes();
R_ClearSprites();
#ifdef FLOORSPLATS
R_ClearVisibleFloorSplats();
#endif
R_RenderBSPNode((INT32)numnodes - 1);
R_ClipSprites();
R_DrawPlanes();
#ifdef FLOORSPLATS
R_DrawVisibleFloorSplats();
#endif
R_DrawMasked();
}
PS_STOP_TIMING(ps_skyboxtime);
R_SetupFrame(player, skybox);
skyVisible = false;
R_SetupFrame(player);
framecount++;
validcount++;
@@ -1765,7 +1570,7 @@ void R_RenderPlayerView(player_t *player)
else
{
portalclipstart = 0;
portalclipend = viewwidth-1;
portalclipend = viewwidth;
R_ClearClipSegs();
}
R_ClearDrawSegs();
@@ -1774,50 +1579,75 @@ void R_RenderPlayerView(player_t *player)
R_ClearVisibleFloorSplats();
#endif
// The head node is the last node output.
Portal_InitList();
// The head node is the last node output.
Mask_Pre(&masks[nummasks - 1]);
curdrawsegs = ds_p;
ps_numbspcalls.value.i = ps_numpolyobjects.value.i = ps_numdrawnodes.value.i = 0;
PS_START_TIMING(ps_bsptime);
R_RenderBSPNode((INT32)numnodes - 1);
PS_STOP_TIMING(ps_bsptime);
Mask_Post(&masks[nummasks - 1]);
R_AddPrecipitationSprites();
PS_START_TIMING(ps_sw_spritecliptime);
R_ClipSprites();
R_ClipSprites(drawsegs, NULL);
PS_STOP_TIMING(ps_sw_spritecliptime);
ps_numsprites.value.i = numvisiblesprites;
// PORTAL RENDERING
// Add skybox portals caused by sky visplanes.
if (skyboxmo[0] && cv_skybox.value)
Portal_AddSkyboxPortals();
PS_START_TIMING(ps_sw_portaltime);
for(portal = portal_base; portal; portal = portal_base)
// Portal rendering. Hijacks the BSP traversal.
if (portal_base)
{
// render the portal
CONS_Debug(DBG_RENDER, "Rendering portal from line %d to %d\n", portal->line1, portal->line2);
portalrender = portal->pass;
portal_t *portal;
R_PortalFrame(&lines[portal->line1], &lines[portal->line2], portal);
for (portal = portal_base; portal; portal = portal_base)
{
portalrender = portal->pass; // Recursiveness depth.
R_PortalClearClipSegs(portal->start, portal->end);
R_ClearFFloorClips();
R_PortalRestoreClipValues(portal->start, portal->end, portal->ceilingclip, portal->floorclip, portal->frontscale);
// Apply the viewpoint stored for the portal.
R_PortalFrame(portal);
validcount++;
// Hack in the clipsegs to delimit the starting
// clipping for sprites and possibly other similar
// future items.
R_PortalClearClipSegs(portal->start, portal->end);
R_RenderBSPNode((INT32)numnodes - 1);
R_ClipSprites();
//R_DrawPlanes();
//R_DrawMasked();
// Hack in the top/bottom clip values for the window
// that were previously stored.
Portal_ClipApply(portal);
// okay done. free it.
portalcullsector = NULL; // Just in case...
portal_base = portal->next;
Z_Free(portal->ceilingclip);
Z_Free(portal->floorclip);
Z_Free(portal->frontscale);
Z_Free(portal);
validcount++;
masks = realloc(masks, (++nummasks)*sizeof(maskcount_t));
Mask_Pre(&masks[nummasks - 1]);
curdrawsegs = ds_p;
portalskipprecipmobjs = portal->isskybox;
// Render the BSP from the new viewpoint, and clip
// any sprites with the new clipsegs and window.
R_RenderBSPNode((INT32)numnodes - 1);
Mask_Post(&masks[nummasks - 1]);
portalskipprecipmobjs = false;
R_ClipSprites(ds_p - (masks[nummasks - 1].drawsegs[1] - masks[nummasks - 1].drawsegs[0]), portal);
Portal_Remove(portal);
}
}
PS_STOP_TIMING(ps_sw_portaltime);
// END PORTAL RENDERING
PS_START_TIMING(ps_sw_planetime);
R_DrawPlanes();
@@ -1828,19 +1658,10 @@ void R_RenderPlayerView(player_t *player)
// draw mid texture and sprite
// And now 3D floors/sides!
PS_START_TIMING(ps_sw_maskedtime);
R_DrawMasked();
R_DrawMasked(masks, nummasks);
PS_STOP_TIMING(ps_sw_maskedtime);
// save value to skyVisiblePerPlayer
// this is so that P1 can't affect whether P2 can see a skybox or not, or vice versa
for (i = 0; i <= splitscreen; i++)
{
if (player != &players[displayplayers[i]])
continue;
skyVisiblePerPlayer[i] = skyVisible;
break;
}
free(masks);
}
// =========================================================================
@@ -1931,6 +1752,8 @@ void R_RegisterEngineStuff(void)
CV_RegisterVar(&cv_grmaxinterpdist);
CV_RegisterVar(&cv_ripplewater);
// Default viewheight is changeable,
// initialized to standard viewheight
//CV_RegisterVar(&cv_viewheight);
+24 -2
View File
@@ -33,6 +33,8 @@ extern size_t validcount, linecount, loopcount, framecount;
// The fraction of a tic being drawn (for interpolation between two tics)
extern fixed_t rendertimefrac;
// Same as rendertimefrac but not suspended when the game is paused
extern fixed_t rendertimefrac_unpaused;
// Evaluated delta tics for this frame (how many tics since the last frame)
extern fixed_t renderdeltatics;
// The current render is a new logical tic
@@ -71,7 +73,24 @@ extern lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ];
// Utility functions.
INT32 R_PointOnSide(fixed_t x, fixed_t y, const node_t *node);
INT32 R_PointOnSegSide(fixed_t x, fixed_t y, const seg_t *line);
FUNCINLINE static ATTRINLINE PUREFUNC INT32 R_PointOnSideRender(fixed_t x, fixed_t y, const node_t *node)
{
// use cross product to determine side quickly
return (INT64)(y - node->y) * node->dx - (INT64)(x - node->x) * node->dy > 0;
}
FUNCINLINE static ATTRINLINE PUREFUNC INT32 R_PointOnSegSide(fixed_t x, fixed_t y, const seg_t *line)
{
fixed_t lx = line->v1->x;
fixed_t ly = line->v1->y;
fixed_t ldx = line->v2->x - lx;
fixed_t ldy = line->v2->y - ly;
// use cross product to determine side quickly
return (INT64)(y - ly) * ldx - (INT64)(x - lx) * ldy > 0;
}
angle_t R_PointToAngle(fixed_t x, fixed_t y);
angle_t R_PointToAngle64(INT64 x, INT64 y);
angle_t R_PointToAngle2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1);
@@ -124,6 +143,7 @@ extern consvar_t cv_fov;
extern consvar_t cv_skybox;
extern consvar_t cv_tailspickup;
extern consvar_t cv_grmaxinterpdist;
extern consvar_t cv_ripplewater;
// Called by startup code.
void R_Init(void);
@@ -140,8 +160,8 @@ void R_SetViewSize(void);
void R_ExecuteSetViewSize(void);
void R_SkyboxFrame(player_t *player);
void R_SetupFrame(player_t *player);
void R_SetupFrame(player_t *player, boolean skybox);
// Called by G_Drawer.
void R_RenderPlayerView(player_t *player);
@@ -150,4 +170,6 @@ void R_RegisterEngineStuff(void);
// return multiplier for HUD uncap
INT32 R_GetHudUncap(void);
// same as above but keeps interpolation during pause
INT32 R_GetMenuUncap(void);
#endif
+51 -82
View File
@@ -23,6 +23,8 @@
#include "r_state.h"
#include "r_splats.h" // faB(21jan):testing
#include "r_sky.h"
#include "r_portal.h"
#include "v_video.h"
#include "w_wad.h"
#include "z_zone.h"
@@ -39,13 +41,7 @@
// good night sweet prince
//#define SHITPLANESPARENCY
//SoM: 3/23/2000: Use Boom visplane hashing.
#define VISPLANEHASHBITS 9
#define VISPLANEHASHMASK ((1<<VISPLANEHASHBITS)-1)
// the last visplane list is outside of the hash table and is used for fof planes
#define MAXVISPLANES ((1<<VISPLANEHASHBITS)+1)
static visplane_t *visplanes[MAXVISPLANES];
visplane_t *visplanes[MAXVISPLANES];
static visplane_t *freetail;
static visplane_t **freehead = &freetail;
@@ -112,50 +108,6 @@ void R_InitPlanes(void)
// FIXME: unused
}
// R_PortalStoreClipValues
// Saves clipping values for later. -Red
void R_PortalStoreClipValues(INT32 start, INT32 end, INT16 *ceil, INT16 *floor, fixed_t *scale)
{
INT32 i;
for (i = 0; i < end-start; i++)
{
*ceil = ceilingclip[start+i];
ceil++;
*floor = floorclip[start+i];
floor++;
*scale = frontscale[start+i];
scale++;
}
}
// R_PortalRestoreClipValues
// Inverse of the above. Restores the old value!
void R_PortalRestoreClipValues(INT32 start, INT32 end, INT16 *ceil, INT16 *floor, fixed_t *scale)
{
INT32 i;
for (i = 0; i < end-start; i++)
{
ceilingclip[start+i] = *ceil;
ceil++;
floorclip[start+i] = *floor;
floor++;
frontscale[start+i] = *scale;
scale++;
}
// HACKS FOLLOW
for (i = 0; i < start; i++)
{
floorclip[i] = -1;
ceilingclip[i] = (INT16)viewheight;
}
for (i = end; i < vid.width; i++)
{
floorclip[i] = -1;
ceilingclip[i] = (INT16)viewheight;
}
}
//
// Water ripple effect!!
// Needs the height of the plane, and the vertical position of the span.
@@ -307,6 +259,24 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
spanfunc();
}
void R_ClearFFloorClips (void)
{
INT32 i, p;
// opening / clipping determination
for (i = 0; i < viewwidth; i++)
{
for (p = 0; p < MAXFFLOORS; p++)
{
ffloor[p].f_clip[i] = (INT16)viewheight;
ffloor[p].c_clip[i] = -1;
}
}
numffloors = 0;
}
//
// R_ClearPlanes
// At begining of frame.
@@ -329,8 +299,6 @@ void R_ClearPlanes(void)
}
}
numffloors = 0;
for (i = 0; i < MAXVISPLANES; i++)
{
for (*freehead = visplanes[i], visplanes[i] = NULL;
@@ -665,12 +633,6 @@ static void R_DrawSkyPlane(visplane_t *pl)
INT32 x;
INT32 angle;
if (!newview->sky)
{
skyVisible = true;
return;
}
wallcolfunc = walldrawerfunc;
// use correct aspect ratio scale
@@ -910,34 +872,41 @@ void R_DrawSinglePlane(visplane_t *pl)
INT32 top, bottom;
UINT8 *scr;
planeripple.active = true;
if (spanfunc == R_DrawTranslucentSpan_8)
if (cv_ripplewater.value)
{
spanfunc = R_DrawTranslucentWaterSpan_8;
planeripple.active = true;
// Copy the current scene, ugh
top = pl->high-8;
bottom = pl->low+8;
if (spanfunc == R_DrawTranslucentSpan_8)
{
spanfunc = R_DrawTranslucentWaterSpan_8;
if (top < 0)
top = 0;
if (bottom > vid.height)
bottom = vid.height;
// Copy the current scene, ugh
top = pl->high-8;
bottom = pl->low+8;
if (splitscreen > 2 && viewplayer == &players[displayplayers[3]]) // Only copy the part of the screen we need
scr = (screens[0] + (top+(viewheight))*vid.width + viewwidth);
else if ((splitscreen == 1 && viewplayer == &players[displayplayers[1]])
|| (splitscreen > 1 && viewplayer == &players[displayplayers[2]]))
scr = (screens[0] + (top+(viewheight))*vid.width);
else if (splitscreen > 1 && viewplayer == &players[displayplayers[1]])
scr = (screens[0] + ((top)*vid.width) + viewwidth);
else
scr = (screens[0] + ((top)*vid.width));
if (top < 0)
top = 0;
if (bottom > vid.height)
bottom = vid.height;
VID_BlitLinearScreen(scr, screens[1]+((top)*vid.width),
vid.width, bottom-top,
vid.width, vid.width);
if (splitscreen > 2 && viewplayer == &players[displayplayers[3]]) // Only copy the part of the screen we need
scr = (screens[0] + (top+(viewheight))*vid.width + viewwidth);
else if ((splitscreen == 1 && viewplayer == &players[displayplayers[1]])
|| (splitscreen > 1 && viewplayer == &players[displayplayers[2]]))
scr = (screens[0] + (top+(viewheight))*vid.width);
else if (splitscreen > 1 && viewplayer == &players[displayplayers[1]])
scr = (screens[0] + ((top)*vid.width) + viewwidth);
else
scr = (screens[0] + ((top)*vid.width));
VID_BlitLinearScreen(scr, screens[1]+((top)*vid.width),
vid.width, bottom-top,
vid.width, vid.width);
}
}
else
{
planeripple.active = false;
}
}
#endif
+3 -2
View File
@@ -18,6 +18,7 @@
#include "r_data.h"
#include "p_polyobj.h"
//SoM: 3/23/2000: Use Boom visplane hashing.
#define VISPLANEHASHBITS 9
#define VISPLANEHASHMASK ((1<<VISPLANEHASHBITS)-1)
// the last visplane list is outside of the hash table and is used for fof planes
@@ -56,6 +57,7 @@ typedef struct visplane_s
boolean noencore;
} visplane_t;
extern visplane_t *visplanes[MAXVISPLANES];
extern visplane_t *floorplane;
extern visplane_t *ceilingplane;
@@ -75,9 +77,8 @@ extern fixed_t *yslope;
extern lighttable_t **planezlight;
void R_InitPlanes(void);
void R_PortalStoreClipValues(INT32 start, INT32 end, INT16 *ceil, INT16 *floor, fixed_t *scale);
void R_PortalRestoreClipValues(INT32 start, INT32 end, INT16 *ceil, INT16 *floor, fixed_t *scale);
void R_ClearPlanes(void);
void R_ClearFFloorClips (void);
void R_MapPlane(INT32 y, INT32 x1, INT32 x2);
void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2);
+317
View File
@@ -0,0 +1,317 @@
// SONIC ROBO BLAST 2 KART
//-----------------------------------------------------------------------------
// Copyright (C) 2024 by Kart Krew.
// Copyright (C) 2020 by Sonic Team Junior.
// Copyright (C) 2000 by DooM Legacy Team.
// Copyright (C) 1996 by id Software, Inc.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file r_portal.c
/// \brief Software renderer portals.
#include "r_portal.h"
#include "r_plane.h"
#include "r_main.h"
#include "doomstat.h"
#include "p_spec.h" // Skybox viewpoints
#include "z_zone.h"
#include "r_things.h"
#include "r_sky.h"
UINT8 portalrender; /**< When rendering a portal, it establishes the depth of the current BSP traversal. */
boolean portalskipprecipmobjs = false;
// Linked list for portals.
portal_t *portal_base, *portal_cap;
line_t *portalclipline;
sector_t *portalcullsector;
INT32 portalclipstart, portalclipend;
portal_t *g_portal; // is curline a portal seg?
void Portal_InitList (void)
{
portalrender = 0;
portal_base = portal_cap = NULL;
}
/** Apply the clipping window from a portal.
*/
void Portal_ClipApply (const portal_t* portal)
{
INT32 i;
INT32 start = portal->start;
INT32 end = portal->end;
INT16 *ceil = portal->ceilingclip;
INT16 *floor = portal->floorclip;
fixed_t *scale = portal->frontscale;
for (i = 0; i < end-start; i++)
{
ceilingclip[start+i] = *ceil;
ceil++;
floorclip[start+i] = *floor;
floor++;
frontscale[start+i] = *scale;
scale++;
}
// HACKS FOLLOW
for (i = 0; i < start; i++)
{
floorclip[i] = -1;
ceilingclip[i] = (INT16)viewheight;
}
for (i = end; i < vid.width; i++)
{
floorclip[i] = -1;
ceilingclip[i] = (INT16)viewheight;
}
}
static portal_t* Portal_Add (const INT16 x1, const INT16 x2)
{
portal_t *portal = Z_Malloc(sizeof(portal_t), PU_LEVEL, NULL);
INT16 *ceilingclipsave = Z_Malloc(sizeof(INT16)*(x2-x1 + 1), PU_LEVEL, NULL);
INT16 *floorclipsave = Z_Malloc(sizeof(INT16)*(x2-x1 + 1), PU_LEVEL, NULL);
fixed_t *frontscalesave = Z_Malloc(sizeof(fixed_t)*(x2-x1 + 1), PU_LEVEL, NULL);
// Linked list.
if (!portal_base)
{
portal_base = portal;
portal_cap = portal;
}
else
{
portal_cap->next = portal;
portal_cap = portal;
}
portal->next = NULL;
// Store clipping values so they can be restored once the portal is rendered.
portal->ceilingclip = ceilingclipsave;
portal->floorclip = floorclipsave;
portal->frontscale = frontscalesave;
portal->start = x1;
portal->end = x2;
// Increase recursion level.
portal->pass = portalrender+1;
portal->isskybox = false;
return portal;
}
void Portal_Remove (portal_t* portal)
{
portalcullsector = NULL;
portal_base = portal->next;
Z_Free(portal->ceilingclip);
Z_Free(portal->floorclip);
Z_Free(portal->frontscale);
Z_Free(portal);
}
/** Creates a portal out of two lines and a determined screen range.
*
* line1 determines the entrance, and line2 the exit.
* x1 and x2 determine the screen's column bounds.
* The view's offset from the entry line center is obtained,
* and then rotated&translated to the exit line's center.
* When the portal renders, it will create the illusion of
* the two lines being seamed together.
*/
void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, const INT32 x2)
{
portal_t* portal = Portal_Add(x1, x2);
// Offset the portal view by the linedef centers
line_t* start = &lines[line1];
line_t* dest = &lines[line2];
angle_t dangle = R_PointToAngle2(0,0,dest->dx,dest->dy) - R_PointToAngle2(start->dx,start->dy,0,0);
fixed_t disttopoint;
angle_t angtopoint;
vertex_t dest_c, start_c;
// looking glass center
start_c.x = (start->v1->x + start->v2->x) / 2;
start_c.y = (start->v1->y + start->v2->y) / 2;
// other side center
dest_c.x = (dest->v1->x + dest->v2->x) / 2;
dest_c.y = (dest->v1->y + dest->v2->y) / 2;
disttopoint = R_PointToDist2(start_c.x, start_c.y, viewx, viewy);
angtopoint = R_PointToAngle2(start_c.x, start_c.y, viewx, viewy);
angtopoint += dangle;
portal->viewx = dest_c.x + FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
portal->viewy = dest_c.y + FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
portal->viewz = viewz + dest->frontsector->floorheight - start->frontsector->floorheight;
portal->viewangle = viewangle + dangle;
portal->clipline = line2;
g_portal = portal; // this tells R_StoreWallRange that curline is a portal seg
}
/** Store the clipping window for a portal using a visplane.
*
* Since visplanes top/bottom windows work in an identical way,
* it can just be copied almost directly.
*/
static void Portal_ClipVisplane (const visplane_t* plane, portal_t* portal)
{
INT16 start = portal->start;
INT16 end = portal->end;
INT32 i;
for (i = 0; i < end - start; i++)
{
// Invalid column.
if (plane->top[i + start] == 65535)
{
portal->ceilingclip[i] = -1;
portal->floorclip[i] = -1;
continue;
}
portal->ceilingclip[i] = plane->top[i + start] - 1;
portal->floorclip[i] = plane->bottom[i + start] + 1;
portal->frontscale[i] = INT32_MAX;
}
}
extern INT32 viewwidth;
static boolean TrimVisplaneBounds (const visplane_t* plane, INT16* start, INT16* end)
{
*start = plane->minx;
*end = plane->maxx + 1;
// Visplanes have 1-px pads on their sides (extra columns).
// Trim them, else it may render out of bounds.
if (*end > viewwidth)
*end = viewwidth;
if (!(*start < *end))
return true;
/** Trims a visplane's horizontal gap to match its render area.
*
* Visplanes' minx/maxx may sometimes exceed the area they're
* covering. This merely adjusts the boundaries to the next
* valid area.
*/
while (plane->bottom[*start] == 0 && plane->top[*start] == 65535 && *start < *end)
{
(*start)++;
}
while (plane->bottom[*end - 1] == 0 && plane->top[*start] == 65535 && *end > *start)
{
(*end)--;
}
return false;
}
/** Creates a skybox portal out of a visplane.
*
* Applies the necessary offsets and rotation to give
* a depth illusion to the skybox.
*/
static void Portal_AddSkybox (const visplane_t* plane)
{
INT16 start, end;
mapheader_t *mh;
portal_t* portal;
if (TrimVisplaneBounds(plane, &start, &end))
return;
portal = Portal_Add(start, end);
Portal_ClipVisplane(plane, portal);
portal->viewx = skyboxmo[0]->x;
portal->viewy = skyboxmo[0]->y;
portal->viewz = 0;
if (skyboxmo[0]->spawnpoint)
portal->viewz = ((fixed_t)skyboxmo[0]->spawnpoint->angle)<<FRACBITS;
portal->viewangle = viewangle + skyboxmo[0]->angle;
mh = mapheaderinfo[gamemap-1];
// If a relative viewpoint exists, offset the viewpoint.
if (skyboxmo[1])
{
fixed_t x = 0, y = 0;
angle_t ang = skyboxmo[0]->angle>>ANGLETOFINESHIFT;
if (mh->skybox_scalex > 0)
x = (viewx - skyboxmo[1]->x) / mh->skybox_scalex;
else if (mh->skybox_scalex < 0)
x = (viewx - skyboxmo[1]->x) * -mh->skybox_scalex;
if (mh->skybox_scaley > 0)
y = (viewy - skyboxmo[1]->y) / mh->skybox_scaley;
else if (mh->skybox_scaley < 0)
y = (viewy - skyboxmo[1]->y) * -mh->skybox_scaley;
// Apply transform to account for the skybox viewport angle.
portal->viewx += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
portal->viewy += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
}
if (mh->skybox_scalez > 0)
portal->viewz += viewz / mh->skybox_scalez;
else if (mh->skybox_scalez < 0)
portal->viewz += viewz * -mh->skybox_scalez;
portal->clipline = -1;
portal->isskybox = true;
}
/** Creates portals for the currently existing sky visplanes.
* The visplanes are also removed and cleared from the list.
*/
void Portal_AddSkyboxPortals (void)
{
visplane_t *pl;
INT32 i;
UINT16 count = 0;
for (i = 0; i < MAXVISPLANES; i++, pl++)
{
for (pl = visplanes[i]; pl; pl = pl->next)
{
//if (pl->minx >= pl->maxx)
//continue;
if (pl->picnum == skyflatnum)
{
Portal_AddSkybox(pl);
pl->minx = 0;
pl->maxx = -1;
count++;
}
}
}
//CONS_Debug(DBG_RENDER, "Skybox portals: %d\n", count);
}
+63
View File
@@ -0,0 +1,63 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2018 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file r_portal.h
/// \brief Software renderer portal struct, functions, linked list extern.
#ifndef __R_PORTAL__
#define __R_PORTAL__
#include "r_data.h"
#include "r_plane.h" // visplanes
/*
* Portal structure for the software renderer.
*/
typedef struct portal_s
{
struct portal_s *next;
// Viewport.
fixed_t viewx;
fixed_t viewy;
fixed_t viewz;
angle_t viewangle;
UINT8 pass; /**< Keeps track of the portal's recursion depth. */
boolean isskybox;
INT32 clipline; /**< Optional clipline for line-based portals. */
// Clipping information.
INT32 start; /**< First horizontal pixel coordinate to draw at. */
INT32 end; /**< Last horizontal pixel coordinate to draw at. */
INT16 *ceilingclip; /**< Temporary screen top clipping array. */
INT16 *floorclip; /**< Temporary screen bottom clipping array. */
fixed_t *frontscale;/**< Temporary screen bottom clipping array. */
} portal_t;
extern portal_t* portal_base;
extern portal_t* portal_cap;
extern UINT8 portalrender;
extern boolean portalskipprecipmobjs;
extern line_t *portalclipline;
extern sector_t *portalcullsector;
extern INT32 portalclipstart, portalclipend;
void Portal_InitList (void);
void Portal_Remove (portal_t* portal);
void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, const INT32 x2);
void Portal_ClipRange (portal_t* portal);
void Portal_ClipApply (const portal_t* portal);
void Portal_AddSkyboxPortals (void);
#endif
+20 -6
View File
@@ -15,6 +15,7 @@
#include "r_local.h"
#include "r_sky.h"
#include "r_portal.h"
#include "r_splats.h"
#include "w_wad.h"
@@ -275,6 +276,7 @@ static void R_Render2sidedMultiPatchColumn(column_t *column)
if (dc_yl <= dc_yh && dc_yh < vid.height && dc_yh > 0)
{
dc_source = (UINT8 *)column + 3;
dc_sourcelength = 0;
if (colfunc == wallcolfunc)
twosmultipatchfunc();
@@ -1446,6 +1448,7 @@ static void R_RenderSegLoop (void)
dc_texturemid = rw_midtexturemid;
dc_source = R_GetColumn(midtexture,texturecolumn);
dc_texheight = textureheight[midtexture]>>FRACBITS;
dc_sourcelength = 0;
colfunc();
// dont draw anything more for this column, since
@@ -1493,6 +1496,7 @@ static void R_RenderSegLoop (void)
dc_texturemid = rw_toptexturemid;
dc_source = R_GetColumn(toptexture,texturecolumn);
dc_texheight = textureheight[toptexture]>>FRACBITS;
dc_sourcelength = 0;
colfunc();
ceilingclip[rw_x] = (INT16)mid;
}
@@ -1530,6 +1534,7 @@ static void R_RenderSegLoop (void)
dc_source = R_GetColumn(bottomtexture,
texturecolumn);
dc_texheight = textureheight[bottomtexture]>>FRACBITS;
dc_sourcelength = 0;
colfunc();
floorclip[rw_x] = (INT16)mid;
}
@@ -1605,6 +1610,12 @@ static INT64 R_CalcSegDist(seg_t* seg, INT64 x2, INT64 y2)
}
}
static inline INT32 get_flat_tex (INT32 texnum)
{
texnum = R_GetTextureNum(texnum);
return textures[texnum]->holes ? 0 : texnum; // R_DrawWallColumn cannot render holey textures
}
//
// R_StoreWallRange
// A wall segment will be drawn
@@ -1632,6 +1643,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
if (ds_p == drawsegs+maxdrawsegs)
{
size_t curpos = curdrawsegs - drawsegs;
size_t pos = ds_p - drawsegs;
size_t newmax = maxdrawsegs ? maxdrawsegs*2 : 128;
if (firstseg)
@@ -1639,6 +1651,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
drawsegs = Z_Realloc(drawsegs, newmax*sizeof (*drawsegs), PU_STATIC, NULL);
ds_p = drawsegs + pos;
maxdrawsegs = newmax;
curdrawsegs = drawsegs + curpos;
if (firstseg)
firstseg = drawsegs + (size_t)firstseg;
}
@@ -1691,6 +1704,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
// borrowed fix from *cough* zdoom *cough*
// [RH] We also need to adjust the openings pointers that
// were already stored in drawsegs.
//for (ds = curdrawsegs; ds < ds_p; ds++)
for (ds = drawsegs; ds < ds_p; ds++)
{
#define ADJUST(p) if (ds->p + ds->x1 >= oldopenings && ds->p + ds->x1 <= oldlast) ds->p = ds->p - oldopenings + openings;
@@ -1862,7 +1876,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
{
fixed_t texheight;
// single sided line
midtexture = R_GetTextureNum(sidedef->midtexture);
midtexture = get_flat_tex(sidedef->midtexture);
texheight = textureheight[midtexture];
// a single sided line is terminal, so it must mark ends
markfloor = markceiling = true;
@@ -2045,15 +2059,15 @@ void R_StoreWallRange(INT32 start, INT32 stop)
{
// Special case... use offsets from 2nd side but only if it has a texture.
side_t *def = &sides[linedef->sidenum[1]];
toptexture = R_GetTextureNum(def->toptexture);
toptexture = get_flat_tex(def->toptexture);
if (!toptexture) //Second side has no texture, use the first side's instead.
toptexture = R_GetTextureNum(sidedef->toptexture);
toptexture = get_flat_tex(sidedef->toptexture);
texheight = textureheight[toptexture];
}
else
{
toptexture = R_GetTextureNum(sidedef->toptexture);
toptexture = get_flat_tex(sidedef->toptexture);
texheight = textureheight[toptexture];
}
if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked
@@ -2078,7 +2092,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
if (worldlow > worldbottom || worldlowslope > worldbottomslope) // Only if VISIBLE!!!
{
// bottom texture
bottomtexture = R_GetTextureNum(sidedef->bottomtexture);
bottomtexture = get_flat_tex(sidedef->bottomtexture);
if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked
if (linedef->flags & ML_DONTPEGBOTTOM)
@@ -2840,7 +2854,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
R_RenderSegLoop();
colfunc = wallcolfunc;
if (portalline) // if curline is a portal, set portalrender for drawseg
if (g_portal) // if curline is a portal, set portalrender for drawseg
ds_p->portalpass = portalrender+1;
else
ds_p->portalpass = 0;
-6
View File
@@ -90,14 +90,8 @@ 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 skyVisiblePerPlayer[MAXSPLITSCREENPLAYERS]; // saved values of skyVisible of each splitscreen player
extern sector_t *viewsector;
extern player_t *viewplayer;
extern UINT8 portalrender;
extern sector_t *portalcullsector;
extern line_t *portalclipline;
extern INT32 portalclipstart, portalclipend;
extern consvar_t cv_allowmlook;
extern consvar_t cv_maxportals;
+217 -149
View File
@@ -25,6 +25,7 @@
#include "r_things.h"
#include "r_patch.h"
#include "r_plane.h"
#include "r_portal.h"
#include "p_tick.h"
#include "p_local.h"
#include "p_slopes.h"
@@ -43,7 +44,7 @@ CV_PossibleValue_t Forceskin_cons_t[MAXSKINS+2];
static void R_InitSkins(void);
#define MINZ (FRACUNIT*4)
#define MINZ (FRACUNIT*16)
#define BASEYCENTER (BASEVIDHEIGHT/2)
typedef struct
@@ -522,7 +523,7 @@ void R_InitSprites(void)
// it can be is do before loading config for skin cvar possible value
R_InitSkins();
for (i = 0; i < numwadfiles; i++)
for (i = 0; i < numwadfiles; i++)
{
R_AddSkins((UINT16)i, false);
R_LoadSpriteInfoLumps(i, wadfiles[i]->numlumps);
@@ -583,6 +584,9 @@ void R_DrawMaskedColumn(column_t *column)
basetexturemid = dc_texturemid;
if (!column || column == 0)
return;
for (; column->topdelta != 0xff ;)
{
// calculate unclipped screen coordinates
@@ -609,14 +613,16 @@ void R_DrawMaskedColumn(column_t *column)
dc_yh = mfloorclip[dc_x]-1;
if (dc_yl <= mceilingclip[dc_x])
dc_yl = mceilingclip[dc_x]+1;
if (dc_yl < 0)
dc_yl = 0;
if (dc_yh >= vid.height)
dc_yh = vid.height - 1;
if (dc_yl <= dc_yh && dc_yh > 0)
if (dc_yl <= dc_yh && dc_yh > 0 && column->length != 0)
{
dc_source = (UINT8 *)column + 3;
dc_sourcelength = column->length;
dc_texturemid = basetexturemid - (topdelta<<FRACBITS);
// Drawn by R_DrawColumn.
@@ -625,6 +631,10 @@ void R_DrawMaskedColumn(column_t *column)
// quick fix... something more proper should be done!!!
if (ylookup[dc_yl])
colfunc();
#ifdef PARANOIA
else
I_Error("R_DrawMaskedColumn: Invalid ylookup for dc_yl %d", dc->yl);
#endif
}
column = (column_t *)((UINT8 *)column + column->length + 4);
}
@@ -674,9 +684,10 @@ static void R_DrawFlippedMaskedColumn(column_t *column)
if (dc_yh >= vid.height)
dc_yh = vid.height - 1;
if (dc_yl <= dc_yh && dc_yh > 0)
if (dc_yl <= dc_yh && dc_yh > 0 && column->length != 0)
{
dc_source = ZZ_Alloc(column->length);
dc_sourcelength = column->length;
for (s = (UINT8 *)column+2+column->length, d = dc_source; d < dc_source+column->length; --s)
*d++ = *s;
dc_texturemid = basetexturemid - (topdelta<<FRACBITS);
@@ -722,7 +733,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
if (overflow_test < 0) overflow_test = -overflow_test;
if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; // ditto
}
// TODO This check should not be necessary. But Papersprites near to the camera will sometimes create invalid values
// for the vissprite's startfrac. This happens because they are not depth culled like other sprites.
// Someone who is more familiar with papersprites pls check and try to fix <3
@@ -794,7 +805,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
dc_colormap += COLORMAP_REMAPOFFSET;
dc_texturemid = vis->texturemid;
dc_texheight = 0;
dc_texheight = SHORT(patch->height);
frac = vis->startfrac;
windowtop = windowbottom = sprbotscreen = INT32_MAX;
@@ -803,8 +814,10 @@ static void R_DrawVisSprite(vissprite_t *vis)
this_scale = FixedMul(this_scale, ((skin_t *)vis->mobj->localskin)->highresscale);
else if (vis->mobj->skin && ((skin_t *)vis->mobj->skin)->flags & SF_HIRES)
this_scale = FixedMul(this_scale, ((skin_t *)vis->mobj->skin)->highresscale);
if (this_scale <= 0)
this_scale = 1;
if (this_scale != FRACUNIT)
{
if (!vis->isScaled)
@@ -837,22 +850,15 @@ static void R_DrawVisSprite(vissprite_t *vis)
if (vis->x2 >= vid.width)
vis->x2 = vid.width-1;
// Something is occasionally setting 1px-wide sprites whose frac is exactly the width of the sprite, causing crashes due to
// accessing invalid column info. Until the cause is found, let's try to correct those manually...
{
fixed_t temp = ((frac + vis->xiscale*(vis->x2-vis->x1))>>FRACBITS) - SHORT(patch->width);
if (temp > 0)
vis->x2 -= temp;
}
localcolfunc = (vis->vflip) ? R_DrawFlippedMaskedColumn : R_DrawMaskedColumn;
lengthcol = patch->height;
lengthcol = SHORT(patch->height);
// Split drawing loops for paper and non-paper to reduce conditional checks per sprite
if (vis->scalestep)
{
fixed_t horzscale = FixedMul(vis->spritexscale, this_scale);
fixed_t scalestep = FixedMul(vis->scalestep, vis->spriteyscale);
pwidth = SHORT(patch->width);
// Papersprite drawing loop
@@ -877,12 +883,10 @@ static void R_DrawVisSprite(vissprite_t *vis)
}
else
{
pwidth = SHORT(patch->width);
// Non-paper drawing loop
for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale)
{
texturecolumn = CLAMP(frac >> FRACBITS, 0, pwidth - 1);
{
texturecolumn = CLAMP(frac >> FRACBITS, 0, SHORT(patch->width) - 1);
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn]));
localcolfunc (column);
@@ -928,7 +932,7 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis)
dc_iscale = FixedDiv(FRACUNIT, vis->scale);
dc_texturemid = FixedDiv(vis->texturemid, this_scale);
dc_texheight = 0;
dc_texheight = SHORT(patch->height);
frac = vis->startfrac;
spryscale = vis->scale;
@@ -943,7 +947,14 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis)
for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale)
{
texturecolumn = CLAMP(frac >> FRACBITS, 0, SHORT(patch->width) - 1);
texturecolumn = frac>>FRACBITS;
if (texturecolumn < 0 || texturecolumn >= patch->width)
{
CONS_Debug(DBG_RENDER, "R_DrawPrecipitationSpriteRange: bad texturecolumn\n");
break;
}
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn]));
R_DrawMaskedColumn(column);
@@ -1156,7 +1167,7 @@ static void R_ProjectSprite(mobj_t *thing)
angle_t pitchnroll = 0;
angle_t sliptiderollangle = 0;
#endif
INT32 dist = -1;
if (cv_grmaxinterpdist.value)
@@ -1258,7 +1269,7 @@ static void R_ProjectSprite(mobj_t *thing)
{
ang = R_PointToAngle (interp.x, interp.y) - interp.angle;
camang = R_PointToAngle (interp.x, interp.y);
if (mirrored)
ang = InvAngle(ang);
}
@@ -1275,9 +1286,9 @@ static void R_ProjectSprite(mobj_t *thing)
// choose a different rotation based on player view
//ang = R_PointToAngle (interp.x, interp.y) - interpangle;
if ((ang < ANGLE_180) && (sprframe->rotate & SRF_RIGHT)) // See from right
if ((sprframe->rotate & SRF_RIGHT) && (ang < ANGLE_180)) // See from right
rot = 6; // F7 slot
else if ((ang >= ANGLE_180) && (sprframe->rotate & SRF_LEFT)) // See from left
else if ((sprframe->rotate & SRF_LEFT) && (ang >= ANGLE_180)) // See from left
rot = 2; // F3 slot
else // Normal behaviour
rot = (ang+ANGLE_202h)>>29;
@@ -1288,7 +1299,7 @@ static void R_ProjectSprite(mobj_t *thing)
}
I_Assert(lump < max_spritelumps);
if (thing->localskin && ((skin_t *)thing->localskin)->flags & SF_HIRES)
this_scale = FixedMul(this_scale, ((skin_t *)thing->localskin)->highresscale);
else if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES)
@@ -1301,7 +1312,7 @@ static void R_ProjectSprite(mobj_t *thing)
#ifdef ROTSPRITE
pitchnroll = 0; // set this to 0, non-paper sprites will affect this value
if (cv_spriteroll.value)
{
if (papersprite)
@@ -1347,10 +1358,10 @@ static void R_ProjectSprite(mobj_t *thing)
if (rotsprite != NULL)
{
spr_width = rotsprite->width << FRACBITS;
spr_height = rotsprite->height << FRACBITS;
spr_offset = rotsprite->leftoffset << FRACBITS;
spr_topoffset = rotsprite->topoffset << FRACBITS;
spr_width = SHORT(rotsprite->width) << FRACBITS;
spr_height = SHORT(rotsprite->height) << FRACBITS;
spr_offset = SHORT(rotsprite->leftoffset) << FRACBITS;
spr_topoffset = SHORT(rotsprite->topoffset) << FRACBITS;
spr_topoffset += FEETADJUST;
// flip -> rotate, not rotate -> flip
@@ -1368,21 +1379,8 @@ static void R_ProjectSprite(mobj_t *thing)
if (spritexscale < 1 || spriteyscale < 1)
return;
if (thing->renderflags & RF_ABSOLUTEOFFSETS)
{
spr_offset = interp.spritexoffset;
spr_topoffset = interp.spriteyoffset;
}
else
{
SINT8 flipoffset = 1;
if ((thing->renderflags & RF_FLIPOFFSETS) && flip)
flipoffset = -1;
spr_offset += interp.spritexoffset * flipoffset;
spr_topoffset += interp.spriteyoffset * flipoffset;
}
spr_offset += interp.spritexoffset;
spr_topoffset += interp.spriteyoffset;
if (flip)
offset = spr_offset - spr_width;
@@ -1459,7 +1457,7 @@ static void R_ProjectSprite(mobj_t *thing)
tx2 += FixedDiv(tx-tx2, div);
tz2 = FixedMul(MINZ, this_scale);
}
if ((tx2 / 4) < -(FixedMul(tz2, fovtan)) || (tx / 4) > FixedMul(tz, fovtan)) // too far off the side?
return;
@@ -1487,7 +1485,7 @@ static void R_ProjectSprite(mobj_t *thing)
return;
range++; // fencepost problem
if (range > 32767)
{
// If the range happens to be too large for fixed_t,
@@ -1530,7 +1528,7 @@ static void R_ProjectSprite(mobj_t *thing)
// PORTAL SPRITE CLIPPING
if (portalrender && portalclipline)
{
if (x2 < portalclipstart || x1 > portalclipend)
if (x2 < portalclipstart || x1 >= portalclipend)
return;
if (P_PointOnLineSide(interp.x, interp.y, portalclipline) != 0)
@@ -1602,7 +1600,6 @@ static void R_ProjectSprite(mobj_t *thing)
// store information in a vissprite
vis = R_NewVisSprite();
vis->renderflags = thing->renderflags;
vis->heightsec = heightsec; //SoM: 3/17/2000
vis->mobjflags = thing->flags;
vis->scale = yscale; //<<detailshift;
@@ -1623,17 +1620,8 @@ static void R_ProjectSprite(mobj_t *thing)
vis->mobj = thing; // Easy access! Tails 06-07-2002
vis->x1 = x1 < 0 ? 0 : x1;
vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
// PORTAL SEMI-CLIPPING
if (portalrender && portalclipline)
{
if (vis->x1 < portalclipstart)
vis->x1 = portalclipstart;
if (vis->x2 > portalclipend)
vis->x2 = portalclipend;
}
vis->x1 = x1 < portalclipstart ? portalclipstart : x1;
vis->x2 = x2 >= portalclipend ? portalclipend-1 : x2;
vis->sector = thing->subsector->sector;
vis->szt = (INT16)((centeryfrac - FixedMul(vis->gzt - viewz, sortscale))>>FRACBITS);
@@ -1843,7 +1831,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
// PORTAL SPRITE CLIPPING
if (portalrender && portalclipline)
{
if (x2 < portalclipstart || x1 > portalclipend)
if (x2 < portalclipstart || x1 >= portalclipend)
return;
if (P_PointOnLineSide(interp.x, interp.y, portalclipline) != 0)
@@ -1877,17 +1865,8 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
vis->scalestep = 0;
vis->paperdistance = 0;
vis->x1 = x1 < 0 ? 0 : x1;
vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
// PORTAL SEMI-CLIPPING
if (portalrender && portalclipline)
{
if (vis->x1 < portalclipstart)
vis->x1 = portalclipstart;
if (vis->x2 > portalclipend)
vis->x2 = portalclipend;
}
vis->x1 = x1 < portalclipstart ? portalclipstart : x1;
vis->x2 = x2 >= portalclipend ? portalclipend-1 : x2;
vis->xscale = xscale; //SoM: 4/17/2000
vis->sector = thing->subsector->sector;
@@ -1987,7 +1966,13 @@ void R_AddPrecipitationSprites(void)
precipmobj_t *th, *next;
// no, no infinite draw distance for precipitation. this option at zero is supposed to turn it off
if (drawdist == 0)
if (drawdist == 0 || curWeather == PRECIP_BLANK || curWeather == PRECIP_STORM_NORAIN)
{
return;
}
// do not render in skybox
if (portalskipprecipmobjs)
{
return;
}
@@ -2015,46 +2000,47 @@ void R_AddPrecipitationSprites(void)
//
// R_SortVisSprites
//
static vissprite_t vsprsortedhead;
void R_SortVisSprites(void)
static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 end)
{
UINT32 i;
UINT32 i, count = 0;
vissprite_t *ds, *dsprev, *dsnext, *dsfirst;
vissprite_t *best = NULL;
vissprite_t unsorted;
fixed_t bestscale;
INT32 bestdispoffset;
if (!visspritecount)
return;
dsfirst = &unsorted;
dsprev = dsfirst;
dsnext = dsfirst;
unsorted.next = unsorted.prev = &unsorted;
I_Assert(start <= end);
dsfirst = R_GetVisSprite(0);
// The first's prev and last's next will be set to
// nonsense, but are fixed in a moment
for (i = 0, dsnext = dsfirst, ds = NULL; i < visspritecount; i++)
for (i = start; i < end; ++i)
{
dsprev = ds;
ds = dsnext;
if (i < visspritecount - 1) dsnext = R_GetVisSprite(i + 1);
ds = R_GetVisSprite(i);
ds->next = dsnext;
ds->prev = dsprev;
// Do not include this sprite, since it is completely obscured
if (ds->cut & SC_NOTVISIBLE)
{
continue;
}
dsnext = ds;
dsprev->next = dsnext;
dsnext->prev = dsprev;
dsprev = dsnext;
count++;
}
// Fix first and last. ds still points to the last one after the loop
dsfirst->prev = &unsorted;
unsorted.next = dsfirst;
if (ds)
ds->next = &unsorted;
unsorted.prev = ds;
dsnext->next = dsfirst;
dsfirst->prev = dsnext;
// pull the vissprites out by scale
vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead;
for (i = 0; i < visspritecount; i++)
vsprsortedhead->next = vsprsortedhead->prev = vsprsortedhead;
for (i = 0; i < count; i++)
{
bestscale = bestdispoffset = INT32_MAX;
for (ds = unsorted.next; ds != &unsorted; ds = ds->next)
@@ -2080,15 +2066,12 @@ void R_SortVisSprites(void)
best = ds;
}
}
if (best)
{
best->next->prev = best->prev;
best->prev->next = best->next;
best->next = &vsprsortedhead;
best->prev = vsprsortedhead.prev;
vsprsortedhead.prev->next = best;
vsprsortedhead.prev = best;
}
best->next->prev = best->prev;
best->prev->next = best->next;
best->next = vsprsortedhead;
best->prev = vsprsortedhead->prev;
vsprsortedhead->prev->next = best;
vsprsortedhead->prev = best;
}
}
@@ -2098,28 +2081,28 @@ void R_SortVisSprites(void)
static drawnode_t *R_CreateDrawNode(drawnode_t *link);
static drawnode_t nodebankhead;
static drawnode_t nodehead;
static void R_CreateDrawNodes(void)
static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean tempskip)
{
drawnode_t *entry;
drawseg_t *ds;
INT32 i, p, best, x1, x2;
fixed_t bestdelta, delta;
vissprite_t *rover;
static vissprite_t vsprsortedhead;
drawnode_t *r2;
visplane_t *plane;
INT32 sintersect;
fixed_t scale = 0;
// Add the 3D floors, thicksides, and masked textures...
for (ds = ds_p; ds-- > drawsegs ;)
for (ds = drawsegs + mask->drawsegs[1]; ds-- > drawsegs + mask->drawsegs[0];)
{
if (ds->numthicksides)
{
for (i = 0; i < ds->numthicksides; i++)
{
entry = R_CreateDrawNode(&nodehead);
entry = R_CreateDrawNode(head);
entry->thickseg = ds;
entry->ffloor = ds->thicksides[i];
}
@@ -2135,7 +2118,7 @@ static void R_CreateDrawNodes(void)
else
{
// Put it in!
entry = R_CreateDrawNode(&nodehead);
entry = R_CreateDrawNode(head);
entry->plane = plane;
entry->seg = ds;
}
@@ -2143,7 +2126,7 @@ static void R_CreateDrawNodes(void)
}
if (ds->maskedtexturecol)
{
entry = R_CreateDrawNode(&nodehead);
entry = R_CreateDrawNode(head);
entry->seg = ds;
}
if (ds->numffloorplanes)
@@ -2175,7 +2158,7 @@ static void R_CreateDrawNodes(void)
}
if (best != -1)
{
entry = R_CreateDrawNode(&nodehead);
entry = R_CreateDrawNode(head);
entry->plane = ds->ffloorplanes[best];
entry->seg = ds;
ds->ffloorplanes[best] = NULL;
@@ -2186,6 +2169,9 @@ static void R_CreateDrawNodes(void)
}
}
if (tempskip)
return;
// find all the remaining polyobject planes and add them on the end of the list
// probably this is a terrible idea if we wanted them to be sorted properly
// but it works getting them in for now
@@ -2201,16 +2187,18 @@ static void R_CreateDrawNodes(void)
PolyObjects[i].visplane = NULL;
continue;
}
entry = R_CreateDrawNode(&nodehead);
entry = R_CreateDrawNode(head);
entry->plane = plane;
// note: no seg is set, for what should be obvious reasons
PolyObjects[i].visplane = NULL;
}
if (visspritecount == 0)
// No vissprites in this mask?
if (mask->vissprites[1] - mask->vissprites[0] == 0)
return;
R_SortVisSprites();
R_SortVisSprites(&vsprsortedhead, mask->vissprites[0], mask->vissprites[1]);
for (rover = vsprsortedhead.prev; rover != &vsprsortedhead; rover = rover->prev)
{
if (rover->szt > vid.height || rover->sz < 0)
@@ -2218,7 +2206,7 @@ static void R_CreateDrawNodes(void)
sintersect = (rover->x1 + rover->x2) / 2;
for (r2 = nodehead.next; r2 != &nodehead; r2 = r2->next)
for (r2 = head->next; r2 != head; r2 = r2->next)
{
if (r2->plane)
{
@@ -2357,9 +2345,9 @@ static void R_CreateDrawNodes(void)
}
}
}
if (r2 == &nodehead)
if (r2 == head)
{
entry = R_CreateDrawNode(&nodehead);
entry = R_CreateDrawNode(head);
entry->sprite = rover;
}
}
@@ -2391,7 +2379,7 @@ static drawnode_t *R_CreateDrawNode(drawnode_t *link)
node->thickseg = NULL;
node->ffloor = NULL;
node->sprite = NULL;
ps_numdrawnodes.value.i++;
return node;
}
@@ -2403,25 +2391,24 @@ static void R_DoneWithNode(drawnode_t *node)
(node->prev = &nodebankhead)->next = node;
}
static void R_ClearDrawNodes(void)
static void R_ClearDrawNodes(drawnode_t* head)
{
drawnode_t *rover;
drawnode_t *next;
for (rover = nodehead.next; rover != &nodehead ;)
for (rover = head->next; rover != head;)
{
next = rover->next;
R_DoneWithNode(rover);
rover = next;
}
nodehead.next = nodehead.prev = &nodehead;
head->next = head->prev = head;
}
void R_InitDrawNodes(void)
{
nodebankhead.next = nodebankhead.prev = &nodebankhead;
nodehead.next = nodehead.prev = &nodehead;
}
//
@@ -2450,8 +2437,8 @@ static boolean R_CheckSpriteVisible(vissprite_t *spr, INT32 x1, INT32 x2)
INT16 sz = spr->sz;
INT16 szt = spr->szt;
fixed_t texturemid, yscale, scalestep = spr->scalestep;
INT32 height;
fixed_t texturemid = 0, yscale = 0, scalestep = spr->scalestep; // "= 0" pleases the compiler
INT32 height = 0;
if (scalestep)
{
@@ -2485,7 +2472,7 @@ static boolean R_CheckSpriteVisible(vissprite_t *spr, INT32 x1, INT32 x2)
// R_ClipVisSprite
// Clips vissprites without drawing, so that portals can work. -Red
static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2)
static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* portal)
{
drawseg_t *ds;
INT32 x;
@@ -2524,8 +2511,36 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2)
ds = curr->user;
if (ds->portalpass > 0 && ds->portalpass <= portalrender)
continue; // is a portal
if (ds->portalpass != 66) // unused?
{
if (ds->portalpass > 0 && ds->portalpass <= portalrender)
continue; // is a portal
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)))
{
// masked mid texture?
/*
if (ds->maskedtexturecol)
R_RenderMaskedSegRange (ds, r1, r2);
*/
// seg is behind sprite
continue;
}
}
r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1;
r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2;
@@ -2668,7 +2683,7 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2)
if (spr->cliptop[x] == -2)
spr->cliptop[x] = -1;
}
// Check if it'll be visible
// Not done for floorsprites.
if (cv_spriteclip.value)
@@ -2676,11 +2691,34 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2)
if (!R_CheckSpriteVisible(spr, x1, x2))
spr->cut |= SC_NOTVISIBLE;
}
if (portal)
{
INT32 start_index = max(portal->start, x1);
INT32 end_index = min(portal->start + portal->end - portal->start, x2);
for (x = x1; x < start_index; x++)
{
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])
spr->clipbot[x] = portal->floorclip[x - portal->start];
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;
}
}
}
void R_ClipSprites(void)
void R_ClipSprites(drawseg_t* dsstart, portal_t* portal)
{
const size_t maxdrawsegs = ds_p - drawsegs;
const size_t maxdrawsegs = ds_p - dsstart;
const INT32 cx = viewwidth / 2;
drawseg_t* ds;
INT32 i;
@@ -2713,7 +2751,7 @@ void R_ClipSprites(void)
}
}
for (ds = ds_p; ds-- > drawsegs;)
for (ds = ds_p; ds-- > dsstart;)
{
if (ds->silhouette || ds->maskedtexturecol)
{
@@ -2743,7 +2781,7 @@ void R_ClipSprites(void)
for (; clippedvissprites < visspritecount; clippedvissprites++)
{
vissprite_t *spr = R_GetVisSprite(clippedvissprites);
if (cv_spriteclip.value
&& (spr->szt > vid.height || spr->sz < 0))
{
@@ -2767,8 +2805,8 @@ void R_ClipSprites(void)
drawsegs_xrange_count = drawsegs_xranges[0].count;
}
R_ClipVisSprite(spr, spr->x1, spr->x2);
R_ClipVisSprite(spr, spr->x1, spr->x2, portal);
if ((spr->cut & SC_NOTVISIBLE) == 0)
numvisiblesprites++;
}
@@ -2785,10 +2823,10 @@ boolean R_ThingVisible (mobj_t *thing)
if (splitscreen)
{
if ((viewssnum == 0 && (thing->renderflags & MFE_DRAWONLYFORP1))
|| (viewssnum == 1 && (thing->renderflags & MFE_DRAWONLYFORP2))
|| (viewssnum == 2 && (thing->renderflags & MFE_DRAWONLYFORP2))
|| (viewssnum == 3 && (thing->renderflags & MFE_DRAWONLYFORP4)))
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;
}
@@ -2812,14 +2850,12 @@ boolean R_ThingWithinDist (mobj_t *thing, fixed_t limit_dist)
//
// R_DrawMasked
//
void R_DrawMasked(void)
static void R_DrawMaskedList (drawnode_t* head)
{
drawnode_t *r2;
drawnode_t *next;
R_CreateDrawNodes();
for (r2 = nodehead.next; r2 != &nodehead; r2 = r2->next)
for (r2 = head->next; r2 != head; r2 = r2->next)
{
if (r2->plane)
{
@@ -2857,7 +2893,39 @@ void R_DrawMasked(void)
r2 = next;
}
}
R_ClearDrawNodes();
}
void R_DrawMasked(maskcount_t* masks, INT32 nummasks)
{
drawnode_t *heads; /**< Drawnode lists; as many as number of views/portals. */
INT32 i;
heads = calloc(nummasks, sizeof(drawnode_t));
for (i = 0; i < nummasks; i++)
{
heads[i].next = heads[i].prev = &heads[i];
viewx = masks[i].viewx;
viewy = masks[i].viewy;
viewz = masks[i].viewz;
viewsector = masks[i].viewsector;
R_CreateDrawNodes(&masks[i], &heads[i], false);
}
for (; nummasks > 0; nummasks--)
{
viewx = masks[nummasks - 1].viewx;
viewy = masks[nummasks - 1].viewy;
viewz = masks[nummasks - 1].viewz;
viewsector = masks[nummasks - 1].viewsector;
R_DrawMaskedList(&heads[nummasks - 1]);
R_ClearDrawNodes(&heads[nummasks - 1]);
}
free(heads);
}
// ==========================================================================
@@ -3295,7 +3363,7 @@ static int skinSortFunc(const void *a, const void *b) //tbh i have no clue what
void sortSkinGrid(void)
{
//CONS_Printf("Sorting skin list (%d)...\n", cv_skinselectgridsort.value);
qs22j(skinsorted, numskins, sizeof(UINT8), skinSortFunc);
qs22j(skinsorted, numskins, sizeof(UINT8), skinSortFunc);
}
//
@@ -3579,7 +3647,7 @@ next_token:
Forceskin_cons_t[numskins+1].value = numskins;
Forceskin_cons_t[numskins+1].strvalue = skins[numskins].name;
}
skin->localskin = local;
// so we dont have to guess
@@ -3606,7 +3674,7 @@ next_token:
CONS_Debug(DBG_SETUP, M_GetText("Incremented %d, %d to %d\n"), skin->kartspeed, skin->kartweight, skinstatscount[skin->kartspeed - 1][skin->kartweight - 1]);
skinsorted[numskins] = numskins;
}
allskins[numallskins] = ( (local) ? localskins : skins )[( (local) ? numlocalskins : numskins )];
local ? numlocalskins++ : numskins++;
+16 -3
View File
@@ -16,6 +16,7 @@
#include "sounds.h"
#include "r_plane.h"
#include "r_portal.h"
#include "r_patch.h"
// "Left" and "Right" character symbols for additional rotation functionality
@@ -55,11 +56,11 @@ extern fixed_t sprtopscreen;
extern fixed_t sprbotscreen;
extern fixed_t windowtop;
extern fixed_t windowbottom;
extern INT32 lengthcol;
fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope);
void R_DrawMaskedColumn(column_t *column);
void R_SortVisSprites(void);
//faB: find sprites in wadfile, replace existing, add new ones
// (only sprites from namelist are added or replaced)
@@ -70,7 +71,19 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel);
void R_AddPrecipitationSprites(void);
void R_InitSprites(void);
void R_ClearSprites(void);
void R_DrawMasked(void);
/** Used to count the amount of masked elements
* per portal to later group them in separate
* drawnode lists.
*/
typedef struct
{
size_t drawsegs[2];
size_t vissprites[2];
fixed_t viewx, viewy, viewz; /**< View z stored at the time of the BSP traversal for the view/portal. Masked sorting/drawing needs it. */
sector_t* viewsector;
} maskcount_t;
void R_DrawMasked(maskcount_t* masks, INT32 nummasks);
boolean R_ThingVisible (mobj_t *thing);
boolean R_ThingWithinDist (mobj_t *thing, fixed_t limit_dist);
@@ -192,7 +205,7 @@ typedef struct vissprite_s
extern UINT32 visspritecount, numvisiblesprites;
void R_ClipSprites(void);
void R_ClipSprites(drawseg_t* dsstart, portal_t* portal);
UINT8 *R_GetSpriteTranslation(vissprite_t *vis);
+154 -47
View File
@@ -11,6 +11,7 @@
/// \file s_sound.c
/// \brief System-independent sound and music routines
#include "d_netcmd.h"
#include "doomdef.h"
#include "doomstat.h"
#include "command.h"
@@ -85,7 +86,6 @@ consvar_t cv_midimusicvolume = {"midimusicvolume", "18", CV_SAVE, soundvolume_co
// number of channels available
consvar_t cv_numChannels = {"snd_channels", "64", CV_SAVE|CV_CALL, CV_Unsigned, SetChannelsNum, 0, NULL, NULL, 0, 0, NULL};
consvar_t surround = {"surround", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
//consvar_t cv_resetmusic = {"resetmusic", "No", CV_SAVE|CV_NOSHOWHELP, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
// Sound system toggles, saved into the config
@@ -108,6 +108,7 @@ static CV_PossibleValue_t music_resync_threshold_cons_t[] = {
{0}
};
consvar_t cv_music_resync_threshold = {"music_resync_threshold", "0", CV_SAVE|CV_CALL, music_resync_threshold_cons_t, I_UpdateSongLagThreshold, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_music_resync_powerups_only = {"music_resync_powerups_only", "No", CV_SAVE|CV_CALL, CV_YesNo, I_UpdateSongLagThreshold, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_invincmusicfade = {"invincmusicfade", "300", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_growmusicfade = {"growmusicfade", "500", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -118,6 +119,14 @@ consvar_t cv_resume = {"resume", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0
consvar_t cv_fading = {"fading", "Off", CV_SAVE|CV_CALL, CV_OnOff, Bird_menu_Onchange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_birdmusic = {"birdmusicstuff", "No", CV_SAVE|CV_CALL, CV_YesNo, Bird_menu_Onchange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_keepmusic = {"keepmusic", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_skipintromusic = {"skipintromusic", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
//consvar_t cv_ignoremusicchanges = {"ignoremusicchanges", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
boolean keepmusic = false;
static void S_CheckEventMus(const char *newmus);
#ifdef HAVE_OPENMPT
openmpt_module *openmpt_mhandle = NULL;
@@ -163,10 +172,6 @@ consvar_t cv_amigatype = {"amigatype", "0", CV_SAVE|CV_CALL|CV_NOINIT, amigatype
#define S_PITCH_PERTURB 1
#define S_STEREO_SWING (96*0x10000)
#ifdef SURROUND
#define SURROUND_SEP -128
#endif
// percent attenuation from front to back
#define S_IFRACVOL 30
@@ -272,7 +277,6 @@ void S_RegisterSoundStuff(void)
CV_RegisterVar(&stereoreverse);
CV_RegisterVar(&precachesound);
CV_RegisterVar(&surround);
CV_RegisterVar(&cv_samplerate);
//CV_RegisterVar(&cv_resetmusic);
CV_RegisterVar(&cv_gamesounds);
@@ -281,13 +285,14 @@ void S_RegisterSoundStuff(void)
CV_RegisterVar(&cv_gamemidimusic);
#endif
//bird music stuff
// bird music stuff
CV_RegisterVar(&cv_playmusicifunfocused);
CV_RegisterVar(&cv_playsoundifunfocused);
CV_RegisterVar(&cv_pausemusic);
CV_RegisterVar(&cv_music_resync_threshold);
CV_RegisterVar(&cv_music_resync_powerups_only);
CV_RegisterVar(&cv_invincmusicfade);
CV_RegisterVar(&cv_growmusicfade);
@@ -299,6 +304,11 @@ void S_RegisterSoundStuff(void)
CV_RegisterVar(&cv_resume);
CV_RegisterVar(&cv_fading);
CV_RegisterVar(&cv_birdmusic);
// bird music stuff end
CV_RegisterVar(&cv_keepmusic);
CV_RegisterVar(&cv_skipintromusic);
//CV_RegisterVar(&cv_ignoremusicchanges);
COM_AddCommand("tunes", Command_Tunes_f);
COM_AddCommand("restartaudio", Command_RestartAudio_f);
@@ -616,11 +626,7 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
}
// Avoid channel reverse if surround
if (reverse
#ifdef SURROUND
&& sep != SURROUND_SEP
#endif
)
if (reverse)
{
sep = (~sep) & 255;
}
@@ -1102,18 +1108,10 @@ boolean S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32
if (reverse)
angle = InvAngle(angle);
#ifdef SURROUND
// Produce a surround sound for angle from 105 till 255
if (surround.value == 1 && (angle > ANG105 && angle < ANG255 ))
*sep = SURROUND_SEP;
else
#endif
{
angle >>= ANGLETOFINESHIFT;
angle >>= ANGLETOFINESHIFT;
// stereo separation
*sep = 128 - (FixedMul(S_STEREO_SWING, FINESINE(angle))>>FRACBITS);
}
// stereo separation
*sep = 128 - (FixedMul(S_STEREO_SWING, FINESINE(angle))>>FRACBITS);
}
// volume calculation
@@ -1260,7 +1258,7 @@ void S_InitSfxChannels(INT32 sfxVolume)
if (S_PrecacheSound())
{
// Initialize external data (all sounds) at start, keep static.
CONS_Printf(M_GetText("Loading sounds... "));
CONS_Printf(M_GetText("Pre-caching sounds..."));
for (i = 1; i < sfx_freeslot0; i++)
if (S_sfx[i].name && !S_sfx[i].data)
@@ -1270,7 +1268,7 @@ void S_InitSfxChannels(INT32 sfxVolume)
if (S_sfx[i].priority && !S_sfx[i].data)
S_sfx[i].data = I_GetSfx(&S_sfx[i]);
CONS_Printf(M_GetText(" pre-cached all sound data\n"));
CONS_Printf(M_GetText("...pre-cached all sound data\n"));
}
}
@@ -1786,9 +1784,7 @@ boolean S_MusicPaused(void)
boolean S_MusicNotInFocus(void)
{
return (
( window_notinfocus && ! cv_playmusicifunfocused.value )
);
return (window_notinfocus && !cv_playmusicifunfocused.value);
}
musictype_t S_MusicType(void)
@@ -1816,10 +1812,8 @@ boolean S_MusicInfo(char *mname, UINT16 *mflags, boolean *looping)
boolean S_MusicExists(const char *mname, boolean checkMIDI, boolean checkDigi)
{
return (
(checkDigi ? W_CheckNumForName(va("O_%s", mname)) != LUMPERROR : false)
|| (checkMIDI ? W_CheckNumForName(va("D_%s", mname)) != LUMPERROR : false)
);
return (checkDigi ? W_CheckNumForName(va("O_%s", mname)) != LUMPERROR : false)
|| (checkMIDI ? W_CheckNumForName(va("D_%s", mname)) != LUMPERROR : false);
}
/// ------------------------
@@ -1979,6 +1973,8 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32
strncpy(newmusic, mmusic, 6);
S_CheckEventMus(newmusic);
if (LUAh_MusicChange(music_name, newmusic, &mflags, &looping, &position, &prefadems, &fadeinms))
return;
@@ -2052,8 +2048,10 @@ void S_StopMusic(void)
|| demo.title) // SRB2Kart: Demos don't interrupt title screen music
return;
if ((cv_birdmusic.value) && (strcasecmp(music_name, mapmusname) == 0))
if (cv_birdmusic.value && (strcasecmp(music_name, mapmusname) == 0))
mapmusresume = I_GetSongPosition();
else
mapmusresume = 0;
if (I_SongPaused())
I_ResumeSong();
@@ -2126,10 +2124,7 @@ void S_SetMusicVolume(INT32 digvolume, INT32 seqvolume)
void S_SetRestoreMusicFadeInCvar (consvar_t *cv)
{
if (!cv_birdmusic.value)
return;
music_refade_cv = cv;
music_refade_cv = cv_birdmusic.value ? cv : 0;
}
int S_GetRestoreMusicFadeIn (void)
@@ -2171,13 +2166,92 @@ boolean S_FadeOutStopMusic(UINT32 ms)
/// Init & Others
/// ------------------------
/*static boolean S_KeepMusic(void)
{
//if (!cv_keepmusic.value)
//return false;
// should i compare songs or maps?
static char oldmusname[7] = "";
if (strcmp(music_name, mapmusname) != 0)
return false;
if (strcmp(oldmusname, mapmusname) == 0)
return true;
strncpy(oldmusname, mapmusname, 7);
oldmusname[6] = '\0';
return false;
}*/
static INT16 oldmap = 0;
static boolean oldencore = false;
static boolean skipmusic = false;
boolean skipintromus = false;
static const char *musicexception_list[16] = {
"vote", "voteea", "voteeb", "racent", "krwin",
"krok", "krlose", "krfail", "kbwin", "kbok",
"kblose", "kstart", "estart", "wait2j", "CHRSHP",
"CHRSHF"
};
//checks for any kind of event music like intermission, vote etc.
//always runs when musicchange gets invoked
static void S_CheckEventMus(const char *newmus)
{
skipmusic = false;
if (!cv_keepmusic.value)
return;
for (int i = 0; i < 16; i++)
if (stricmp(music_name, musicexception_list[i]) == 0 || stricmp(newmus, musicexception_list[i]) == 0) // weird? sure! but were lucky enough newmus reflects whats being replaced
{
skipmusic = true;
break;
}
//CONS_Printf("musname = %s\n", music_name);
//CONS_Printf("newmus = %s\n", newmus);
//CONS_Printf("newmus = %d\n", skipmusic);
}
//this one compares map and encoremode instead of the music itself
//makes tunes work and stuff
void S_CheckMap(void)
{
if (!cv_keepmusic.value)
{
keepmusic = false;
return;
}
keepmusic = (!skipmusic && gamestate == GS_LEVEL && oldmap == gamemap && oldencore == encoremode);
oldencore = encoremode;
oldmap = gamemap;
}
//
// Per level startup code.
// Kills playing sounds at start of level,
// determines music if any, changes music.
//
void S_Start(void)
void S_InitMapMusic(void)
{
if (!cv_skipintromusic.value)
skipintromus = false;
else
{
char *maptitle = G_BuildMapTitle(gamemap);
skipintromus = cv_skipintromusic.value && stricmp(maptitle, "Wandering Falls") != 0; // thanks diggle!
if (maptitle)
Z_Free(maptitle);
}
if (mapmusflags & MUSIC_RELOADRESET)
{
strncpy(mapmusname, mapheaderinfo[gamemap-1]->musname, 7);
@@ -2187,13 +2261,48 @@ void S_Start(void)
mapmusresume = 0;
}
//if (cv_resetmusic.value) // Starting ambience should always be restarted
S_StopMusic();
if (keepmusic)
return;
if (leveltime < (starttime + (TICRATE/2))) // SRB2Kart
S_ChangeMusicEx((encoremode ? "estart" : "kstart"), 0, false, mapmusposition, 0, 0);
else
// Starting ambience should always be restarted
// lug: but not when we keep the map music lol
S_StopMusic();
if (skipintromus)
return;
if (leveltime < MUSICSTARTTIME) // SRB2Kart
S_ChangeMusicInternal((encoremode ? "estart" : "kstart"), false); //S_StopMusic();
//S_ChangeMusicEx((encoremode ? "estart" : "kstart"), 0, false, mapmusposition, 0, 0);
}
void S_StartMapMusic(boolean restore)
{
//no need to constantly run this after race has started
if (leveltime > MUSICSTARTTIME)
return;
if (keepmusic && !restore) // make sure this doesent kill the music when its called from P_RestoreMusic in some cases
return;
if (skipintromus)
{
if (leveltime < starttime)
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
if (leveltime == MUSICSTARTTIME)
S_ShowMusicCredit();
return;
}
if (leveltime < starttime) // SRB2Kart
S_ChangeMusicInternal((encoremode ? "estart" : "kstart"), false); // yes this will be spammed otherwise encore and some stuff WILL overwrite it
else if (leveltime == starttime) // The GO! sound stops the level start ambience
S_StopMusic();
else if (leveltime == MUSICSTARTTIME) // Plays the music after the starting countdown.
{
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
S_ShowMusicCredit();
}
}
void S_RestartMusic(void)
@@ -2388,7 +2497,7 @@ static void GameDigiMusic_OnChange(void)
digital_disabled = false;
I_StartupSound(); // will return early if initialised
I_InitMusic();
if (Playing())
P_RestoreMusic(&players[consoleplayer]);
else
@@ -2425,14 +2534,12 @@ static void ModFilter_OnChange(void)
{
if (openmpt_mhandle)
openmpt_module_set_render_param(openmpt_mhandle, OPENMPT_MODULE_RENDER_INTERPOLATIONFILTER_LENGTH, cv_modfilter.value);
}
static void StereoSep_OnChange(void)
{
if (openmpt_mhandle)
openmpt_module_set_render_param(openmpt_mhandle, OPENMPT_MODULE_RENDER_STEREOSEPARATION_PERCENT, cv_stereosep.value);
}
static void AmigaFilter_OnChange(void)
+13 -2
View File
@@ -32,7 +32,6 @@ extern consvar_t stereoreverse;
extern consvar_t cv_soundvolume, cv_digmusicvolume;//, cv_midimusicvolume;
extern consvar_t cv_numChannels;
extern consvar_t surround;
extern consvar_t cv_audbuffersize;
//extern consvar_t cv_resetmusic;
extern consvar_t cv_gamedigimusic;
@@ -55,6 +54,7 @@ extern consvar_t cv_amigatype;
//bird music stuff
extern consvar_t cv_music_resync_threshold;
extern consvar_t cv_music_resync_powerups_only;
extern consvar_t cv_invincmusicfade;
extern consvar_t cv_growmusicfade;
@@ -68,6 +68,13 @@ extern consvar_t cv_resume;
extern consvar_t cv_fading;
extern consvar_t cv_birdmusic;
extern consvar_t cv_keepmusic;
extern consvar_t cv_skipintromusic;
//extern consvar_t cv_ignoremusicchanges;
extern boolean keepmusic;
extern boolean skipintromus;
#define MUSICSTARTTIME (starttime + (TICRATE/2))
extern consvar_t precachesound;
typedef enum
@@ -101,7 +108,11 @@ void S_InitSfxChannels(INT32 sfxVolume);
//
void S_StopSounds(void);
void S_ClearSfx(void);
void S_Start(void);
void S_InitMapMusic(void);
void S_StartMapMusic(boolean restore);
void S_CheckMap(void);
// Stops music and restarts it from same position. Used for instant applying changes to amiga filters.
void S_RestartMusic(void);
+29 -12
View File
@@ -366,15 +366,13 @@ double averageFPS = 0.0f;
#define USE_FPS_SAMPLES
#ifdef USE_FPS_SAMPLES
#define MAX_FRAME_TIME 0.05
#define MAX_FRAME_TIME (0.05)
#define NUM_FPS_SAMPLES (16) // Number of samples to store
#define NUM_FPS_SAMPLES2 (32) // Number of samples to store for inaccurate counter
static double total_frame_time = 0.0;
static int frame_index;
static double fps_samples[NUM_FPS_SAMPLES2];
static int fps_index;
static double fps_samples[NUM_FPS_SAMPLES];
#endif
static boolean fps_init = false;
@@ -383,7 +381,6 @@ static precise_t fps_enter = 0;
void SCR_CalculateFPS(void)
{
precise_t fps_finish = 0;
int i;
double frameElapsed = 0.0;
@@ -398,10 +395,10 @@ void SCR_CalculateFPS(void)
fps_enter = fps_finish;
#ifdef USE_FPS_SAMPLES
total_frame_time += frameElapsed;
if (cv_accuratefps.value)
{
total_frame_time += frameElapsed;
if (frame_index++ >= NUM_FPS_SAMPLES || total_frame_time >= MAX_FRAME_TIME)
{
averageFPS = 1.0 / (total_frame_time / frame_index);
@@ -411,13 +408,33 @@ void SCR_CalculateFPS(void)
}
else
{
fps_samples[fps_index] = frameElapsed / NUM_FPS_SAMPLES2;
fps_index = (fps_index + 1) % NUM_FPS_SAMPLES2;
if (total_frame_time >= MAX_FRAME_TIME)
{
static int sampleIndex = 0;
int i;
averageFPS = 0.0;
for (i = 0; i < NUM_FPS_SAMPLES2; i++)
averageFPS += fps_samples[i];
averageFPS = 1.0 / averageFPS;
fps_samples[sampleIndex] = frameElapsed;
sampleIndex++;
if (sampleIndex >= NUM_FPS_SAMPLES)
sampleIndex = 0;
averageFPS = 0.0;
for (i = 0; i < NUM_FPS_SAMPLES; i++)
{
averageFPS += fps_samples[i];
}
if (averageFPS > 0.0)
{
averageFPS = 1.0 / (averageFPS / NUM_FPS_SAMPLES);
}
}
while (total_frame_time >= MAX_FRAME_TIME)
{
total_frame_time -= MAX_FRAME_TIME;
}
}
#else
// Direct, unsampled counter.
+3 -3
View File
@@ -39,12 +39,12 @@
// we try to re-allocate a minimum of buffers for stability of the memory,
// so all the small-enough tables based on screen size, are allocated once
// and for all at the maximum size.
#define MAXVIDWIDTH 2560 // don't set this too high because actually
#define MAXVIDHEIGHT 1440 // lots of tables are allocated with the MAX size.
#define MAXVIDWIDTH 5120 // don't set this too high because actually
#define MAXVIDHEIGHT 2880 // lots of tables are allocated with the MAX size.
#define BASEVIDWIDTH 320 // NEVER CHANGE THIS! This is the original
#define BASEVIDHEIGHT 200 // resolution of the graphics.
// max res for png capture; seperated it so both MAXVID values can be lower for software performance reasons; OpenGL does not care about those anyways
// max res for png capture; just here to prevent some crashes on very high resoltions; tho you should never go this high cause ogl allocs certain things with MAXVIDWIDTH and MAXVIDHEIGHT too Zzz...
#define MAXPNGWIDTH 7680
#define MAXPNGHEIGHT 4320
+93 -92
View File
@@ -47,11 +47,7 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T);
// May be incorrect for other platforms, but we don't currently have a way to
// query the scheduler granularity. SDL will do what's needed to make this as
// low as possible though.
#if defined(_WIN32)
#define MIN_SLEEP_DURATION_MS 1.6
#else
#define MIN_SLEEP_DURATION_MS 2.1
#endif
#include <stdio.h>
#include <time.h>
@@ -115,6 +111,7 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T);
#endif
#if defined (__unix__) || (defined (UNIXCOMMON) && !defined (__APPLE__))
#include <poll.h>
#include <errno.h>
#include <sys/wait.h>
#define NEWSIGNALHANDLER
@@ -548,10 +545,9 @@ typedef struct
feild_t tty_con;
// when printing general stuff to stdout stderr (Sys_Printf)
// we need to disable the tty console stuff
// this increments so we can recursively disable
static INT32 ttycon_hide = 0;
// lock to prevent clearing partial lines, since not everything
// printed ends on a newline.
static boolean ttycon_ateol = true;
// some key codes that the terminal may be using
// TTimo NOTE: I'm not sure how relevant this is
static INT32 tty_erase;
@@ -579,63 +575,31 @@ static inline void tty_FlushIn(void)
// TTimo NOTE: it seems on some terminals just sending '\b' is not enough
// so for now, in any case we send "\b \b" .. yeah well ..
// (there may be a way to find out if '\b' alone would work though)
// Hanicef NOTE: using \b this way is unreliable because of terminal state,
// it's better to use \r to reset the cursor to the beginning of the
// line and clear from there.
static void tty_Back(void)
{
char key;
ssize_t d;
key = '\b';
d = write(STDOUT_FILENO, &key, 1);
key = ' ';
d = write(STDOUT_FILENO, &key, 1);
key = '\b';
d = write(STDOUT_FILENO, &key, 1);
(void)d;
write(STDOUT_FILENO, "\r", 1);
if (tty_con.cursor>0)
{
write(STDOUT_FILENO, tty_con.buffer, tty_con.cursor);
}
write(STDOUT_FILENO, " \b", 2);
}
static void tty_Clear(void)
{
size_t i;
write(STDOUT_FILENO, "\r", 1);
if (tty_con.cursor>0)
{
for (i=0; i<tty_con.cursor; i++)
{
tty_Back();
write(STDOUT_FILENO, " ", 1);
}
write(STDOUT_FILENO, "\r", 1);
}
}
// clear the display of the line currently edited
// bring cursor back to beginning of line
static inline void tty_Hide(void)
{
//I_Assert(consolevent);
if (ttycon_hide)
{
ttycon_hide++;
return;
}
tty_Clear();
ttycon_hide++;
}
// show the current line
// FIXME TTimo need to position the cursor if needed??
static inline void tty_Show(void)
{
size_t i;
ssize_t d;
//I_Assert(consolevent);
I_Assert(ttycon_hide>0);
ttycon_hide--;
if (ttycon_hide == 0 && tty_con.cursor)
{
for (i=0; i<tty_con.cursor; i++)
{
d = write(STDOUT_FILENO, tty_con.buffer+i, 1);
}
}
(void)d;
}
// never exit without calling this, or your terminal will be left in a pretty bad state
@@ -702,50 +666,65 @@ void I_GetConsoleEvents(void)
// we use this when sending back commands
event_t ev = {0,0,0,0};
char key = 0;
ssize_t d;
struct pollfd pfd =
{
.fd = STDIN_FILENO,
.events = POLLIN,
.revents = 0,
};
if (!consolevent)
return;
ev.type = ev_console;
ev.data1 = 0;
if (read(STDIN_FILENO, &key, 1) == -1 || !key)
return;
for (;;)
{
if (poll(&pfd, 1, 0) < 1 || !(pfd.revents & POLLIN))
return;
// we have something
// backspace?
// NOTE TTimo testing a lot of values .. seems it's the only way to get it to work everywhere
if ((key == tty_erase) || (key == 127) || (key == 8))
{
if (tty_con.cursor > 0)
ev.type = ev_console;
ev.data1 = 0;
if (read(STDIN_FILENO, &key, 1) == -1 || !key)
return;
// we have something
// backspace?
// NOTE TTimo testing a lot of values .. seems it's the only way to get it to work everywhere
if ((key == tty_erase) || (key == 127) || (key == 8))
{
tty_con.cursor--;
tty_con.buffer[tty_con.cursor] = '\0';
tty_Back();
if (tty_con.cursor > 0)
{
tty_con.cursor--;
tty_con.buffer[tty_con.cursor] = '\0';
tty_Back();
}
ev.data1 = KEY_BACKSPACE;
}
ev.data1 = KEY_BACKSPACE;
}
else if (key < ' ') // check if this is a control char
{
if (key == '\n')
else if (key < ' ') // check if this is a control char
{
tty_Clear();
tty_con.cursor = 0;
ev.data1 = KEY_ENTER;
if (key == '\n')
{
tty_Clear();
tty_con.cursor = 0;
ev.data1 = KEY_ENTER;
}
else if (key == 0x4) // ^D, aka EOF
{
// shut down, most unix programs behave this way
I_Quit();
}
else continue;
}
else return;
else if (tty_con.cursor < sizeof(tty_con.buffer))
{
// push regular character
ev.data1 = tty_con.buffer[tty_con.cursor] = key;
tty_con.cursor++;
// print the current line (this is differential)
write(STDOUT_FILENO, &key, 1);
}
if (ev.data1) D_PostEvent(&ev);
//tty_FlushIn();
}
else if (tty_con.cursor < sizeof (tty_con.buffer))
{
// push regular character
ev.data1 = tty_con.buffer[tty_con.cursor] = key;
tty_con.cursor++;
// print the current line (this is differential)
d = write(STDOUT_FILENO, &key, 1);
}
if (ev.data1) D_PostEvent(&ev);
//tty_FlushIn();
(void)d;
}
#elif defined (_WIN32)
@@ -941,9 +920,16 @@ static void I_RegisterChildSignals(void)
void I_OutputMsg(const char *fmt, ...)
{
size_t len;
char txt[8192];
char *txt;
va_list argptr;
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);
vsprintf(txt, fmt, argptr);
va_end(argptr);
@@ -977,7 +963,10 @@ void I_OutputMsg(const char *fmt, ...)
DWORD bytesWritten;
if (co == INVALID_HANDLE_VALUE)
{
free(txt);
return;
}
if (GetFileType(co) == FILE_TYPE_CHAR && GetConsoleMode(co, &bytesWritten))
{
@@ -993,11 +982,16 @@ void I_OutputMsg(const char *fmt, ...)
if (oldLength > 0)
{
LPVOID blank = malloc(oldLength);
if (!blank) return;
if (!blank)
{
free(txt);
return;
}
memset(blank, ' ', oldLength); // Blank out.
oldLines = malloc(oldLength*sizeof(TCHAR));
if (!oldLines)
{
free(txt);
free(blank);
return;
}
@@ -1032,18 +1026,20 @@ void I_OutputMsg(const char *fmt, ...)
}
#else
#ifdef HAVE_TERMIOS
if (consolevent)
if (consolevent && ttycon_ateol)
{
tty_Hide();
tty_Clear();
ttycon_ateol = false;
}
#endif
if (!framebuffer)
fprintf(stderr, "%s", txt);
#ifdef HAVE_TERMIOS
if (consolevent)
if (consolevent && txt[len-1] == '\n')
{
tty_Show();
write(STDOUT_FILENO, tty_con.buffer, tty_con.cursor);
ttycon_ateol = true;
}
#endif
@@ -1052,6 +1048,7 @@ void I_OutputMsg(const char *fmt, ...)
fflush(stderr);
#endif
free(txt);
}
//
@@ -2672,6 +2669,7 @@ void I_GamepadRumble(INT32 device_id, UINT16 low_strength, UINT16 high_strength,
(void)device_id;
(void)low_strength;
(void)high_strength;
(void)duration;
#else
I_Assert(device_id > 0); // Gamepad devices are always ID 1 or higher
@@ -2689,6 +2687,9 @@ void I_SetGamepadIndicatorColor(INT32 device_id, UINT8 red, UINT8 green, UINT8 b
{
#if !(SDL_VERSION_ATLEAST(2,0,14))
(void)device_id;
(void)red;
(void)green;
(void)blue;
#else
I_Assert(device_id > 0); // Gamepad devices are always ID 1 or higher
+7 -7
View File
@@ -93,6 +93,7 @@ static UINT16 SAMPLERATE = 44100;
/// ------------------------
UINT8 sound_started = false;
static UINT32 stutter_threshold;
static Mix_Music *music;
@@ -592,6 +593,9 @@ Countstutter (int len)
{
UINT32 bytes;
if (!cv_birdmusic.value || gamestate != GS_LEVEL)
return;
if (hu_stopped)
{
music_stutter_bytes += len;
@@ -627,8 +631,7 @@ static void count_music_bytes(int chan, void *stream, int len, void *udata)
music_bytes += len;
if (cv_birdmusic.value && gamestate == GS_LEVEL)
Countstutter(len);
Countstutter(len);
}
static void music_loop(void)
@@ -1041,12 +1044,9 @@ UINT32 I_GetSongPosition(void)
// 8M: 1 | 8S: 2 | 16M: 2 | 16S: 4
}
void I_UpdateSongLagThreshold (void)
void I_UpdateSongLagThreshold(void)
{
if (!cv_birdmusic.value)
return;
stutter_threshold = cv_music_resync_threshold.value/1000.0*(4*44100);
stutter_threshold = cv_music_resync_powerups_only.value ? 0 : (cv_music_resync_threshold.value/1000.0*(4*44100));
}
/// ------------------------
+82 -16
View File
@@ -155,6 +155,8 @@ static patch_t *envelope;
player_t *stplyr;
UINT8 stplyrnum;
boolean directortextactive = false;
// SRB2kart
hudinfo_t hudinfo[NUMHUDITEMS] =
@@ -662,23 +664,30 @@ static void ST_overlayDrawer(void)
if (!hu_showscores) // hide the following if TAB is held
{
if (cv_showdirectorhud.value && ((demo.playback && (!demo.title || !modeattacking)) || !P_IsLocalPlayer(stplyr)) && !splitscreen)
if (cv_showdirectorhud.value && !splitscreen && ((demo.playback && !demo.freecam && (!demo.title || !modeattacking)) || !P_IsLocalPlayer(stplyr)) && !K_DirectorIsPlayerAlone())
{
char directortext[20] = {0};
snprintf(directortext, 20, "Director: %s", cv_director.value ? "On" : "Off");
if (directortoggletimer < 4*TICRATE)
directortextactive = true;
if ((!demo.playback && directortoggletimer < 13*TICRATE) || (demo.playback && directortoggletimer < 4*TICRATE))
{
V_DrawString(1, BASEVIDHEIGHT-8-1, V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANSHALF|V_ALLOWLOWERCASE, directortext);
if (renderisnewtic)
directortoggletimer++;
if (directortoggletimer < 4*TICRATE)
V_DrawString(1, BASEVIDHEIGHT-8-1, V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANSHALF|V_ALLOWLOWERCASE, directortext);
else if (cv_translucenthud.value != 0)
V_DrawString(1, BASEVIDHEIGHT-8-1, V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_80TRANS|V_ALLOWLOWERCASE, directortext); // idk if V_80TRANS is good?
}
else if (cv_translucenthud.value != 0)
V_DrawString(1, BASEVIDHEIGHT-8-1, V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_80TRANS|V_ALLOWLOWERCASE, directortext); // idk if V_80TRANS is good?
}
else
{
directortoggletimer = 0;
directortextactive = false;
}
if (cv_showviewpointtext.value)
{
@@ -695,7 +704,7 @@ static void ST_overlayDrawer(void)
V_DrawCenteredString((BASEVIDWIDTH/2), BASEVIDHEIGHT-32, V_SNAPTOBOTTOM|V_HUDTRANS|V_ALLOWLOWERCASE, player_names[stplyr-players]);
}
}
else if (!demo.title)
else if (!demo.title && !demo.freecam)
{
if (!splitscreen)
{
@@ -799,25 +808,82 @@ static void ST_overlayDrawer(void)
}
}
void ST_DrawDemoTitleEntry(void)
static void ST_DrawTextInput(INT32 x, INT32 y, textinput_t *input, INT32 flags)
{
static UINT8 skullAnimCounter = 0;
char *nametodraw;
static const INT32 MAXINPUTWIDTH = (MAXSTRINGLENGTH-1)*8;
skullAnimCounter++;
if (renderisnewtic)
skullAnimCounter++;
skullAnimCounter %= 8;
nametodraw = demo.titlename;
while (V_StringWidth(nametodraw, 0) > MAXSTRINGLENGTH*8 - 8)
nametodraw++;
char nametodraw[MAXSTRINGLENGTH*2+1] = {0};
size_t drawstart = 0;
size_t drawend = 0; // Only used for selection
INT32 skullx = x;
while (V_SubStringWidth(input->buffer+drawstart, input->cursor-drawstart, V_ALLOWLOWERCASE) > MAXINPUTWIDTH)
++drawstart;
size_t drawlength = V_SubStringLengthToFit(input->buffer+drawstart, MAXINPUTWIDTH+8, V_ALLOWLOWERCASE)+1;
drawend = drawstart + drawlength;
memcpy(nametodraw, input->buffer+drawstart, drawlength);
if (input->length)
skullx += V_SubStringWidth(nametodraw, input->cursor-drawstart, V_ALLOWLOWERCASE);
V_DrawString(x, y, V_ALLOWLOWERCASE|flags, nametodraw);
// draw text cursor for name
if (skullAnimCounter < 4) // blink cursor
V_DrawCharacter(skullx, y+3, '_'|flags, false);
// draw selection
if (input->select != input->cursor)
{
size_t start = min(input->select, input->cursor);
size_t end = max(input->select, input->cursor);
INT32 startx = 0;
INT32 width = 0;
// I couldn't figure out one formula so here's bunch of separate cases
if (start < drawstart && end > drawend) // Selection covers whole visible portion of demo name
{
startx = -2;
width = V_StringWidth(nametodraw, V_ALLOWLOWERCASE)+4;
}
else if (start < drawstart) // Only left side of selection is off visible part
{
startx = -2;
size_t len = (end - start) - (drawstart - start);
width = V_SubStringWidth(nametodraw, len, V_ALLOWLOWERCASE)+2;
}
else if (end > drawend) // Only right side of selection is off visible part
{
startx = V_SubStringWidth(nametodraw, start-drawstart, V_ALLOWLOWERCASE);
width = V_StringWidth(nametodraw+(start-drawstart), V_ALLOWLOWERCASE)+2;
}
else // All selection is on visible part
{
startx = V_SubStringWidth(nametodraw, start-drawstart, V_ALLOWLOWERCASE);
width = V_SubStringWidth(nametodraw+(start-drawstart), end-start, V_ALLOWLOWERCASE);
}
V_DrawFill(x+startx, y, width, 8, 103|V_TRANSLUCENT|flags);
}
}
void ST_DrawDemoTitleEntry(void)
{
#define x (BASEVIDWIDTH/2 - 139)
#define y (BASEVIDHEIGHT/2)
M_DrawTextBox(x, y + 4, MAXSTRINGLENGTH, 1);
V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, nametodraw);
if (skullAnimCounter < 4)
V_DrawCharacter(x + 8 + V_StringWidth(nametodraw, 0), y + 12,
'_' | 0x80, false);
ST_DrawTextInput(x + 8, y + 12, &demo.titlenameinput, 0);
M_DrawTextBox(x + 30, y - 24, 26, 1);
V_DrawString(x + 38, y - 16, V_ALLOWLOWERCASE, "Enter the name of the replay.");
+2
View File
@@ -146,4 +146,6 @@ extern UINT16 objectsdrawn;
extern consvar_t cv_lessflicker;
extern consvar_t cv_stagetitle;
extern boolean directortextactive;
#endif
+133 -88
View File
@@ -528,7 +528,7 @@ const char *GetPalette(void)
return "PLAYPAL";
}
static void LoadMapPalette(void)
void V_ReloadPalette(void)
{
LoadPalette(GetPalette());
}
@@ -540,7 +540,7 @@ static void LoadMapPalette(void)
void V_SetPalette(INT32 palettenum)
{
if (!pLocalPalette)
LoadMapPalette();
V_ReloadPalette();
#ifdef HWRENDER
if (rendermode == render_opengl)
@@ -575,7 +575,7 @@ static void CV_palette_OnChange(void)
if (loaded_config == false)
return;
// reload palette
LoadMapPalette();
V_ReloadPalette();
V_SetPalette(0);
}
@@ -1112,7 +1112,7 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
if (x >= vid.width || y >= vid.height)
return; // off the screen
if (x < 0)
{
w += x;
@@ -1126,7 +1126,7 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
if (w <= 0 || h <= 0)
return; // zero width/height wouldn't draw anything
if (x + w > vid.width)
w = vid.width-x;
if (y + h > vid.height)
@@ -1149,7 +1149,7 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
}
c &= 255;
if (alphalevel)
{
const UINT8 *fadetable = ((UINT8 *)transtables + ((alphalevel-1)<<FF_TRANSSHIFT) + (c*256));
@@ -1611,21 +1611,19 @@ void V_DrawFadeScreen(UINT16 color, UINT8 strength)
}
#endif
{
const UINT8 *fadetable =
(color > 0xFFF0) // Grab a specific colormap palette?
? R_GetTranslationColormap(color | 0xFFFF0000, strength, GTC_CACHE)
: ((color & 0xFF00) // Color is not palette index?
? ((UINT8 *)colormaps + strength*256) // Do COLORMAP fade.
: ((UINT8 *)transtables + ((9-strength)<<FF_TRANSSHIFT) + color*256)); // Else, do TRANSMAP** fade.
const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
UINT8 *buf = screens[0];
const UINT8 *fadetable =
(color > 0xFFF0) // Grab a specific colormap palette?
? R_GetTranslationColormap(color | 0xFFFF0000, strength, GTC_CACHE)
: ((color & 0xFF00) // Color is not palette index?
? ((UINT8 *)colormaps + strength*256) // Do COLORMAP fade.
: ((UINT8 *)transtables + ((9-strength)<<FF_TRANSSHIFT) + color*256)); // Else, do TRANSMAP** fade.
const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
UINT8 *buf = screens[0];
// heavily simplified -- we don't need to know x or y
// position when we're doing a full screen fade
for (; buf < deststop; ++buf)
*buf = fadetable[*buf];
}
// heavily simplified -- we don't need to know x or y
// position when we're doing a full screen fade
for (; buf < deststop; ++buf)
*buf = fadetable[*buf];
}
// Simple translucency with one color, over a set number of lines starting from the top.
@@ -2497,7 +2495,7 @@ void V_DrawThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *str
default:
break;
}
charflags = (option & V_CHARCOLORMASK);
colormap = V_GetStringColormap(charflags);
@@ -2845,11 +2843,14 @@ INT32 V_LevelNameHeight(const char *string)
//
// Find string width from hu_font chars
//
INT32 V_StringWidth(const char *string, INT32 option)
INT32 V_SubStringWidth(const char *string, INT32 length, INT32 option)
{
INT32 c, w = 0;
INT32 spacewidth = 4, charwidth = 0;
size_t i;
ssize_t i;
if (length < 0)
length = strlen(string);
switch (option & V_SPACINGMASK)
{
@@ -2865,7 +2866,7 @@ INT32 V_StringWidth(const char *string, INT32 option)
break;
}
for (i = 0; i < strlen(string); i++)
for (i = 0; string[i] && i < length; i++)
{
c = string[i];
if ((UINT8)c >= 0x80 && (UINT8)c <= 0x8F) //color parsing! -Inuyasha 2.16.09
@@ -2884,11 +2885,14 @@ INT32 V_StringWidth(const char *string, INT32 option)
//
// Find string width from hu_font chars, 0.5x scale
//
INT32 V_SmallStringWidth(const char *string, INT32 option)
INT32 V_SmallSubStringWidth(const char *string, INT32 length, INT32 option)
{
INT32 c, w = 0;
INT32 spacewidth = 2, charwidth = 0;
size_t i;
ssize_t i;
if (length < 0)
length = strlen(string);
switch (option & V_SPACINGMASK)
{
@@ -2904,7 +2908,7 @@ INT32 V_SmallStringWidth(const char *string, INT32 option)
break;
}
for (i = 0; i < strlen(string); i++)
for (i = 0; string[i] && i < length; i++)
{
c = string[i];
if ((UINT8)c >= 0x80 && (UINT8)c <= 0x8F) //color parsing! -Inuyasha 2.16.09
@@ -2923,12 +2927,15 @@ INT32 V_SmallStringWidth(const char *string, INT32 option)
//
// Find string width from tny_font chars
//
INT32 V_ThinStringWidth(const char *string, INT32 option)
INT32 V_ThinSubStringWidth(const char *string, INT32 length, INT32 option)
{
INT32 c, w = 0;
INT32 spacewidth = 2, charwidth = 0;
boolean lowercase = (option & V_ALLOWLOWERCASE);
size_t i;
ssize_t i;
if (length < 0)
length = strlen(string);
switch (option & V_SPACINGMASK)
{
@@ -2945,7 +2952,7 @@ INT32 V_ThinStringWidth(const char *string, INT32 option)
break;
}
for (i = 0; i < strlen(string); i++)
for (i = 0; string[i] && i < length; i++)
{
c = string[i];
if ((UINT8)c >= 0x80 && (UINT8)c <= 0x8F) //color parsing! -Inuyasha 2.16.09
@@ -2963,7 +2970,7 @@ INT32 V_ThinStringWidth(const char *string, INT32 option)
else
{
w += (charwidth ? charwidth
: ((option & V_6WIDTHSPACE && i < strlen(string)-1) ? max(1, SHORT(tny_font[c]->width)-1) // Reuse this flag for the alternate bunched-up spacing
: ((option & V_6WIDTHSPACE && i < length-1) ? max(1, SHORT(tny_font[c]->width)-1) // Reuse this flag for the alternate bunched-up spacing
: SHORT(tny_font[c]->width)));
}
}
@@ -2972,6 +2979,45 @@ INT32 V_ThinStringWidth(const char *string, INT32 option)
return w;
}
//
// Find maximum length for substring taken from current string to fit into given width
//
INT32 V_SubStringLengthToFit(const char *string, INT32 width, INT32 option)
{
INT32 c, w = 0;
INT32 spacewidth = 4, charwidth = 0;
INT32 i;
switch (option & V_SPACINGMASK)
{
case V_MONOSPACE:
spacewidth = 8;
/* FALLTHRU */
case V_OLDSPACING:
charwidth = 8;
break;
case V_6WIDTHSPACE:
spacewidth = 6;
default:
break;
}
for (i = 0; string[i] && w < width; i++)
{
c = string[i];
if ((UINT8)c >= 0x80 && (UINT8)c <= 0x8F) //color parsing! -Inuyasha 2.16.09
continue;
c = toupper(c) - HU_FONTSTART;
if (c < 0 || c >= HU_FONTSIZE || !hu_font[c])
w += spacewidth;
else
w += (charwidth ? charwidth : SHORT(hu_font[c]->width));
}
return max(i-1, 0);
}
char V_GetSkincolorChar(INT32 color)
{
char cstart = 0x80;
@@ -3143,7 +3189,7 @@ INT32 heatindex[MAXSPLITSCREENPLAYERS] = {0, 0, 0, 0};
// Perform a particular image postprocessing function.
//
void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param)
void V_DoPostProcessor(INT32 view, player_t *player, INT32 param)
{
#if NUMSCREENS < 5
// do not enable image post processing for ARM, SH and MIPS CPUs
@@ -3151,6 +3197,7 @@ void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param)
(void)type;
(void)param;
#else
(void)param; // unused motion blur stuff
INT32 yoffset, xoffset;
#ifdef HWRENDER
@@ -3161,6 +3208,9 @@ void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param)
if (view < 0 || view > 3 || view > splitscreen)
return;
if (!player->postimgflags)
return;
if ((view == 1 && splitscreen == 1) || view >= 2)
yoffset = viewheight;
else
@@ -3171,10 +3221,11 @@ void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param)
else
xoffset = 0;
if (type == postimg_water)
UINT8 *tmpscr = screens[4];
UINT8 *srcscr = screens[0];
if (player->postimgflags & POSTIMG_WATER)
{
UINT8 *tmpscr = screens[4];
UINT8 *srcscr = screens[0];
INT32 y;
// Set disStart to a range from 0 to FINEANGLE, incrementing by 128 per tic
angle_t disStart = (((leveltime-1)*128) + (rendertimefrac / (FRACUNIT/128))) & FINEMASK;
@@ -3211,29 +3262,30 @@ void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param)
}
/*
Unoptimized version
for (x = 0; x < vid.width*vid.bpp; x++)
{
newpix = (x + sine);
Unoptimized version
for (x = 0; x < vid.width*vid.bpp; x++)
{
newpix = (x + sine);
if (newpix < 0)
newpix = 0;
else if (newpix >= vid.width)
newpix = vid.width-1;
if (newpix < 0)
newpix = 0;
else if (newpix >= vid.width)
newpix = vid.width-1;
tmpscr[y*vid.width + x] = srcscr[y*vid.width+newpix]; // *(transme + (srcscr[y*vid.width+x]<<8) + srcscr[y*vid.width+newpix]);
}*/
tmpscr[y*vid.width + x] = srcscr[y*vid.width+newpix]; // *(transme + (srcscr[y*vid.width+x]<<8) + srcscr[y*vid.width+newpix]);
}*/
disStart += 22;//the offset into the displacement map, increment each game loop
disStart &= FINEMASK; //clip it to FINEMASK
}
VID_BlitLinearScreen(tmpscr+vid.width*vid.bpp*yoffset+xoffset, screens[0]+vid.width*vid.bpp*yoffset+xoffset,
viewwidth*vid.bpp, viewheight, vid.width*vid.bpp, vid.width);
UINT8 *tmp = tmpscr;
tmpscr = srcscr;
srcscr = tmp;
}
else if (type == postimg_motion) // Motion Blur!
{
UINT8 *tmpscr = screens[4];
UINT8 *srcscr = screens[0];
/*if (player->postimgflags & POSTIMG_MOTION) // Motion Blur!
{
INT32 x, y;
// TODO: Add a postimg_param so that we can pick the translucency level...
@@ -3242,30 +3294,12 @@ void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param)
for (y = yoffset; y < yoffset+viewheight; y++)
{
for (x = xoffset; x < xoffset+viewwidth; x++)
{
tmpscr[y*vid.width + x]
= colormaps[*(transme + (srcscr [(y*vid.width)+x ] <<8) + (tmpscr[(y*vid.width)+x]))];
}
tmpscr[y*vid.width + x] = colormaps[*(transme + (srcscr [(y*vid.width)+x ] <<8) + (tmpscr[(y*vid.width)+x]))];
}
VID_BlitLinearScreen(tmpscr+vid.width*vid.bpp*yoffset+xoffset, screens[0]+vid.width*vid.bpp*yoffset+xoffset,
viewwidth*vid.bpp, viewheight, vid.width*vid.bpp, vid.width);
}
else if (type == postimg_flip) // Flip the screen upside-down
{
UINT8 *tmpscr = screens[4];
UINT8 *srcscr = screens[0];
INT32 y, y2;
}*/
for (y = yoffset, y2 = yoffset+viewheight - 1; y < yoffset+viewheight; y++, y2--)
M_Memcpy(&tmpscr[(y2*vid.width)+xoffset], &srcscr[(y*vid.width)+xoffset], viewwidth);
VID_BlitLinearScreen(tmpscr+vid.width*vid.bpp*yoffset+xoffset, screens[0]+vid.width*vid.bpp*yoffset+xoffset,
viewwidth*vid.bpp, viewheight, vid.width*vid.bpp, vid.width);
}
else if (type == postimg_heat) // Heat wave
if (player->postimgflags & POSTIMG_HEAT) // Heat wave
{
UINT8 *tmpscr = screens[4];
UINT8 *srcscr = screens[0];
INT32 y;
// Make sure table is built
@@ -3306,40 +3340,53 @@ void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param)
heatindex[view] %= vid.height;
}
VID_BlitLinearScreen(tmpscr+vid.width*vid.bpp*yoffset+xoffset, screens[0]+vid.width*vid.bpp*yoffset+xoffset,
viewwidth*vid.bpp, viewheight, vid.width*vid.bpp, vid.width);
UINT8 *tmp = tmpscr;
tmpscr = srcscr;
srcscr = tmp;
}
else if (type == postimg_mirror) // Flip the screen on the x axis
if ((player->postimgflags & POSTIMG_FLIP) && !(player->postimgflags & POSTIMG_MIRROR)) // Flip the screen upside-down
{
INT32 y, y2;
for (y = yoffset, y2 = yoffset+viewheight - 1; y < yoffset+viewheight; y++, y2--)
M_Memcpy(&tmpscr[(y2*vid.width)+xoffset], &srcscr[(y*vid.width)+xoffset], viewwidth);
UINT8 *tmp = tmpscr;
tmpscr = srcscr;
srcscr = tmp;
}
else if ((player->postimgflags & POSTIMG_MIRROR) && !(player->postimgflags & POSTIMG_FLIP)) // Flip the screen on the x axis
{
UINT8 *tmpscr = screens[4];
UINT8 *srcscr = screens[0];
INT32 y, x, x2;
for (y = yoffset; y < yoffset+viewheight; y++)
{
for (x = xoffset, x2 = xoffset+((viewwidth*vid.bpp)-1); x < xoffset+(viewwidth*vid.bpp); x++, x2--)
tmpscr[y*vid.width + x2] = srcscr[y*vid.width + x];
}
VID_BlitLinearScreen(tmpscr+vid.width*vid.bpp*yoffset+xoffset, screens[0]+vid.width*vid.bpp*yoffset+xoffset,
viewwidth*vid.bpp, viewheight, vid.width*vid.bpp, vid.width);
UINT8 *tmp = tmpscr;
tmpscr = srcscr;
srcscr = tmp;
}
else if (type == postimg_mirrorflip) // Flip the screen upside-down and on the x axis
else if ((player->postimgflags & POSTIMG_MIRROR) && (player->postimgflags & POSTIMG_FLIP)) // Flip the screen upside-down and on the x axis
{
UINT8 *tmpscr = screens[4];
UINT8 *srcscr = screens[0];
INT32 y, x;
for (y = yoffset; y < yoffset + viewheight; y++)
for (x = xoffset; x < xoffset + viewwidth; x++)
tmpscr[((yoffset + viewheight - 1 - y) * vid.width) + xoffset + viewwidth - (x - xoffset) - 1] = srcscr[(y * vid.width) + x];
VID_BlitLinearScreen(tmpscr+vid.width*vid.bpp*yoffset+xoffset, screens[0]+vid.width*vid.bpp*yoffset+xoffset,
viewwidth*vid.bpp, viewheight, vid.width*vid.bpp, vid.width);
UINT8 *tmp = tmpscr;
tmpscr = srcscr;
srcscr = tmp;
}
VID_BlitLinearScreen(srcscr+vid.width*vid.bpp*yoffset+xoffset, tmpscr+vid.width*vid.bpp*yoffset+xoffset,
viewwidth*vid.bpp, viewheight, vid.width*vid.bpp, vid.width);
#endif
}
// Taken from my videos-in-SRB2 project
// Generates a color look-up table
// which has up to 64 colors at each channel
@@ -3373,8 +3420,6 @@ void V_Init(void)
UINT8 *base = vid.buffer;
const INT32 screensize = vid.rowbytes * vid.height;
LoadMapPalette();
for (i = 0; i < NUMSCREENS; i++)
screens[i] = NULL;
+15 -4
View File
@@ -49,6 +49,9 @@ extern UINT8 colorlookup[CLUTSIZE][CLUTSIZE][CLUTSIZE];
void InitColorLUT(void);
// Loads the correct palette into memory
void V_ReloadPalette(void);
// Set the current RGB palette lookup to use for palettized graphics
void V_SetPalette(INT32 palettenum);
@@ -234,15 +237,23 @@ void V_DrawCreditString(fixed_t x, fixed_t y, INT32 option, const char *string);
INT32 V_CreditStringWidth(const char *string);
// Find string width from hu_font chars
INT32 V_StringWidth(const char *string, INT32 option);
INT32 V_SubStringWidth(const char *string, INT32 length, INT32 option);
#define V_StringWidth(string, option) V_SubStringWidth(string, -1, option)
// Find string width from hu_font chars, 0.5x scale
INT32 V_SmallStringWidth(const char *string, INT32 option);
INT32 V_SmallSubStringWidth(const char *string, INT32 length, INT32 option);
#define V_SmallStringWidth(string, option) V_SmallSubStringWidth(string, -1, option)
// Find string width from tny_font chars
INT32 V_ThinStringWidth(const char *string, INT32 option);
INT32 V_ThinSubStringWidth(const char *string, INT32 length, INT32 option);
#define V_ThinStringWidth(string, option) V_ThinSubStringWidth(string, -1, option)
// Find maximum length for substring taken from current string to fit into given width
INT32 V_SubStringLengthToFit(const char *string, INT32 width, INT32 option);
char V_GetSkincolorChar(INT32 color);
void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param);
typedef struct player_s player_t;
void V_DoPostProcessor(INT32 view, player_t *player, INT32 param);
void V_DrawPatchFill(patch_t *pat);
+254 -10
View File
@@ -2120,6 +2120,225 @@ int W_VerifyNMUSlumps(const char *filename)
return W_VerifyFile(filename, NMUSlist, false);
}
static int W_NameStartsWith(const char *name, lumpchecklist_t *checklist)
{
size_t j;
for (j = 0; checklist[j].len && checklist[j].name; ++j)
{
if (strncasecmp(name, checklist[j].name, checklist[j].len) == 0)
return true;
}
return false;
}
// 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)
{
size_t i, j;
// if we're here it's a WAD file
wadinfo_t header;
filelump_t lumpinfo;
// read the header
if (fread(&header, 1, sizeof header, fp) == sizeof header
&& header.numlumps < INT16_MAX
&& strncmp(header.identification, "ZWAD", 4)
&& strncmp(header.identification, "IWAD", 4)
&& strncmp(header.identification, "PWAD", 4)
&& strncmp(header.identification, "SDLL", 4))
{
return true;
}
header.numlumps = LONG(header.numlumps);
header.infotableofs = LONG(header.infotableofs);
// let seek to the lumpinfo list
if (fseek(fp, header.infotableofs, SEEK_SET) == -1)
return true;
for (i = 0; i < header.numlumps; i++)
{
// fill in lumpinfo for this wad file directory
if (fread(&lumpinfo, sizeof (lumpinfo), 1 , fp) != 1)
return -1;
lumpinfo.filepos = LONG(lumpinfo.filepos);
lumpinfo.size = LONG(lumpinfo.size);
if (lumpinfo.size == 0)
continue;
for (j = 0; j < NUMSPRITES; j++)
if (!strncmp(lumpinfo.name, sprnames[j], 4)) // Sprites
continue;
if (W_NameStartsWith(lumpinfo.name, checklist))
return true;
}
return false;
}
static int W_CheckPK3Contains(FILE *fp, lumpchecklist_t *checklist)
{
zend_t zend;
zlentry_t zlentry;
long file_size;/* size of zip file */
long data_size;/* size of data inside zip file */
UINT16 numlumps;
size_t i;
char pat_central[] = {0x50, 0x4b, 0x01, 0x02, 0x00};
char pat_end[] = {0x50, 0x4b, 0x05, 0x06, 0x00};
char lumpname[9];
// Haha the ResGetLumpsZip function doesn't
// check for file errors, so neither will I.
// Central directory bullshit
fseek(fp, 0, SEEK_END);
file_size = ftell(fp);
if (!ResFindSignature(fp, pat_end, max(0, ftell(fp) - (22 + 65536))))
return true;
fseek(fp, -4, SEEK_CUR);
if (fread(&zend, 1, sizeof zend, fp) < sizeof zend)
return true;
data_size = sizeof zend;
numlumps = SHORT(zend.entries);
fseek(fp, LONG(zend.cdiroffset), SEEK_SET);
char *cdir = (char*)(malloc(LONG(zend.cdirsize)));
if (fread(cdir, 1, LONG(zend.cdirsize), fp) < (UINT32)(LONG(zend.cdirsize)))
return true;
size_t offset = 0;
for (i = 0; i < numlumps; i++)
{
zentry_t *zentry = (zentry_t*)(cdir + offset);
char* fullname;
char* trimname;
char* dotpos;
if (memcmp(zentry->signature, pat_central, 4) != 0)
return false;
fullname = (char*)(malloc(SHORT(zentry->namelen) + 1));
strlcpy(fullname, (char*)(zentry + 1), SHORT(zentry->namelen) + 1);
// Strip away file address and extension for the 8char name.
if ((trimname = strrchr(fullname, '/')) != 0)
trimname++;
else
trimname = fullname; // Care taken for root files.
if (*trimname) // Ignore directories, well kinda
{
if ((dotpos = strrchr(trimname, '.')) == 0)
dotpos = fullname + strlen(fullname); // Watch for files without extension.
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))
return true;
}
if (W_NameStartsWith(fullname, checklist))
return true;
free(fullname);
offset += sizeof *zentry + SHORT(zentry->namelen) + SHORT(zentry->xtralen) + SHORT(zentry->commlen);
data_size +=
sizeof *zentry + SHORT(zentry->namelen) + SHORT(zentry->xtralen) + SHORT(zentry->commlen);
if (fseek(fp, LONG(zentry->offset), SEEK_SET) != 0)
return false;
if (fread(&zlentry, 1, sizeof(zlentry_t), fp) < sizeof (zlentry_t))
return false;
data_size +=
sizeof zlentry + SHORT(zlentry.namelen) + SHORT(zlentry.xtralen) + LONG(zlentry.compsize);
}
free(cdir);
if (data_size < file_size)
{
const char * error = "ZIP file has holes (%ld extra bytes)\n";
CONS_Alert(CONS_ERROR, error, (file_size - data_size));
return -1;
}
else if (data_size > file_size)
{
const char * error = "Reported size of ZIP file contents exceeds file size (%ld extra bytes)\n";
CONS_Alert(CONS_ERROR, error, (data_size - file_size));
return -1;
}
else
{
return false;
}
}
static int W_CheckFileContains(const char *filename, lumpchecklist_t *checklist)
{
FILE *handle;
int contains = false;
if (!checklist)
I_Error("No checklist for %s\n", filename);
// open wad file
if ((handle = W_OpenWadFile(&filename, false)) == NULL)
return -1;
if (stricmp(&filename[strlen(filename) - 4], ".pk3") == 0)
contains = W_CheckPK3Contains(handle, checklist);
else
{
// detect wad file by the absence of the other supported extensions
if (stricmp(&filename[strlen(filename) - 4], ".soc")
&& stricmp(&filename[strlen(filename) - 4], ".lua"))
{
contains = W_CheckWADContains(handle, checklist);
}
}
fclose(handle);
return contains;
}
int W_CheckPostLoadList(const char *filename)
{
static lumpchecklist_t postloadlist[] =
{
{"Lua/", 4},
{"SOC/", 4},
{"Skins/", 6},
{"S_SKIN", 6},
{"LUA_", 4},
{"SOC_", 4},
{"MAINCFG", 7},
{"OBJCTCFG", 8},
{"MAP", 3},
{NULL, 0},
};
return W_CheckFileContains(filename, postloadlist);
}
/** \brief Generates a virtual resource used for level data loading.
*
* \param lumpnum_t reference
@@ -2145,11 +2364,11 @@ virtres_t* vres_GetMap(lumpnum_t lumpnum)
size_t *vsizecache;
// Remember that we're assuming that the WAD will have a specific set of lumps in a specific order.
UINT8 *wadData = W_CacheLumpNum(lumpnum, PU_LEVEL);
UINT8 *wadData = (UINT8*)(W_CacheLumpNum(lumpnum, PU_LEVEL));
filelump_t *fileinfo = (filelump_t *)(wadData + LONG(((wadinfo_t *)wadData)->infotableofs));
i = LONG(((wadinfo_t *)wadData)->numlumps);
vsizecache = Z_Malloc(sizeof(size_t)*i, PU_LEVEL, NULL);
vsizecache = (size_t*)(Z_Malloc(sizeof(size_t)*i, PU_LEVEL, NULL));
for (realentry = 0; realentry < i; realentry++)
{
@@ -2161,7 +2380,7 @@ virtres_t* vres_GetMap(lumpnum_t lumpnum)
numlumps++;
}
vlumps = Z_Malloc(sizeof(virtlump_t)*numlumps, PU_LEVEL, NULL);
vlumps = (virtlump_t*)(Z_Malloc(sizeof(virtlump_t)*numlumps, PU_LEVEL, NULL));
// Build the lumps, skipping over empty entries.
for (i = 0, realentry = 0; i < numlumps; realentry++)
@@ -2169,10 +2388,20 @@ virtres_t* vres_GetMap(lumpnum_t lumpnum)
if (vsizecache[realentry] == 0)
continue;
vlumps[i].size = vsizecache[realentry];
const char *name = (fileinfo + realentry)->name;
if (strlen(name) == 5 && memcmp(name, "MAP", 3) == 0)
{
numlumps--; // We skip map marker, so 1 of entries becomes empty
continue; // This will skip i++ so we will write to same entry
}
// Play it safe with the name in this case.
memcpy(vlumps[i].name, (fileinfo + realentry)->name, 8);
memcpy(vlumps[i].name, name, 8);
vlumps[i].name[8] = '\0';
vlumps[i].data = 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++;
}
@@ -2193,16 +2422,25 @@ virtres_t* vres_GetMap(lumpnum_t lumpnum)
}
numlumps++;
vlumps = Z_Malloc(sizeof(virtlump_t)*numlumps, PU_LEVEL, NULL);
vlumps = (virtlump_t*)(Z_Malloc(sizeof(virtlump_t)*numlumps, PU_LEVEL, NULL));
for (i = 0; i < numlumps; i++, 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 (strlen(name) == 5 && memcmp(name, "MAP", 3) == 0)
{
--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
continue;
}
vlumps[i].size = W_LumpLength(lumpnum);
memcpy(vlumps[i].name, W_CheckNameForNum(lumpnum), 8);
memcpy(vlumps[i].name, name, 8);
vlumps[i].name[8] = '\0';
vlumps[i].data = W_CacheLumpNum(lumpnum, PU_LEVEL);
vlumps[i].data = (UINT8*)(W_CacheLumpNum(lumpnum, PU_LEVEL));
}
}
vres = Z_Malloc(sizeof(virtres_t), PU_LEVEL, NULL);
vres = (virtres_t*)(Z_Malloc(sizeof(virtres_t), PU_LEVEL, NULL));
vres->vlumps = vlumps;
vres->numlumps = numlumps;
@@ -2222,7 +2460,13 @@ void vres_Free(virtres_t* vres)
}
while (vres->numlumps--)
Z_Free(vres->vlumps[vres->numlumps].data);
{
if (vres->vlumps[vres->numlumps].data)
{
Z_Free(vres->vlumps[vres->numlumps].data);
}
}
Z_Free(vres->vlumps);
Z_Free(vres);
}
+2
View File
@@ -226,4 +226,6 @@ void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5);
int W_VerifyNMUSlumps(const char *filename);
int W_CheckPostLoadList(const char *filename);
#endif // __W_WAD__