Compare commits

...

781 Commits

Author SHA1 Message Date
haooy
21a7b58c82 Reset players hp when needed
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
Reset players hp when needed
2025-10-08 00:05:10 +00:00
mourningsickness
133c4e5b12
shavit-hud.sp - add perf% to center hud (#1259)
Co-authored-by: rtldg <rtldg@protonmail.com>
2025-10-07 23:55:27 +00:00
rtldg
7cbb250541 Make it easier to change the max tier
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
2025-10-01 00:00:03 +00:00
mourningsickness
a350d7982c
Add tier selection menu to mapsleft and mapsdone menus (with "All" option, for current functionality) (#1262) 2025-09-30 23:44:38 +00:00
rtldg
a5bec0403b
Merge pull request #1258 from normalamron/pracfix
Some checks are pending
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Waiting to run
Compile / Release (push) Blocked by required conditions
2025-09-30 23:34:50 +00:00
mourningsickness
7d3913bc3e
add !worldrecord/!wr aliases (!serverrecord/!sr) (#1257) 2025-09-30 23:33:03 +00:00
rtldg
1993c22112 changelog moment 2025-09-30 23:32:24 +00:00
normalamron
71c674663f prevent prac warning spam in start zone 2025-08-09 22:15:33 +03:00
rtldg
0ebfa900b9 bump to srcwr💾 v2.0.4
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
2025-07-31 02:11:42 +00:00
rtldg
128940ff19 Fix the on-ground 0.5s start-timer even further dot dot dot 2025-07-25 01:17:07 +00:00
rtldg
00feb624c2 Fix the on-ground 0.5s start-timer check from 89e97dfd3d 2025-07-23 23:06:24 +00:00
rtldg
309cdf3acf Update CSGO m_afButtonDisabled signature 2025-07-19 22:01:10 +00:00
rtldg
871c67deac bump srcwr💾 to v2.0.3 to fix bad replay paths 2025-07-19 19:26:10 +00:00
rtldg
f924177098
Merge pull request #1254 from mourningsickness/master 2025-07-19 03:43:38 +00:00
mourningsickness
b1e8e15043
shavit-replay-playback.sp - fix error in case where style == -1
L 07/18/2025 - 06:35:33: [SM] Exception reported: Array index out-of-bounds (index -1, limit 256)
L 07/18/2025 - 06:35:33: [SM] Blaming: shavit/shavit-replay-playback.smx
L 07/18/2025 - 06:35:33: [SM] Call stack trace:
L 07/18/2025 - 06:35:33: [SM]   [1] Line 3015, shavit-replay-playback.sp::DeleteConfirmation_Callback
2025-07-18 20:41:39 -07:00
rtldg
f14cbf5aff Fix replay path formatting when using srcwr💾 2025-07-18 17:30:29 +00:00
rtldg
d08a3078e1 use srcwr💾 v2.0.1 for working linux builds 2025-07-18 01:57:40 +00:00
rtldg
16ccd0cc7c
Use an extension to save replays asynchronously (#1253) 2025-07-17 22:42:22 +00:00
rtldg
70308f3d6a Clarify shavit_replay_timelimit 0.0/disabled not recording replays 2025-07-15 06:52:16 +00:00
rtldg
378a2eae70 Include eventqueuefixfix in release zips 2025-07-15 01:12:20 +00:00
mourningsickness
0b0be25c78
shavit-misc.sp - don't stop timer on tpto if paused with pause movement enabled (#1249) 2025-07-15 00:46:59 +00:00
rtldg
dce67fada9
Merge pull request #1251 from KawaiiClan/master 2025-07-15 00:40:42 +00:00
mourningsickness
326caccb06
shavit-zones.sp - make it so slay/stoptimer zones don't apply if paused
rip skronk's hour long bhop_thc time
2025-07-12 10:37:46 -07:00
rtldg
4f43b628ae Fix savestates not enabling recording (found by happydez) 2025-07-09 20:17:18 +00:00
olivia
466bcf62df
shavit-checkpoints.sp - fix aFrames and iPreFrames not always being set (#1244)
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
2025-07-01 21:10:58 +00:00
rtldg
0c4a0d139d
Merge pull request #1247 from KawaiiClan/master 2025-07-01 17:54:23 +00:00
olivia
c0d5efb309
shavit-replay-playback.sp - close replay menu on spawn (if it's open) 2025-07-01 06:25:03 -07:00
olivia
14b9674962
shavit-stats.sp - fix error due to IsPlayerAlive() being called on disconnected client (#1245)
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
2025-06-26 14:36:20 +00:00
rtldg
ee96ef9f7f poke version & changelog for next version AGAIN
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
2025-06-24 15:50:35 +00:00
rtldg
69ffbc1d7f v3.5.1 2025-06-24 15:34:50 +00:00
rtldg
bb09568d97 Keep all menus open forever
Some checks are pending
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Waiting to run
Compile / Release (push) Blocked by required conditions
2025-06-23 20:46:02 +00:00
olivia
877b71aa4d shavit-wr.sp - add back buttons to !delete menus (QoL)
no reason to not be able to go back from these submenus

Co-authored-by: rtldg <rtldg@protonmail.com>
2025-06-23 20:43:55 +00:00
rtldg
f0ccf6dc0a fix olivia's name in author lists (from e81d091ed0) 2025-06-23 20:16:37 +00:00
rtldg
003f377319 poke version & changelog for next version
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
2025-06-06 14:58:13 +00:00
rtldg
f31c4f6ede Bump to v3.5.0 to get the ball rolling again dot dot dot 2025-06-06 14:51:11 +00:00
rtldg
321cdb28d9 more changelog stuff
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
2025-05-16 07:36:52 +00:00
rtldg
4969429727 Merge branch 'fucker' 2025-05-16 07:29:50 +00:00
rtldg
b29cc54d0b Fix the Migration_MoreFirstLoginStuff queries from rtldg/sqldumb (surely.. hopefully..) 2025-05-16 07:10:04 +00:00
rtldg
91ca6a7ea9 Use IsMapValid instead of GetMapDisplayName sometimes
For reasons, only known to God and Gaben, `GetMapDisplayName` will start failing.

Something along these lines:
- make hundreds (or thousand+) maps named `test_{i}.bsp`
- start server
- delete them all
- make `test_{i+1}.bsp`
- `sm_map test_{i+1}.bsp`
- "Invalid map :("

thinker emoji
2025-05-15 22:45:11 +00:00
olivia
49105001d3
shavit-chat - fix chat messages near (or at) max length overflowing into a broken message (#1241)
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
2025-05-12 06:14:25 +00:00
Nora
cd4f1c9248
Prevent gB_ForceJump when teleporting to a checkpoint in the start zone (#1240)
Co-authored-by: rtldg <55846624+rtldg@users.noreply.github.com>
2025-05-12 05:17:24 +00:00
rtldg
0151ace718 fix shavit-zones cvar change callback errors (found by caliph)
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
2025-05-07 00:02:44 +00:00
olivia
b1a2f06432
add player PB to !style menu (#1239)
* shavit-core.sp - add player pb to style menu

helps to see if you've already beaten a map on a style without changing to it first

* shavit-core.sp - move pb to only after a wr is found

* shavit-core.sp - fix whitespace
2025-05-06 23:46:28 +00:00
rtldg
6124d0fceb
Merge pull request #1238 from mourningsickness/master
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
shavit-core.sp - typo (^:
2025-05-02 00:04:09 +00:00
olivia
5214a2d6f7
shavit-core.sp - typo (^: 2025-05-01 16:39:23 -07:00
rtldg
7e1c3f0dc3 fix: prevent unnecessary jump when using !r or switching to TAS
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
2025-04-27 00:53:15 +00:00
rtldg
158edbe158 Make firstlogin pull from old runs if possible
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
2025-04-23 23:43:25 +00:00
rtldg
983a3c8e74 Mark Steam Datagram Relay IPs
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
2025-04-21 00:42:35 +00:00
olivia
3d0cd96319 Add FirstLogin to database and profile (#1234)
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
fix FirstLogin query for sqlite

fix statsmenu query oopsie teehee :3

sql-create-tables-and-migrations.sp - fix queries for sqlite

Simplify firstlogin column initialization
2025-04-19 22:26:29 +00:00
Awesomerly
354c2445c2
Startzone speed limit flexibility (#1219)
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
* Add config flag for MaxPrestrafe override

* Allow zoners to edit startzone data

* Use start zone data field for prestrafe limit

* Add prespeed type 6 that behaves like 5 and prevents prehopping

* Fix formatting

* Bodged up code for 1 second prehop cooldown on prestrafe mode 6

* Make anti prespeed a little bit better (maybe????)

* Tiredly twiddle with prespeed style 6 impl

* Add description to maxprestrafe style-setting

* nitpicky styling things

* Use GetGameTickCount instead of GetSysTickCount

* ;

---------

Co-authored-by: rtldg <55846624+rtldg@users.noreply.github.com>
Co-authored-by: rtldg <rtldg@protonmail.com>
2025-04-12 15:54:54 +00:00
olivia
f8833972ec
disable setting style cookie if style cookies are disabled (#1233)
Some checks are pending
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Waiting to run
Compile / Release (push) Blocked by required conditions
* shavit-core.sp - disable style cookie is style cookies are disabled

Edge case causing this change, but if style cookies are disabled on a server, no reason to save it.
2025-04-12 04:32:21 +00:00
olivia
2726865399
shavit-misc Add cvar UnNoclipOnRestart (#1232)
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
* shavit-misc Add cvar UnNoclipOnRestart


Add functionality to turn off noclip on timer restart, disabled by default u.u

I used to use a separate plugin I made for this, but figured it should be in the main plugin itself as a cvar instead. Since adding as a cvar, may as well see if it is wanted upstream.

* shavit-misc.sp shavit_misc_unnocliponrestart 1 by default (^:
2025-04-11 01:41:20 +00:00
rtldg
420c8e02ea Fix not being able to overlap bonus+main endzones
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
2025-03-30 20:01:59 +00:00
rtldg
d93ed28816 CBasePlayer->m_afButtonDisabled gamedata for csgo
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
2025-03-24 16:53:37 +00:00
swaggamer69
78f55f9a1a
swap sm_p to sm_noclip in shavit_misc_noclipme description (#1230)
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
2025-03-23 06:48:02 +00:00
rtldg
e072be6313 Check ModifySpeed case-insensitively for player_speedmod
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
2025-03-13 10:55:58 +00:00
rtldg
bf5ec55a6a save m_afButtonDisabled & m_afButtonForced in checkpoints (mainly for player_speedmod)
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
this makes kz_bhop_genkai a bit more bearable at times

this also isn't perfect since restarting doesn't reset them
2025-03-09 07:49:04 +00:00
rtldg
2013968f1c We will ALWAYS have the extra CSS ladder checkpoint variables
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
2025-03-06 12:33:27 +00:00
rtldg
90a6714beb
Fix things (for CS:S) after 2025-02-18 update (#1226)
* some wip windows gamedata

* maybe correct cstrike x32 linux gamedata

* update some offsets with x64 versions

* x64 offsets for ladder things

* maybe okay x64 css sigs

* fill out the OS and X64 offsets more

* A few typos

* Try to fix m_surfaceFriction for TAS

* rolls around on the floor groaning

* remove unnecessary CHECKED comments in gamedata

* update workflow versions

* Migrate from ProcessMovement/ProcessMovementPost to PreThink/PostThinkPost

* Revert "Migrate from ProcessMovement/ProcessMovementPost to PreThink/PostThinkPost"

This reverts commit c829a783b0.

* Make sure MaybeDoPhysicsUntouch() is called in ProcessMovementPost

* misc

* Prevent changing sv_autobunnyhoping (like via .cfg files)

* Don't break CSGO TAS yet

* Edit some gamedata comments
2025-03-06 12:14:36 +00:00
rtldg
8ecc2a7829 Some autobhop zone fixes
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.11) (push) Has been cancelled
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
commit d451cee41dc2f59fb367141bfd62ddcc778101c0
Author: rtldg <rtldg@protonmail.com>
Date:   Fri Feb 28 12:18:37 2025 +0000

    add another customzones cookie womp

commit d1395bcc6836cd01f2751ac9fd104124c7affeff
Author: rtldg <rtldg@protonmail.com>
Date:   Fri Feb 28 12:18:29 2025 +0000

    Fix Autobhop zones not replicating sv_autobunnyhopping

commit c225702fc50964684734f2fb64b190edac54db0c
Author: rtldg <rtldg@protonmail.com>
Date:   Fri Feb 28 12:18:11 2025 +0000

    make autobhop & nojump zones visible by default
2025-02-28 12:20:41 +00:00
rtldg
ad008dc00a add a few more things to the changelog
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.11) (push) Has been cancelled
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
2025-02-26 03:04:39 +00:00
rtldg
23fa606920 Fix typo from #1201
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.11) (push) Has been cancelled
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
2025-02-22 11:17:00 +00:00
rtldg
f54775044c didn't save a file for the func_rot_button commit...
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.11) (push) Has been cancelled
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
2025-02-19 00:25:11 +00:00
rtldg
04ad339fe8 Add handling for func_rot_button zones 2025-02-16 02:07:12 +00:00
rtldg
94ebb97c79 check for sv_autobunnyhopping even if not csgo 🕵
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.11) (push) Has been cancelled
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
2025-02-12 00:20:08 +00:00
rtldg
b150073754 make shavit-mapchooser grab tiers even if not mysql
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.11) (push) Has been cancelled
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
2025-02-11 03:52:42 +00:00
rtldg
ad48aa3345 fix some advertisements colors not working 2025-02-11 03:51:53 +00:00
rumour
2bbb3865f8 make !beamer more reliable and stuck in walls less (if at all!)
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.11) (push) Has been cancelled
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
2025-01-20 00:32:15 +00:00
rtldg
ab75ef4c43
Merge pull request #1222 from Awesomerly/thegame
Some checks failed
Compile / Build SM ${{ matrix.sm-version }} (1.11) (push) Has been cancelled
Compile / Build SM ${{ matrix.sm-version }} (1.12) (push) Has been cancelled
Compile / Release (push) Has been cancelled
Fix database verison parsing
2025-01-10 19:35:33 +00:00
Awe
e5976001cf Fix database verison parsing 2025-01-10 14:17:53 -05:00
rtldg
57e3dce711 experiment with calling EntityCollisionRulesChanged on solid zone p2 2025-01-04 02:16:18 +00:00
rtldg
dfc9276edc fill changelog for next release (when?) 2025-01-04 02:13:05 +00:00
rtldg
3175172241 experiment with calling EntityCollisionRulesChanged on solid zones 2024-12-14 17:20:33 +00:00
rtldg
2dd385a8eb okay actually fr unbreak sm 1.12 workflow builds 2024-11-16 17:15:35 +00:00
rtldg
54c04a0219
Update shavit-wr.sp 2024-11-16 16:56:44 +00:00
rtldg
17e60114a4
probably unbreak sm 1.12 builds with my good friends fempty and bempty 2024-11-16 16:52:18 +00:00
rtldg
ef2e2bb0dc
Merge pull request #1221 from Awesomerly/hookzone-tweak
Add new zone types to hookzone menu
2024-11-16 16:49:39 +00:00
Awe
7c80025574 Add new zone types to hookzone menu 2024-10-30 16:49:00 -04:00
rtldg
d4d5004615 reenable workflows on sm 1.12 to check for problem 2024-10-27 07:53:56 +00:00
rtldg
9434dc9438 edit the DeprecateExactInt sql error handling a bit for #1218 2024-10-18 04:22:13 +00:00
rtldg
187bd2c975 do something to not error on negative sv_friction and negative sv_accelerate 2024-10-09 04:45:35 +00:00
rtldg
e41ba9fa95 probably fix exact_time_int deprecation issue (#1218) 2024-10-02 02:44:31 +00:00
rtldg
f96a57412b rename FillBoxMinMax to BoxPointsToMinsMaxs 2024-10-02 02:41:36 +00:00
rtldg
ee0fe65b01 fix bad casts that broke Custom Airaccelerate & Custom Speed Limit zones from 7aca8755a4 2024-09-23 04:05:13 +00:00
Nairda
1b67644197
Clarify logic for testing writeability with faketestfile_69.replay (#1217)
* Update replay-stocks.sp

* Update replay-stocks.sp

XDDD

* Update replay-stocks.sp

ecksdee.

* Update replay-stocks.sp

f.. you

* Update replay-stocks.sp

hucvfrsdtbh
2024-09-23 01:36:25 +00:00
rtldg
fee7df2919 document some API structs 2024-09-23 01:34:52 +00:00
rtldg
bac325cd07
Add comments next to the magic editaxis string 2024-08-20 18:12:31 +00:00
Awesomerly
c9cfbefa27
Add no-jump and autobhop zones. (#1216)
* Make no jump zone appear in menu

* Preliminary implementation of nojump zone

* Add scaffolding for autobhop zone

* Add implementation of autobhop zone

* Add new zone types to shavit-zones-json

* some touchups for the autobhop & nojump zones

---------

Co-authored-by: rtldg <rtldg@protonmail.com>
2024-08-20 17:53:24 +00:00
rtldg
2a23c05853 add a note for a_or_d_only in shavit-styles.cfg 2024-08-17 01:03:41 +00:00
rtldg
da78976c56 add shavit_zones_enable_stage_restart & make !stagerestart send you to startzone if your timer is stopped 2024-08-09 17:27:06 +00:00
rtldg
30ae74fd9f
Merge pull request #1215 from Awesomerly/stagerestart_thingy
Make stage restart command take player to beginning when in end zone
2024-07-30 22:48:15 +00:00
Awe
4465e53d3b Make stage restart command take player to beginning in end zone 2024-07-30 12:43:06 -04:00
rtldg
101ab536ab todo comment next to the OnLeaveZone stuff for AirAccelerate & Custom Speed Limit zones 2024-07-29 13:54:27 +00:00
rtldg
feeb4ae445 try to fix errors with looping replay bots that use disabled styles
L 07/25/2024 - 19:46:15: [SM] Exception reported: Array index out-of-bounds (index -1, limit 256)
L 07/25/2024 - 19:46:15: [SM] Blaming: shavit/shavit-replay-playback.smx
L 07/25/2024 - 19:46:15: [SM] Call stack trace:
L 07/25/2024 - 19:46:15: [SM]   [1] Line 3620, D:\sourcemod-1.10.0-git6545-windows_v3.4.2\addons\sourcemod\scripting\shavit-replay-playback.sp::FindNextLoop
L 07/25/2024 - 19:46:15: [SM]   [2] Line 1924, D:\sourcemod-1.10.0-git6545-windows_v3.4.2\addons\sourcemod\scripting\shavit-replay-playback.sp::AddReplayBots
L 07/25/2024 - 19:46:15: [SM]   [3] Line 1542, D:\sourcemod-1.10.0-git6545-windows_v3.4.2\addons\sourcemod\scripting\shavit-replay-playback.sp::Timer_Cron
L 07/25/2024 - 19:46:18: [SM] Exception reported: Array index out-of-bounds (index -1, limit 256)
L 07/25/2024 - 19:46:18: [SM] Blaming: shavit/shavit-replay-playback.smx
L 07/25/2024 - 19:46:18: [SM] Call stack trace:
L 07/25/2024 - 19:46:18: [SM]   [1] Line 3620, D:\sourcemod-1.10.0-git6545-windows_v3.4.2\addons\sourcemod\scripting\shavit-replay-playback.sp::FindNextLoop
L 07/25/2024 - 19:46:18: [SM]   [2] Line 1924, D:\sourcemod-1.10.0-git6545-windows_v3.4.2\addons\sourcemod\scripting\shavit-replay-playback.sp::AddReplayBots
L 07/25/2024 - 19:46:18: [SM]   [3] Line 1542, D:\sourcemod-1.10.0-git6545-windows_v3.4.2\addons\sourcemod\scripting\shavit-replay-playback.sp::Timer_Cron
2024-07-29 13:53:58 +00:00
Nairda
2751ec1f2d
Use "KiD Fearless" instead of "kidfearless" in shavit-checkpoints author list (#1214)
OCD fix
2024-07-29 13:49:52 +00:00
rtldg
7aca8755a4 force sv_enablebunnyhopping 1 in Custom Speed Limit zones (for _strafe); make AirAccelerate & Custom Speed Limit zones check the player's track #1212 2024-07-24 18:35:47 +00:00
rtldg
e35e835841 shavit-replay-playback: hook triggers on late-load 2024-07-11 09:58:18 +00:00
rtldg
4652e36cc6 allow the !recentrecords menu to be sorted by style 2024-07-06 10:05:53 +00:00
rtldg
3609adf2aa use style runspeed instead of m_flMaxspeed for tas (and autoprestrafe)
(autoprestrafe is broken on 250 runspeed otherwise...)
2024-06-02 20:15:22 +00:00
rtldg
44ac27a41d
Merge pull request #1209 from BoomShotKapow/patch-2
Allow updating replay bot name without being a WR
2024-05-28 04:08:00 +00:00
BoomShot
654f9aa239
Allow updating replay bot name without being a WR
This allows editing the replay bot's name through the frame_cache_t of the replay data, which is useful for personal replays. Without this change, the replay bot's name after calling Shavit_StartReplayFromFrameCache would be the current WR's player name.
2024-05-28 00:07:04 -04:00
Awesomerly
2805cd94c6
Add teleport to stage start command (#1207)
* Add teleport command

* Slight cleanups for sm_teleport

* Make stage restart only work if map is surf

* Change /teleport to be /stagerestart, etc

* Make sm_teleport behave like sm_tele

* Unregister /sr command because it's already taken

* Update shavit-zones.sp

---------

Co-authored-by: rtldg <55846624+rtldg@users.noreply.github.com>
2024-04-27 19:55:42 +00:00
rtldg
b773e74049
Merge pull request #1208 from Awesomerly/dhook_rm
Remove dhooks include file
2024-04-27 00:01:34 +00:00
rtldg
6751aa323b purge BotAddCommand gamedata and revert to bot_add (but add ServerExecute()) 2024-04-26 23:45:52 +00:00
Awe
659d70af24 Remove dhooks include file 2024-04-24 14:56:14 -04:00
rtldg
1f1a897927 silly sourcemod sizeof array syntax 2024-04-23 21:00:39 +00:00
rtldg
16a927cd91 drop support for sourcemod 1.10 2024-04-23 20:53:18 +00:00
rtldg
5814a7c3d8 revert to tf_bot_add instead of NextBot.. gamedata & fix maintainbotquota sig 2024-04-23 19:47:21 +00:00
rtldg
9876d4c3db caught this in tf2 because when you spawn the observer target is a camera or something 2024-04-23 19:40:01 +00:00
rtldg
b63e3c8f8f sm 1.11 ifdef wrapper 2024-04-23 18:57:42 +00:00
rtldg
5421c6006a working PreventBunnyJumping on Windows 2024-04-19 20:59:22 +00:00
rtldg
7ce6233cf4 wip tf2 stuff post 2024-04-18 2024-04-19 18:08:41 +00:00
rtldg
66c730a897 fixups for mapchooser nominate menu after sqlite support was added to shavit-rankings 2024-03-26 20:02:27 +00:00
rtldg
1102a0971c
Merge pull request #1195 from Nairdaa/patch-35
Update shavit-mapchooser.sp
2024-03-12 12:58:13 +00:00
Nairda
388f561f58
add backwards check for sync (#1194)
* add backwards check for sync

* Update shavit-core.sp

now it works
2024-03-12 12:57:49 +00:00
Nairda
c2dbf6d779 Update shavit-core.sp
add backwards hsw sync
2024-03-12 12:55:15 +00:00
enimmy
d57ec73adb
add keyhint forwards and forceUpdate (#1201)
* add keyhint forwards/remove unused params from topleft forwards

* allow forcing keyhint through pre forward

* implement track/style params, edit force updating logic

* doc touchups

* fix typo

* do some styling since the blame was already affected by the indentation changes

---------

Co-authored-by: Nimmy2222 <99696781+Nimmy2222@users.noreply.github.com>
Co-authored-by: rtldg <55846624+rtldg@users.noreply.github.com>
2024-03-12 12:51:37 +00:00
rtldg
64d6a1d9f3
fix README Build from source link 2024-01-27 17:44:18 +00:00
rtldg
efb659adfb
Merge pull request #1200 from Nimmy2222/master
add jumpstats to readme
2023-12-31 17:16:42 +00:00
Nimmy2222
835678d816
Update README.md 2023-12-29 19:27:12 -05:00
rtldg
7fb0f45c2c This rankings query was doing the wrong thing in WHERE 2023-12-13 09:29:23 +00:00
rtldg
e8ff7fe663 increase menu-input blocker length 2023-12-13 09:21:25 +00:00
rtldg
91a2df62af
update workflow sp dep versions 2023-11-18 03:52:08 +00:00
rtldg
d337145b5f
disable sm1.12 workflow builds since it has bugs 2023-11-18 03:47:05 +00:00
rtldg
ce9d1e45b2 small readme updates 2023-11-18 03:44:38 +00:00
rtldg
9b96f9dffd stripper cfgs touchups for that thing that I forgot the name of 2023-11-18 03:18:09 +00:00
rtldg
c2a9017810
Make sure CSS uses the more ladder checkpoint stuff 2023-11-18 02:59:38 +00:00
rtldg
c1c84e17a3
Merge pull request #1197 from lilac1337/patch-3
use correct gravity for LG
2023-11-12 08:35:57 +00:00
swaggamer69
f9bb0a39f8
use correct gravity for LG
it's historically always been 400
2023-11-11 16:23:57 -05:00
rtldg
f6fdd7b0aa untested In Start/End zone speed removal if !hud removed speed... 2023-08-08 17:41:27 +00:00
rtldg
60c4f399f1 add bhop_wasd to shavit-mapfixes.cfg 2023-07-10 10:25:40 +00:00
Nairda
c6c38b0816
Update shavit-mapchooser.sp
ocd
2023-07-06 04:35:24 +02:00
rtldg
d69bd18407 stop that random map change thing 2023-07-04 01:23:01 +00:00
rtldg
cf90d110e3 styles cfg note on autostrafe option 4 / basic autostrafer 2023-06-23 21:01:41 +00:00
rtldg
d48ed993c6
Merge pull request #1193 from Nairdaa/patch-33
fix hsw sync
2023-06-21 01:45:17 +00:00
rtldg
309aa7a189 get the shavit_misc_prespeed 1&&>=3 working again with the on-ground timer 2023-06-21 01:41:07 +00:00
Nairda
5a0b8c2df5
fix hsw sync 2023-06-20 22:37:57 +02:00
azalty
ca60971410
Godmode fix for DMG_CRUSH and point_hurt (#1188)
* godmod fix for DMG_CRUSH and point_hurt

* Added the "shavit_misc_godmode 4" option

* fix error about `default` case not being last. `default` can be removed too since the convar has min/max limits

---------

Co-authored-by: rtldg <55846624+rtldg@users.noreply.github.com>
2023-04-29 14:59:44 +00:00
rtldg
4bbef8aa61 don't eat non-timer bot names - for nuko 2023-04-27 16:11:11 +00:00
rtldg
31fcd7ecb5 don't let tf2 bots duck on surf ramps. it makes the spec view look fucky 2023-04-27 15:07:07 +00:00
rtldg
3a1e6a60cd timeleft hud - minutes to seconds at 150s 2023-04-10 11:03:59 +00:00
rtldg
afdf236fe9 round up fractional ticks when calculating finish time 2023-04-09 13:24:18 +00:00
rtldg
9423ef79ad save !wr menu record page for back button 2023-04-09 13:11:11 +00:00
rtldg
86b36436df add note about startinair 2023-04-08 16:27:54 +00:00
rtldg
79c307fea8 fix maplist type 3 not clearing maps list 2023-03-31 05:42:52 +00:00
rtldg
fee8edeeda make sure it logs about sqlite pow hate 2023-03-16 10:35:04 +00:00
rtldg
787aa8ff34
sqlite rankings support & GetWeightedPoints deprecation (#1182)
* Wip sqlite rankings support & GetWeightedPoints deprecation

* Update shavit-rankings.sp

* maybe everything is working now?
2023-03-16 10:24:40 +00:00
rtldg
9210b84d50 fix some native definition & optional things 2023-03-06 23:38:04 +00:00
rtldg
3757993e50 make replay frames resize failures not kill the server 2023-03-04 06:46:45 +00:00
Jacob Davidson
e4c58dd952
Added map reroll to Shavit-MapChooser (#1184)
* Added map reroll to Shavit-MapChooser and necessary update to phrases

* fixed wr replay for Shavit-Ghost

* fixed to work with latency

* Fixed issues with Pull Request

* Delete shavit-ghost.sp

* fixed if statments to be consistant and removed spaces/tabs

* additional spaces removed

* Removed Bool and fixed translations

* Fixed nomination issue and map loop issue

* Fixed Novote bug by adding check for reroll.

* small touchs of love

---------

Co-authored-by: rtldg <55846624+rtldg@users.noreply.github.com>
2023-02-26 07:09:13 +00:00
Nairda
a4c214c981 fix showing 100% perf with no jumps on scroll 2023-02-26 05:57:48 +00:00
xhaooy
9eceb51ea6 reset hp on restart #1187
Co-authored-by: rtldg <rtldg@protonmail.com>
2023-02-26 05:48:19 +00:00
xhaooy
830ebc1b73 reset sv_enablebunnyhopping & sv_airaccelerate flags for late loading #1187
Co-authored-by: rtldg <rtldg@protonmail.com>
2023-02-26 05:44:01 +00:00
rtldg
7bd954880a RecalcHighestStage typo caught by Haze 2023-02-23 20:15:00 +00:00
rtldg
888b4be951 fix maplist clearing after sm ReadMapList fix 2023-02-21 21:35:41 +00:00
rtldg
2a254a32a1 csgo linux gamedata 2023-02-03 v2 2023-02-03 20:02:48 +00:00
rtldg
7728c640bf hopefully working csgo linux gamedata 2023-02-03 2023-02-03 19:47:51 +00:00
rtldg
afa6b07da8 fix wrong variable used in LessStupidGetMapDisplayName 2023-01-05 11:48:58 +00:00
rtldg
b468f9d67a fix stale zone cache entries being checked, preventing start/end zone placement sometimes 2023-01-04 20:49:56 +00:00
rtldg
bb49da4d9c add !specbot to shavit-misc as an alias for !spec ... (which makes it spec the replay bot if it exists) 2022-12-30 12:12:00 +00:00
rtldg
412812693f update steamid-stocks to handle 64-bit ids on csgo 2022-12-30 12:11:32 +00:00
rtldg
9400b7c7e3 probably fix a bug that allowed you to rtv to a different map after the mapvote can change the map from a previous rtv 2022-12-26 05:49:33 +00:00
rtldg
6ded3770d6
fix typo in shavit_core_save_ips description 2022-12-17 01:18:06 +00:00
rtldg
e19f069a8c fix tf2 Windows PhysicsCheckForEntityUntouch signature 2022-12-04 23:50:33 +00:00
rtldg
06bce65bcc update gamedata for tf2 vscript update 2022-12-02 03:24:36 +00:00
rtldg
2dbb211742 move 0.11s timer absolute minimum stuff 2022-12-02 00:46:20 +00:00
rtldg
1f8461f64b make salvage replay-files have frame-count in filename 2022-12-01 23:39:06 +00:00
Artem Veschitsky
f19df1ca3f
Add CI. (#1180)
* Add CI.

* Add missing include files.

* wget dependencies instead

* add something to deal with forward slashes in github.ref_name

* nevermind, set-output is being deprecated by github

Co-authored-by: rtldg <rtldg@protonmail.com>
2022-11-25 22:18:00 +00:00
rtldg
cbf703bb9f
suppress another missing return value warning 2022-11-25 21:34:40 +00:00
rtldg
e0c59404c3
supress warning about missing explicit return value 2022-11-25 21:30:49 +00:00
rtldg
62d508705f shit code for !editmi 2022-11-16 00:40:07 +00:00
rtldg
2bcd20fac7 make ZF_Origin store floats with decimals instead of as hexadecimal
(this makes it more readable in json dumps of zones)
2022-11-15 21:33:36 +00:00
rtldg
960484585d I keep forgetting things and making a million commits 2022-11-14 22:15:19 +00:00
rtldg
5fec9a2fe1 change url paths 2022-11-14 22:10:43 +00:00
rtldg
12d7e5590d zones typo galore 2022-11-14 20:42:59 +00:00
rtldg
9cf9d7ff27 shavit-zones-http -> shavit-zones-json & some shit 2022-11-14 19:47:08 +00:00
rtldg
7a81b44655 wip shavit-zones-http stuff 2022-11-13 23:49:59 +00:00
jedso
f7ff341131
make shavit_zones_box_offset a bool (which also affects height offset) & correct TF2 bounding box values (#1179)
* Add correct gCV_BoxOffset default value for TF2 bounding box

* Include correct height for TF2 bounding box in SetZoneMinsMaxs

* make shavit_zones_box_offset a bool & use height

* use division-by-2 instead of shift

Co-authored-by: rtldg <55846624+rtldg@users.noreply.github.com>
2022-11-13 04:26:30 +00:00
rtldg
a7e3fe517c tf2: fix 0vel underwater & hook PreventBunnyJumping 2022-11-08 21:11:18 +00:00
rtldg
a6da4358de tf2: only check for 'jointeam spectate' so we don't break the class menu popup 2022-11-02 23:09:05 +00:00
rtldg
f1bea169d2 silence tf_bot_count change notification 2022-11-02 21:55:45 +00:00
rtldg
fefb0ffe6f tf2: fix jump counter & shavit_core_blockprejump 2022-11-02 21:47:04 +00:00
rtldg
91f05dfbf9
Update m_surfaceFriction signature for CSGO Linux 2022-10-22 06:39:08 +00:00
rtldg
83293832fd update CSGO Windows MaintainBotQuota signature 2022-10-22 04:58:09 +00:00
rtldg
0cf281f509 v3.4.2 2022-10-17 12:33:29 +00:00
rtldg
07727e1db0 faster query for deprecate exact_time_int (and more migration logging) 2022-10-17 12:22:39 +00:00
rtldg
f16b9aa7f3 mark SteamWorks_SetHTTPRequestAbsoluteTimeoutMS as optional 2022-10-17 12:20:19 +00:00
rtldg
d0d3c62ff5 v3.4.1 2022-10-16 21:51:19 +00:00
rtldg
5ac888c3a0 add some error logging to replay recorder & something that might help with a segmented replay saving edge case 2022-10-16 21:38:42 +00:00
rtldg
4fee1e4cc1 crap workaround for times not parsing correctly because of commas 2022-10-15 20:32:17 +00:00
rtldg
3db30bea98 v3.4.0 2022-10-14 15:17:59 +00:00
rtldg
783fd4f0a7 more followup commits for ccname & chat rank nonsense 2022-10-14 15:14:23 +00:00
rtldg
5c098bd155 update changelog again 2022-10-14 12:10:58 +00:00
rtldg
0d81991083 update changelog 2022-10-14 11:47:21 +00:00
rtldg
349ba586c7
Merge pull request #1177 from jedso/mapzones-rowid-fix
Add SQLite migration to fix mapzones having NULL id for all rows
2022-10-08 07:02:27 +00:00
jedso
dc2c186249 Use sqlite_master to explicitly check for id's type 2022-10-07 21:17:39 +10:30
rtldg
f0ea0a01c1
Merge branch 'master' into mapzones-rowid-fix 2022-10-06 08:26:00 +00:00
rtldg
4eb31820b1
Merge pull request #1176 from jedso/playertimes_fk
Add migration to update or add auth FK constraint in playertimes
2022-10-06 08:23:24 +00:00
rtldg
fd687dd2d7 i keep forgetting things. please ignore these commits 2022-10-06 08:21:46 +00:00
rtldg
c631f6635b add jedso to top credits 2022-10-06 08:19:19 +00:00
rtldg
9ef34bce59 Add missing users to users table 2022-10-06 08:19:01 +00:00
rtldg
7a79fc03e8 it does have printf though 2022-10-06 08:10:38 +00:00
rtldg
236829cc33 FORMAT(time,9) doesn't work on sqlite 2022-10-06 08:02:14 +00:00
rtldg
09c0d228b4 filter invalid maps in !map, !nominate, and map votes 2022-10-05 19:15:24 +00:00
jedso
5f717553d9 Add SQLite statements to re-create mapzones with INTEGER PRIMARY KEY 2022-10-01 21:39:04 +09:30
jedso
119e7ff4c8 Store SQLite mapzones CREATE TABLE statement for re-use in migration 2022-10-01 21:37:24 +09:30
jedso
b0889f77ee Change mapzones CREATE TABLE for SQLite to use INTEGER PRIMARY KEY 2022-10-01 21:36:45 +09:30
jedso
e196e04de6 Add query to check for NULL SQLite id row in mapzones 2022-10-01 21:34:28 +09:30
rtldg
8eefcd5b68 mark ripext natives as optional 2022-09-30 17:27:02 +00:00
rtldg
de9cbc8470
Merge branch 'master' into playertimes_fk 2022-09-29 06:19:40 +00:00
rtldg
2b2a1fcb12 queue migrations slightly better to handle multiple queries (relevant to #1176) 2022-09-29 06:17:33 +00:00
lilac1337
b868208520
show timer in hud when started in start zone (#1174)
* show timer in hud when started in start zone

aaaaaaaaaaaaaaaaaa

* oops

* remove convar check and change time check to 0.3s

Co-authored-by: rtldg <55846624+rtldg@users.noreply.github.com>
2022-09-29 03:49:58 +00:00
jedso
098b7d4977 Add SQLite statements to re-create playertimes with FK constraint 2022-09-26 23:08:12 +09:30
jedso
d718620aa3 Store SQLite playertimes CREATE TABLE statement for re-use in migration 2022-09-26 23:08:12 +09:30
jedso
a1b04e38ba Change playertimes CREATE TABLE statement to include FK constraint 2022-09-26 23:08:12 +09:30
jedso
23901be52d Add MySQL ALTER TABLE queries to drop and/or add auth FK constraint 2022-09-26 23:08:12 +09:30
jedso
3cef031e91 Add initial migration queries for MySQL/SQLite 2022-09-26 23:08:05 +09:30
rtldg
e4f2d35f6c use upsert in sqlite users table update per #1175 2022-09-25 14:11:21 +00:00
rtldg
87c2b1e436 left over format param from exact_time_int deprecation 2022-09-25 02:02:55 +00:00
rtldg
2e2db2165f IsClientConnected can be removed from IsValidClient 2022-09-24 06:16:47 +00:00
rtldg
894b039e4e deprecate exact_time_int 2022-09-24 05:45:01 +00:00
rtldg
5ccd0efd04 make the autostage thing start at 1. starting at 2 was dumb 2022-09-24 04:59:47 +00:00
rtldg
ea8f14fa07 use smaller zone widths for the epic zone edit axis stuff 2022-09-24 04:57:22 +00:00
rtldg
7a8060a0bf cleanup some small shavit-core gamedata code 2022-09-19 14:18:00 +00:00
rtldg
2e9ba205a0
Merge pull request #1173 from MSWS/patch-2
Break once we find a valid record
2022-09-19 11:09:40 +00:00
Isaac Boaz
4d78090e5f
Break once we find a valid record 2022-09-18 15:13:44 -07:00
rtldg
b115726abb set forwardmove & sidemove on replay bots because why not 2022-09-16 11:36:29 +00:00
rtldg
fdbbc11d2a add !autoreset as alias for !autorestart 2022-09-15 13:15:39 +00:00
Isaac Boaz
e3aab46e01
Added !autorestart | Feat/autorestart (#1170)
* Add autorestart

* Revert HUD Change

* small changes

* Update shavit-misc.sp

Co-authored-by: rtldg <55846624+rtldg@users.noreply.github.com>
2022-09-15 12:07:40 +00:00
Isaac Boaz
f4cd4e9e6a
Add translation for !extend & update m_iRoundTime | Feat/extensionqol (#1172)
* Add extension translation

* Set currents coreboard roundtime
2022-09-15 11:33:51 +00:00
rtldg
a1a1c6adfa
actually do the Shavit_GetMapsStringMap map display name thing right #1168 2022-08-27 01:19:30 +00:00
rtldg
3d16f5ffa7
make Shavit_GetMapsStringMap use map display name #1168 2022-08-24 04:07:26 +00:00
rtldg
6a9e697ff6
remove forgotton todos from shavit-zones-http.sp 2022-08-21 10:46:33 +00:00
rtldg
bf106d9ff2
StringToInt(defaulthudcvar_string) because .IntValue can get fucked by the source engine casting to f32 2022-08-18 04:47:59 +00:00
rtldg
04d65d2fa5
update origin notice around GiveSkinnedWeapon 2022-08-15 13:06:05 +00:00
rtldg
864b46379b
save pos on enhanced (tier list) !nominate menu 2022-08-15 12:58:45 +00:00
BoomShot
b78ae36a0e
remove the steamid verification kick thing in OnClientPutInServer (#1047) 2022-08-15 10:37:00 +00:00
rtldg
bdea503697
add typo handler for 1r -> !r and 1b -> !b 2022-08-15 10:32:16 +00:00
rtldg
0ffdbb9b5a
remove debug comment 2022-08-07 08:44:05 +00:00
rtldg
5fc891d6fa
move velocity_limit logic to work around duck spam 2022-08-07 07:25:20 +00:00
rtldg
1ea49018e0
move clantag forward declarations from core.inc to misc.inc 2022-08-05 04:29:33 +00:00
Nairda
5ec9d0fa11
Update README.md (#1163)
* Update README.md

* Update README.md

Co-authored-by: rtldg <55846624+rtldg@users.noreply.github.com>
2022-08-05 04:26:50 +00:00
Nairda
790f0a392b
Update README.md (#1162)
* Update README.md

because misleading

* Update README.md

Co-authored-by: rtldg <55846624+rtldg@users.noreply.github.com>
2022-08-05 04:26:41 +00:00
NukoOoOoOoO
21c6204062
Use signature instead of doing netprop±offset (#1158) 2022-07-25 18:47:25 +00:00
jedso
578636d528
[TF2] Fix broken NoWeaponDrops (shavit-misc) (#1160)
* Fix broken shavit_misc_noweapondrops for TF2

* Set dropped weapon lifetime OnConfigsExecuted
2022-07-25 16:59:58 +00:00
rtldg
68a57b9123 remove admin requirement for debug targetname 2022-07-22 23:23:58 +00:00
rtldg
1c82605db5 draw zone edit axis sides thing 2022-07-22 22:42:40 +00:00
rtldg
cdbeb52976 add some test defines for bhoptimer_helper 2022-07-21 22:01:27 +00:00
rtldg
e322606492 typo in shavit_misc_bad_setlocalangles_fix implentation 2022-07-21 18:05:11 +00:00
rtldg
1ed7a68ab3 fix changelog commit links 2022-07-21 15:48:53 +00:00
rtldg
e76ab45a55 readme updates 2022-07-20 19:55:18 +00:00
rtldg
9c5c29c6ca v3.3.2 2022-07-20 19:45:11 +00:00
rtldg
f703aca4d6 spawn looping replay bots on different ticks 2022-07-20 19:30:44 +00:00
lilac1337
cec7805047 avantasia fix 2022-07-20 19:00:37 +00:00
BoomShotKapow
7878784887 Fix parameter documentation 2022-07-20 18:51:35 +00:00
rtldg
898c46379d random things 2022-07-20 15:58:18 +00:00
rtldg
bf25061444 de-page zone adjust menu 2022-07-20 15:32:54 +00:00
rtldg
1e7459a6c4 have the customzones cookie be long & no high bit shenanigans 2022-07-20 13:41:47 +00:00
rtldg
684ade8dd9 fix typo for czones 2022-07-18 01:03:30 +00:00
rtldg
6ceab1283c slightly rearrange chat rank validation check stuff 2022-07-16 01:26:37 +00:00
rtldg
5ba8ede632 v3.3.1 2022-07-11 14:29:36 +00:00
rtldg
a778908e32 only wait for tiers in mapchooser if rankings & mysql 2022-07-11 14:16:57 +00:00
rtldg
4ac0b4da5d make the InsertZones cache.iDatabaseID setting more robust! 2022-07-11 13:20:11 +00:00
rtldg
d78393f084 try to get this ccname chat rank stuff not racing 2022-07-11 11:06:58 +00:00
rtldg
5c14dfcc60 add ZF_Origin & fix a lot of broken button stuff 2022-07-05 04:45:20 +00:00
rtldg
27ec578c7d don't draw zones around hooked buttons 2022-07-05 01:56:23 +00:00
rtldg
0f7360f374 fix loop exiting early and error on invalid entity 2022-07-05 01:37:58 +00:00
rtldg
fb42a370fe update zone cache database id on zone creation 2022-07-05 00:51:15 +00:00
rtldg
8900e4b6ff open a menu for !deletesetstart 2022-07-04 21:19:27 +00:00
rtldg
72ae96e0c8 fix creating a zone and not being able to delete it without reloading the map 2022-07-04 21:03:58 +00:00
rtldg
1449b9b3d5 revert this !top thing back so points have commas 2022-07-01 13:31:09 +00:00
lilac1337
7e44264f13
add a-only (#1150)
* add a-only

* Update shavit-styles.cfg

* Update shavit-styles.cfg

* Update shavit-styles.cfg

Co-authored-by: rtldg <55846624+rtldg@users.noreply.github.com>
2022-07-01 13:22:14 +00:00
rtldg
64bd95a73b add a_or_d_only style setting 2022-07-01 13:17:38 +00:00
rtldg
760d84e420 update changelog 2022-06-29 19:25:23 +00:00
rtldg
bdfa61e3f9 fix !addspawn after zones wip pr 2022-06-29 19:23:40 +00:00
rtldg
8aad5e6f00 update changelog 2022-06-28 19:26:15 +00:00
rtldg
6dc1fb66e4 split mapzones form & target migration for sqlite 2022-06-28 19:23:39 +00:00
rtldg
7819aa1ace changelog 2022-06-28 13:34:58 +00:00
rtldg
0360b957e4 i introduced a bug that made ccname queries race admin auth queries 2022-06-28 13:32:49 +00:00
rtldg
8b4db28cfb update changelog 2022-06-28 04:24:22 +00:00
rtldg
1a86a2b643 v3.3.0 2022-06-28 02:46:50 +00:00
rtldg
4c21dc96f9 try to let specs rtv until the cooldown triggers 2022-06-28 02:22:41 +00:00
rtldg
5056917d78 some log messages 2022-06-28 02:16:24 +00:00
rtldg
489fd3cbf1 add something to the !wr menu to open steam profiles... 2022-06-27 14:25:27 +00:00
rtldg
c3f67d77f2 add some gamedata notes 2022-06-24 12:45:12 +00:00
rtldg
4486528880 preliminary postgresql support 2022-06-23 09:10:22 +00:00
rtldg
178d42e2fd update tf2 gamedata for 2022-06-21 update 2022-06-22 16:38:13 +00:00
rtldg
1a03bdac13 fix permission style setting typo oops 2022-06-21 14:29:46 +00:00
rtldg
8237b249c5 remove SHAVIT_LOG_QUERIES 2022-06-21 11:53:59 +00:00
rtldg
78eeb38c12 remove testing prints 2022-06-20 13:00:10 +00:00
rtldg
9cbed1972b shavit_replay_disable_hibernation 2022-06-20 11:50:33 +00:00
rtldg
fa28502a0d buffer playtime disconnect queries to prevent map change query traffic jams 2022-06-20 11:03:12 +00:00
rtldg
2efbc4a653 send map & api-key headers with steamworks too (untested) 2022-06-17 09:19:26 +00:00
rtldg
3e29099ab8 ensure we have a valid AdvertisementCycle index 2022-06-16 13:04:12 +00:00
rtldg
d922cebf97 add auto stage thing #1147 2022-06-13 07:03:16 +00:00
rtldg
0f44dd1710 add shavit_core_log_sql & remove Database2/Transaction2 methmodmaps 2022-06-13 06:28:46 +00:00
rtldg
fa6ccdbded make sqlite run migrations automatically too 2022-06-13 05:46:10 +00:00
rtldg
7c251ef81d add Back to admin commands to go back to admin menu 2022-06-13 05:42:40 +00:00
rtldg
8e0e5ec8c1 add buttons, scrolls, and anglediff to huddata_t 2022-06-12 16:08:40 +00:00
rtldg
6bba2072fe use MaxClients instead of MAXPLAYERS because 2022-06-12 15:33:13 +00:00
rtldg
4315221b86 remove USE_RIPEXT define and add cvar 2022-06-12 15:30:37 +00:00
rtldg
85adfa3bb2 add space to translation because it prints the color code 2022-06-12 14:50:56 +00:00
rtldg
e3aac2d24e
zones wip (#1143)
* backup a lot of this zone_cache_t stuff since i'm going to do something else first

* AAAAAAAAAAAAAA

* add the sTarget checking

* this pr will get squashed so this message doesn't matter

* wip Shavit_RemoveZone

* wip ZF_Solid and TODO notes

* move hook thing

* do some zone insert stuff that doesn't reload *every* zone

* condense some zone editing global variables

* add some spaces to some ifs

* remove gV_MapZones

* remove random loop

* big change

* remove ClearZone()

* .

* ..

* add speed to zone beam settings

* add bhop_n0bs1_css stripper cfg for shit zone

* ...

* remove draw timer to OnConfigsExecuted because interval cvar

* change string for mapfixes print

* wew

* rename iSource to iForm and add sSource

* add Shavit_ReloadZones() and rename some source things

* add shavit-zones-http.sp

* add a getarray

* adjust the http api format slightly

* remove Shavit_GetStageZone() & fix zone inserts

* api update

* convar edits

* increase buf size

* wrong buf...

* normalize points inside Shavit_AddZone

* rename ZonesNotLocal to ZonesNotSQL

* small cleanup

* add the zone hooking menu stuff

* make the confirm menu Exit button STOP DRAWING!!!

* only try to draw trigger_multiples

* asdf

* typo

* improvements

* add distance to menu

* use PassesTriggerFilters like rngfix

* finish some docs

* make dist be meters

* more hooking tele things

* remove all this migration stuff

* add entity under crosshair

* shorten stage translation message
2022-06-12 14:43:16 +00:00
rtldg
affac70f99 make the shavit-chat OnRebuildAdminCache use a timer 2022-06-10 10:53:20 +00:00
rtldg
41f50505f9 fix flag access & admin reloads in for shavit-chat 2022-06-10 08:15:32 +00:00
rtldg
bfa9aa45e4 rework !ccmsg off & !ccname off slightly 2022-06-10 07:29:01 +00:00
rtldg
4cf01f5ec4 revert WriteNavMesh stuff to kid's since writing 1-size values = a shit ton of file->Write calls 2022-06-08 10:55:47 +00:00
rtldg
22acb5b6c2 increase ShowHudText buf size for csgo/protobuf (sourcemod/pr1777) 2022-06-07 17:06:07 +00:00
rtldg
09917f91d9 fix adminmenu 2.0 2022-06-07 16:53:01 +00:00
rtldg
8f11f9aaf1
reset speedmod on starttimer since it seems fine 2022-05-29 02:55:26 +00:00
rtldg
79baadf541 add shavit_misc_bad_setlocalangles_fix 2022-05-27 03:16:44 +00:00
rtldg
6fc6ca86bc remove unused/broken beamer code 2022-05-27 01:57:47 +00:00
rtldg
4bfa75a32c replace many instances of NULL_VECTOR because sourcemod is fucking stupid 2022-05-26 09:19:39 +00:00
rtldg
d8a9dd7d7b add sm_beamer 2022-05-26 08:44:37 +00:00
rtldg
ed481b216c don't clone database handle if it's 0 2022-05-26 00:35:58 +00:00
rtldg
7dddfe25f3 make wr menu also print steamids to chat for #1146 2022-05-25 13:01:07 +00:00
rtldg
ef3ca621c4 add more contributors & copyright attributions. mostly done via git blame but also it's also likely i missed some people. 2022-05-25 11:43:57 +00:00
rtldg
5b5652a34d fix typo 2022-05-23 03:15:38 +00:00
rtldg
96ef03e458 make slay zones *actually* force suicide. only slay if timer != stopped 2022-05-22 07:46:13 +00:00
rtldg
c2e50761ec add basic strafer thing to autogain 2022-05-21 23:44:35 +00:00
BoomShot
e817a9ada7
Small fix for shavit-core (#1144) 2022-05-21 13:36:22 +00:00
rtldg
53463d8fb9 alternative teleport angle hijack stuff 2022-05-19 08:39:48 +00:00
rtldg
22a68b491b add HUD_SPECTATORSDEAD 2022-05-17 02:37:41 +00:00
rtldg
bc62b92983 add ent_fire to cheat commands list (for csgo) 2022-05-16 00:13:34 +00:00
rtldg
d816423eb6 fix some csgo maps that having missing filtername keys 2022-05-12 07:42:58 +00:00
rtldg
a23348d843 add !maprestart and !mapreload aliases 2022-05-12 07:27:27 +00:00
rtldg
acf47a11b1 add Zone_Speedmod for oblivious 2022-05-10 01:51:00 +00:00
rtldg
ab73e36a15 czones: use same settings for all bonuses & let more types be editable 2022-05-09 23:55:00 +00:00
rtldg
2616712c9e some closestpos debug prints 2022-05-05 04:59:20 +00:00
Shahrazad
487e3db9d0
Use and duplicate other's checkpoints implementation (#1142)
* add target param for Shavit_TeleportToCheckpoint(), Shavit_OnTeleport() and Shavit_OnTeleportPre()

* Use others' checkpoints implementation

* Automatically refresh current checkpoint index

* add owner param for Shavit_OnCheckpointMenuSelect()

* add duplicate param for Shavit_OnSavePre() & Shavit_OnSave(), etc.

* use persistent cp initial

* temporarily no more for using persistent checkpoints

* final check and add convar for using others cp

* Update shavit-misc.phrases.txt

* reorder parameters

* changes

* AHHHHHHHHHHHHHHHHHHH GIT YOU FUCKING FAILED THE PATCH MERGE YOU PIECE OF SHIT

Co-authored-by: rtldg <55846624+rtldg@users.noreply.github.com>
2022-05-04 02:25:40 +00:00
rtldg
1bbd4ba82e update changelog 2022-05-04 00:09:52 +00:00
rtldg
e0162afce3 update changelog 2022-04-27 18:59:17 +00:00
rtldg
7c842afdf0 v3.2.0 2022-04-27 16:04:24 +00:00
rtldg
9a3b80f418 fix checkpoint menu message from showing every kz-style change 2022-04-27 15:44:04 +00:00
rtldg
c8ed191d11 m_iPrimaryAmmoType can be -1 for knives 2022-04-26 14:55:35 +00:00
rtldg
a25417cc8a add infinite ammo options for all guns to shavit_misc_weaponcommands 2022-04-26 14:44:59 +00:00
rtldg
b2b2fe3344 add fClosestReplayLength to huddata_t and Shavit_GetClosestReplayTime 2022-04-23 17:09:35 +00:00
rtldg
b956ffb8aa make the reset checkpoints button also trigger Shavit_OnDelete (#1138) 2022-04-23 13:41:51 +00:00
rtldg
e344ea2d89 add v3.2.0 changes to changelog in prep for next release 2022-04-21 15:32:39 +00:00
rtldg
158f0b8546 disable the extra css ladder stuff from checkpoints for now 2022-04-21 13:22:44 +00:00
rtldg
f1ad55fddf add note to shavit_hud_ticksperupdate 2022-04-21 13:18:41 +00:00
rtldg
14e71dbbb4 make the buttons in the wr submenu not do stuff 2022-04-16 17:37:08 +00:00
rtldg
c170393447 add UppercaseString because why not 2022-04-16 00:33:28 +00:00
rtldg
cf5bc4b7db make sure the center keys doesn't send multiple times per tick 2022-04-15 22:39:45 +00:00
rtldg
2ac4190865 small changes to checkpoint practice mode thing & force param 2022-04-15 22:39:45 +00:00
rtldg
48ffd9bc71 add shavit_hud_block_spotted_hint 2022-04-15 22:39:39 +00:00
rtldg
1230bf9266 remove Shavit_Core_CookiesRetrieved 2022-04-15 22:33:08 +00:00
rtldg
fb5c247953 add some checks if shavit-zones is loaded 2022-04-15 15:51:54 +00:00
rtldg
9902b8adac some potential steamid future proofing 2022-04-12 18:42:25 +00:00
rtldg
aa1f0eb169 make Shavit_StartReplayFromFile retrieve name correctly 2022-04-12 18:14:04 +00:00
rtldg
1802f998fc add some more semi-tested ladder stuff to checkpoints 2022-04-12 02:14:58 +00:00
Shahrazad
b090743bae change default tranking multiplier to 0.0 2022-04-11 14:06:02 +00:00
rtldg
9d771dfdba move TimerAction enum to shavit-checkpoints.sp 2022-04-11 14:03:58 +00:00
Shahrazad
6d208a8595
merge CP menus & shavit-kz.sp, etc. (#1137)
* fix normal CP menu spams on changing the style from non-kz to kz styles

* fix normal CP menu spams on changing from non-kz to kz styles, again

* merge OpenKZCPMenu() into OpenNormalCPMenu() and rename it to OpenCPMenu()

* fix handle error on server restart in KZCP styles

* 1. Added "kzcheckpoints_ontele" and "kzcheckpoints_ontele" style settings(merged in `shavit-kz.sp`).
2. Added "force"(ignore style access) parameter for "Shavit_LoadSnapshot()" and "Shavit_LoadCheckpointCache()".
3. Made "segments" as a style setting instead of special strings.
   (use "segments" as specialstrings is still feasible)

note: maybe better to change TAS's default ranking multiplier to "0.0" since segmented style is also "0.0".

* 😵‍💫

* updated shavit-checkpoints.sp

* updated style-settings.sp
2022-04-11 13:58:18 +00:00
rtldg
c6ced66503 merge TrimTrailingInvalidUnicode into SanerGetClientName 2022-04-08 16:15:39 +00:00
rtldg
ad258dc047 fix table name array and move around 2022-04-02 12:40:46 +00:00
rtldg
ea3bd05124 mark hud messages unreliable so the hud updates more often 2022-04-02 10:35:15 +00:00
Nairda
d7785f91ce
add two additional commands for nomlist (#1136)
* add two additional commands for nomlist

that are more intuitive

* Update shavit-mapchooser.sp
2022-04-02 09:15:58 +00:00
rtldg
ef51513fcc rename CreateInterface gamedata to CreateInterface_Server 2022-03-29 12:47:01 +00:00
defiy
76aaecdb6e change autogain velocity setting so boosters on bhop_linear_gif aren't affected by vertical velocity 2022-03-29 03:58:20 +00:00
rtldg
ddb902e663 make sure not to put nominations twice on the map vote 2022-03-27 13:31:19 +00:00
rtldg
e0bdbfc20f edit TRFilter_NoPlayers 2022-03-27 08:44:15 +00:00
rtldg
d6aaa8e413 clean some random tiers usage stuff in shavit-mapchooser 2022-03-26 13:30:07 +00:00
rtldg
fda64ad102 add bhop_drop bonus to mapfixes since that's apparently a problem too 2022-03-24 14:28:55 +00:00
GAMMACASE
8f07c1d510
Fix targetname and classname locking (#1135)
* Move resettargetname cvars to shavit-zones

* Prevent Touch function to proceed when it should be skipped
2022-03-24 14:20:35 +00:00
rtldg
3a6592cc5e faster LowercaseString 2022-03-23 14:22:10 +00:00
rtldg
554606a210 move Shavit_GetStageWR/PB docs to wr.inc 2022-03-23 10:42:00 +00:00
rtldg
85ff178f47 move CheckRTV to OnClientDisconnect_Post so it works properly ™️ 2022-03-23 10:30:46 +00:00
rtldg
361884b17d correct style setting SetArray size 2022-03-23 10:25:52 +00:00
rtldg
f642afe016 add max checkpoint count to checkpoint menu 2022-03-22 04:08:59 +00:00
rtldg
57326e1843 edit Shavit_SaveCheckpointCache to add target & clone handles 2022-03-21 04:30:33 +00:00
rtldg
86af6ca07b removed Shavit_OnCheckpointCacheDeleted, added Shavit_SetTimesTeleported(), added Shavit_LoadCheckpointCache, and added Shavit_SaveCheckpointCache 2022-03-20 11:42:18 +00:00
rtldg
ea9a962711 hopefully the last commit for Shavit_SetCheckpoint (#1133) 2022-03-19 13:11:41 +00:00
rtldg
8f59007d1d change position logic again for Shavit_SetCheckpoint (#1133) 2022-03-19 12:34:15 +00:00
rtldg
91ec294f42 try to improve usage of handles in Shavit_SetCheckpoint() & fix errors (#1133) 2022-03-19 11:41:52 +00:00
Nairda
b05393cf9f
rename shavit_checkpoints_checkpoints to shavit_checkpoints_enabled (#1132)
* yes

* undo indentation changes

* shavit_checkpoints_checkpointsenabled -> shavit_checkpoints_enabled

Co-authored-by: rtldg <55846624+rtldg@users.noreply.github.com>
2022-03-18 02:24:55 +00:00
Nairda
bcc82992e5
Update doc comments for Shavit_Core_CookiesRetrieved & Shavit_ShouldProcessFrame (#1131) 2022-03-18 02:21:49 +00:00
GAMMACASE
0fee1862c8
Change the behaviour of shavit_misc_resettargetname (#1123)
* Redo shavit_misc_resettargetname

Also changes the way event abuses are fixed

* Obsolete shavit_misc_resettargetname/classname cvars

Also few minor optimisations to the code

* Revert the deletion of shavit_misc_resettargetname/classname

* Move targetname/classname resets to OnStartPre() forward

* Rename shavit_misc_resettargetname cvar

* Move event reset code to shavit-zones

Also replaces PhysicsCheckForEntityUntouch() function call with PhysicsRemoveTouchedList()

* don't hook teleport on bots & some random code-style changes

* remove added whitespace

Co-authored-by: rtldg <55846624+rtldg@users.noreply.github.com>
2022-03-18 02:17:19 +00:00
Ciallo
d58d3ee1d5
fix creating replay-directories issue & hopefully first map load replays (#1130)
* fix creating replay-directories issue

* call Shavit_OnStyleConfigLoaded on lateloads

* use the stock for loading the replay folder path

* reorder some replay playback cvar usage

Co-authored-by: rtldg <55846624+rtldg@users.noreply.github.com>
2022-03-17 12:00:22 +00:00
Ciallo
73601ffd0a don't do the checkpoints menu thing if checkpoints cvar is disabled 2022-03-16 21:52:02 +00:00
rtldg
89e8f69f6a update changelog 2022-03-15 13:11:42 +00:00
rtldg
724244f3e8 stop calculating vel twice 2022-03-14 05:36:58 +00:00
rtldg
70f29d3ca5 fix replay props having a bad index for cachedframes 2022-03-14 02:06:59 +00:00
rtldg
de8a82707b add Shavit_OnSavePre & Shavit_OnTeleportPre and ignore return value from Shavit_OnSave & Shavit_OnTeleport 2022-03-14 01:47:15 +00:00
rtldg
033179edf0 v3.2.0a 2022-03-05 13:50:46 +00:00
rtldg
d77fa13ebe v3.1.3 2022-02-27 09:45:58 +00:00
rtldg
807baa13ad make sure a timer works 2022-02-27 07:09:04 +00:00
rtldg
8c00da8a5a update changelog 2022-02-27 05:31:16 +00:00
rtldg
69445ebab5 add some more checkpoint forwards so mpbhops_but_working can work with segmented styles 2022-02-27 05:11:04 +00:00
rtldg
98fcc37b7b remove a bool around that might affect some rare checkpoints error 2022-02-27 04:07:13 +00:00
rtldg
060ce5e660 check replay header for time if replay-playback is unloaded 2022-02-24 23:10:22 +00:00
rtldg
80e8480b7a add Shavit_GetReplayEntityFlags & have scroll count work for replay bots (non-prop) #1125 2022-02-24 06:24:33 +00:00
rtldg
4e89fb60d9 halve potential GetRankForTime search space for lots of records 2022-02-21 19:29:12 +00:00
rtldg
2e791a8237 set wrname on wr for when the query takes a second 2022-02-21 19:15:32 +00:00
rtldg
840490cc54 this should let you change shavit_zones_box_offset without reloading the plugin 2022-02-21 18:39:28 +00:00
rtldg
98ee179927 make prespeed_ez_vel work with just angles too 2022-02-21 18:31:15 +00:00
rtldg
525b62753b change prespeed_ez_vel velocity vector calculation 2022-02-20 22:42:57 +00:00
rtldg
a4e2dccc12 sort convars so finding things is easier 2022-02-18 02:23:23 +00:00
rtldg
614b16ce17 add bhop_apathy and bhop_interloper to mapfixes 2022-02-17 22:06:52 +00:00
rtldg
bb7cde71ec easier way to find GetPlayerMaxSpeed offset on CSGO that nuko told me 2022-02-17 20:31:04 +00:00
rtldg
363627603b maybe this style playtime thing will finally go away 2022-02-17 19:32:29 +00:00
rtldg
89e97dfd3d don't start non-prespeed styles unless on ground for .5s 2022-02-13 20:37:15 +00:00
rtldg
2360d71494 add bhop_blackshit to mapfixes 2022-02-12 21:13:03 +00:00
rtldg
fc4aac0c47 remove forgotten params & add !czone & maintain menu pos 2022-02-12 20:57:28 +00:00
NukoOoOoOoO
9c634868cb
sm_czones implementation (#1119)
* Initial czones implementation

* ok men

* read cookie

* :pepega:

* Update shavit-zones.sp

* UltraThin lets goooo

* Translation, ZoneDisplay_None

* format a little bit

* more readable

* Fix typo and i did this on phone

* getting translation properly, thank you haze <3

* make GetZoneName check for >=ZONETYPES_SIZE

* i dont know why this was in common.txt, maybe parallel universe is real

* some random things

* combine custom-zone cookies

Co-authored-by: rtldg <55846624+rtldg@users.noreply.github.com>
2022-02-12 20:49:20 +00:00
rtldg
a6ade753fe add startinair style setting 2022-02-10 22:02:52 +00:00
Nairda
120f82eaf4
add test_ to default mapchooser exclusion list (#1121)
add default "test_" maps to be excluded from being shown in nominations and mapvotes
2022-02-10 20:14:29 +00:00
rtldg
22c9e50ed7 remove some warnings & TODOs 2022-02-09 22:28:16 +00:00
rtldg
2ef8407292 add note to SanerGetClientName & sourcemod 1.11 2022-02-09 22:16:14 +00:00
rtldg
ef5ac148b3 fix lowgrav & ladder combo sometimes breaking for chogi gf 2022-02-09 21:55:13 +00:00
rtldg
44eb29e27c some random error about a null checkpoints array comes up sometimes
L 01/24/2022 - 17:51:57: [SM] Exception reported: Invalid Handle 0 (error: 4)
L 01/24/2022 - 17:51:57: [SM] Blaming: shavit-checkpoints.smx
L 01/24/2022 - 17:51:57: [SM] Call stack trace:
L 01/24/2022 - 17:51:57: [SM]   [0] ArrayList.Length.get
L 01/24/2022 - 17:51:57: [SM]   [1] Line 1088, D:\sourcemod-1.10.0-git6528-windows\addons\sourcemod\scripting\shavit-checkpoints.sp::OpenNormalCPMenu
L 01/24/2022 - 17:51:57: [SM]   [2] Line 949, D:\sourcemod-1.10.0-git6528-windows\addons\sourcemod\scripting\shavit-checkpoints.sp::OpenCheckpointsMenu
L 01/24/2022 - 17:51:57: [SM]   [3] Line 787, D:\sourcemod-1.10.0-git6528-windows\addons\sourcemod\scripting\shavit-checkpoints.sp::Command_Checkpoints
2022-02-09 21:23:15 +00:00
rtldg
0bde3c42b6 add some random things to prevent stupid small replay files from trying to load or save 2022-02-09 20:50:49 +00:00
rtldg
0c459505c8 don't disable detour if detour was never enabled 2022-02-09 20:38:42 +00:00
rtldg
3b8ed08692
Merge pull request #1120 from Nairdaa/patch-24
stats exploit fix for playtime per style
2022-02-08 05:25:27 +00:00
Nairda
253321ced6
stats exploit
fix exploit allowing to "farm" playtime while spectating
2022-02-04 04:05:24 +00:00
rtldg
a0153de9f8 don't let mp_humanteam get in the way of jointeam 1 (for css spectate menu prompt on first join) 2022-02-04 02:21:28 +00:00
rtldg
7aeaa1a02d add futiles to mapfixes because the antijump speedmods are a bit annoying when we clear the events so it doesn't let the player jump again
sorry for when i broke the player_speedmods button disabling in 3.0.8 lol
2022-02-02 23:28:29 +00:00
rtldg
987eebb3b0 draw perfs keyhint even in startzone so the hud doesn't resize constantly 2022-02-01 19:20:19 +00:00
rtldg
9a5ff64fc5 add speedmod & lagged movement values to debug targetname hud thing 2022-01-31 20:49:08 +00:00
rtldg
26dfdcc927 invert this duck autogain nsl boolean 2022-01-29 15:30:36 +00:00
rtldg
d335ec7262 v3.1.2 2022-01-28 17:19:29 +00:00
rtldg
7399512f5e add bhop_lowg to mapfixes 2022-01-28 16:54:46 +00:00
rtldg
0000000146 csgo can have non-string values in the variant of AcceptInput for player_speedmod 2022-01-22 18:06:40 +00:00
rtldg
0000000868 use Plugin_Stop instead of Plugin_Handled in command-listener 2022-01-21 08:39:08 +00:00
rtldg
0000000fbb some changelog stuff 2022-01-20 21:01:12 +00:00
rtldg
0000000b2b Revert "update scoreboard/clantag more often" -- css scoreboard update interval is 1s
This reverts commit a8016dff00.
2022-01-20 16:50:39 +00:00
rtldg
00000008fd make sure the z isn't scaled just in case for prespeed_ez_vel 2022-01-20 18:45:34 +00:00
rtldg
dd0059f15f use a formula for the max prestrafe 2022-01-19 12:38:27 +00:00
rtldg
d95ddbbf8c changelog updates 2022-01-19 11:21:27 +00:00
rtldg
a1d30afdbe oh god the typoooo v3.1.1 2022-01-19 11:11:28 +00:00
rtldg
b042a6c170 v3.1.1 & CHANGELOG.md 2022-01-19 11:09:53 +00:00
rtldg
345461a838 hijack angles when autoprestrafing 2022-01-19 09:41:09 +00:00
rtldg
894ecdff48 make sure the DumbSetVelocity only happens if we scale prespeed speed 2022-01-19 09:41:09 +00:00
rtldg
117d2d277c set snapshot.fplayer_speedmod when checkpointing a bot so players don't get stuck 2022-01-19 09:41:08 +00:00
rtldg
7a11acf2e6 remove points_calced_from since it should only update on wr now so it's unnecessary 2022-01-19 09:41:01 +00:00
rtldg
b3b7de37e2 trim out some unnecessary point recalculations 2022-01-19 01:24:03 +00:00
rtldg
aef89e9bb4 add awful prestrafe limit thing because tas autoprestrafe on 128 tick goes slightly higher than 290.0 2022-01-18 17:55:03 +00:00
rtldg
01a62b5d6b hopefully save oldyaw for tas better 2022-01-18 15:56:56 +00:00
rtldg
9434e1395f silent offset messages 2022-01-18 15:06:52 +00:00
rtldg
37a3a63bad small edits to shavit-tas 2022-01-18 15:05:18 +00:00
rtldg
fda843a09f add !hideweps alias 2022-01-18 14:43:01 +00:00
rtldg
bacc5672fc remove auto-find-offsets cvar for m_surfaceFriction since it has false positives 2022-01-18 14:41:20 +00:00
rtldg
c8c87347a5 move the tas setting defaults below the specialstring setter stuff 2022-01-15 17:12:40 +00:00
rtldg
d1b2ffd461 normalize angle difference just in case 2022-01-15 13:02:45 +00:00
NukoOoOoOoO
e43c011711
basic autostrafe (#1114) 2022-01-15 12:56:38 +00:00
rtldg
062efd4772 prefix expected rank with # 2022-01-15 12:54:00 +00:00
rtldg
ecbc7edca2 add back reset checkpoints option when tas menu stuff 2022-01-15 12:49:09 +00:00
rtldg
3d40d4f809 add !adverts 2022-01-15 12:19:17 +00:00
rtldg
6d296caf36 make pb menu usage a bit nicer and less buggy 2022-01-15 12:08:01 +00:00
rtldg
2909a38179 fill replay name with steamid by default 2022-01-15 11:41:54 +00:00
rtldg
4167001b5c make block_pstrafe do nothing when autostrafe is enabled 2022-01-15 11:34:10 +00:00
rtldg
6c88f45ba0 make sure we wrap a shavit-mapchooser native in a check for the module being loaded 2022-01-14 08:11:40 +00:00
rtldg
9adc56e284 something to not print the timer message prefix space thing if there's no prefix 2022-01-13 17:50:36 +00:00
rtldg
4d9f3f9a1b move this tas vel change into an else statement 2022-01-13 12:43:52 +00:00
rtldg
ac9b204ffd only 1 decimal for timescale in menu 2022-01-13 03:29:11 +00:00
rtldg
b4d13836ea remove forgotten chat timescale float print thing 2022-01-13 03:22:18 +00:00
rtldg
6921f38214 make most of the timeleft messages silent 2022-01-11 11:41:57 +00:00
rtldg
cdd8c56a5e v3.1.1a 2022-01-11 11:04:40 +00:00
rtldg
0133300a40 v3.1.0 2022-01-11 10:14:39 +00:00
rtldg
b4b79d2159 update topleft on when changing spectatee 2022-01-11 10:13:28 +00:00
rtldg
5d47c2dd1b make !times open pb menu 2022-01-11 09:47:52 +00:00
rtldg
150bd15b55 move !extend to shavit-timelimit 2022-01-11 09:44:39 +00:00
rtldg
f474a944ae option whether to draw !keys in the center or menu for csgo 2022-01-11 07:54:31 +00:00
rtldg
e1e404714b delete shavit-info 2022-01-11 07:23:57 +00:00
rtldg
91241c235c make sure that onstop forward runs 2022-01-11 05:43:44 +00:00
rtldg
573e97e9dc hsw shouldn't track strafes on w 2022-01-10 19:41:18 +00:00
rtldg
ec881bbae5 some final touch ups 2022-01-09 19:28:37 +00:00
rtldg
cf7c1d85bb something that might let people unrtv after a non-rtv'd mapvote 2022-01-09 18:35:45 +00:00
rtldg
0adf03b575 no decimal for timedifference when >= 60 2022-01-09 14:05:58 +00:00
rtldg
918cfde75d i don't want to see 'Timeleft: 1 minutes' 2022-01-09 13:53:11 +00:00
rtldg
46550e7a83 extend some hud stuff 2022-01-09 13:48:39 +00:00
rtldg
7675b60567 hud forward stuff 2022-01-09 10:48:48 +00:00
rtldg
5882e458db some more random maps to mapfixes 2022-01-08 16:37:06 +00:00
rtldg
5b8a149343 bonus filter for bhop_appaisaniceman3 to mapfixes 2022-01-08 08:18:26 +00:00
rtldg
dedbba5ec9 add bhop_appaisaniceman3 to mapfixes 2022-01-08 08:11:57 +00:00
rtldg
b11b82b286 update some random strings 2022-01-07 16:52:12 +00:00
rtldg
f4d2d6d653 fix memory leak in spec_next/spec_prev listener. thx @Ciallo-Ani 2022-01-07 16:19:43 +00:00
rtldg
590d1fb290 adjustments to !pb 2022-01-07 15:44:22 +00:00
NukoOoOoOoO
3be3b4e3b2
Implementation of !pb / !time (#636) (#1108)
* Initial implementation of !pb / !time

* Lowercase map name
2022-01-07 14:41:55 +00:00
Nora
3f3474f463
[Prebuilt] Fix start zone in wrong place. (#1106) 2022-01-06 10:59:49 +00:00
rtldg
18a4e1e306 document tas style settings 2022-01-06 10:59:09 +00:00
rtldg
fbdfc7bbea check if valid index of course :) 2022-01-05 21:11:50 +00:00
rtldg
0cc406c962 add 0.5x playback for replay bots 2022-01-05 21:08:26 +00:00
rtldg
871f59c235 save persistent data on ForcePlayerSuicide() / kill / CommitSuicide() 2022-01-05 12:18:45 +00:00
rtldg
776d32b0ef fix NoPlayers trace filter used for IsSurfing 2022-01-05 08:50:30 +00:00
rtldg
85c1617658 adjust specialstring style key setting 2022-01-05 08:14:26 +00:00
rtldg
fa58b0f7fe add shavit_chat_enabled 2022-01-05 04:54:57 +00:00
rtldg
0286df9edd miscellaneous tas fixes 2022-01-04 17:36:59 +00:00
rtldg
9c4f626076 fix Shavit_GetZoneID :^) 2022-01-04 15:41:43 +00:00
rtldg
3a87717250 correct tas style settings names 2022-01-04 14:56:12 +00:00
rtldg
3816aa3646 add something for tas jumping out of the start zone with a 0 offset 2022-01-04 14:50:50 +00:00
rtldg
baa824e872 add Shavit_GetZoneTrack, Shavit_GetZoneType, and Shavit_GetZoneID 2022-01-04 14:25:51 +00:00
rtldg
e8e8f71657 rename some tas things & give style settings per feature 2022-01-04 13:31:42 +00:00
rtldg
a115632b7b add chat messages for tas commands 2022-01-04 08:04:27 +00:00
rtldg
58dbd6d1c3 don't hook tas PostThinkPost for bots 2022-01-04 07:51:23 +00:00
rtldg
c089b3af9d add tas-feature toggle commands 2022-01-04 07:46:17 +00:00
rtldg
b25afa84a3 reopen tas settings menu to correct page 2022-01-03 18:48:23 +00:00
rtldg
d2763d337b add missing timescale handler for the tasmenu 2022-01-03 17:59:36 +00:00
rtldg
ccb0caee7b add edge-jumping to tas 2022-01-03 17:59:21 +00:00
defiy
4880735a71 use different way of setting velocity in tas-oblivious to help with boosters boosting too much (like on bhop_ragequit) 2022-01-03 07:58:17 +00:00
rtldg
527864b426 try to prevent annoying autojump spam 2022-01-03 07:51:37 +00:00
rtldg
240caba1a2 tas & timescale menu changes 2022-01-03 07:40:49 +00:00
rtldg
1d841372a9 adjust style settings for example tas style 2022-01-02 19:26:20 +00:00
defiy
6bc371e940 handle +duck for autogain 2022-01-02 17:42:35 +00:00
rtldg
3b5ed62b28 add sm_tasm alias 2022-01-02 17:26:56 +00:00
rtldg
b34a4e6677 add key overrides to tas menu 2022-01-02 17:26:29 +00:00
rtldg
42c4550df5 fix autogain not starting where you're aiming from 0 velocity 2022-01-02 17:04:47 +00:00
rtldg
c9c6a333a4 make all these tas functions stocks 2022-01-02 16:21:21 +00:00
rtldg
ba5ad21661 add tas settings menu & missing autojump natives 2022-01-02 15:40:59 +00:00
rtldg
da172f07aa tas credits & override fixes 2022-01-02 14:46:44 +00:00
rtldg
576c773134 finish adding apis for tas & such 2022-01-02 14:13:09 +00:00
rtldg
8a9fe14274 lowercase style settings that are set from specialstring 2022-01-02 13:23:53 +00:00
rtldg
1633201e16 put xutax & oblivious autostrafe types behind style setting 2022-01-02 12:33:42 +00:00
defiy
e3ed6027ca add oblivious autogain tas & prestrafe stuff 2022-01-02 12:17:55 +00:00
rtldg
2fa06031de shape into shavit-tas 2022-01-02 11:49:00 +00:00
XutaxKamay
1ce6acc5f4 xutax autostrafer stuff 2022-01-02 11:18:39 +00:00
rtldg
d83b62c070 change how we check for segments in shavit-checkpoints 2022-01-02 06:45:34 +00:00
rtldg
794c379bf2 add menu parameter to Shavit_OnCheckpointMenuMade 2022-01-02 06:42:48 +00:00
rtldg
578dd01e1a add +/- timescale to checkpoints menu 2022-01-02 05:54:41 +00:00
rtldg
0c91c19ba6 trim whitespace & add licenses 2022-01-01 10:15:28 +00:00
rtldg
168968800d add missing MarkNativeAsOptional for Shavit_GetReplayFolderPath 2022-01-01 10:15:28 +00:00
BoomShotKapow
0775d10d81 Add default parameters to stock function 2022-01-01 10:15:28 +00:00
rtldg
ae0145430a remove some sourcemod 1.11 warnings 2022-01-01 10:15:18 +00:00
BoomShotKapow
3348e54316 SourceMod 1.11 dev changes & Query -> Query2 2022-01-01 10:12:53 +00:00
rtldg
005f7d97f6 use dhooks.inc from sourcemod-1.11.0-git6837 2022-01-01 07:58:10 +00:00
BoomShotKapow
d37ca33ea4 add kz_bhop_strafe_comjump2 and kz_bhop_strafe_comjump2_v2 to mapfixes 2022-01-01 07:44:05 +00:00
BoomShotKapow
b17979aad0 Minor fix to KillAllZones 2022-01-01 07:18:07 +00:00
EvanIMK
4ec8a620be add Shavit_IsClientUsingHide() 2022-01-01 07:13:31 +00:00
rtldg
73d21ea9d1 set everything in specialstring as regular style keys 2022-01-01 07:12:10 +00:00
rtldg
ee7e13579f correct internal buffer sizes used for GetStyleStrings 2022-01-01 06:49:33 +00:00
rtldg
870c62a8c9 don't tele on style-change while dead & fix !r while dead not respawning 2022-01-01 05:02:09 +00:00
rtldg
89238b5b9b add example sample tas style to shavit-styles.cfg 2021-12-31 19:17:44 +00:00
rtldg
f193679a9d get all the tas_timescale stuff working PERFECTLY 2021-12-31 19:00:58 +00:00
rtldg
8e0736e3d3 add prespeed_ez_vel 2021-12-31 18:58:30 +00:00
rtldg
bff7ace887 more time stopping stuff for times that are too low 2021-12-31 18:58:30 +00:00
rtldg
17d7255145 adjust gitattributes again 2021-12-31 18:58:30 +00:00
rtldg
a750753a62 show toplefthud when spectating idle central !replay bot 2021-12-31 18:58:30 +00:00
rtldg
c00865c9ee make debug targetname thing a !hud option instead of cvar 2021-12-31 18:58:30 +00:00
rtldg
94b3c41f41 bump replay file version since end-zone-offset is now being used correctly for playertimes.... 2021-12-30 11:29:32 +00:00
rtldg
431fd18ecb make shavit-hud update topleft on track change 2021-12-30 10:17:14 +00:00
rtldg
cd2a74240a make style/track change callbacks actually change before calling 2021-12-30 10:17:01 +00:00
rtldg
900083b321 make ihatemain & advertisements silent messages 2021-12-30 09:25:14 +00:00
rtldg
0a99f06ff4 mess around with the timer starting & restarting code 2021-12-30 09:24:12 +00:00
rtldg
01a2e616a6 make smc_display_timeleft display time until map vote in chat 2021-12-30 07:53:28 +00:00
rtldg
8827864fb8 delay wrhrank queries since they're slow and block all the other queries which is very annoying for me since it's like a 4s query so i just sit there waiting for my cookies & such to load 2021-12-29 21:33:16 +00:00
rtldg
c177dfb671 combine wr & leaderboard queries 2021-12-29 21:11:19 +00:00
rtldg
43d6a31ac0 make shavit-wr validmaps query union mapzones&playertimes 2021-12-29 19:58:10 +00:00
rtldg
426d6af3c5 add some notes deleting some handles returned from natives 2021-12-29 19:31:12 +00:00
rtldg
ede141d8c0 recalc on wr delete & remove recalc on map end 2021-12-29 19:06:23 +00:00
rtldg
4c46975584 remove unnecessary query 2021-12-29 18:13:32 +00:00
rtldg
345d6bf28e cleanup mvp test stuff that i think didn't work 2021-12-29 18:10:19 +00:00
BoomShotKapow
94d8d91a82 fix wrholderrank table creation error with versions of mysql 8.0 (#1097) 2021-12-29 11:40:13 +00:00
rtldg
cd91255c52 make timer_countdown_timescale = fTimescale * style_timescale 2021-12-29 11:39:57 +00:00
rtldg
35391f36d1 make stoptimer confirmation menu work with styles and add some more forwards 2021-12-29 09:24:18 +00:00
rtldg
62c2a26e48 make spectate command use !spec handler 2021-12-29 09:24:18 +00:00
rtldg
53aeec31f2 get more stoptimer confirmation menus working 2021-12-29 09:24:18 +00:00
rtldg
aa7887ecf4 make some of these admin menus reopen 2021-12-29 09:24:18 +00:00
rtldg
caeb35febd make GetStyleSettingBool check float instead of int 2021-12-29 09:24:18 +00:00
rtldg
4aac85d3fd add some tas_timescale stuff and stuff kid-tas 2021-12-29 09:23:57 +00:00
rtldg
1509e77728 hopefully stop timer commands menu from being wiped on plugins reload 2021-12-29 08:55:20 +00:00
Nairda
fff864ffba
update sm_save & sm_tele descriptions to match readme (#1102) 2021-12-27 11:13:10 +00:00
rtldg
0da9781973
Merge pull request #1101 from Nairdaa/patch-20
( ͡° ͜ʖ ͡°)
2021-12-27 11:10:46 +00:00
Nairda
8241de2b65
( ͡° ͜ʖ ͡°) 2021-12-27 12:09:44 +01:00
rtldg
f89816449a add !prevcp, !nextcp, and !deletecp 2021-12-27 11:06:45 +00:00
rtldg
f14ae3a604 ensure timescale-change callback is called on Shavit_LoadSnapshot 2021-12-27 11:03:12 +00:00
rtldg
c68d50a4d0 show 'Refresh menu' on every zone menu page 2021-12-27 11:03:12 +00:00
rtldg
78b276c350 change comment 2021-12-27 11:03:12 +00:00
rtldg
243ff9cbe6
Merge pull request #1099 from your0mind/master
Update README.md for command "!save"
2021-12-27 11:02:39 +00:00
Kiselev Denis
c6de66fe18
Update README.md for command "!save" 2021-12-26 19:07:40 +03:00
rtldg
f10d9442c3
Merge pull request #1096 from Nairdaa/patch-19
Update README.md
2021-12-22 08:35:46 +00:00
rtldg
3c59adce57 all valve_fs search-paths from maps folder reader 2021-12-22 08:16:34 +00:00
rtldg
223611d7a9 make cleaner !profile queries 2021-12-22 08:16:28 +00:00
Nairda
e208060156
Update README.md 2021-12-21 23:55:26 +01:00
rtldg
396f2017c5 add prespeed_type, blockprejump, nozaxisspeed, and restrictnoclip as available style settings 2021-12-21 00:38:14 +00:00
rtldg
7ca35b908b Revert "shavit_misc_staticprestrafe -> shavit_core_staticprestrafe"
This reverts commit c4783eae37.
2021-12-21 00:38:06 +00:00
rtldg
a79016397a wrap CalculateRunTime offset stuff in cvar check 2021-12-21 00:33:45 +00:00
rtldg
03c3af1a4f it's fine to have all the speedmod stuff in a post hook 2021-12-21 00:33:45 +00:00
rtldg
4b711b1fab add Shavit_GetReplayFolderPath_Stock 2021-12-21 00:33:45 +00:00
rtldg
25e6f29e7c change !resume message colors 2021-12-21 00:33:45 +00:00
rtldg
2e627fe3e2 update velocity-difference if pause-movement is enabled 2021-12-21 00:33:45 +00:00
rtldg
a146b51fb1 gimp Shavit_OnTimeIncrement and adjust tick->time stuff 2021-12-21 00:33:45 +00:00
rtldg
39c9d96924 don't do zone offset stuff on mins/maxs if the offset is bigger than the zone's x/y half-distance
xc_fox_shrine_japan_v1 will crash if i make a 16unit zone at the top (maybe elsewhere too?) so that's why this was added.
2021-12-21 00:33:45 +00:00
rtldg
6952bab715 add some unused zone things until i get around to messing with it more 2021-12-21 00:33:45 +00:00
rtldg
1802dd8007 fix the player_speedmod button disable flags not working (for things like bhop_futile) 2021-12-17 00:56:18 +00:00
rtldg
51427be3e9
Merge pull request #1094 from BoomShotKapow/master
Minor changes to replay-recorder
2021-12-16 10:21:59 +00:00
rtldg
2d98efd16c add more mapfixes for overthinker bonus 2021-12-16 10:08:13 +00:00
BoomShot
de1d1d5145
Fix isBestReplay being out of order 2021-12-16 04:08:13 -06:00
BoomShot
c14b133a42
Update documentation for Shavit_OnReplaySaved (#1) 2021-12-16 04:01:17 -06:00
rtldg
a8016dff00 update scoreboard/clantag more often 2021-12-15 12:57:51 +00:00
rtldg
6573e0cbbc add shavit_misc_resetclassname_main and such 2021-12-15 01:57:57 +00:00
rtldg
254eea7780 skip function stuff if shavit_rankings_weighting = 1 2021-12-14 11:26:27 +00:00
rtldg
c36bac0c84 move the perf measuring & bOnGround setting back since it's problematic with resetting stamina and I don't want to add another variable for if we were on the ground in the tick or something like that 2021-12-14 11:03:20 +00:00
rtldg
59ec8eb6e5 add bhop_decbble to mapfixes 2021-12-12 02:34:23 +00:00
rtldg
07de010a28 skip delay if we skip seconds on a replay bot 2021-12-11 04:11:52 +00:00
rtldg
0db2b30a77 base strafe count on input vel instead of buttons 2021-12-07 08:27:05 +00:00
rtldg
8830035af5 move strafe & perf measuring to OnPlayerRunCmdPost 2021-12-07 08:15:22 +00:00
rtldg
729f060f91 add shavit_core_save_ips if you don't want ips 2021-12-07 06:00:36 +00:00
rtldg
2316fac678 just use snapshot since that's what gA_Timers[] are made of 2021-12-07 05:53:20 +00:00
rtldg
04eea994d8 allow any number of kz buttons 2021-12-07 05:37:49 +00:00
rtldg
86b23b33a2 fix some kz button restarting things & add track param to Shavit_MarkKZMap() & Shavit_IsKZMap() 2021-12-05 01:52:04 +00:00
rtldg
f02ac94bbf let you press climb_endbuttons without being on the ground 2021-12-05 00:52:48 +00:00
rtldg
1946de926b move some more things into maps-folder-stocks.inc 2021-12-05 00:24:31 +00:00
rtldg
76988a509b seriously no 0s times please 2021-12-03 23:01:44 +00:00
rtldg
29d50b69c1 fix logic for easteregg ranks now that !ranks & !chatranks are merged 2021-12-01 22:22:25 +00:00
rtldg
2015027ed6 select track>0 because group by track>0 2021-12-01 04:34:50 +00:00
rtldg
616de1ce97 make sure some handles are deleted by littering deletes everywhere 2021-11-30 03:03:11 +00:00
rtldg
4fef03f925 remove new db connection stuff 2021-11-29 06:36:42 +00:00
rtldg
f5652c641e don't print practice mode warning when teleporting to practice mode checkpoint while already in practice mode 2021-11-29 05:02:19 +00:00
rtldg
f3ec01870b don't display stop confirmation when in practice mode 2021-11-29 04:46:47 +00:00
rtldg
2067dc7c38 change zones.cfg parsing to jump to keys instead of hoping they're in order 2021-11-29 04:34:23 +00:00
rtldg
13d6d586b3 add missing zone styles for Zone_Gravity & Zone_NoTimerGravity 2021-11-29 03:47:20 +00:00
rtldg
3a978f196d adjust gitattributes 2021-11-29 03:46:51 +00:00
rtldg
c55531168d add Zone_NoTimerGravity and Zone_Gravity 2021-11-28 21:56:05 +00:00
rtldg
e32b79c941 make the setmaptier query not error 2021-11-28 06:02:20 +00:00
rtldg
b6a81e04e3 add some missing min/max cvar values 2021-11-28 04:15:28 +00:00
rtldg
64088b6147 fix !wr <mapname> matches menu giving the wrong map 2021-11-28 03:54:52 +00:00
rtldg
20dd2a9665 might help with '0.0%-0.1%' chat ranks 2021-11-28 03:35:34 +00:00
rtldg
6d21e25679 add some scuffed code to let you !settier N bhop_different_map 2021-11-28 03:08:41 +00:00
rtldg
4d1a0b5eb3 print steamid to chat when using !profile <otherplayer> 2021-11-28 02:23:32 +00:00
rtldg
f8f336d21a finish up this crusty code that'll use mapchooser maps in !profile 2021-11-28 01:54:25 +00:00
rtldg
79cd7f1225 add more things to anti-sv_cheats command list 2021-11-27 20:24:46 +00:00
rtldg
3c5958eb93 add some hacky menu stuff so the zone returns after hitting exit on the zone-edit menu 2021-11-27 20:19:38 +00:00
rtldg
183e758971 make recent-records use the cvar properly 2021-11-27 04:45:48 +00:00
rtldg
3574080e8e remove decimal from this cvar that doesn't use it 2021-11-27 03:21:50 +00:00
rtldg
58e2cbcf51 Merge remote-tracking branch 'shavitush/master' 2021-11-26 08:16:47 +00:00
rtldg
7e5d94a281
Merge pull request #1092 from shavitush/shavitush-patch-1
removed sponsor links
2021-11-26 08:15:59 +00:00
shavit
14dc4662eb
removed sponsor links
i don't work on this anymore so yea..
2021-11-26 02:10:25 +02:00
rtldg
c89e1d4400 use shavit-mapchooser list for some shavit-stats stuff 2021-11-22 19:41:18 +00:00
rtldg
d45429127a mess around with StopChatSound stuff 2021-11-22 05:55:39 +00:00
rtldg
2ccf4c9446
Merge pull request #1090 from Nairdaa/patch-17
fix typo
2021-11-22 05:46:40 +00:00
rtldg
3d49060550
Merge pull request #1091 from Nairdaa/patch-18
translation phrase name change to make more sense
2021-11-22 05:46:31 +00:00
rtldg
910c253b8f
Merge branch 'master' into patch-18 2021-11-22 05:46:17 +00:00
Nairda
92a123de78
remove new line cus puff asked 2021-11-22 06:44:30 +01:00
rtldg
b78a6ec4ec draw start & end zone when !r or !end 2021-11-22 05:41:28 +00:00
Nairda
7bcea67f9e
Update shavit-chat.phrases.txt 2021-11-22 06:38:41 +01:00
Nairda
86747ac16c
translation phrase change to make more sense 2021-11-22 06:37:01 +01:00
Nairda
3613676b81
fix typo 2021-11-22 06:30:11 +01:00
rtldg
86a19a559c break out of loops after finding player 2021-11-22 05:26:04 +00:00
rtldg
fb62419006 stop tracking styleplaytime when dead 2021-11-22 04:34:59 +00:00
rtldg
bc978b6add send message to target player after !ccadd 2021-11-22 03:27:10 +00:00
rtldg
ad837a7d24 remove nomination on disconnect 2021-11-16 00:14:55 +00:00
rtldg
da734db699 add some stuff so we can use mapchooser's maps in mapsleft/mapsdone 2021-11-15 18:54:31 +00:00
rtldg
a2003f72c8 forgot to delete all_maps 2021-11-14 22:48:18 +00:00
rtldg
693e1ce641 OnClientPutInServer -> OnClientConnected to help prevent race condition 2021-11-14 22:04:34 +00:00
rtldg
cdb4b5746e add Shavit_GetMapsArrayList and Shavit_GetMapsStringMap 2021-11-12 23:16:51 +00:00
rtldg
30935885d4 merge !ranks and !chatranks 2021-11-12 21:21:21 +00:00
rtldg
473273627e make ccname not have an empty name 2021-11-12 20:06:10 +00:00
rtldg
9534fd5881 make !sp take priority over !addspawn 2021-11-12 19:36:07 +00:00
rtldg
ba05d685c4 Revert "remove !addspawn & !delspawn since we have !sp now"
This reverts commit 4b4773f8a5.
2021-11-12 19:24:30 +00:00
rtldg
8ce9cd97b4 fixup some gun spawning stuff 2021-11-12 19:02:31 +00:00
rtldg
4b4773f8a5 remove !addspawn & !delspawn since we have !sp now 2021-11-12 16:45:56 +00:00
rtldg
4e16365991 disable setting force_timescale automatically on timescale 2021-11-11 21:00:16 +00:00
rtldg
bc59190021 adjust lowgrav & slowmow style setting defaults 2021-11-11 20:59:17 +00:00
rtldg
07b165b3ad fix css perfs not showing if sync not enabled 2021-11-08 21:36:30 +00:00
rtldg
bd596bec75 add sm_addzone & sm_delzone aliases 2021-11-08 15:58:46 +00:00
rtldg
64414f61e0 misc sql changes 2021-11-08 15:29:34 +00:00
rtldg
7e04e840c4 mess around with the csgo hud a bit 2021-11-06 13:55:41 +00:00
rtldg
30574923e5 add untested climb_zone_ parsing 2021-11-06 13:52:04 +00:00
rtldg
3485ed02e6 make AddHUDLine use a reference for iLines 2021-11-04 23:13:55 +00:00
rtldg
3295e23553 add some wip hud forwards & csgo !keys stuff 2021-11-04 23:06:27 +00:00
rtldg
48d8e01769 add kzcheckpoints_ladders style setting 2021-11-04 16:46:16 +00:00
rtldg
361826908e lower the minimum_time when prespeed is set 2021-11-04 14:55:08 +00:00
rtldg
f344fddcdf add Loading to zone hud 2021-11-03 10:34:57 +00:00
rtldg
03d44c9d23 adjust !keys alignment 2021-11-03 09:52:27 +00:00
rtldg
aba539856e merge bhopstats to remove dependency 2021-11-03 09:34:52 +00:00
BoomShotKapow
70ca6ace3d Add a native for getting Shavit's replay folder path for personal replays 2021-11-03 08:20:52 +00:00
BoomShotKapow
b3f89493b0 Add bhop_horseshit_5 to mapfixes 2021-11-03 08:06:58 +00:00
rtldg
0e3c4e274e use updated ClosestPos stuff to not search preframes or postframes 2021-11-02 21:22:20 +00:00
rtldg
bce7c04afe add matches to !wr menu 2021-11-02 20:11:00 +00:00
rtldg
04c8cb8a85 remove shavit_checkpoints_experimental_segmented_eyeangle_fix / shavit_misc_experimental_segmented_eyeangle_fix 2021-11-02 19:32:51 +00:00
rtldg
d9a0714622 hijack angles on setstart restart 2021-11-02 19:32:07 +00:00
rtldg
9cb2298764 add !tptozone 2021-11-02 18:51:47 +00:00
rtldg
a68b21e9bd add !drawallzones/!drawszones & shavit_zones_allowdrawallzones 2021-11-02 18:21:14 +00:00
rtldg
c2ea042a6c remove unnecessary increment 2021-11-02 16:54:14 +00:00
rtldg
3c46d9c257 add something to migrate cvars from shavit-replay and shavit-misc 2021-11-02 15:55:33 +00:00
rtldg
849bc0ed76 add more stripper configs for empty classnames 2021-11-02 13:09:39 +00:00
rtldg
709887d5ff remove some unused files 2021-10-29 01:33:04 +00:00
rtldg
b9c6c47db4 swap #include <shavit> with <shavit/core> 2021-10-28 21:18:53 +00:00
rtldg
d95771f9b4 readd shavit.inc as includes includer 2021-10-28 21:09:48 +00:00
rtldg
7e55e7d8ea move shavit.inc to shavit/core.inc 2021-10-28 21:09:22 +00:00
rtldg
5e91ded7b5 rename some checkpoint cvars & ensure shavit-replay-recorder generates cfg 2021-10-28 19:52:43 +00:00
rtldg
98505fd999 lower minimum_time to 3.75 2021-10-28 14:50:51 +00:00
rtldg
5a39f5ce45 add stripper config for bhop_continuity 2021-10-28 14:44:20 +00:00
rtldg
2fc7254149 add minimum_time & minimum_time_bonus style settings 2021-10-28 13:53:44 +00:00
rtldg
862d5e8c7b enable time difference by default because I'll include the closestpos ext in release zips 2021-10-28 11:58:10 +00:00
rtldg
f61ea0f070 fix name changes not showing up in chat 2021-10-27 19:13:22 +00:00
rtldg
8b4fdf3f34 touch up TrimTrailingInvalidUnicode() a little 2021-10-27 19:02:25 +00:00
rtldg
0591499471 make sure default pistol is given on cookiescached 2021-10-26 21:40:17 +00:00
rtldg
5312c31253 add SanerGetClientName 2021-10-26 21:35:01 +00:00
rtldg
8a31bc84aa replace shavit_misc_weaponsspawngood with !hud settings. also add default-pistol thing 2021-10-26 20:41:18 +00:00
rtldg
b5d8ad6e9a make sure changing map tier recalcs points 2021-10-26 15:37:50 +00:00
rtldg
2fb61d4807 remove .i from style_setting_t
should be faster this way
2021-10-26 14:23:58 +00:00
rtldg
184f157c25 make the AFTER sql stuff only happen on mysql 2021-10-25 13:04:18 +00:00
rtldg
b54de50c1a mess with some #include's and include-guards 2021-10-25 13:01:38 +00:00
rtldg
b364871df5 add steamid-stocks.inc 2021-10-25 12:40:24 +00:00
rtldg
9571e247b5 don't delete the stylecommands stringmap 2021-10-21 10:13:51 +00:00
rtldg
e52759791d prevent reload from refreshing zones twice 2021-10-21 09:52:50 +00:00
rtldg
b8170c6799 make sure to set points_calced_from too 2021-10-21 09:35:58 +00:00
rtldg
f224a2782d make shavit-replay-playback not require shavit-replay-recorder 2021-10-19 08:57:29 +00:00
rtldg
d901c6bf91 make maps-folder-stocks.inc 2021-10-19 08:57:19 +00:00
rtldg
a449fe6f69 add comments to stripper configs 2021-10-18 16:40:54 +00:00
rtldg
673b172871 mess around with point calculation queries again 2021-10-18 07:23:01 +00:00
rtldg
1bb7b3e274 remove Shavit_OpenStatsMenu 2021-10-18 07:23:01 +00:00
rtldg
966ceea5f8 finish splitting shavit.inc 2021-10-18 07:22:50 +00:00
rtldg
b09be9f5de make Shavit_HijackAngles calculate the number of ticks 2021-10-17 05:18:02 +00:00
rtldg
7493c7d548 remove unused #pragma dynamic 2021-10-17 05:09:20 +00:00
rtldg
49ea502662 rename guns.sp to weapon-stocks.inc 2021-10-17 05:08:30 +00:00
rtldg
df2e45f478 Merge branch 'master' into reorg 2021-10-17 04:48:48 +00:00
rtldg
cb8c7e8d56 add shavit_rankings_new_db_connection, shavit_stats_new_db_connection, and shavit_wr_new_db_connection 2021-10-17 04:46:01 +00:00
rtldg
4b51bd7116 remove shavit_core_timernozone 2021-10-16 15:44:55 +00:00
rtldg
b88367d079 allow setstart outside of start-zone and add shavit_zones_extra_spawn_height 2021-10-16 15:24:36 +00:00
rtldg
f724863bc7 move some weapon stocks to another file 2021-10-16 13:54:50 +00:00
rtldg
5d26e76ec2 remove shavit_misc_bhopsounds 0 2021-10-16 13:32:30 +00:00
rtldg
73b17941ce change !hide's settransmit hook to also hide dead players like btimes
so players can't use a speclist cheat in csgo
2021-10-16 13:26:53 +00:00
rtldg
d59399b59c add bhop_desert_smoke stripper cfg to remove shit prebuilt zones 2021-10-16 13:07:06 +00:00
rtldg
09693df6eb add bhop_blueblocks stripper cfg to remove server-crashing ent 2021-10-16 13:06:44 +00:00
rtldg
4e1f2db8ca clarify SayText2 buffer size comment 2021-10-16 04:45:19 +00:00
rtldg
499ba4c4ab Merge branch 'master' into reorg 2021-10-13 03:28:23 +00:00
rtldg
df2e9c402d fix own playtime display & rank in menu 2021-10-13 03:26:13 +00:00
rtldg
3a73b63544 Merge branch 'master' into reorg 2021-10-11 16:06:32 +00:00
rtldg
4d8faa1099 fix isBestReplay and isTooLong being swapped in Shavit_OnReplaySaved 2021-10-11 16:04:52 +00:00
rtldg
3ef2cf3f0e Merge branch 'master' into reorg 2021-10-11 14:55:59 +00:00
rtldg
474627e437 csgo doesn't need the quadruple percent-sign 2021-10-11 14:55:23 +00:00
rtldg
55b6253b30 use OnPlayerRunCmdPost for recording replay frames 2021-10-11 11:41:36 +00:00
rtldg
6325212dfb Merge branch 'master' into reorg 2021-10-11 06:02:44 +00:00
rtldg
0f66a081a3 remove css flashlight on !spec 2021-10-11 06:01:40 +00:00
rtldg
9dbd08eec9 Merge branch 'master' into reorg 2021-10-11 03:19:15 +00:00
rtldg
07a50717c4 remove debugging print 2021-10-11 03:18:57 +00:00
rtldg
e5a3af1aa7 Merge branch 'master' into reorg 2021-10-11 03:04:47 +00:00
rtldg
a0a2cce04a add wip alternatecenterkeys for css linux gamers 2021-10-11 03:04:37 +00:00
rtldg
af48f2d695 add note about adding more migrations to alter table to fix column order (for faster queries) 2021-10-10 07:51:41 +00:00
rtldg
41882d3465 reorganize playertimes columns (in create table). speed up point recalculation by inlining things where possible and caching wr last calculated against. 2021-10-10 07:50:45 +00:00
rtldg
60c614df9d add points_calced_from 2021-10-10 06:12:51 +00:00
rtldg
c81f958efb fix it changing human names on connect 2021-10-10 06:02:55 +00:00
rtldg
7ca863f04b move sql table creation and migrations 2021-10-10 05:14:37 +00:00
rtldg
f0908643f6 finish moving checkpoint stuff 2021-10-09 09:17:58 +00:00
rtldg
96496f14ba move most checkpoint stuff out of misc and into shavit-checkpoints 2021-10-09 05:40:33 +00:00
rtldg
0b31c6a608 remove Shavit_OpenCheckpointMenu 2021-10-08 15:07:08 +00:00
rtldg
d02cc0bd22 move some more stuff around 2021-10-08 15:03:09 +00:00
rtldg
8449c8b9d9 move physicsuntouch stuff to a different file 2021-10-08 14:46:36 +00:00
rtldg
ab0fc28c26 make replay reading/writing functions stocks 2021-10-08 10:59:56 +00:00
rtldg
77265805ac move anti-sv_cheats to own file 2021-10-08 10:30:52 +00:00
rtldg
611d0131c8 prevent plugin reloads recording half-replays 2021-10-08 10:20:52 +00:00
rtldg
1f090f9d27 move style_setting_t & license notice 2021-10-08 10:13:16 +00:00
rtldg
1140769b62 fix the replay recording after splitting up the files 2021-10-08 10:08:04 +00:00
rtldg
2e579b82ef move styles loaded forward 2021-10-08 09:54:11 +00:00
rtldg
58da675a7c prevent bots from querying playtime 2021-10-08 09:32:25 +00:00
rtldg
a0bf3b65e9 move style settings into own file 2021-10-08 09:04:45 +00:00
rtldg
93826ddfd8 cache float & int values for faster GetStyleSettings 2021-10-08 08:34:26 +00:00
rtldg
24337ba172 use .inc for shavit-replay-stocks 2021-10-07 20:09:30 +00:00
rtldg
4ad6706b47 fix some shavit-replay errors 2021-10-07 20:05:55 +00:00
rtldg
c33ea7c0d0 move UpdateStepSound stuff to shavit-replay 2021-10-07 19:48:51 +00:00
rtldg
c4783eae37 shavit_misc_staticprestrafe -> shavit_core_staticprestrafe 2021-10-07 19:30:33 +00:00
rtldg
cb3aad5ab4 initial commit for reorganization effort 2021-10-07 19:01:00 +00:00
rtldg
c5d4679c9a add missing sync display in css 2021-10-07 16:48:46 +00:00
rtldg
06521023a0
Merge pull request #1086 from Nairdaa/patch-12
fix typo
2021-10-07 16:01:09 +00:00
rtldg
89de43b916 update dead fly repo link 2021-10-07 16:00:24 +00:00
Nairda
b8b6da0780
fix typo 2021-10-07 18:00:08 +02:00
rtldg
4e577fbe9b change !ccadd and !ccdelete flag from CHAT to RCON 2021-10-07 15:45:42 +00:00
rtldg
3def8154be mess with some dotfiles and merge FEATURES.md into README.md 2021-10-07 15:41:36 +00:00
rtldg
3552f29853 Replace Shavit_GetStyleSetting() in some places 2021-10-07 13:43:09 +00:00
rtldg
d86ac3f434 remove unnecessary TimerStatus casting 2021-10-07 12:25:08 +00:00
rtldg
0ec8bdb92b move charset stuff to GetTimerDatabaseHandle 2021-10-07 09:51:48 +00:00
rtldg
bfbeff6a86
Merge pull request #1084 from Sirhephaestus/patch-3
Spelling error
2021-10-07 05:11:49 +00:00
rtldg
ea419d0481
Merge pull request #1085 from e54385991/patch-1
fix 1.10 compile
2021-10-07 05:11:34 +00:00
rtldg
cf51054460 make rtv change map on novote 2021-10-07 05:09:23 +00:00
e54385991
612c81f01a
fix 1.10 compile 2021-10-07 12:47:50 +08:00
rtldg
4f98303b4c fix !map menu using wrong param for client 2021-10-07 03:54:31 +00:00
rtldg
ae82d9a5ad add shavit_rankings_weighting_limit 2021-10-06 07:14:31 +00:00
rtldg
0164d15910 fix shavit-mapchooser error with novote & rtv 2021-10-06 04:52:12 +00:00
Sirhephaestus
3e6d79942a
Spelling error 2021-10-05 22:39:58 -04:00
rtldg
6c66c70094 test multiple sql connections in shavit-rankings 2021-10-05 16:28:51 +00:00
rtldg
7383cba61f remove duplicate map tier retreival 2021-10-05 16:17:01 +00:00
rtldg
838d33510b make shavit_rankings_weighting 1.0 not use a sql-function 2021-10-05 14:34:01 +00:00
rtldg
235cc9f241 work on improving rankings queries 2021-10-05 11:00:13 +00:00
rtldg
a3e3e0682b add smc_mapvote_printtoconsole 2021-10-05 05:48:08 +00:00
rtldg
9b00e1f16a replace playertimer_t with timer_snapshot_t 2021-10-05 05:31:53 +00:00
rtldg
22a87ce3ee add Shavit_GuessPointsForTime so we can recalc styles only on WR 2021-10-05 04:43:10 +00:00
rtldg
3388c7b5d3 !map without args will show the menu using the smc map list. !map mapname will still use the entire maps folder 2021-10-05 03:00:03 +00:00
rtldg
4f8fd211f3 test speeding up recalc queries 2021-10-04 14:12:47 +00:00
rtldg
523ce285a1 3.0.9a 2021-10-04 14:12:05 +00:00
84 changed files with 26035 additions and 12162 deletions

11
.gitattributes vendored
View File

@ -1,9 +1,10 @@
* text=auto
*.sp diff=sourcepawn
*.txt diff=astextplain
*.cfg diff=astextplain
*.inc diff=sourcepawn linguist-language=SourcePawn
*.sp diff=sourcepawn linguist-language=SourcePawn
*.txt diff
*.cfg diff
*.smx binary
*.mp3 binary
*.vmt binary
*.vtf binary
*.vmt diff
*.vtf binary

3
.github/FUNDING.yml vendored
View File

@ -1,2 +1 @@
github: [shavitush]
custom: https://paypal.me/shavitush

84
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,84 @@
name: Compile
on: [push, pull_request, workflow_dispatch]
jobs:
compile:
runs-on: ubuntu-latest
strategy:
matrix:
sm-version: [ '1.12' ]
name: "Build SM ${{ matrix.sm-version }}"
steps:
- name: Prepare env
shell: bash
run: echo "GITHUB_SHA_SHORT=${GITHUB_SHA::7}" >> $GITHUB_ENV
- uses: actions/checkout@v4
- name: Setup SP
uses: rumblefrog/setup-sp@master
with:
version: ${{ matrix.sm-version }}
- name: Download and extract dependencies
shell: bash
run: |
# Mac zip just because it's smaller & we don't repack the extensions...
wget https://github.com/ErikMinekus/sm-ripext/releases/download/1.3.1/sm-ripext-1.3.1-mac.zip
unzip sm-ripext-1.3.1-mac.zip "addons/sourcemod/scripting/include/*"
wget https://github.com/clugg/sm-json/archive/refs/tags/v5.0.1.tar.gz
tar --strip-components=1 -xvzf v5.0.1.tar.gz sm-json-5.0.1/addons/sourcemod/scripting/include
wget https://github.com/hermansimensen/eventqueue-fix/archive/refs/heads/main.tar.gz
tar --strip-components=1 -xvzf main.tar.gz -C addons/sourcemod
rm -rf *.zip *.tar.gz addons/sourcemod/.git* addons/sourcemod/LICENSE
wget https://github.com/srcwr/eventqueuefixfix/releases/download/v1.0.1/eventqueuefixfix-v1.0.1-def5b0e-windows-x32.zip
unzip eventqueuefixfix-v1.0.1-def5b0e-windows-x32.zip "addons/sourcemod/extensions/*"
rm "addons/sourcemod/extensions/eventqueuefixfix.pdb"
wget https://github.com/srcwr/srcwrfloppy/releases/download/v2.0.4/srcwrfloppy-v2.0.4.zip
unzip -qO UTF-8 srcwrfloppy-v2.0.4.zip "addons/sourcemod/extensions/*"
rm "addons/sourcemod/extensions/srcwr💾.pdb"
- name: Run compiler
shell: bash
run: |
cd addons/sourcemod
mkdir plugins
for src in $(find scripting -maxdepth 1 -type f -name "*.sp");
do
spcomp $src -o=plugins/$(basename $src .sp)'.smx' -i=scripting/include -v2
done
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: bhoptimer-${{ github.head_ref || github.ref_name }}-sm${{ matrix.sm-version }}-${{ env.GITHUB_SHA_SHORT }}
path: |
addons
materials
sound
CHANGELOG.md
LICENSE
README.md
retention-days: 14
release:
name: Release
if: github.ref_type == 'tag'
needs: compile
runs-on: ubuntu-latest
steps:
- name: Download artifacts
uses: actions/download-artifact@v4
- name: Archive artifacts
shell: bash
run: find * -maxdepth 0 -type d -exec zip -rq {}.zip {} \;
- uses: ncipollo/release-action@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
draft: true
name: ${{ github.ref_name }}
artifacts: "*.zip"

View File

@ -1,29 +0,0 @@
sudo: false
addons:
apt_packages:
- lib32stdc++6 # needed for spcomp
env:
- SMVERSION=1.10
before_script:
# install smbuilder
- git clone https://github.com/splewis/sm-builder
- cd sm-builder
- pip install --user -r requirements.txt
- python setup.py install --prefix=~/.local
- cd ..
# install the sourcemod compiler
- SMPACKAGE="http://sourcemod.net/latest.php?os=linux&version=${SMVERSION}"
- wget $SMPACKAGE
- tar xfz $(basename $SMPACKAGE)
- cd addons/sourcemod/scripting/
- chmod +x spcomp
- PATH+=":$PWD"
- cd ../../..
script:
- smbuilder --flags="-E"

1895
CHANGELOG.md Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,64 +0,0 @@
# shavit's simple bhop timer
*a bhop server should be simple*
### Features
---
#### shavit-core (REQUIRED)
`bhoptimer`'s core.
It handles connections to the database and exposes an API (natives/forwards) for developers and other modules.
Calculations, gameplay mechanics and such are all handled by the core plugin.
Includes *but not limited to*: Custom chat messages and colors, snapshots, pausing/resuming, styles (configurable), automatic bunnyhopping, strafe/sync meters that work for most playstyles, double-step fixer (+ds), practice mode, +strafe blocking, +left/right blocking, pre-jump blocking, HSW style (including SHSW) that cannot be abused with joypads, per-style `sv_airaccelerate` values, teleportation commands (start/end).
#### shavit-zones (REQUIRED)
The zones plugins handles everything related to map zones (such as start/end zone etc) and is necessary for `bhoptimer` to operate.
Zones are trigger based and are very lightweight.
The zones plugin includes some less common features such as: Multiple tracks (main/bonus), zone editing (after setup), snapping zones to walls/corners/grid, zone setup using the cursor's position, configurable sprite/colors for zone types, zone tracks (main/bonus - can be extended), manual adjustments of coordinates before confirmations, teleport zones, glitch zones, no-limit zones (for styles like 400-velocity), flat/3D boxes for zone rendering, an API and more.
It also contains support for built-in map timers (KZ) and the [Fly](https://github.com/3331/fly) zoning standard.
#### shavit-chat
The chat plugin manipulates chat messages sent by players.
It includes custom chat names, tags, colors and all can be defined by the players/admins.
Admins need the chat flag, or the "shavit_chat" override (good for a donator perk).
There's a user-friendly command named !cchelp so the users can easily understand what's going on.
In addition, it integrates with rankings and allows you to have titles for players according to their ranking, relative ranking or points in the server using !chatranks.
#### shavit-hud
The HUD plugin is `bhoptimer`'s OSD frontend.
It shows most (if not all) of the information that the player needs to see.
`shavit-hud` integrates with [Bunnyhop Statistics](https://github.com/shavitush/bhopstats) for CS:S.
Some features are: Per-player settings (!hud), truevel and gradient-like display (CS:GO).
#### shavit-misc
This plugin handles miscellaneous things used in bunnyhop servers.
Such as: Segmented runs, team handling (respawning/spectating too), spectators list (!specs), smart player hiding that works for spectating too, teleportation to other players, weapon commands (!knife/!usp/!glock) and ammo management, segmented checkpoints, noclipping (can be set to work for VIPs/admins only), drop-all, godmode, prespeed blocking, prespeed limitation, chat tidying, radar hiding, weapon drop cleaning, player collision removal, auto-respawning, spawn points generator, radio removal, scoreboard manipulation, model opacity changes, fixed runspeed, automatic and configurable chat advertisements, player ragdoll removal and WR messages.
#### shavit-rankings
Enables !rank, !top and introduces map tiers (!settier).
Each record gets points assigned to it according to the map's tier and overall - how good the time is.
This system doesn't allow "rank grinding" by beating all of the easy maps on the server but instead, awards the players that get the best times on the hardest maps and styles.
#### shavit-replay
Creates a replay bot that records the players' world records and playback them on command (!replay/automatic).
The replay bot playback can be stopped (if central) and the saved replay can be deleted by server administrators.
Replay bots will change their clan tags/names according to the server's configuration.
#### shavit-sounds
Will play custom sounds when event actions happen.
Such as: Getting a world record, improving your own record, getting the worst record in the server, beating a map for the first time or setting a rank #X record.
#### shavit-stats
The statistics plugin is a statistics frontend for the players.
It displays rankings, maps done, maps left, server records, SteamID, country, map completion, last login date and more useful information!
#### shavit-timelimit
Sets a dynamic map time limit according to the average completion time of the map.
#### shavit-wr (REQUIRED)
Saves the players' records to the database and allows players to see the server's records.
The ability to see records for other maps also exists and can be lazily looked up (!wr map_name, or a part of the map's name).

265
README.md
View File

@ -2,43 +2,269 @@
### RECOMPILE ALL YOUR PLUGINS THAT USE `#include <shavit>` OR STUFF WILL BREAK
### Build status
[![Build status](https://travis-ci.org/shavitush/bhoptimer.svg?branch=master)](https://travis-ci.org/shavitush/bhoptimer)
### CS:GO is dead. Support won't be removed and gamedata should:tm: still work but it isn't actively tested.
[AlliedModders thread](https://forums.alliedmods.net/showthread.php?t=265456)
[AlliedModders thread](https://forums.alliedmods.net/showthread.php?t=265456) // !!! OUTDATED !!!
[Download](https://github.com/shavitush/bhoptimer/releases)
# shavit's bhop timer
This is (nearly) an all-in-one server plugin for Counter-Strike: Source, Counter-Strike: Global Offensive, and Team Fortress 2 that adds a timer system and many other utilities, so you can install it and run a proper bunnyhop server.
This is nearly an all-in-one server plugin suite for Counter-Strike: Source, Counter-Strike: Global Offensive, and Team Fortress 2 that adds a timer system and many other utilities, so you can install it and run a proper bunnyhop server.
Includes a records system, map zones (start/end marks etc), bonuses, HUD with useful information, chat processor, miscellaneous such as weapon commands/spawn point generator, bots that replay the best records of the map, sounds, statistics, segmented running, a fair & competitive rankings system and more!
Includes a records system, map zones (start/end marks etc), bonuses, HUD with useful information, chat processor, miscellaneous things such as weapon commands/spawn point generator, bots that replay the best records of the map, sounds, statistics, segmented running, a fair & competitive rankings system, and more!
[Mapzones Setup Demonstration](https://youtu.be/OXFMGm40F6c)
# Requirements:
* Steam version of Counter-Strike: Source, Counter-Strike: Global Offensive, or Team Fortress 2.
* [Metamod:Source](https://www.sourcemm.net/downloads.php?branch=stable) and [SourceMod 1.10 or above](https://www.sourcemod.net/downloads.php?branch=stable) installed.
* A MySQL database (preferably locally hosted) if your database is likely to grow big, or if you want to use the rankings plugin. MySQL server version of 5.5.5 or above (MariaDB equivalent works too) is highly recommended.
* [DHooks](https://github.com/peace-maker/DHooks2/releases)
* [Metamod:Source](https://www.sourcemm.net/downloads.php?branch=stable) and [SourceMod](https://www.sourcemod.net/downloads.php?branch=stable) 1.12 or higher.
* A MySQL database (preferably locally hosted) if your database is likely to grow big, or if you want to use the rankings plugin. MySQL server version of 5.5.5 or above (MariaDB equivalent works too) is required.
# Optional requirements, for the best experience:
* [eventqueuefix](https://github.com/hermansimensen/eventqueue-fix)
* Some booster fixing and scaling booster delays by timescale. (Use this instead of `boosterfix`)
* [Bunnyhop Statistics](https://forums.alliedmods.net/showthread.php?t=286135)
* Used for scroll styles and also required for TF2.
* Allows for timescaling boosters and is used to fix some exploits. (Use this instead of `boosterfix`)
* (included in bhoptimer release zips)
* Along with using [eventqueuefixfix](https://github.com/srcwr/eventqueuefixfix) at the same time to fix eventqueuefix on Windows after the 2025-02-18 update.
* [srcwr💾](https://github.com/srcwr/srcwrfloppy)
* Saves replays asynchronously (read: doesn't lag the server when saving a replay).
* (included in bhoptimer release zips)
* [SteamWorks](https://forums.alliedmods.net/showthread.php?t=229556)
* Used to grab `{serverip}` in advertisements.
* [DynamicChannels](https://github.com/Vauff/DynamicChannels)
# Installation:
Refer to the [wiki page](https://github.com/shavitush/bhoptimer/wiki/1.-Installation-(from-source)).
# Installation
# Required plugins:
- `shavit-core`
- `shavit-zones`
- `shavit-wr`
* [Build from source](https://github.com/shavitush/bhoptimer/wiki/1.-Installation-(from-source))
* [Download an existing release](https://github.com/shavitush/bhoptimer/releases) - installing is simply drag & drop into the game server's directory.
# Configuration
The [wiki](https://github.com/shavitush/bhoptimer/wiki) contains most relevant information regarding configuration, under the 2nd category's pages.
Configuration files are in `cfg/sourcemod/plugin.shavit-*.cfg` and `addons/sourcemod/configs/shavit-*`.
# bhoptimer modules:
### shavit-core (REQUIRED)
`bhoptimer`'s core.
It handles connections to the database and exposes an API (natives/forwards) for developers and other modules.
Calculations, gameplay mechanics and such are all handled by the core plugin.
Includes *but not limited to*: Custom chat messages and colors, snapshots, pausing/resuming, styles (configurable), automatic bunnyhopping, strafe/sync meters that work for most playstyles, double-step fixer (+ds), practice mode, +strafe blocking, +left/right blocking, pre-jump blocking, HSW style (including SHSW) that cannot be abused with joypads, per-style `sv_airaccelerate` values, teleportation commands (start/end).
```
Player commands:
!style, !styles, !diff, !difficulty - Choose your bhop style.
!s, !start, !r, !restart - Start your timer.
!b, !bonus, !b1, !b2, etc - Start your timer on the bonus track.
!m, !main - Start your timer on the main track.
!end - Teleport to endzone.
!bend, !bonusend - Teleport to endzone of the bonus track.
!stop - Stop your timer.
!pause, !unpause, !resume - Toggle pause.
!auto, !autobhop - Toggle autobhop.
Admin commands:
!deletemap (RCON flag) - Deletes all map data.
!wipeplayer (BAN flag) - Wipes all bhoptimer data for specified player.
!migration (ROOT flag) - Force a database migration to run.
```
### shavit-wr (REQUIRED)
Saves the players' records to the database and allows players to see the server's records.
The ability to see records for other maps also exists and can be lazily looked up (!wr map_name, or a part of the map's name).
```
Player commands:
!wr, !worldrecord - View the leaderboard of a map. Usage: !wr [map]
!bwr, !bworldrecord, !bonusworldrecord - View the *bonus* leaderboard of a map. Usage: !bwr [map]
!recent, !recentrecords, !rr - View the recent #1 times set.
!pb, !time, !times - View a player's times on a specific map.
Admin commands: (RCON flag)
!delete, !deleterecord, !deleterecords - Opens a record deletion menu interface.
!deletall - Deletes all the records for this map.
```
### shavit-zones (REQUIRED)
The zones plugins handles everything related to map zones (such as start/end zone etc) and is necessary for `bhoptimer` to operate.
Zones are trigger based and are very lightweight.
The zones plugin includes some less common features such as: Multiple tracks (main/bonus), zone editing (after setup), snapping zones to walls/corners/grid, zone setup using the cursor's position, configurable sprite/colors for zone types, zone tracks (main/bonus - can be extended), manual adjustments of coordinates before confirmations, teleport zones, glitch zones, no-limit zones (for styles like 400-velocity), flat/3D boxes for zone rendering, an API and more.
It also contains support for built-in map timers (KZ) and the [Fly](https://github.com/PMArkive/fly) zoning standard.
```
Player commands:
!set, !setstart, !ss, !sp, !startpoint - Set your current position as the teleport location on restart.
!deletestart, !deletesetstart, !delss, !delsp - Delete your spawn point.
!drawallzones, !drawzones - Draws all zones (if the server has the cvar for this enabled).
Admin commands: (RCON flag)
!zones, !mapzones, !addzone - Opens the mapzones menu.
!deletezone, !delzone - Delete a mapzone.
!deleteallzones - Delete all mapzones.
!modifier - Changes the axis modifier for the zone editor. Usage: !modifier <number>
!addspawn - Adds a custom spawn location.
!delspawn - Deletes a custom spawn location.
!zoneedit, !editzone, !modifyzone - Modify an existing zone.
!setstart, !spawnpoint, !ss, !sp - Set your restart position & angles in a start zone.
!tptozone - Teleport to a zone.
Admin commands: (ROOT flag)
!reloadzonesettings - Reloads the zone settings.
```
### shavit-chat
The chat plugin manipulates chat messages sent by players.
It includes custom chat names, tags, colors and all can be defined by the players/admins.
Admins need the chat flag, or the "shavit_chat" override (good for a donator perk).
There's a user-friendly command named !cchelp so the users can easily understand what's going on.
In addition, it integrates with rankings and allows you to have titles for players according to their ranking, relative ranking or points in the server using !chatranks.
```
Player commands:
!cchelp - Provides help with setting a custom chat name/message color.
!ccname - Toggles/sets a custom chat name. Usage: !ccname <text> or !ccname "off" to disable.
!ccmsg, !ccmessage - Toggles/sets a custom chat message color. Usage: !ccmsg <color> or !ccmsg "off" to disable.
!chatrank, !chatranks - View a menu with the chat ranks available to you.
Admin commands: (CHAT flag)
!ccadd - Give a user ccname & ccmsg access by steamid. Usage: !ccadd <steamid>
Admin commands: (ROOT flag)
!ccdelete - Remove a user's ccname & ccmsg access that was granted by !ccadd. Usage: !ccdelete <steamid>
!cclist - Print the custom chat setting of all online players.
!reloadchatranks - Reloads the chatranks config file.
```
### shavit-hud
The HUD plugin is `bhoptimer`'s OSD frontend.
It shows most (if not all) of the information that the player needs to see.
Some features are: Per-player settings (!hud), truevel, and gradient-like display (CS:GO).
```
Player commands:
!hud, !options - Opens the HUD settings menu.
!keys, !showkeys, !showmykeys - Draw plugin keys on screen.
!master, !masterhud - Toggles the HUD.
!center, !centerhud - Toggles the center text HUD.
!zonehud - Toggles the zone HUD.
!hidewep, !hideweap, !hideweapon - Toggles weapon hiding.
!2dvel, !truevel, !truvel - Toggles 2D ('true') velocity.
```
### shavit-mapchooser
Replaces `mapchooser` to provide `bhoptimer` integration into nomination and map vote menus.
```
Admin commands: (CHANGEMAP flag)
!forcemapvote - Forces the map vote to happen.
!reloadmaplist - Reloads the maplist.
!reloadmap, !restartmap - Reloads the current map.
!loadunzonedmap - Loads a random map from the maps folder that is unzoned.
```
### shavit-checkpoints
This plugin handles checkpoint related things such as segmented runs & savestates/persistent-data.
```
Player commands:
!cp, !cpmenu, !checkpoint, !checkpoints - Opens the checkpoints menu.
!save - Saves a checkpoint.
!tele - Teleports to a checkpoint (default: 1). Usage: !tele [number]
!prevcp - Selects the previous checkpoint.
!nextcp - Selects the next checkpoint.
!deletecp - Deletes the current checkpoint.
```
### shavit-misc
This plugin handles miscellaneous things used in bunnyhop servers.
Such as: team handling (respawning/spectating too), spectators list (!specs), smart player hiding that works for spectating too, teleportation to other players, weapon commands (!knife/!usp/!glock) and ammo management, noclipping (can be set to work for VIPs/admins only), drop-all, godmode, prespeed blocking, prespeed limitation, chat tidying, radar hiding, weapon drop cleaning, player collision removal, auto-respawning, spawn points generator, radio removal, scoreboard manipulation, model opacity changes, fixed runspeed, automatic and configurable chat advertisements, player ragdoll removal, and WR messages.
```
Player commands:
!specs, !spectators - Show a list of spectators.
!spec, !spectate - Moves you to the spectators' team. Usage: !spec [target]
!hide, !unhide - Toggle players' hiding.
!tpto, !goto - Teleport to another player. Usage: !tpto [target]
!usp, !glock, !knife - Spawn a USP/Glock/Knife.
!nc, !prac, !practice, !noclipme, +noclip, sm_noclip - Toggles noclip.
!adverts - Prints all adverts to the client.
```
### shavit-rankings
Enables !rank, !top and introduces map tiers (!settier).
Each record gets points assigned to it according to the map's tier and overall - how good the time is.
This system doesn't allow "rank grinding" by beating all of the easy maps on the server but instead, awards the players that get the best times on the hardest maps and styles.
```
Player commands:
!tier, !maptier - Prints the map's tier to chat.
!rank - Show your or someone else's rank. Usage: !rank [name]
!top - Show the top 100 players.
Admin commands: (RCON flag)
!settier, !setmaptier - Change the map's tier. Usage: !settier <tier>
!recalcmap - Recalculate the current map's records' points.
Admin commands: (ROOT flag)
!recalcall - Recalculate the points for every map on the server. Run this after you change the ranking multiplier for a style or after you install the plugin.
```
### shavit-replay-playback
Creates a replay bot that records the players' world records and playback them on command (!replay/automatic).
The replay bot playback can be stopped (if central) and the saved replay can be deleted by server administrators.
Replay bots will change their clan tags/names according to the server's configuration.
```
Player commands:
!replay - Opens the replay bot menu.
Admin commands: (RCON flag)
!deletereplay - Open replay deletion menu.
```
### shavit-replay-recorder
This is now the actual plugin that records the replays. ||I wanted to split shavit-replay so I could deal with reloading plugins without losing replay data better.||
### shavit-sounds
Will play custom sounds when event actions happen.
Such as: Getting a world record, improving your own record, getting the worst record in the server, beating a map for the first time or setting a rank #X record.
### shavit-stats
The statistics plugin is a statistics frontend for the players.
It displays rankings, maps done, maps left, server records, SteamID, country, map completion, last login date, and more useful information!
```
Player commands:
!p, !profile, !stats - Show the player's profile. Usage: !profile [target]
!mapsdone - Shows the maps the player has finished.
!mapsleft - Shows maps that the player has not finished yet.
!playtime - Shows the top playtime list.
```
### shavit-timelimit
Sets a dynamic map time limit according to the average completion time of the map.
```
Admin commands: (CHANGEMAP flag)
!extend, !extendmap - Extend the map.
```
### shavit-tas
Provides autostrafers and other TAS related functionality.
```
Player commands:
+autostrafer/-autostrafer, !autostrafer - Toggle the autostrafer.
+autoprestrafe/-autoprestrafe, !autoprestrafe - Toggle automatically prestrafing.
+autojumponstart/-autojumponstart, !autojumponstart - Toggle jumping automatically on start.
+edgejump/-edgejump, !edgejump - Toggle edge jumping.
```
# Recommended plugins:
* [MomSurfFix](https://forums.alliedmods.net/showthread.php?p=2680743) ([github](https://github.com/GAMMACASE/MomSurfFix))
@ -51,6 +277,8 @@ Refer to the [wiki page](https://github.com/shavitush/bhoptimer/wiki/1.-Installa
- Allows players to toggle trigger visibility.
* [ShowPlayerClips](https://forums.alliedmods.net/showthread.php?p=2661942) ([github](https://github.com/GAMMACASE/ShowPlayerClips))
- Allows players to toggle player clip visibility.
* [JumpStats](https://github.com/Nimmy2222/bhop-get-stats)
- Covers SSJ, Jhud, StrafeTrainer, Strafe Offsets and FJT. Colors, HUD positioning editor, cookies, etc
* [shavit-ssj](https://github.com/Nairdaa/shavit-ssj)
- Speed of Sixth Jump + more, customisable settings with cookies remembering user prefered settings.
* [shavit-jhud](https://github.com/blankbhop/jhud)
@ -62,7 +290,8 @@ Refer to the [wiki page](https://github.com/shavitush/bhoptimer/wiki/1.-Installa
* [mpbhops_but_better](https://github.com/rtldg/mpbhops_but_working)
- A cleaner and faster mpbhops/mpbh plugin that also makes door vertical-boosters consistent and frozen.
* TODO: `paint`, `ljstats`, `bash2`
### CS:GO
* [NoViewPunch](https://github.com/hermansimensen/NoViewPunch)
- Removes the viewpunch from landing in CS:GO.
* [CS:GO Movement unlocker](https://forums.alliedmods.net/showthread.php?t=255298)
- Enables prespeeding (no 240 velocity cap for runspeed anymore)

View File

@ -1,59 +1,65 @@
"Map fixes"
{
"bhop_amaranthglow"
"bhop_strafecontrol"
{
"shavit_zones_prebuilt_visual_offset" "16"
}
"bhop_crash_egypt"
{
"shavit_misc_resettargetname_main" "player"
}
"bhop_downtown"
{
"shavit_misc_resettargetname_main" "fil_fw"
}
"bhop_drop"
{
"shavit_misc_resettargetname_main" "activator_boost"
}
"bhop_kirous"
{
"shavit_misc_resettargetname_main" "state0"
}
"bhop_microwave"
{
"shavit_misc_resettargetname" "0"
}
"bhop_overthinker"
{
"shavit_misc_resettargetname_main" "noobinside"
"shavit_misc_resettargetname_bonus" "filter_bonus"
}
"bhop_overthinker_go"
{
"shavit_misc_resettargetname_main" "noobinside"
"shavit_misc_resettargetname_bonus" "filter_bonus"
}
"bhop_shutdown"
{
"shavit_misc_resettargetname_main" "asdf"
}
"bhop_space"
{
"shavit_misc_resettargetname" "0"
}
"bhop_symbiotic"
{
"shavit_misc_resettargetname_main" "filter_main"
"shavit_misc_resettargetname_bonus" "filter_bonus"
"shavit_zones_extra_spawn_height" "1.0"
}
"bhop_tranquility"
{
"shavit_zones_prebuilt_visual_offset" "16"
}
"kz_bhop_izanami"
"bhop_amaranthglow"
{
"shavit_misc_resettargetname" "0"
"shavit_zones_prebuilt_visual_offset" "16"
}
"bhop_apathy"
{
"shavit_zones_resettargetname_main" "apathy"
}
"bhop_crash_egypt"
{
"shavit_zones_resettargetname_main" "player"
}
"bhop_japan"
{
"shavit_zones_resetclassname_main" "beginner"
}
"bhop_space"
{
"shavit_zones_resetclassname_main" "sadface"
}
"bhop_shutdown"
{
"shavit_zones_resettargetname_main" "asdf"
}
"bhop_interloper"
{
"shavit_zones_resettargetname_main" "lol"
}
"bhop_wasd"
{
"shavit_zones_resettargetname_main" "default"
}
"bhop_solitude"
{
"shavit_zones_forcetargetnamereset" "1"
}
"bhop_drop"
{
"shavit_zones_forcetargetnamereset" "1"
"shavit_zones_resettargetname_main" "activator_boost"
"shavit_zones_resettargetname_bonus" "activator_boost3"
}
"kz_bhop_kairo"
{
"shavit_zones_forcetargetnamereset" "1"
"shavit_zones_resettargetname_main" "tped"
"shavit_zones_resetclassname_main" "cp0filter"
}
"bhop_avantasia"
{
"rngfix_triggerjump" "0"
}
}

View File

@ -55,7 +55,7 @@
{
"enabled" "1"
"tracks" "0"
"styles" "1;2;3;4;5;6;8;9;10;11;12;13;14;15;16"
"styles" "1;2;3;4;5;6;8;9;11;12;13;14;15;16"
}
"Bonus Normal Bot"
{
@ -71,7 +71,7 @@
}
"TAS Bot"
{
"enabled" "0"
"enabled" "1"
"tracks" "0;1;2;3;4;5;6;7;8"
"styles" "10"
}

View File

@ -22,21 +22,31 @@
"autobhop" "1" // Enable autobhopping and +ds?
"easybhop" "1" // Enable easybhop (disable stamina reset)?
"prespeed" "0" // Allow prespeeding regardless of the prespeed server setting? If set to 2, the value of shavit_core_nozaxisspeed will be respected as well.
"prespeed_ez_vel" "0" // Whether to set velocity on first jump for prespeed styles. 0 = Disabled. >0 = set velocity to this amount (e.g. 3500).
"velocity_limit" "0.0" // Velocity limit: set to 0.0 for unlimited, 400.00 for 400vel styles etc.
"bunnyhopping" "1" // Per-style sv_enablebunnyhopping. Leave as 1 if you want bunnyhopping to maintain player speed. This setting will override _strafe map settings.
// Convar overrides
"prespeed_type" "-1" // Set the specific value of shavit_misc_prespeed to use for this style. -1 will use the current shavit_misc_prespeed value. Requires "prespeed" to be 0.
"blockprejump" "-1" // Set the specific value of shavit_core_blockprejump to use for this style. -1 will use the current shavit_core_blockprejump value.
"nozaxisspeed" "-1" // Set the specific value of shavit_core_nozaxisspeed to use for this style. -1 will use the current shavit_core_nozaxisspeed value.
"restrictnoclip" "-1" // Set the specific value of shavit_misc_restrictnoclip to use for this style. -1 will use the current shavit_misc_restrictnoclip value.
// Physics
"airaccelerate" "1000.0" // sv_airaccelerate value for the style.
"runspeed" "260.00" // Running speed. Requires DHooks, shavit-misc and shavit_misc_staticprestrafe set to 1.
"maxprestrafe" "0.0" // The max prestrafe that still allows your timer to start/restart. You generally do *not* need or want to change this unless for surf things (combined with style-setting "prespeed_type" "6" or cvar "shavit_misc_prespeed 6"). Default is 0.0 (disabled).
"gravity" "1.0" // Gravity setting, 1.0 for default. Standard for low gravity styles is 0.6.
"speed" "1.0" // Speed multiplier, 1.0 for default. Standard for slowmo styles is 0.5.
"timescale" "1.0" // Timing will scale with this setting.
"speed" "1.0" // Speed multiplier, 1.0 for default. Standard for slowmo styles is 0.5. This a multiplier for m_flLaggedMovementValue.
"timescale" "1.0" // Timing will scale with this setting. This is a multiplier for m_flLaggedMovementValue but also affects the timer increase speed.
"force_timescale" "0" // Force the timescale every jump? Default is 0 for normal timescales.
"velocity" "1.0" // % of horizontal velocity to keep per jump. a value 0.9 will make the player lose 10% of their velocity per jump. Likewise, values above 1 will result in speed gains.
"bonus_velocity" "0.0" // Bonus velocity to gain per jump. If set to e.g. 100.0, the player will gain 100 bonus velocity per jump.
"min_velocity" "0.0" // Minimum amount of horizontal velocity to keep per jump. If set to 600.0, the player can't have less than 600 velocity per jump.
"jump_multiplier" "0.0" // Mulitplier for the vertical velocity per jump. 0.0 for disabled.
"jump_bonus" "0.0" // Bonus vertical velocity to gain per jump. If set to e.g. 100.0, the player will gain 100 bonus vertial velocity per jump.
"startinair" "0" // 0 = Start-zones will only start the timer if the player is on the ground. 1 = timer will start without requiring the player to be on the ground in the start zone. This means with 1 that it will basically only start the timer counter once you've left the start-zone. This should only be used on gamemodes that are intended for this kind of mechanic (i.e. not bhop). Also it might be easily abusable. GL. Also this probably won't work unless you set either `"prespeed" "1"` or `"nozaxisspeed" "0"`.
// Mode settings
"block_w" "0" // Block +forward (W).
@ -44,17 +54,21 @@
"block_s" "0" // Block +back (S).
"block_d" "0" // Block +moveright (D).
"block_use" "0" // Block +use (E).
"a_or_d_only" "0" // Force A-only / D-only. You still want to block_w & block_s too. The default shavit-styles.cfg has an A/D-Only style example also.
"force_hsw" "0" // Force half-sideways gameplay. 1 for regular HSW and 2 for surf-HSW.
"force_groundkeys" "0" // Forces the above settings even while on ground. e.g. enabling this will not allow W/D or W/A prestrafing when playing styles that disable the keys.
"block_pleft" "0" // Block +left. 2 to stop timer.
"block_pright" "0" // Block +right. 2 to stop timer.
"block_pstrafe" "0" // Prevent button inconsistencies (including +pstrafe). May have false positives when players lag. Will prevent some strafe hacks too. Set this to 2 to also stop the timer.
"kzcheckpoints" "0" // KZ styled checkpoints. They reset upon timer start and you don't get reverted to a save state, and you cannot save when airborne or someone else's checkpoints.
// Feature excluding
"unranked" "0" // Unranked style. No ranking points and no records.
"noreplay" "0" // Disable replay bot for this style. Automatically included for unranked styles.
// Minimum times (to help try to prevent accidents/cheats)
"minimum_time" "3.5" // Minimum time a main-track run needs to be.
"minimum_time_bonus" "0.5" // Minimum time a bonus-track run needs to be.
// Sync/strafes
"sync" "1" // Measure synchronization between strafes.
"strafe_count_w" "0" // Count W (+forward) for the strafe counter.
@ -70,6 +84,21 @@
"specialstring" "" // For modularity. Separated with semicolon. Built-in flags: "segments".
"permission" "" // Permission required. Syntax: "flag;override". For example "p;style_tas" to require the 'p' flag or the "style_tas" override.
"ordering" "0" // Ordering in menus where styles appear. If this value is not present, style ID will be used instead.
// KZ settings
"kzcheckpoints" "0" // KZ styled checkpoints. They reset upon timer start and you don't get reverted to a save state, and you cannot save when airborne or someone else's checkpoints.
"kzcheckpoints_ladders" "0" // KZ styled checkpoints allowed to checkpoint onto ladders (like GOKZ)
"kzcheckpoints_ontele" "-1" // The style to be changed to on client teleporting to a checkpoint in KZ styles. The destination style will be inaccessible if enabled. -1 or set "kzcheckpoints" to 0 for disabled.
"kzcheckpoints_onstart" "-1" // The style to be changed to on client getting inside the start zone in KZ styles. This style will be inaccessible if enabled. -1 or set "kzcheckpoints" to 0 for disabled.
// TAS settings
"segments" "0" // Segments styled checkpoints. 0 for disabled.
"tas" "0" // 0 = Do nothing. 1 = Currently sets the following keys unless they are explicity disabled: `tas_timescale -1`, `autostrafe 1`, `autoprestrafe 1`, `edgejump 1`, and `autojumponstart 1`
"tas_timescale" "0" // TAS-like timescaling. 0 = Disabled. -1 = User can edit the timescale (TAS menu, sm_ts, sm_tsplus, sm_tsminus). >0 = Fixed tas-timescale value for the style (e.g. 0.5 for a fixed timescale). Total time-increase-rate for the player = timescale * tas_timescale
"autostrafe" "0" // 0 = Disabled. 1 = 1tick autostrafer. 2 = velocity/autogain. 3 = velocity/autogain (no speed loss). 4 = a basic +moveleft/+moveright presser when turning. -1 = Lets players toggle between 1tick and velocity/autogain.
"autoprestrafe" "0" // 0 = Disabled. 1 = Enables TAS prestrafer on the ground to reach.
"edgejump" "0" // 0 = Disabled. 1 = Automatically jumps when the player will fall off a ledge next tick.
"autojumponstart" "0" // 0 = Disabled. 1 = Automatically jumps when the player will leave the start zone.
}
"1"
@ -163,7 +192,7 @@
"force_hsw" "1"
"strafe_count_w" "1"
"strafe_count_w" "0"
"strafe_count_a" "1"
"strafe_count_s" "0"
"strafe_count_d" "1"
@ -173,11 +202,11 @@
"6"
{
"name" "D-Only"
"shortname" "D"
"name" "A/D-Only"
"shortname" "A/D"
"htmlcolor" "9C5BBA"
"command" "d; donly"
"clantag" "D"
"command" "a; aonly; ad; d; donly"
"clantag" "A/D"
"autobhop" "1"
"easybhop" "1"
@ -185,12 +214,11 @@
"airaccelerate" "1000.0"
"runspeed" "260.00"
"a_or_d_only" "1"
"block_w" "1"
"block_a" "1"
"block_s" "1"
"strafe_count_w" "0"
"strafe_count_a" "0"
"strafe_count_s" "0"
"rankingmultiplier" "1.50"
@ -204,8 +232,9 @@
"command" "sr; seg; segment; segmented"
"clantag" "SEG"
"rankingmultiplier" "0.0"
"specialstring" "segments"
"segments" "1"
"rankingmultiplier" "0.0"
}
"8"
@ -216,9 +245,7 @@
"command" "lg; lowgrav"
"clantag" "LG"
"gravity" "0.6"
"unranked" "1"
"gravity" "0.5"
}
"9"
@ -229,9 +256,21 @@
"command" "slow; slowmo"
"clantag" "SLOW"
"speed" "0.5"
"timescale" "0.5"
}
"unranked" "1"
"10"
{
"name" "TAS"
"shortname" "TAS"
"htmlcolor" "123456"
"command" "tas"
"clantag" "TAS"
"tas" "1"
"segments" "1"
"specialstring" "bash_bypass; oryx_bypass"
"rankingmultiplier" "0.0"
}
}

View File

@ -16,11 +16,11 @@
"Start"
{
"visible" "1"
"red" "67"
"green" "210"
"blue" "230"
"alpha" "255"
"width" "0.5"
@ -30,11 +30,11 @@
"End"
{
"visible" "1"
"red" "165"
"green" "19"
"blue" "194"
"alpha" "255"
"width" "0.5"
}
@ -42,11 +42,11 @@
"Glitch_Respawn"
{
"visible" "0"
"red" "255"
"green" "200"
"blue" "0"
"alpha" "255"
"width" "0.5"
}
@ -54,11 +54,11 @@
"Glitch_Stop"
{
"visible" "0"
"red" "255"
"green" "200"
"blue" "0"
"alpha" "255"
"width" "0.5"
}
@ -66,11 +66,11 @@
"Glitch_Slay"
{
"visible" "0"
"red" "255"
"green" "200"
"blue" "0"
"alpha" "255"
"width" "0.5"
}
@ -78,23 +78,23 @@
"Freestyle"
{
"visible" "1"
"red" "25"
"green" "25"
"blue" "255"
"alpha" "195"
"width" "0.5"
}
"Nolimit"
"Custom Speed Limit"
{
"visible" "1"
"red" "247"
"green" "3"
"blue" "255"
"alpha" "50"
"width" "0.5"
}
@ -102,11 +102,11 @@
"Teleport"
{
"visible" "0"
"red" "255"
"green" "200"
"blue" "0"
"alpha" "255"
"width" "4.0"
}
@ -114,11 +114,11 @@
"Easybhop"
{
"visible" "1"
"red" "57"
"green" "196"
"blue" "92"
"alpha" "175"
"width" "2.5"
}
@ -126,11 +126,11 @@
"Slide"
{
"visible" "1"
"red" "244"
"green" "66"
"blue" "92"
"alpha" "255"
"width" "1.5"
}
@ -138,11 +138,11 @@
"Airaccelerate"
{
"visible" "1"
"red" "118"
"green" "102"
"blue" "173"
"alpha" "255"
"width" "1.5"
}
@ -150,157 +150,277 @@
"Stage"
{
"visible" "1"
"red" "255"
"green" "153"
"blue" "0"
"alpha" "255"
"width" "0.5"
}
"Bonus Start"
"No Timer Gravity"
{
"visible" "1"
"red" "255"
"green" "0"
"blue" "255"
"alpha" "255"
"width" "1.0"
}
"Gravity"
{
"visible" "1"
"red" "255"
"green" "0"
"blue" "255"
"alpha" "255"
"width" "1.0"
}
"Speedmod"
{
"visible" "1"
"red" "255"
"green" "0"
"blue" "255"
"alpha" "255"
"width" "1.0"
}
"No Jump"
{
"visible" "1"
"red" "255"
"green" "0"
"blue" "255"
"alpha" "255"
"width" "0.1"
}
"Autobhop"
{
"visible" "1"
"red" "255"
"green" "0"
"blue" "255"
"alpha" "255"
"width" "0.1"
}
"Bonus 1 Start"
{
"visible" "1"
"red" "255"
"green" "255"
"blue" "255"
"alpha" "255"
"width" "0.1"
}
"Bonus End"
"Bonus 1 End"
{
"visible" "1"
"red" "123"
"green" "20"
"blue" "250"
"alpha" "255"
"width" "0.1"
}
"Bonus Glitch_Respawn"
"Bonus 1 Glitch_Respawn"
{
"visible" "0"
"red" "255"
"green" "200"
"blue" "0"
"alpha" "255"
"width" "0.1"
}
"Bonus Glitch_Stop"
"Bonus 1 Glitch_Stop"
{
"visible" "0"
"red" "255"
"green" "200"
"blue" "0"
"alpha" "255"
"width" "0.1"
}
"Bonus Glitch_Slay"
"Bonus 1 Glitch_Slay"
{
"visible" "0"
"red" "255"
"green" "200"
"blue" "0"
"alpha" "255"
"width" "0.1"
}
"Bonus Freestyle"
"Bonus 1 Freestyle"
{
"visible" "1"
"red" "25"
"green" "25"
"blue" "255"
"alpha" "195"
"width" "0.1"
}
"Bonus Nolimit"
"Bonus 1 Custom Speed Limit"
{
"visible" "1"
"red" "247"
"green" "3"
"blue" "255"
"alpha" "50"
"width" "0.1"
}
"Bonus Teleport"
"Bonus 1 Teleport"
{
"visible" "0"
"red" "255"
"green" "200"
"blue" "0"
"alpha" "255"
"width" "2.0"
}
"Bonus Easybhop"
"Bonus 1 Easybhop"
{
"visible" "1"
"red" "57"
"green" "196"
"blue" "92"
"alpha" "175"
"width" "1.75"
}
"Bonus Slide"
"Bonus 1 Slide"
{
"visible" "1"
"red" "244"
"green" "66"
"blue" "92"
"alpha" "255"
"width" "1.0"
}
"Bonus Airaccelerate"
"Bonus 1 Airaccelerate"
{
"visible" "1"
"red" "118"
"green" "102"
"blue" "173"
"alpha" "255"
"width" "1.0"
}
"Bonus Stage"
"Bonus 1 Stage"
{
"visible" "1"
"red" "204"
"green" "153"
"blue" "255"
"alpha" "255"
"width" "0.5"
}
"Bonus 1 No Timer Gravity"
{
"visible" "1"
"red" "255"
"green" "0"
"blue" "255"
"alpha" "255"
"width" "1.0"
}
"Bonus 1 Gravity"
{
"visible" "1"
"red" "255"
"green" "0"
"blue" "255"
"alpha" "255"
"width" "1.0"
}
"Bonus 1 Speedmod"
{
"visible" "1"
"red" "255"
"green" "0"
"blue" "255"
"alpha" "255"
"width" "1.0"
}
"Bonus 1 No Jump"
{
"visible" "1"
"red" "255"
"green" "0"
"blue" "255"
"alpha" "255"
"width" "0.1"
}
"Bonus 1 Autobhop"
{
"visible" "1"
"red" "255"
"green" "0"
"blue" "255"
"alpha" "255"
"width" "0.1"
}
}
}

View File

@ -1,6 +1,6 @@
"Games"
{
// A guide to find most of these signatures and offsets: https://www.youtube.com/watch?v=ekyLf6hu4qI
// A guide to find most of these signatures and offsets: https://www.youtube.com/watch?v=ekyLf6hu4qI and another https://www.youtube.com/watch?v=J7eHgK_UYOk
"#default"
{
@ -11,10 +11,22 @@
"Signatures"
{
"CreateInterface"
"CreateInterface_Server"
{
"library" "server"
"windows" "@CreateInterface"
"windows64" "@CreateInterface"
"linux" "@CreateInterface"
"linux64" "@CreateInterface"
}
"CreateInterface_Engine"
{
"library" "engine"
"windows" "@CreateInterface"
"windows64" "@CreateInterface"
"linux" "@CreateInterface"
"linux64" "@CreateInterface"
}
}
@ -23,42 +35,61 @@
"OS"
{
"windows" "1"
"windows64" "1"
"linux" "2"
"linux64" "2"
}
"X64"
{
"windows" "0"
"windows64" "1"
"linux" "0"
"linux64" "1"
}
"ProcessMovement"
{
"windows" "1"
"windows64" "1"
"linux" "2"
"linux64" "2"
}
}
}
"csgo"
{
"Addresses"
{
"m_surfaceFriction"
{
"signature" "CBasePlayer->m_surfaceFriction"
"read" "4" // skip the first 4 bytes
}
}
"Offsets"
{
// search string "#SFUI_Notice_SprayPaint_TooClose" to find IsAbleToApplySpray and then go to the next function to find GetPlayerMaxSpeed. Then calculate the vtable offset.
// search string: "func_pushable" and you can find CBaseTrigger::PassesTriggerFilters / CBaseVPhysicsTrigger::PassesTriggerFilters. Follow references to these functions to find the vtable and then calculate the offset...
"CBaseTrigger::PassesTriggerFilters"
{
"windows" "210"
"linux" "211"
}
// search string: "start %f %f %f" and then check the function call offsets above it and convert them to vtable offsets (divide by 4 most likely or whatever)
"CCSPlayer::GetPlayerMaxSpeed"
{
"windows" "506"
"linux" "507"
"mac" "507"
}
// add 1 to the css offset and hope it works
// add 1 to the css offset and hope it works (or look around the references to "Invalid counterterrorist spawnpoint")
"CGameRules::IsSpawnPointValid"
{
"windows" "77"
"linux" "78"
"mac" "78"
}
// can be found inside BotAddCommand
"WEAPONTYPE_UNKNOWN"
{
"windows" "19"
"linux" "19"
"mac" "19"
}
// search string: "Can't find specific footstep sound!" to find CBasePlayer::PlayStepSound.
// then find the vtable from references and CBasePlayer::UpdateStepSound is right before PlayStepSound
"CBasePlayer::UpdateStepSound"
@ -66,6 +97,24 @@
"windows" "409"
"linux" "410"
}
// TODO
"m_surfaceFriction"
{
"windows" "8"
"linux" "8"
}
// TODO
"GetClusterForOrigin"
{
"windows" "12"
"linux" "12"
}
// TODO
"GetArea"
{
"windows" "65"
"linux" "65"
}
}
"Signatures"
@ -74,96 +123,247 @@
"Player::DoAnimationEvent"
{
"windows" "\x55\x8B\xEC\x56\x8B\xF1\x57\x80\xBE\x2A\x2A\x2A\x2A\x00\x74\x2A\x51"
"linux" "\x55\x89\xE5\x83\xEC\x28\x89\x5D\xF4\x8B\x5D\x08\x89\x75\xF8\x8B\x75\x0C\x89\x7D\xFC\x8B\x7D\x10\x80\xBB\x44\x23\x00\x00\x00"
"linux" "\x55\x89\xE5\x57\x56\x53\x83\xEC\x0C\x8B\x5D\x2A\x8B\x75\x2A\x8B\x7D\x2A\x80\xBB\x2A\x2A\x2A\x2A\x00\x75"
}
// search string: "-nobots"
// search string: "-nobots". On Linux this leads to `AreBotsAllowed()`, which can check the references to find MaintainBotQuota
"BotManager::MaintainBotQuota"
{
"windows" "\x55\x8B\xEC\x83\xEC\x18\x89\x4D\x2A\xFF\x15"
"linux" "\x55\x89\xE5\x83\xEC\x78\x89\x7D\x2A\x8B\x7D\x2A\x89\x5D\x2A\x89\x75\x2A"
}
// search string: "Error - no profile for '%s' exists."
"CCSBotManager::BotAddCommand"
{
"windows" "\x55\x8B\xEC\xA1\x2A\x2A\x2A\x2A\x53\x56\x57\x80\x78\x2A\x00"
"linux" "\x55\x89\xE5\x57\x56\x53\x83\xEC\x4C\x8B\x15\x2A\x2A\x2A\x2A\x8B\x7D\x2A\x8B\x75\x2A\x0F\xB6\x5D\x2A"
"windows" "\x55\x8B\xEC\x83\xEC\x14\x89\x4D\x2A\xFF\x15"
"linux" "\x55\x89\xE5\x57\x56\x53\x83\xEC\x2C\xE8\x2A\x2A\x2A\x2A\x84\xC0\x74\x2A\xA1"
}
// search string: "remove 0x%p: %s-%s" to find PhysicsRemoveToucher.
// Find PhysicsCheckForEntityUntouch by checking the functions that call PhysicsRemoveToucher.
// This sucks to find.
"PhysicsCheckForEntityUntouch"
{
"windows" "\x55\x8B\xEC\x83\xEC\x08\x56\x8B\xF1\x8B\x86\xD0\x00\x00\x00"
"linux" "\x55\x89\xE5\x57\x56\x53\x83\xEC\x2C\x8B\x5D\x08\xC7\x44\x24\x04\x01\x00\x00\x00\x89\x1C\x24"
"linux" "\x55\x89\xE5\x57\x56\x53\x83\xEC\x24\x8B\x75\x2A\x6A\x01\x56"
}
// search string: "remove 0x%p: %s-%s (%d-%d) [%d in play, %d max]\n".
// function with one argument is PhysicsRemoveTouchedList
// Also, this function is referenced (at least on linux) by `CPhysicsPropRespawnable::Event_Killed()` (which includes the string "PROP_CLEARFLAGS"
"PhysicsRemoveTouchedList"
{
"windows" "\x55\x8B\xEC\x83\xEC\x0C\x57\x8B\xF9\x8B\x87\x2A\x2A\x2A\x2A\xD1\xE8\xA8\x01\x0F\x84"
"linux" "\x55\x89\xE5\x57\x56\x53\x83\xEC\x34\x6A\x01\xFF\x75\x2A\xE8\x2A\x2A\x2A\x2A\x83\xC4\x10"
}
// search string: "sv_friction", look for instruction like this: "mov some_register, offset sv_friction_cvar"
// xref sv_friction_cvar, look for the place that it gets called and has this:
// *(float*)(a1[1] + some_offset) * (float(__thiscall)(void*))(*(uintptr_t*)sv_friction + GetFloatIndex*sizeof(void*))(sv_friction)
// make a signature for some_offset
// if it's unclear: https://youtu.be/xiNQ00X4R_I
// On Ghidra + Windows CSGO, the references are sometimes missing.
// You can find a variable/memory-location holding -25.0 with a memory search.
// This variable is referenced in the same function as where you can find this signature.
"CBasePlayer->m_surfaceFriction"
{
"windows" "\xF3\x0F\x10\x80\x2A\x2A\x2A\x2A\xF3\x0F\x59\x45\x2A\xF3\x0F\x11\x45"
"linux" "\xF3\x0F\x10\xB8\x2A\x2A\x2A\x2A\xA1"
}
// search "sv_maxusrcmdprocessticks_warning at server" to find CPlayerMove::RunCommand
// then sig the the `mov REG1,dword ptr [REG2 + OFFSET_TO_BUTTON_DISABLED_HERE]`
// looks like these in decompiled form:
// (windows) `param_3[0xc] = param_3[0xc] & ~param_2[0x32b];`
// (linux) `*(uint *)(param_3 + 0x30) = uVar12 & ~param_2[0x331];`
"CBasePlayer->m_afButtonDisabled"
{
"windows" "\x8B\x86\x2A\x2A\x2A\x2A\xF7\xD0\x21\x47"
"linux" "\x8b\x93\x2A\x2A\x2A\x2A\xF7\xD2\x21\xd0"
}
}
}
"cstrike"
{
"Addresses"
{
}
"Offsets"
{
// https://asherkin.github.io/vtable/
// https://asherkin.github.io/vtable/ (you can drop a .so from your srcds into this)
// search string: "func_pushable" and you can find CBaseTrigger::PassesTriggerFilters / CBaseVPhysicsTrigger::PassesTriggerFilters. Follow references to these functions to find the vtable and then calculate the offset...
"CBaseTrigger::PassesTriggerFilters"
{
"windows" "203"
"windows64" "203"
"linux" "204"
"linux64" "204"
}
// https://asherkin.github.io/vtable/ (you can drop a .so from your srcds into this)
// search string: "start %f %f %f" and then check the function call offsets above it and convert them to vtable offsets (divide by 4 most likely or whatever)
"CCSPlayer::GetPlayerMaxSpeed"
{
"windows" "438"
"linux" "439"
"mac" "439"
"windows" "445"
"windows64" "445"
"linux" "446"
"linux64" "446"
}
// https://asherkin.github.io/vtable/
// https://asherkin.github.io/vtable/ (you can drop a .so from your srcds into this)
// search string: "Invalid counterterrorist spawnpoint" and then look for the first function call in each iteration of the loop
"CGameRules::IsSpawnPointValid"
{
"windows" "76"
"windows64" "77" // yes, same as linux64 (according to vtable site)
"linux" "77"
"mac" "77"
"linux64" "77"
}
// can be found inside BotAddCommand
"WEAPONTYPE_UNKNOWN"
{
"windows" "9"
"linux" "9"
"mac" "9"
}
// https://asherkin.github.io/vtable/
// https://asherkin.github.io/vtable/ (you can drop a .so from your srcds into this)
// search string: "water" to find CBasePlayer::UpdateStepSound. At the bottom there's a vtable call to ::PlayStepSound. Grab that, divide by 4, subtract 1. Bam, UpdateStepSound...
"CBasePlayer::UpdateStepSound"
{
"windows" "358"
"linux" "359"
"windows" "364"
"windows64" "364"
"linux" "365"
"linux64" "365"
}
// find in CCSGameMovement::CheckForLadders which references CCSPlayer::CanGrabLadder
//
// Find CCSPlayer::CanGrabLadder by searching for 4096.0f, then find the function (CheckForLadders) that references it...
// CanGrabLadder might look like this on Windows (or just use symbols on Linux)
// undefined4 __thiscall CCSPlayer::CanGrabLadder(int param_1_00,float *param_1,float *param_2)
// {
// float10 extraout_ST0;
// float fVar1;
// float fVar2;
//
// (*(code *)**(undefined4 **)(param_1_00 + 0x1790))();
// if ((float10)0 < (float10)*(float *)(param_1_00 + 0x1798) - extraout_ST0) {
// fVar1 = *param_1 - *(float *)(param_1_00 + 0x17a8);
// fVar2 = param_1[1] - *(float *)(param_1_00 + 0x17ac);
// if (fVar2 * fVar2 + fVar1 * fVar1 < 4096.0) {
// return 0;
// }
// if ((((NAN(*(float *)(param_1_00 + 0x179c)) || NAN(*param_2)) !=
// (*(float *)(param_1_00 + 0x179c) == *param_2)) &&
// ((NAN(*(float *)(param_1_00 + 0x17a0)) || NAN(param_2[1])) !=
// (*(float *)(param_1_00 + 0x17a0) == param_2[1]))) &&
// ((NAN(*(float *)(param_1_00 + 0x17a4)) || NAN(param_2[2])) !=
// (*(float *)(param_1_00 + 0x17a4) == param_2[2]))) {
// return 0;
// }
// }
// return 1;
// }
"CCSPlayer::m_lastStandingPos"
{
"windows" "6016"
"windows64" "6640"
"linux" "6036" // +20 wow that's easy!
"linux64" "6688" // +48 wow that's easy!
}
// find CCSPlayer::CanGrabLadder via 4096.0f or symbols on linux...
"CCSPlayer::m_ladderSurpressionTimer"
{
"windows" "6032"
"windows64" "6668"
"linux" "6052" // +20 wow that's easy!
"linux64" "6716" // +48 wow that's easy!
}
// find CCSPlayer::CanGrabLadder via 4096.0f or symbols on linux...
"CCSPlayer::m_lastLadderNormal"
{
"windows" "6044"
"windows64" "6672"
"linux" "6064" // +20 wow that's easy!
"linux64" "6720" // +48 wow that's easy!
}
// find CCSPlayer::CanGrabLadder via 4096.0f or symbols on linux...
"CCSPlayer::m_lastLadderPos"
{
"windows" "6056"
"windows64" "6684"
"linux" "6076" // +20 wow that's easy!
"linux64" "6732" // +48 wow that's easy!
}
// TODO
"GetClusterForOrigin"
{
"windows" "11"
"linux" "11"
}
// TODO
"GetArea"
{
"windows" "64"
"linux" "64"
}
}
"Signatures"
{
// search string: "ReloadEffect" to find CWeaponCSBase::SendReloadEvents and then DoAnimationEvent is probably the second to last function called there.
// search string: "ReloadEffect" to find CWeaponCSBase::SendReloadEvents and then CCSPlayer::DoAnimationEvent is probably the second to last function called there.
"Player::DoAnimationEvent"
{
"windows" "\x55\x8B\xEC\x83\xEC\x10\x89\x4D\xFC\x83\x7D\x08\x02"
"windows" "\x55\x8B\xEC\x83\xEC\x0C\x89\x4D\x2A\x83\x7D\x2A\x02"
"windows64" "\x44\x89\x44\x24\x2A\x89\x54\x24\x2A\x48\x89\x4C\x24\x2A\x48\x83\xEC\x38\x83\x7C\x24\x2A\x02"
"linux" "@_ZN9CCSPlayer16DoAnimationEventE17PlayerAnimEvent_ti"
"linux64" "@_ZN9CCSPlayer16DoAnimationEventE17PlayerAnimEvent_ti"
}
// search string: "-nobots"
// search string: "-nobots" (and then look for the function that also references "fill" and "match" (or just the function with 0 or 1 parameters...))
"BotManager::MaintainBotQuota"
{
"windows" "\x55\x8B\xEC\x83\xEC\x14\xFF\x15"
"windows64" "\x48\x83\xEC\x78\xFF\x15"
"linux" "@_ZN13CCSBotManager16MaintainBotQuotaEv"
"linux64" "@_ZN13CCSBotManager16MaintainBotQuotaEv"
}
// search string: "Error - no profile for '%s' exists."
"CCSBotManager::BotAddCommand"
// search string: "Server is hibernating" to find SetHibernating and then go to its references
// NOTE 2025-02-19: Function has been inlined on Windows into SV_Think...
"CGameServer::UpdateHibernationState"
{
"windows" "\x55\x8B\xEC\xA1\x2A\x2A\x2A\x2A\x80\x78\x2A\x00\x75\x2A\x83\xB8\x2A\x2A\x2A\x2A\x00"
"linux" "@_ZN13CCSBotManager13BotAddCommandEibPKc12CSWeaponType17BotDifficultyType"
"library" "engine"
//"windows" ""
"windows64" "\x48\x89\x5C\x24\x2A\x56\x48\x83\xEC\x40\x8B\x05"
"linux" "@_ZN11CGameServer22UpdateHibernationStateEv.part.0"
"linux64" "@_ZN11CGameServer14SetHibernatingEb"
}
// search string: "remove 0x%p: %s-%s" to find PhysicsRemoveToucher.
// Find PhysicsCheckForEntityUntouch by checking the functions that call PhysicsRemoveToucher.
// (should be the function with one argument (this ptr))
"PhysicsCheckForEntityUntouch"
{
"windows" "\x55\x8B\xEC\x83\xEC\x08\x56\x8B\xF1\x8B\x86"
"windows" "\x55\x8B\xEC\x83\xEC\x08\x57\x8B\xF9\x8B\x87"
"windows64" "\x40\x57\x48\x83\xEC\x20\x8B\x81"
"linux" "@_ZN11CBaseEntity28PhysicsCheckForEntityUntouchEv"
"linux64" "@_ZN11CBaseEntity28PhysicsCheckForEntityUntouchEv"
}
// search string: "Could not add bot to the game: Team is full"
// search string: "Could not add bot to the game: Team is full" to find CCSBotManager::BotAddCommand and then follow the if-statement up to find the function call that was full (because TeamFull())
// protip: on csgo we just use mp_randomspawn instead.
"CCSGameRules::TeamFull"
{
"windows" "\x55\x8B\xEC\x56\x8B\xF1\xE8\x2A\x2A\x2A\x2A\x8B\x45\x2A\x83\xE8\x02"
"windows64" "\x48\x89\x5C\x24\x2A\x57\x48\x83\xEC\x20\x8B\xFA\x48\x8B\xD9\xE8\x2A\x2A\x2A\x2A\x83\xEF\x02"
"linux" "@_ZN12CCSGameRules8TeamFullEi"
"linux64" "@_ZN12CCSGameRules8TeamFullEi"
}
// search string: "remove 0x%p: %s-%s (%d-%d) [%d in play, %d max]\n".
// function with one argument is PhysicsRemoveTouchedList
"PhysicsRemoveTouchedList"
{
"windows" "\x55\x8B\xEC\x83\xEC\x08\x53\x8B\x5D\x2A\x8B\x83"
"windows64" "\x40\x55\x56\x48\x83\xEC\x58"
"linux" "@_ZN11CBaseEntity24PhysicsRemoveTouchedListEPS_"
"linux64" "@_ZN11CBaseEntity24PhysicsRemoveTouchedListEPS_"
}
// look for CGameMovement::CategorizePosition by searching for 140.0f
// and you will see something something `*(_DWORD*)(a1[1] + some_offset) = 0x3F800000` right at the top
// make a signature at "mov dword ptr[eax+some_offset], 3F800000h"
"CBasePlayer->m_surfaceFriction"
{
"windows" "\xC7\x80\x2A\x2A\x2A\x2A\x00\x00\x80\x3F\x8B\x07"
"windows64" "\xC7\x80\x2A\x2A\x2A\x2A\x00\x00\x80\x3F\x48\x8B\x01"
"linux" "\xC7\x80\x2A\x2A\x2A\x2A\x00\x00\x80\x3F\x8B\x03"
"linux64" "\xC7\x80\x2A\x2A\x2A\x2A\x00\x00\x80\x3F\x48\x8B\x07"
}
// search "sv_maxusrcmdprocessticks_warning at server" to find CPlayerMove::RunCommand
// then sig the the `mov REG1,dword ptr [REG2 + OFFSET_TO_BUTTON_DISABLED_HERE]`
"CBasePlayer->m_afButtonDisabled"
{
"windows" "\x8B\x87\x2A\x2A\x2A\x2A\xF7\xD0\x23\xC1"
"windows64" "\x8B\x87\x2A\x2A\x2A\x2A\xF7\xD0"
"linux" "\x8B\x93\x2A\x2A\x2A\x2A\xF7\xD2"
"linux64" "\x8B\x83\x2A\x2A\x2A\x2A\xF7\xD0\x21\xD0"
}
}
}
@ -172,23 +372,36 @@
{
"Offsets"
{
// https://asherkin.github.io/vtable/
"CBaseTrigger::PassesTriggerFilters"
{
"windows" "207"
"linux" "208"
}
// https://asherkin.github.io/vtable/
"CGameRules::IsSpawnPointValid"
{
"windows" "76"
"linux" "77"
"mac" "77"
}
// https://asherkin.github.io/vtable/
"CBasePlayer::UpdateStepSound"
{
"windows" "362"
"linux" "363"
"windows" "368"
"linux" "369"
}
}
"Signatures"
{
// search string: "BumperCar.Jump" to find CTFGameMovement::CheckJumpButton.
// Then the call to PreventBunnyJumping is right above the string reference somewhere...
// Update 2024-04-18: This fucking bitch got inlined on Windows so this signature is now to the first jump instruction of it to gtfo of doing the velocity stuff. https://i.imgur.com/LDq6Ubo.png
"CTFGameMovement::PreventBunnyJumping"
{
"windows" "\x75\x2A\x8B\x47\x2A\x8D\x77\x2A\x0F\x57\xC0"
"linux" "@_ZN15CTFGameMovement19PreventBunnyJumpingEv"
}
// search string: "Usage: setang_exact pitch yaw" to find setang_exact's handler. Then the last function call in the handler is DoAnimationEvent.
"Player::DoAnimationEvent"
{
@ -198,28 +411,29 @@
// search string: "match"
"BotManager::MaintainBotQuota"
{
"windows" "\x55\x8B\xEC\x81\xEC\x14\x01\x00\x00\xA1"
"windows" "\x55\x8B\xEC\xA1\x2A\x2A\x2A\x2A\x81\xEC\x10\x01\x00\x00\x83\xB8\x2A\x2A\x2A\x2A\x00"
"linux" "@_ZN13CTFBotManager16MaintainBotQuotaEv"
}
// search string: "CreatePlayerBot: Unable to create bot"
"NextBotCreatePlayerBot<CTFBot>"
{
"windows" "\x55\x8B\xEC\x56\x57\x68\x2A\x2A\x2A\x2A\xE8"
"linux" "@_Z22NextBotCreatePlayerBotI6CTFBotEPT_PKcb"
}
// search string: "remove 0x%p: %s-%s" to find PhysicsRemoveToucher.
// Find PhysicsCheckForEntityUntouch by checking the functions that call PhysicsRemoveToucher.
"PhysicsCheckForEntityUntouch"
{
"windows" "\x55\x8B\xEC\x83\xEC\x08\x56\x8B\xF1\x8B\x86\x2A\x2A\x2A\x2A\xD1\xE8"
"windows" "\x55\x8B\xEC\x83\xEC\x08\x57\x8B\xF9\x8B\x87\x2A\x2A\x2A\x2A\xD1\xE8"
"linux" "@_ZN11CBaseEntity28PhysicsCheckForEntityUntouchEv"
}
// search string: "scoreboard_minigame"
"CTFGameRules::CalcPlayerScore"
{
"windows" "\x55\x8B\xEC\x56\x8B\x75\x2A\x85\xF6\x75\x2A\x33\xC0\x5E\x5D\xC3\x8B\x56"
"windows" "\x55\x8B\xEC\x57\x8B\x7D\x2A\x85\xFF\x75\x2A\x33\xC0\x5F\x5D\xC3\x8B\x57"
"linux" "@_ZN12CTFGameRules15CalcPlayerScoreEP12RoundStats_tP9CTFPlayer"
}
// search string: "remove 0x%p: %s-%s (%d-%d) [%d in play, %d max]\n".
// function with one argument is PhysicsRemoveTouchedList
"PhysicsRemoveTouchedList"
{
"windows" "\x55\x8B\xEC\x83\xEC\x08\x53\x8B\x5D\x2A\x8B\x83"
"linux" "@_ZN11CBaseEntity24PhysicsRemoveTouchedListEPS_"
}
}
}
}

View File

@ -270,9 +270,9 @@ typeset SteamWorksHTTPDataReceived
typeset SteamWorksHTTPBodyCallback
{
function void (const char sData[]);
function void (const char sData[], any value);
function void (const int data[], any value, int datalen);
function void (const char[] sData);
function void (const char[] sData, any value);
function void (const int[] data, any value, int datalen);
};
#else

View File

@ -5,7 +5,7 @@
#define _closestpos_included
methodmap ClosestPos < Handle {
public native ClosestPos(ArrayList input, int offset=0);
public native ClosestPos(ArrayList input, int offset=0, int startidx=0, int count=2147483647);
public native int Find(float pos[3]);
};

View File

@ -1,18 +1,43 @@
/*
MIT License
Copyright (c) 2019-2020 KiD Fearless
Copyright (c) 2021-2022 rtldg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#if defined _convar_class_included
#endinput
#endif
#define _convar_class_included
// todo: track previous default values
// todo: track previous default values
static ArrayList _ConvarList;
enum struct convar_t
{
char name[255];
ConVar cvar;
char description[512];
char defValue[512];
char name[255];
bool GetMin(float& input)
{
@ -46,14 +71,19 @@ methodmap Convar < ConVar
convar_t savedValue;
savedValue.cvar = cvar;
strcopy(savedValue.name, sizeof(savedValue.name), name);
strcopy(savedValue.description, 512, description);
strcopy(savedValue.defValue, sizeof(savedValue.defValue), defaultValue);
// Can't set default values :T
savedValue.SetMin(hasMin, min);
savedValue.SetMax(hasMax, max);
convar = savedValue;
// Have to do it this way instead of `convar = savedValue;` because SM 1.12 is a whiny bitch.
convar.name = savedValue.name;
convar.cvar = savedValue.cvar;
convar.description = savedValue.description;
convar.defValue = convar.defValue;
_ConvarList.PushArray(savedValue);
@ -78,6 +108,7 @@ methodmap Convar < ConVar
return false;
}
_ConvarList.Sort(Sort_Ascending, Sort_String);
// Check if the file exists.
char local[PLATFORM_MAX_PATH];
@ -126,20 +157,12 @@ methodmap Convar < ConVar
{
continue;
}
// make a copy of our description
char descr[512];
descr = convar.description;
// format newlines as comments
ReplaceString(descr, 512, "\n", "\n// ");
ReplaceString(convar.description, 512, "\n", "\n// ");
// write the values and bounds to the file if they exist
file.WriteLine("// %s", descr);
// get the convar name and default value to write to file
char name[64];
convar.cvar.GetName(name, 64);
file.WriteLine("// %s", convar.description);
file.WriteLine("// -");
file.WriteLine("// Default: \"%s\"", convar.defValue);
@ -152,7 +175,7 @@ methodmap Convar < ConVar
{
file.WriteLine("// Maximum: \"%02f\"", x);
}
file.WriteLine("%s \"%s\"\n", name, convar.defValue);
file.WriteLine("%s \"%s\"\n", convar.name, convar.defValue);
}
// end with newline
file.WriteLine("");
@ -238,14 +261,8 @@ methodmap Convar < ConVar
continue;
}
char descr[512];
descr = convar.description;
ReplaceString(descr, 512, "\n", "\n// ");
file.WriteLine("// %s", descr);
char name[64];
convar.cvar.GetName(name, 64);
ReplaceString(convar.description, 512, "\n", "\n// ");
file.WriteLine("// %s", convar.description);
file.WriteLine("// -");
file.WriteLine("// Default: \"%s\"", convar.defValue);
@ -257,16 +274,16 @@ methodmap Convar < ConVar
{
file.WriteLine("// Maximum: \"%02f\"", x);
}
// only difference is that now we check for a stored value.
char storedValue[512];
if(convars.GetString(name, storedValue, 512))
if(convars.GetString(convar.name, storedValue, 512))
{
file.WriteLine("%s \"%s\"\n", name, storedValue);
file.WriteLine("%s \"%s\"\n", convar.name, storedValue);
}
else
{
file.WriteLine("%s \"%s\"\n", name, convar.defValue);
file.WriteLine("%s \"%s\"\n", convar.name, convar.defValue);
}
}
file.WriteLine("");
@ -277,7 +294,7 @@ methodmap Convar < ConVar
char pluginName[64];
GetPluginFilename(GetMyHandle(), pluginName, 64);
LogError("Failed to auto generate config for %s, make sure the directory has write permission.", pluginName);
if(clearWhenDone)
{
delete _ConvarList;
@ -286,7 +303,7 @@ methodmap Convar < ConVar
delete convars;
return false;
}
delete convars;
}
if(fileExists)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,152 @@
/*
* Anti-sv_cheats and anti- cheat-command stuff
* by: rtldg
*
* This file is part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
// This code annoys everyone but admins would sometimes set sv_cheats 1 and then
// forget to toggle it back off when they were done playing around so then people
// would join and teleport into the endzone and set dumb times. And now we're here...
// Just add some aliases to your autoexec:
// alias cheats "sm_rcon shavit_core_disable_sv_cheats 0 ; sm_rcon sv_cheats 1"
// alias cheat "sm_rcon shavit_core_disable_sv_cheats 0 ; sm_rcon sv_cheats 1"
Convar gCV_DisableSvCheats = null;
#if !DEBUG
ConVar sv_cheats = null;
char gS_CheatCommands[][] = {
"ent_create",
"ent_orient",
"ent_pause",
"ent_fire",
"ent_remove",
"ent_remove_all",
"ent_setname",
"ent_setpos",
"ent_teleport",
"firetarget",
"setpos",
"setpos_exact",
"setpos_player",
// can be used to kill other players
"explode",
"explodevector",
"kill",
"killvector",
"give",
};
#endif
void Anti_sv_cheats_cvars()
{
gCV_DisableSvCheats = new Convar("shavit_core_disable_sv_cheats", "1", "Force sv_cheats to 0.", 0, true, 0.0, true, 1.0);
#if !DEBUG
sv_cheats = FindConVar("sv_cheats");
sv_cheats.AddChangeHook(sv_cheats_hook);
for (int i = 0; i < sizeof(gS_CheatCommands); i++)
{
AddCommandListener(Command_Cheats, gS_CheatCommands[i]);
}
#endif
}
void Anti_sv_cheats_OnConfigsExecuted()
{
if (gCV_DisableSvCheats.BoolValue)
{
#if !DEBUG
sv_cheats.SetInt(0);
#endif
}
}
void Remove_sv_cheat_Impluses(int client, int &impulse)
{
#if !DEBUG
if (impulse && sv_cheats.BoolValue && !(GetUserFlagBits(client) & ADMFLAG_ROOT))
{
switch (impulse)
{
// Likely incomplete list of the most cheaty impulses...
// 76 = spawn npc
// 81 = something cubemap
// 82 = create jeep
// 83 = create airboat
// 102 = something node
// 195 = something node
// 196 = something node
// 197 = something node
// 202 = something bloodsplat
// 203 = remove entity
case 76, 81, 82, 83, 102, 195, 196, 197, 202, 203:
{
impulse = 0;
}
}
}
#endif
}
#if !DEBUG
public void sv_cheats_hook(ConVar convar, const char[] oldValue, const char[] newValue)
{
if (gCV_DisableSvCheats.BoolValue)
{
sv_cheats.SetInt(0);
}
}
public Action Command_Cheats(int client, const char[] command, int args)
{
if (!sv_cheats.BoolValue || client == 0)
{
return Plugin_Continue;
}
if (StrContains(command, "kill") != -1 || StrContains(command, "explode") != -1)
{
bool bVector = StrContains(command, "vector") != -1;
bool bKillOther = args > (bVector ? 3 : 0);
if (!bKillOther)
{
return Plugin_Continue;
}
}
if (!(GetUserFlagBits(client) & ADMFLAG_ROOT))
{
return Plugin_Stop;
}
return Plugin_Continue;
}
#endif

View File

@ -0,0 +1,87 @@
/*
* shavit's Timer - area_and_cluster_stages.sp
* by: carnifex
*
* This file is part of shavit's Timer.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
// originally sourced from https://github.com/hermansimensen/mapstages
Address IVEngineServer;
Handle gH_GetCluster;
Handle gH_GetArea;
void LoadDHooks_mapstages(GameData gamedata)
{
StartPrepSDKCall(SDKCall_Static);
if (!PrepSDKCall_SetFromConf(gamedata, SDKConf_Signature, "CreateInterface"))
{
SetFailState("Failed to get CreateInterface");
}
PrepSDKCall_AddParameter(SDKType_String, SDKPass_Pointer);
PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Pointer, VDECODE_FLAG_ALLOWNULL);
PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain);
Handle CreateInterface = EndPrepSDKCall();
if (CreateInterface == null)
{
SetFailState("Unable to prepare SDKCall for CreateInterface");
}
char interfaceName[64];
if (!GameConfGetKeyValue(gamedata, "IVEngineServer", interfaceName, sizeof(interfaceName)))
{
SetFailState("Failed to get IVEngineServer interface name");
}
IVEngineServer = SDKCall(CreateInterface, interfaceName, 0);
if (!IVEngineServer)
{
SetFailState("Failed to get IVEngineServer pointer");
}
StartPrepSDKCall(SDKCall_Raw);
if (!PrepSDKCall_SetFromConf(gamedata, SDKConf_Virtual, "GetClusterForOrigin"))
{
SetFailState("Couldn't find GetClusterForOrigin offset");
}
PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_Plain);
PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain);
gH_GetCluster = EndPrepSDKCall();
StartPrepSDKCall(SDKCall_Raw);
if (!PrepSDKCall_SetFromConf(gamedata, SDKConf_Virtual, "GetArea"))
{
SetFailState("Couldn't find GetArea offset");
}
PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_Plain);
PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain);
gH_GetArea = EndPrepSDKCall();
delete CreateInterface;
}
public int GetClusterForOrigin(const float pos[3])
{
return SDKCall(gH_GetCluster, IVEngineServer, pos);
}
public int GetAreaForOrigin(const float pos[3])
{
return SDKCall(gH_GetArea, IVEngineServer, pos);
}

View File

@ -2,7 +2,8 @@
* Bunnyhop Statistics API - Include file
* by: shavit
*
* This file is part of Bunnyhop Statistics API.
* Originally from Bunnyhop Statistics API (https://github.com/shavitush/bhopstats)
* but edited to be part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
@ -16,21 +17,12 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
*/
#if defined _bhopstats_included
#if defined _shavit_bhopstats_included
#endinput
#endif
#define _bhopstats_included
#define BHOPSTATS_VERSION "1.2.0"
enum CheatType
{
Cheat_HighPerfects = 0,
Cheat_Auto,
Cheat_JumpSpam
}
#define _shavit_bhopstats_included
/**
* Called when the jump key is pressed.
@ -40,7 +32,7 @@ enum CheatType
* @param perfect Was the jump perfectly timed?
* @noreturn
*/
forward void Bunnyhop_OnJumpPressed(int client, bool onground, bool perfect);
forward void Shavit_Bhopstats_OnJumpPressed(int client, bool onground, bool perfect);
/**
* Called when the jump key is released.
@ -49,7 +41,7 @@ forward void Bunnyhop_OnJumpPressed(int client, bool onground, bool perfect);
* @param onground True if the jump key will do anything for the player when tapped.
* @noreturn
*/
forward void Bunnyhop_OnJumpReleased(int client, bool onground);
forward void Shavit_Bhopstats_OnJumpReleased(int client, bool onground);
/**
* Called when the player touches the ground.
@ -57,7 +49,7 @@ forward void Bunnyhop_OnJumpReleased(int client, bool onground);
* @param client Client index.
* @noreturn
*/
forward void Bunnyhop_OnTouchGround(int client);
forward void Shavit_Bhopstats_OnTouchGround(int client);
/**
* Called when the player leaves the ground, by either jumping or falling from somewhere.
@ -70,7 +62,7 @@ forward void Bunnyhop_OnTouchGround(int client);
* @param ladder Did the client leave the ground by leaving a ladder, aka ladderstrafing?
* @noreturn
*/
forward void Bunnyhop_OnLeaveGround(int client, bool jumped, bool ladder);
forward void Shavit_Bhopstats_OnLeaveGround(int client, bool jumped, bool ladder);
/**
* Retrieves the amount of separate +jump inputs since the player left the ground.
@ -78,7 +70,7 @@ forward void Bunnyhop_OnLeaveGround(int client, bool jumped, bool ladder);
* @param client Client index.
* @return Amount of +jump inputs since the left the ground, or 0 if the player is on ground.
*/
native int Bunnyhop_GetScrollCount(int client);
native int Shavit_Bhopstats_GetScrollCount(int client);
/**
* Checks if the player is on ground, or if the jump key will function as in actually triggering a jump or altering velocity.
@ -87,7 +79,7 @@ native int Bunnyhop_GetScrollCount(int client);
* @param client Client index.
* @return Boolean value of 'is the player on ground?'
*/
native bool Bunnyhop_IsOnGround(int client);
native bool Shavit_Bhopstats_IsOnGround(int client);
/**
* Checks if the player is holding his jump key.
@ -95,16 +87,16 @@ native bool Bunnyhop_IsOnGround(int client);
* @param client Client index.
* @return Boolean value of 'is the player holding the jump key?''
*/
native bool Bunnyhop_IsHoldingJump(int client);
native bool Shavit_Bhopstats_IsHoldingJump(int client);
/**
* Gets a percentage of perfectly timed bunnyhops.
* Resets at player connection or the Bunnyhop_ResetPerfectJumps native for it is called.
* Resets at player connection or the Shavit_Bhopstats_ResetPerfectJumps native for it is called.
*
* @param client Client index.
* @return Perfect jump percentage. Results are from 0.0 to 100.0.
*/
native float Bunnyhop_GetPerfectJumps(int client);
native float Shavit_Bhopstats_GetPerfectJumps(int client);
/**
* Resets the perfect jumps percentage of a player back to 0.0.
@ -112,13 +104,13 @@ native float Bunnyhop_GetPerfectJumps(int client);
* @param client Client index.
* @noreturn
*/
native void Bunnyhop_ResetPerfectJumps(int client);
native void Shavit_Bhopstats_ResetPerfectJumps(int client);
methodmap BunnyhopStats __nullable__
methodmap Shavit_BunnyhopStats __nullable__
{
public BunnyhopStats(int client)
public Shavit_BunnyhopStats(int client)
{
return view_as<BunnyhopStats>(client);
return view_as<Shavit_BunnyhopStats>(client);
}
property int index
@ -133,83 +125,72 @@ methodmap BunnyhopStats __nullable__
{
public get()
{
return Bunnyhop_GetScrollCount(this.index);
return Shavit_Bhopstats_GetScrollCount(this.index);
}
}
property bool OnGround
{
{
public get()
{
return Bunnyhop_IsOnGround(this.index);
return Shavit_Bhopstats_IsOnGround(this.index);
}
}
}
property bool HoldingJump
{
{
public get()
{
return Bunnyhop_IsHoldingJump(this.index);
return Shavit_Bhopstats_IsHoldingJump(this.index);
}
}
}
property float PerfectJumps
{
{
public get()
{
return Bunnyhop_GetPerfectJumps(this.index);
return Shavit_Bhopstats_GetPerfectJumps(this.index);
}
}
}
public void ResetPrefects()
{
Bunnyhop_ResetPerfectJumps(this.index);
Shavit_Bhopstats_ResetPerfectJumps(this.index);
}
public static int GetScrollCount(int client)
{
return Bunnyhop_GetScrollCount(client);
}
{
return Shavit_Bhopstats_GetScrollCount(client);
}
public static bool IsOnGround(int client)
{
return Bunnyhop_IsOnGround(client);
}
{
return Shavit_Bhopstats_IsOnGround(client);
}
public static bool IsHoldingJump(int client)
{
return Bunnyhop_IsHoldingJump(client);
}
{
return Shavit_Bhopstats_IsHoldingJump(client);
}
public static float GetPerfectJumps(int client)
{
return Bunnyhop_GetPerfectJumps(client);
}
{
return Shavit_Bhopstats_GetPerfectJumps(client);
}
public static float ResetPrefectJumps(int client)
{
return Bunnyhop_ResetPerfectJumps(client);
}
public static void ResetPrefectJumps(int client)
{
Shavit_Bhopstats_ResetPerfectJumps(client);
}
}
public SharedPlugin __pl_bhopstats =
{
name = "bhopstats",
file = "bhopstats.smx",
#if defined REQUIRE_PLUGIN
required = 1
#else
required = 0
#endif
};
#if !defined REQUIRE_PLUGIN
public void __pl_bhopstats_SetNTVOptional()
public void __pl_shavit_bhopstats_SetNTVOptional()
{
MarkNativeAsOptional("Bunnyhop_GetScrollCount");
MarkNativeAsOptional("Bunnyhop_IsOnGround");
MarkNativeAsOptional("Bunnyhop_IsHoldingJump");
MarkNativeAsOptional("Bunnyhop_GetPerfectJumps");
MarkNativeAsOptional("Bunnyhop_ResetPerfectJumps");
MarkNativeAsOptional("Shavit_Bhopstats_GetScrollCount");
MarkNativeAsOptional("Shavit_Bhopstats_IsOnGround");
MarkNativeAsOptional("Shavit_Bhopstats_IsHoldingJump");
MarkNativeAsOptional("Shavit_Bhopstats_GetPerfectJumps");
MarkNativeAsOptional("Shavit_Bhopstats_ResetPerfectJumps");
}
#endif

View File

@ -0,0 +1,178 @@
/*
* Bunnyhop Statistics API - Plugin
* by: shavit
*
* Originally from Bunnyhop Statistics API (https://github.com/shavitush/bhopstats)
* but edited to be part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#pragma newdecls required
#pragma semicolon 1
bool gB_OnGround[MAXPLAYERS+1];
bool gB_PlayerTouchingGround[MAXPLAYERS+1];
int gI_Scrolls[MAXPLAYERS+1];
int gI_Buttons[MAXPLAYERS+1];
bool gB_JumpHeld[MAXPLAYERS+1];
int gI_Jumps[MAXPLAYERS+1];
int gI_PerfectJumps[MAXPLAYERS+1];
Handle gH_Forwards_OnJumpPressed = null;
Handle gH_Forwards_OnJumpReleased = null;
Handle gH_Forwards_OnTouchGround = null;
Handle gH_Forwards_OnLeaveGround = null;
public void Bhopstats_CreateNatives()
{
CreateNative("Shavit_Bhopstats_GetScrollCount", Native_GetScrollCount);
CreateNative("Shavit_Bhopstats_IsOnGround", Native_IsOnGround);
CreateNative("Shavit_Bhopstats_IsHoldingJump", Native_IsHoldingJump);
CreateNative("Shavit_Bhopstats_GetPerfectJumps", Native_Bhopstats_GetPerfectJumps);
CreateNative("Shavit_Bhopstats_ResetPerfectJumps", Native_ResetPerfectJumps);
}
public void Bhopstats_CreateForwards()
{
gH_Forwards_OnJumpPressed = CreateGlobalForward("Shavit_Bhopstats_OnJumpPressed", ET_Event, Param_Cell, Param_Cell);
gH_Forwards_OnJumpReleased = CreateGlobalForward("Shavit_Bhopstats_OnJumpReleased", ET_Event, Param_Cell, Param_Cell);
gH_Forwards_OnTouchGround = CreateGlobalForward("Shavit_Bhopstats_OnTouchGround", ET_Event, Param_Cell);
gH_Forwards_OnLeaveGround = CreateGlobalForward("Shavit_Bhopstats_OnLeaveGround", ET_Event, Param_Cell, Param_Cell, Param_Cell);
}
public void Bhopstats_OnClientPutInServer(int client)
{
gB_OnGround[client] = false;
gB_PlayerTouchingGround[client] = false;
gI_Scrolls[client] = 0;
gI_Buttons[client] = 0;
gB_JumpHeld[client] = false;
gI_Jumps[client] = 0;
gI_PerfectJumps[client] = 0;
SDKHook(client, SDKHook_PostThinkPost, Bhopstats_PostThinkPost);
}
public int Native_GetScrollCount(Handle handler, int numParams)
{
return gI_Scrolls[GetNativeCell(1)];
}
public int Native_IsOnGround(Handle handler, int numParams)
{
return view_as<int>(gB_OnGround[GetNativeCell(1)]);
}
public int Native_IsHoldingJump(Handle handler, int numParams)
{
return view_as<int>(gI_Buttons[GetNativeCell(1)] & IN_JUMP);
}
public int Native_Bhopstats_GetPerfectJumps(Handle handler, int numParams)
{
int client = GetNativeCell(1);
return view_as<int>((float(gI_PerfectJumps[client]) / gI_Jumps[client]) * 100.0);
}
public int Native_ResetPerfectJumps(Handle handler, int numParams)
{
int client = GetNativeCell(1);
gI_Jumps[client] = 0;
gI_PerfectJumps[client] = 0;
return 0;
}
public void Bhopstats_PostThinkPost(int client)
{
if(!IsPlayerAlive(client))
{
return;
}
int buttons = GetClientButtons(client);
bool bOldOnGround = gB_OnGround[client];
int iGroundEntity;
if (gB_ReplayPlayback && IsFakeClient(client))
{
iGroundEntity = (Shavit_GetReplayEntityFlags(client) & FL_ONGROUND) ? 0 : -1;
}
else
{
iGroundEntity = GetEntPropEnt(client, Prop_Send, "m_hGroundEntity");
}
bool bOnLadder = (GetEntityMoveType(client) == MOVETYPE_LADDER);
gB_OnGround[client] = (iGroundEntity != -1 || GetEntProp(client, Prop_Send, "m_nWaterLevel") >= 2 || bOnLadder);
gB_JumpHeld[client] = (buttons & IN_JUMP && !(gI_Buttons[client] & IN_JUMP));
if(gB_PlayerTouchingGround[client] && gB_OnGround[client])
{
Call_StartForward(gH_Forwards_OnTouchGround);
Call_PushCell(client);
Call_Finish();
gB_PlayerTouchingGround[client] = false;
}
else if(!gB_PlayerTouchingGround[client] && ((gB_JumpHeld[client] && iGroundEntity != -1) || iGroundEntity == -1 || bOnLadder))
{
Call_StartForward(gH_Forwards_OnLeaveGround);
Call_PushCell(client);
Call_PushCell(gB_JumpHeld[client]);
Call_PushCell(bOnLadder);
Call_Finish();
gB_PlayerTouchingGround[client] = true;
gI_Scrolls[client] = 0;
}
if(gB_JumpHeld[client])
{
gI_Scrolls[client]++;
Call_StartForward(gH_Forwards_OnJumpPressed);
Call_PushCell(client);
Call_PushCell(gB_OnGround[client]);
Call_Finish();
if(gB_OnGround[client])
{
gI_Jumps[client]++;
if(!bOldOnGround)
{
gI_PerfectJumps[client]++;
}
}
}
else if(gI_Buttons[client] & IN_JUMP && !(buttons & IN_JUMP))
{
Call_StartForward(gH_Forwards_OnJumpReleased);
Call_PushCell(client);
Call_PushCell(gB_OnGround[client]);
Call_Finish();
}
gI_Buttons[client] = buttons;
}

View File

@ -0,0 +1,84 @@
#if defined _shavit_chat_colors_included
#endinput
#endif
#define _shavit_chat_colors_included
char gS_GlobalColorNames[][] =
{
"{default}",
"{def}",
"{team}",
"{green}"
};
char gS_GlobalColors[][] =
{
"\x01",
"\x01",
"\x03",
"\x04"
};
char gS_CSGOColorNames[][] =
{
"{blue}",
"{bluegrey}",
"{darkblue}",
"{darkred}",
"{gold}",
"{grey}",
"{grey2}",
"{lightgreen}",
"{lightred}",
"{lime}",
"{orchid}",
"{yellow}",
"{palered}"
};
char gS_CSGOColors[][] =
{
"\x0B",
"\x0A",
"\x0C",
"\x02",
"\x10",
"\x08",
"\x0D",
"\x05",
"\x0F",
"\x06",
"\x0E",
"\x09",
"\x07"
};
stock void FormatColors(char[] buffer, int size, bool colors, bool escape, bool csgo, bool funky_chars=true)
{
if(colors)
{
for(int i = 0; i < sizeof(gS_GlobalColorNames); i++)
{
ReplaceString(buffer, size, gS_GlobalColorNames[i], gS_GlobalColors[i]);
}
if(csgo)
{
for(int i = 0; i < sizeof(gS_CSGOColorNames); i++)
{
ReplaceString(buffer, size, gS_CSGOColorNames[i], gS_CSGOColors[i]);
}
}
if (funky_chars) ReplaceString(buffer, size, "^", "\x07");
ReplaceString(buffer, size, "{RGB}", "\x07");
if (funky_chars) ReplaceString(buffer, size, "&", "\x08");
ReplaceString(buffer, size, "{RGBA}", "\x08");
}
if(escape)
{
ReplaceString(buffer, size, "%%", "");
}
}

View File

@ -0,0 +1,54 @@
/*
* shavit's Timer - chat.inc file
* by: rtldg
*
* This file is part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#if defined _shavit_chat_included
#endinput
#endif
#define _shavit_chat_included
/*
* Retrieves the player's chatrank trimmed and without colors.
*
* @param client Client index
* @param buf Buffer to put the put the chatrank into
* @param buflen Size of buf
* @param includename Include {name} in result.
* @noreturn
*/
native void Shavit_GetPlainChatrank(int client, char[] buf, int buflen, bool includename=false);
public SharedPlugin __pl_shavit_chat =
{
name = "shavit-chat",
file = "shavit-chat.smx",
#if defined REQUIRE_PLUGIN
required = 1
#else
required = 0
#endif
};
#if !defined REQUIRE_PLUGIN
public void __pl_shavit_chat_SetNTVOptional()
{
MarkNativeAsOptional("Shavit_GetPlainChatrank");
}
#endif

View File

@ -0,0 +1,344 @@
/*
* shavit's Timer - Checkpoints
* by: shavit, kidfearless, Nairda, GAMMA CASE, rtldg, sh4hrazad, Ciallo-Ani, olivia
*
* This file is part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#if defined _shavit_checkpoints_included
#endinput
#endif
#define _shavit_checkpoints_included
enum struct cp_cache_t
{
float fPosition[3];
float fAngles[3];
float fVelocity[3];
MoveType iMoveType;
float fGravity;
float fSpeed;
float fStamina;
bool bDucked;
bool bDucking;
float fDucktime; // m_flDuckAmount in csgo
float fDuckSpeed; // m_flDuckSpeed in csgo; doesn't exist in css
int iFlags;
timer_snapshot_t aSnapshot;
char sTargetname[64];
char sClassname[64];
ArrayList aFrames;
int iPreFrames;
bool bSegmented;
int iGroundEntity;
int iSteamID;
ArrayList aEvents;
ArrayList aOutputWaits;
float vecLadderNormal[3];
// This handle will be deleted when the checkpoint is deleted, or something like that...
// If you want to keep this (which you probably should) then you'd have
// to use StringMap.Clone() (owned clone) or CloneHandle() (shared object).
StringMap customdata;
bool m_bHasWalkMovedSinceLastJump; // csgo only
float m_ignoreLadderJumpTime; // csgo only
float m_lastStandingPos[3]; // css only
float m_ladderSurpressionTimer[2]; // css only // 0 = duration, 1 = remaining
float m_lastLadderNormal[3]; // css only
float m_lastLadderPos[3]; // css only
// used by player_speedmod
int m_afButtonDisabled;
// used by trigger_playermovement
int m_afButtonForced;
}
/**
* Called when a player will be teleported with checkpoints.
*
* @param client Client index that will be teleported to the checkpoint.
* @param index Checkpoint that was teleported to.
* @param target Target index that owns the checkpoint.
* @return Plugin_Continue to allow teleporting, anything else to prevent.
*/
forward Action Shavit_OnTeleportPre(int client, int index, int target);
/**
* Called when a player has been teleported with checkpoints.
*
* @param client Client index that has been teleported to the checkpoint.
* @param index Checkpoint that was teleported to.
* @param target Target index that owns the checkpoint.
* @return Unused. Use Shavit_OnTeleportPre if you want to block teleporting.
*/
forward Action Shavit_OnTeleport(int client, int index, int target);
/**
* Called when a player is saving a checkpoint.
*
* @param client Client index.
* @param index Checkpoint that was saved to.
* @param overflow Does this checkpoint shift the rest.
* @param duplicate Whether the checkpoint to be saved is a duplicate of others
* @return Plugin_Continue to allow saving, anything else to prevent.
*/
forward Action Shavit_OnSavePre(int client, int index, bool overflow, bool duplicate);
/**
* Called when a player has saved a checkpoint.
*
* @param client Client index.
* @param index Checkpoint that was saved to.
* @param overflow Does this checkpoint shift the rest.
* @param duplicate Whether the checkpoint that has been saved is a duplicate of others
* @return Unused. Use Shavit_OnSavePre if you want to block checkpoint saving.
*/
forward Action Shavit_OnSave(int client, int index, bool overflow, bool duplicate);
/**
* Called when a player deletes a checkpoint.
*
* @param client Client index.
* @param index Checkpoint that will be deleted.
* @param cleared Whether the checkpoint is being deleted due to all the checkpoints being cleared/reset.
The return value CANNOT be used to block deletion of these.
*
* @return Plugin_Continue to continue deletion, anything else to prevent.
*/
forward Action Shavit_OnDelete(int client, int index, bool cleared);
/**
* Called after the checkpoint menu has been made and before it's sent to the client.
*
* @param client Client index.
* @param segmented If the menu was a segmented menu
* @param menu Handle to the menu so you can .AddItem().
* @return Plugin_Handled or Plugin_Stop to stop the menu.
*/
forward Action Shavit_OnCheckpointMenuMade(int client, bool segmented, Menu menu);
/**
* Called before a selection is processed in the main checkpoint menu.
*
* @param client Client index who selects in the menu
* @param param2 Second parameter in the callback, usually the item selected.
* @param info reference copy of the info string used in the callback
* @param maxlength length of the info buffer
* @param currentCheckpoint Clients current checkpoint selected
* @param maxCPs Max checkpoints the client can use
* @param owner Client index who owns the current checkpoint
* @return Plugin_Continue to continue the callback. Return Plugin_Stop to prevent the checkpoints menu from reopening.
*/
forward Action Shavit_OnCheckpointMenuSelect(int client, int param2, char[] info, int maxlength, int currentCheckpoint, int maxCPs, int owner);
/**
* Called when a checkpoint cache is saved.
*
* @param client The client the checkpoint cache is being saved for.
* @param cache The resulting checkpoint cache structure.
* @param index The resulting checkpoint index for this checkpoint cache. -1 if the cache is being saved as "persistent data" for rejoins/spectating. 0 if not being saved to checkpoints list.
* @param target The target of the checkpoint cache.
*
* @noreturn
*/
forward void Shavit_OnCheckpointCacheSaved(int client, cp_cache_t cache, int index, int target);
/**
* Called when a checkpoint cache is being loaded.
*
* @param client The client who is loading the checkpoint cache.
* @param cache The cache.
* @param index The checkpoint index for this cache. -1 if the cache is being loaded from "persistent data" for rejoins/spectating. 0 if the cache is being loaded usually by Shavit_LoadCheckpointCache().
*
* @noreturn
*/
forward void Shavit_OnCheckpointCacheLoaded(int client, cp_cache_t cache, int index);
/**
* Gets the total number of CPs that a client has saved
*
* @param client Client index
*
* @return Total number of checkpoints
*/
native int Shavit_GetTotalCheckpoints(int client);
/**
* Gets CP data for a client at specified index
*
* @param client Client index
* @param index Index of CP to get
* @param cpcache Buffer to store cp data in sizeof(cp_cache_t)
* @param size Size of the cpcache buffer, e.g sizeof(cp_cache_t)
*
* @noreturn
*/
native bool Shavit_GetCheckpoint(int client, int index, any[] cpcache, int size = sizeof(cp_cache_t));
/**
* Sets checkpoint data at the given index for the given client
*
* @param client Client index
* @param index Index of CP to set, or -1 to push cp as last. 0 to push cp to first without erasing.
* @param cpcache Buffer to store cp data in sizeof(cp_cache_t)
* @param size Size of the cpcache buffer, e.g sizeof(cp_cache_t)
* @param cheapCloneHandle False means we duplicate aFrames, aEvents, and aOutputWaits (ArrayList.Clone). True means we clone the handle (CloneHandle).
*
* @noreturn
*/
native void Shavit_SetCheckpoint(int client, int index, any[] cpcache, int size = sizeof(cp_cache_t), bool cheapCloneHandle=true);
/**
* Teleports client to the checkpoint at given target and index
*
* @param client Client index to be teleported
* @param index Index of CP to teleport to
* @param suppress Supress checkpoint message
* @param target Player index that owns the checkpoint. 0 to use the client variable.
*
* @noreturn
*/
native void Shavit_TeleportToCheckpoint(int client, int index, bool suppress = false, int target=0);
/**
* Clears all saved checkpoints for the specified client
*
* @param client Client index
*
* @noreturn
*/
native void Shavit_ClearCheckpoints(int client);
/**
* Saves a new checkpoint and returns the new checkpoint index
*
* @param client Client index
*
* @return The new current checkpoint
*/
native int Shavit_SaveCheckpoint(int client);
/**
* Gets the current checkpoint index.
*
* @param client Client index
*
* @return The current checkpoint
*/
native int Shavit_GetCurrentCheckpoint(int client);
/**
* Sets the current checkpoint index.
*
* @param client Client index
* @param index New index to use
*
* @noreturn
*/
native void Shavit_SetCurrentCheckpoint(int client, int index);
/**
* Gets how many times the client has teleported to checkpoints.
*
* @param client Client index
*
* @return The number of times the client has teleported to checkpoints.
*/
native int Shavit_GetTimesTeleported(int client);
/**
* Sets the number of times the client has teleported to checkpoints.
* This is useful to have if you intend to implement a plugin to save "persistent data" between map changes".
*
* @param client Client index
* @param count Teleport count
* @noreturn
*/
native void Shavit_SetTimesTeleported(int client, int count);
/**
* Checks whether the client has savestate data.
*
* @param client Client index
*
* @return Whether a savestate or rejoin-savestate data exists for the client.
*/
native bool Shavit_HasSavestate(int client);
/**
* Loads a cp_cache_t on a player. AKA teleports players.
*
* @param client Client index
* @param cache Input cp_cache_t
* @param index -1 if you want the cp_cache_t to be loaded as "persistent data". 0 if not. greater-than-zero if you know what you're doing and intentionally want to spoof the cp_cache_t as a checkpoint index for some reason... I recommend looking at shavit-checkpoints.sp to see how "index" and "isPersistentData" are used to see what kind of difference there is.
* @param size sizeof(cp_cache_t) to mostly ensure the calling plugin has a matching cp_cache_t.
* @param force Forcibly load the cp_cache_t without checking the style access for a player.
*
* @return Returns whether the checkpoint cache was able to be loaded.
*/
native bool Shavit_LoadCheckpointCache(int client, any[] cache, int index, int size = sizeof(cp_cache_t), bool force = false);
/**
* Saves a cp_cache_t from a player.
*
* @param saver The client saving the checkpoint.
* @param target The target the checkpoint cache is being saved from.
* @param cache Output cp_cache_t
* @param index -1 if you want the cp_cache_t to be saved as "persistent data". 0 if not. greater-than-zero if you what you're doing and intentionally want to spoof the cp_cache_t creation as a checkpoint index for some reason... I recommend looking at shavit-checkpoints.sp to see how "index" and "isPersistentData" are used to see what kind of difference there is.
* @param size sizeof(cp_cache_t) to mostly ensure the calling plugin has a matching cp_cache_t.
* @param saveReplay Whether or not replay frames will be saved.
*
* @noreturn
*/
native void Shavit_SaveCheckpointCache(int saver, int target, any[] cache, int index, int size = sizeof(cp_cache_t), bool saveReplay = false);
public SharedPlugin __pl_shavit_checkpoints =
{
name = "shavit-checkpoints",
file = "shavit-checkpoints.smx",
#if defined REQUIRE_PLUGIN
required = 1
#else
required = 0
#endif
};
#if !defined REQUIRE_PLUGIN
public void __pl_shavit_checkpoints_SetNTVOptional()
{
MarkNativeAsOptional("Shavit_GetTotalCheckpoints");
MarkNativeAsOptional("Shavit_GetCheckpoint");
MarkNativeAsOptional("Shavit_SetCheckpoint");
MarkNativeAsOptional("Shavit_TeleportToCheckpoint");
MarkNativeAsOptional("Shavit_ClearCheckpoints");
MarkNativeAsOptional("Shavit_SaveCheckpoint");
MarkNativeAsOptional("Shavit_GetCurrentCheckpoint");
MarkNativeAsOptional("Shavit_SetCurrentCheckpoint");
MarkNativeAsOptional("Shavit_GetTimesTeleported");
MarkNativeAsOptional("Shavit_SetTimesTeleported");
MarkNativeAsOptional("Shavit_HasSavestate");
MarkNativeAsOptional("Shavit_LoadCheckpointCache");
MarkNativeAsOptional("Shavit_SaveCheckpointCache");
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,254 @@
/*
* shavit's Timer - hud.inc file
* by: shavit
*
* This file is part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#if defined _shavit_hud_included
#endinput
#endif
#define _shavit_hud_included
#define HUD_NONE 0
#define HUD_MASTER (1 << 0) // master setting
#define HUD_CENTER (1 << 1) // show hud as hint text
#define HUD_ZONEHUD (1 << 2) // show start/end zone hud
#define HUD_OBSERVE (1 << 3) // show the HUD of the player you spectate
#define HUD_SPECTATORS (1 << 4) // show list of spectators
#define HUD_KEYOVERLAY (1 << 5) // show a key overlay
#define HUD_HIDEWEAPON (1 << 6) // hide the player's weapon
#define HUD_TOPLEFT (1 << 7) // show top left white HUD with WR/PB times
#define HUD_SYNC (1 << 8) // shows sync at right side of the screen (css only)
#define HUD_TIMELEFT (1 << 9) // shows time left at right tside of the screen (css only)
#define HUD_2DVEL (1 << 10) // shows 2d velocity
#define HUD_NOSOUNDS (1 << 11) // disables sounds on personal best, world record etc
#define HUD_NOPRACALERT (1 << 12) // hides practice mode chat alert
#define HUD_USP (1 << 13) // makes you spawn with a USP
#define HUD_GLOCK (1 << 14) // makes you spawn with a Glock
#define HUD_DEBUGTARGETNAME (1 << 15) // admin option to show current targetname & classname
#define HUD_SPECTATORSDEAD (1 << 16) // for only showing spectators list when you're dead/spectating.
#define HUD_PERFS_CENTER (1 << 17) // for the perf percentage in the center hud. e.g. "Jumps: 20 (66.6%)"
// HUD2 - these settings will *disable* elements for the main hud
#define HUD2_TIME (1 << 0)
#define HUD2_SPEED (1 << 1)
#define HUD2_JUMPS (1 << 2)
#define HUD2_STRAFE (1 << 3)
#define HUD2_SYNC (1 << 4)
#define HUD2_STYLE (1 << 5)
#define HUD2_RANK (1 << 6)
#define HUD2_TRACK (1 << 7)
#define HUD2_SPLITPB (1 << 8)
#define HUD2_MAPTIER (1 << 9)
#define HUD2_TIMEDIFFERENCE (1 << 10)
#define HUD2_PERFS (1 << 11)
#define HUD2_TOPLEFT_RANK (1 << 12)
#define HUD2_VELOCITYDIFFERENCE (1 << 13)
#define HUD2_USPSILENCER (1 << 14) // spawns usps with a silencer on
#define HUD2_GLOCKBURST (1 << 15) // spawns glocks with burst
#define HUD2_CENTERKEYS (1 << 16) // CSGO option to toggle whether !keys is shown as center-text or in that panel thing.
#define HUD_DEFAULT (HUD_MASTER|HUD_CENTER|HUD_ZONEHUD|HUD_OBSERVE|HUD_TOPLEFT|HUD_SYNC|HUD_TIMELEFT|HUD_2DVEL|HUD_SPECTATORS)
#define HUD_DEFAULT2 (HUD2_PERFS)
stock bool HUD1Enabled(int hudbits, int flag)
{
return (hudbits & flag) != 0;
}
stock bool HUD2Enabled(int hudbits, int flag)
{
return (hudbits & flag) == 0;
}
enum ZoneHUD
{
ZoneHUD_None,
ZoneHUD_Start,
ZoneHUD_End
};
enum struct huddata_t
{
int iTarget;
float fTime;
int iSpeed;
int iStyle;
int iTrack;
int iJumps;
int iStrafes;
int iRank;
float fSync;
float fPB;
float fWR;
bool bReplay;
bool bPractice;
TimerStatus iTimerStatus;
ZoneHUD iZoneHUD;
int iHUDSettings;
int iHUD2Settings;
int iPreviousSpeed;
float fClosestReplayTime;
float fClosestVelocityDifference;
int iMapTier;
float fClosestReplayLength;
int iButtons;
int iScrolls;
int iScrollsPrev;
float fAngleDiff;
}
/**
* Called when top left HUD updates.
*
* @param client Client index that recieves the hud.
* @param target Target entity that is either the client or what the client is spectating.
* @param topleft Reference to the HUD buffer.
* @param topleftlength Max length of the topleft buffer.
* @param track Target's track.
* @param style Target's style.
*
* @return Plugin_Handled or Plugin_Stop to block the HUD message from appearing. Anything else to pass along new values.
*/
forward Action Shavit_OnTopLeftHUD(int client, int target, char[] topleft, int topleftlength, int track, int style);
/**
* Called before the top left HUD updates and used to build the string for shavit-hud.
*
* @param client Client index that recieves the hud.
* @param target Target entity that is either the client or what the client is spectating.
* @param topleft Reference to the HUD buffer.
* @param topleftlength Max length of the topleft buffer.
* @param track Target's track.
* @param style Target's style.
* @param forceUpdate Force even if the client has disabled HUD_TOPLEFT.
*
* @return Plugin_Handled or Plugin_Stop to block the HUD message from appearing. Plugin_Changed to use own topleft string instead of shavit-hud building it.
*/
forward Action Shavit_PreOnTopLeftHUD(int client, int target, char[] topleft, int topleftlength, int track, int style, bool &forceUpdate);
/**
* Called when key hint (bottom left) HUD updates (Source 2013 only).
*
* @param client Client index that recieves the hud.
* @param target Target entity that is either the client or what the client is spectating.
* @param keyhint Reference to the HUD buffer.
* @param keyhintlength Max length of the keyhint buffer.
* @param track Target's track.
* @param style Target's style.
*
* @return Plugin_Handled or Plugin_Stop to block the HUD message from appearing. Anything else to pass along new values.
*/
forward Action Shavit_OnKeyHintHUD(int client, int target, char[] keyhint, int keyhintlength, int track, int style);
/**
* Called before the key hint HUD (bottom left) updates and used to build the string for shavit-hud (Source 2013 only).
*
* @param client Client index that recieves the hud.
* @param target Target entity that is either the client or what the client is spectating.
* @param keyhint Reference to the HUD buffer.
* @param keyhintlength Max length of the keyhint buffer.
* @param track Target's track.
* @param style Target's style.
* @param forceUpdate Force even if the client has disabled HUD_SYNC, HUD_TIMELEFT, and HUD2_PERFS.
*
* @return Plugin_Handled or Plugin_Stop to block the HUD message from appearing. Plugin_Changed to use own keyhint string instead of shavit-hud building it.
*/
forward Action Shavit_PreOnKeyHintHUD(int client, int target, char[] keyhint, int keyhintlength, int track, int style, bool &forceUpdate);
/**
* Called before the center hud updates.
*
* @param client Client index that recieves the hud.
* @param target Target entity that is either the client or what the client is spectating.
* @param buffer Reference to the HUD buffer.
* @param buflen Max length of the buffer.
* @param data huddata_t which contains target info.
*
* @return Plugin_Handled or Plugin_Stop to block the HUD message from appearing. Plugin_Changed if you modify the buffer string.
*/
forward Action Shavit_PreOnDrawCenterHUD(int client, int target, char[] buffer, int buflen, huddata_t data);
/**
* Called before the !keys hud updates.
*
* @param client Client index that recieves the hud.
* @param target Target entity that is either the client or what the client is spectating.
* @param style The target's style.
* @param buttons The target's buttons.
* @param anglediff The difference from the target's last angles and current angles.
* @param buffer Reference to the HUD buffer.
* @param buflen Max length of the buffer.
* @param scrolls How many scrolls the player has so far (relevant for non-auto styles).
* @param prevscrolls How many scrolls previously.
* @param alternate_center_keys True when you should draw a Linux-specific format since fonts & alignment are different.
*
* @return Plugin_Handled or Plugin_Stop to block the HUD message from appearing. Plugin_Changed if you modify the buffer string.
*/
forward Action Shavit_PreOnDrawKeysHUD(int client, int target, int style, int buttons, float anglediff, char[] buffer, int buflen, int scrolls, int prevscrolls, bool alternate_center_keys);
/**
* Force an HUD update for a player. Requires shavit-hud.
*
* @param client Client index.
* @param spectators Should also update it for the player's spectators?
* @error Error code 200 if client isn't valid.
* @return Amount of players that had their HUD updated (client + spectators) or -1 on error.
*/
native int Shavit_ForceHUDUpdate(int client, bool spectators);
/**
* Gets the HUD settings of a player.
* See the HUD_* defines for information.
*
* @param client Client index.
* @return HUD settings.
*/
native int Shavit_GetHUDSettings(int client);
/**
* Gets the HUD2 settings of a player.
* See the HUD2_* defines for information.
*
* @param client Client index.
* @return HUD settings.
*/
native int Shavit_GetHUD2Settings(int client);
public SharedPlugin __pl_shavit_hud =
{
name = "shavit-hud",
file = "shavit-hud.smx",
#if defined REQUIRE_PLUGIN
required = 1
#else
required = 0
#endif
};
#if !defined REQUIRE_PLUGIN
public void __pl_shavit_hud_SetNTVOptional()
{
MarkNativeAsOptional("Shavit_ForceHUDUpdate");
MarkNativeAsOptional("Shavit_GetHUDSettings");
MarkNativeAsOptional("Shavit_GetHUD2Settings");
}
#endif

View File

@ -0,0 +1,84 @@
/*
* shavit's Timer - mapchooser.inc file
* by: SlidyBat, KiD Fearless, mbhound, rtldg
*
* This file is part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#if defined _shavit_mapchooser_included
#endinput
#endif
#define _shavit_mapchooser_included
/**
* Called when a player RTV's.
* Requires shavit-mapchooser.
*
* @param client Client index.
* @noreturn
*/
forward void SMC_OnRTV(int client);
/**
* Called when a player UNRTV's.
* Requires shavit-mapchooser.
*
* @param client Client index.
* @noreturn
*/
forward void SMC_OnUnRTV(int client);
/**
* Called when the map changes from an RTV.
* Requires shavit-mapchooser.
*
* @noreturn
*/
forward void SMC_OnSuccesfulRTV();
/**
* Returns the ArrayList of maps currently on rotation.
*
* @return The ArrayList of Maps. Don't delete this handle.
*/
native ArrayList Shavit_GetMapsArrayList();
/**
* Returns the StringMap of maps currently on rotation.
*
* @return the StringMap of maps. Don't delete this handle.
*/
native StringMap Shavit_GetMapsStringMap();
public SharedPlugin __pl_shavit_mapchooser =
{
name = "shavit-mapchooser",
file = "shavit-mapchooser.smx",
#if defined REQUIRE_PLUGIN
required = 1
#else
required = 0
#endif
};
#if !defined REQUIRE_PLUGIN
public void __pl_shavit_mapchooser_SetNTVOptional()
{
MarkNativeAsOptional("Shavit_GetMapsArrayList");
MarkNativeAsOptional("Shavit_GetMapsStringMap");
}
#endif

View File

@ -0,0 +1,254 @@
/*
* shavit's Timer - maps-folder-stocks.inc file
* by: rtldg, kidfearless
*
* This file is part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#if defined _shavit_mapsfolderstocks_included
#endinput
#endif
#define _shavit_mapsfolderstocks_included
stock bool WriteNavMesh(const char[] map, bool skipExistsCheck = false)
{
char sTempMap[PLATFORM_MAX_PATH];
FormatEx(sTempMap, PLATFORM_MAX_PATH, "maps/%s.nav", map);
if (skipExistsCheck || !FileExists(sTempMap))
{
File file = OpenFile(sTempMap, "wb");
if (file != null)
{
int zero[1];
static int defaultNavMesh[51] = {
-17958194, 16, 1, 128600, 16777217, 1, 1, 0, -1007845376, 1112014848, 1107304447, -1035468800,
1139638272, 1107304447, 1107304447, 1107304447, 0, 0, 0, 0, 4, -415236096, 2046820547, 2096962,
65858, 0, 49786, 536822394, 33636864, 0, 12745216, -12327104, 21102623, 3, -1008254976, 1139228672,
1107304447, 1, 0, 0, 0, 4386816, 4386816, 4161536, 4161536, 4161536, 20938752, 16777216, 33554432, 0, 0
};
file.Write(defaultNavMesh, sizeof(defaultNavMesh), 4);
file.Write(zero, 1, 1);
delete file;
}
return true;
}
return false;
}
stock bool WriteNavMeshBz2(const char[] map, bool skipExistsCheck = false)
{
char sTempMap[PLATFORM_MAX_PATH];
FormatEx(sTempMap, PLATFORM_MAX_PATH, "maps/%s.nav.bz2", map);
if (skipExistsCheck || !FileExists(sTempMap))
{
File file = OpenFile(sTempMap, "wb");
if (file != null)
{
static int defaultNavMeshBz2[132/4] = {
0x39685A42, 0x26594131, 0xB8955953, 0x0000B354,
0xFEC56E4E, 0x80004004, 0x0040D800, 0x40100040,
0x00011800, 0xA0114182, 0xA7127200, 0x915133AA,
0x04B501A0, 0x64A03285, 0x31190D0D, 0x96F2A658,
0x864651CE, 0xA93468D3, 0xD269C634, 0x66EE82B6,
0x3B1D4103, 0xD4BE309C, 0x58DF5463, 0xC0076E1B,
0x346C6DC1, 0x8B9FD47B, 0x0385015D, 0x3B260D99,
0xF43C28F0, 0xD071CFB3, 0xC95DFC92, 0x4242E114,
0xCC52E156
};
file.Write(defaultNavMeshBz2, sizeof(defaultNavMeshBz2), 4);
delete file;
}
return true;
}
return false;
}
stock void CreateAllNavFiles()
{
StringMap mapList = new StringMap();
DirectoryListing dir = OpenDirectory("maps", true);
if (dir == null)
{
return;
}
char fileName[PLATFORM_MAX_PATH];
FileType type;
// Loop through maps folder.
// If .bsp, mark as need .nav
// If .nav, mark as have .nav
while (dir.GetNext(fileName, sizeof(fileName), type))
{
if (type != FileType_File)
{
continue;
}
int length = strlen(fileName);
if (length < 5 || fileName[length-4] != '.') // a.bsp
{
continue;
}
if (fileName[length-3] == 'b' && fileName[length-2] == 's' && fileName[length-1] == 'p')
{
fileName[length-4] = 0;
mapList.SetValue(fileName, false, false); // note: false for 'replace'
}
else if (fileName[length-3] == 'n' && fileName[length-2] == 'a' && fileName[length-1] == 'v')
{
fileName[length-4] = 0;
mapList.SetValue(fileName, true, true); // note: true for 'replace'
}
}
delete dir;
// StringMap shenanigans are used so we don't call FileExists() 2000 times
StringMapSnapshot snapshot = mapList.Snapshot();
for (int i = 0; i < snapshot.Length; i++)
{
snapshot.GetKey(i, fileName, sizeof(fileName));
bool hasNAV = false;
mapList.GetValue(fileName, hasNAV);
if (!hasNAV)
{
WriteNavMesh(fileName, true);
}
}
delete snapshot;
delete mapList;
}
stock bool ReadMapsFolderHandler(const char path[PLATFORM_MAX_PATH], bool is_stringmap, Handle data, bool lowercase, bool display, bool iter_subfolders, bool use_valve_fs, char[][] exclude_prefixes, int exclude_count)
{
bool first_iteration = StrEqual(path, "maps");
DirectoryListing dir = OpenDirectory(path, use_valve_fs, NULL_STRING);
if (dir == null)
{
return false;
}
char buffer[PLATFORM_MAX_PATH];
FileType type;
while (dir.GetNext(buffer, sizeof(buffer), type))
{
if (type == FileType_Directory)
{
if (buffer[0] == '.' && (buffer[1] == 0 || (buffer[1] == '.' && buffer[2] == 0)))
{
continue;
}
if (iter_subfolders)
{
char subfolder[PLATFORM_MAX_PATH];
FormatEx(subfolder, sizeof(subfolder), "%s/%s", path, buffer);
ReadMapsFolderHandler(subfolder, is_stringmap, data, lowercase, display, iter_subfolders, use_valve_fs, exclude_prefixes, exclude_count);
}
}
else if (type == FileType_File)
{
int length = strlen(buffer);
if (length < 5 || buffer[length-4] != '.') // a.bsp
{
continue;
}
if ((buffer[length-3] == 'b' && buffer[length-2] == 's' && buffer[length-1] == 'p') ||
(buffer[length-3] == 'u' && buffer[length-2] == 'g' && buffer[length-1] == 'c'))
{
buffer[length-4] = 0;
if (lowercase)
{
LowercaseString(buffer);
}
bool skip = false;
for (int i = 0; i < exclude_count; i++)
{
if (strncmp(buffer, exclude_prefixes[i], strlen(exclude_prefixes[i]), lowercase) == 0)
{
skip = true;
break;
}
}
if (skip)
{
continue;
}
if (!display && !first_iteration)
{
char temp[PLATFORM_MAX_PATH];
int skip_this = 5; // strlen("maps/")
FormatEx(temp, sizeof(temp), "%s/%s", path[skip_this], buffer);
buffer = temp;
}
if (is_stringmap)
{
view_as<StringMap>(data).SetValue(buffer, false, false);
}
else
{
view_as<ArrayList>(data).PushString(buffer);
}
}
}
}
delete dir;
return true;
}
static char empty_excludes[][] = {""};
stock bool ReadMapsFolderStringMap(StringMap data, bool lowercase=true, bool display=false, bool iter_subfolders=true, bool use_valve_fs=true, char[][] exclude_prefixes=empty_excludes, int exclude_count=0)
{
return ReadMapsFolderHandler("maps", true, data, lowercase, display, iter_subfolders, use_valve_fs, exclude_prefixes, exclude_count);
}
// don't forget to declare your ArrayList like below :)))
//// ArrayList maps = new ArrayList(ByteCountToCells(PLATFORM_MAX_PATH));
stock bool ReadMapsFolderArrayList(ArrayList data, bool lowercase=true, bool display=false, bool iter_subfolders=true, bool use_valve_fs=true, char[][] exclude_prefixes=empty_excludes, int exclude_count=0)
{
return ReadMapsFolderHandler("maps", false, data, lowercase, display, iter_subfolders, use_valve_fs, exclude_prefixes, exclude_count);
}

View File

@ -0,0 +1,71 @@
/*
* shavit's Timer - misc.inc file
* by: EvanIMK, rtldg
*
* This file is part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#if defined _shavit_misc_included
#endinput
#endif
#define _shavit_misc_included
/**
* Checks if a player is hiding players
*
* @param client Client index.
* @return Boolean value.
*/
native bool Shavit_IsClientUsingHide(int client);
/**
* Called before clan tag variables are processed.
*
* @param client Client index.
* @param clantag Reference to the clan tag buffer.
* @param clantaglength Max length of the customtag buffer.
* @return Plugin_Handled or Plugin_Stop to block the clan tag from changing. Anything else to pass along new values.
*/
forward Action Shavit_OnClanTagChangePre(int client, char[] clantag, int clantaglength);
/**
* Called after clan tags are changed.
*
* @param client Client index.
* @param customtag Reference to the custom clan tag buffer.
* @param customtaglength Max length of the customtag buffer.
* @noreturn
*/
forward void Shavit_OnClanTagChangePost(int client, char[] customtag, int customtaglength);
public SharedPlugin __pl_shavit_misc =
{
name = "shavit-misc",
file = "shavit-misc.smx",
#if defined REQUIRE_PLUGIN
required = 1
#else
required = 0
#endif
};
#if !defined REQUIRE_PLUGIN
public void __pl_shavit_misc_SetNTVOptional()
{
MarkNativeAsOptional("Shavit_IsClientUsingHide");
}
#endif

View File

@ -0,0 +1,56 @@
/*
* physicsuntouch.inc
* by: rumour
*
* Originally from EndTouch Fix (https://github.com/rumourA/End-Touch-Fix)
* but edited to be part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#if defined _physicuntouch_included
#endinput
#endif
#define _physicuntouch_included
#define EFL_CHECK_UNTOUCH (1<<24)
Handle gH_PhysicsCheckForEntityUntouch;
stock void LoadPhysicsUntouch(Handle gamedata)
{
StartPrepSDKCall(SDKCall_Entity);
if (!PrepSDKCall_SetFromConf(gamedata, SDKConf_Signature, "PhysicsCheckForEntityUntouch"))
{
SetFailState("Failed to get PhysicsCheckForEntityUntouch");
}
gH_PhysicsCheckForEntityUntouch = EndPrepSDKCall();
}
stock bool GetCheckUntouch(int client)
{
int flags = GetEntProp(client, Prop_Data, "m_iEFlags");
return (flags & EFL_CHECK_UNTOUCH) != 0;
}
stock void MaybeDoPhysicsUntouch(int client)
{
if (GetCheckUntouch(client))
{
SDKCall(gH_PhysicsCheckForEntityUntouch, client);
}
}

View File

@ -0,0 +1,175 @@
/*
* shavit's Timer - rankings.inc file
* by: shavit
*
* This file is part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#if defined _shavit_rankings_included
#endinput
#endif
#define _shavit_rankings_included
/**
* Gets called when a map's tier is assigned.
* Only called once per map, if the rankings plugin is enabled.
* The exception is if the admin changes the current map's tier.
*
* @param map Map display name.
* @param tier Map's tier.
* @noreturn
*/
forward void Shavit_OnTierAssigned(const char[] map, int tier);
/**
* Gets called when the server acknowledges the client's ranking status.
* It is called after OnClientPostAdminCheck and at forced rank recalculations.
*
* @param client Client index.
* @param rank Client's rank. (0 if unranked or unassigned)
* @param points Client's points. (0.0 if unranked or unassigned)
* @param first True if the forward is called after the initial connection, false if it is caused by recalculation.
* @noreturn
*/
forward void Shavit_OnRankAssigned(int client, int rank, float points, bool first);
/**
* Gets the map tier for a specified map.
* Use the map's display name.
*
* @param map Map to get the tier of. Using "" will get the current map's tier.
* @return Map tier. 0 if no results were found.
*/
native int Shavit_GetMapTier(const char[] map = "");
/**
* Gets a StringMap that contains all the cached map tiers.
* The returned StringMap must be deleted from memory after use!
*
* @return StringMap with {const char[]: map, int: tier} structure.
*/
native StringMap Shavit_GetMapTiers();
/**
* Gets player points.
*
* @param client Client index.
* @return Points. 0.0 if unranked.
*/
native float Shavit_GetPoints(int client);
/**
* Gets player rank.
*
* @param client Client index.
* @return Rank. 0 if unranked.
*/
native int Shavit_GetRank(int client);
/**
* Gets the amount of players with over 0 points.
*
* @return Amount of ranked players.
*/
native int Shavit_GetRankedPlayers();
/**
* Deletes tier setting for the specified map.
* Points recalculation will run right after this is finished.
*
* @param map Map name.
* @noreturn
*/
native void Shavit_Rankings_DeleteMap(const char[] map);
/**
* Retrieves the amount of #1 records a player has.
* Requires shavit-rankings.
*
* @param client Client index.
* @param track Track to retrieve WRs from. -1 to use all tracks. All bonus tracks are combined.
* @param style Style to retrieve WRs from. -1 to use all styles.
* @param usecvars Whether to depend on the value of `shavit_stats_mvprankones` and `shavit_stats_mvprankones_maintrack`.
* @return The number of WRs.
*/
native int Shavit_GetWRCount(int client, int track = -1, int style = -1, bool usecvars = true);
/**
* Retrieves the number of players who hold #1 records.
* Requires shavit-rankings.
*
* @param track Track to retrieve WRs from. -1 to use all tracks. All bonus tracks are combined.
* @param style Style to retrieve WRs from. -1 to use all styles.
* @param usecvars Whether to depend on the value of `shavit_stats_mvprankones` and `shavit_stats_mvprankones_maintrack`.
* @return The number of WR holders. 0 if none.
*/
native int Shavit_GetWRHolders(int track = -1, int style = -1, bool usecvars = true);
/**
* Retrieves the player's rank based on how many #1 records they hold.
* Requires shavit-rankings.
* Only works with MySQL 8.0+ or with MariaDB 10.2+.
*
* @param client Client index.
* @param track Track to retrieve WRs from. -1 to use all tracks. All bonus tracks are combined.
* @param style Style to retrieve WRs from. -1 to use all styles.
* @param usecvars Whether to depend on the value of `shavit_stats_mvprankones` and `shavit_stats_mvprankones_maintrack`.
* @return The rank. 0 if none, or not supported.
*/
native int Shavit_GetWRHolderRank(int client, int track = -1, int style = -1, bool usecvars = true);
/*
* Calculates how many points a time will give.
* Used to minimize number of SQL queries.
* Requires shavit-rankings.
*
* @param track The track the time is from.
* @param style The style the time is from.
* @param tier The map tier. -1 to use the current map's tier.
* @param time The time you want to calculate the points for.
* @param wr WR.
*
* @return The number of points the time would give.
*/
native float Shavit_GuessPointsForTime(int track, int style, int tier, float time, float wr);
public SharedPlugin __pl_shavit_rankings =
{
name = "shavit-rankings",
file = "shavit-rankings.smx",
#if defined REQUIRE_PLUGIN
required = 1
#else
required = 0
#endif
};
#if !defined REQUIRE_PLUGIN
public void __pl_shavit_rankings_SetNTVOptional()
{
MarkNativeAsOptional("Shavit_GetMapTier");
MarkNativeAsOptional("Shavit_GetMapTiers");
MarkNativeAsOptional("Shavit_GetPoints");
MarkNativeAsOptional("Shavit_GetRank");
MarkNativeAsOptional("Shavit_GetRankedPlayers");
MarkNativeAsOptional("Shavit_Rankings_DeleteMap");
MarkNativeAsOptional("Shavit_GetWRCount");
MarkNativeAsOptional("Shavit_GetWRHolders");
MarkNativeAsOptional("Shavit_GetWRHolderRank");
MarkNativeAsOptional("Shavit_GuessPointsForTime");
}
#endif

View File

@ -0,0 +1,429 @@
/*
* shavit's Timer - replay file stocks & format
* by: shavit, rtldg, KiD Fearless, carnifex, Nairda, EvanIMK
*
* This file is part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#if defined _shavit_replay_file_included
#endinput
#endif
#define _shavit_replay_file_included
// History of REPLAY_FORMAT_SUBVERSION:
// 0x01: standard origin[3], angles[2], and buttons
// 0x02: flags added movetype added
// 0x03: integrity stuff: style, track, and map added to header. preframe count added (unimplemented until later though)
// 0x04: steamid/accountid written as a 32-bit int instead of a string
// 0x05: postframes & fTickrate added
// 0x06: mousexy and vel added
// 0x07: fixed iFrameCount because postframes were included in the value when they shouldn't be
// 0x08: added zone-offsets to header
// 0x09: bumped with no actual file changes because time calculation in regards to offsets have been changed/fixed since it seems to have been using the end-zone-offset incorrectly (and should now be fine hopefully since 2021-12-21 / a146b51fb16febf1847657fba7ef9e0c056d7476)
#define REPLAY_FORMAT_V2 "{SHAVITREPLAYFORMAT}{V2}"
#define REPLAY_FORMAT_FINAL "{SHAVITREPLAYFORMAT}{FINAL}"
#define REPLAY_FORMAT_SUBVERSION 0x09
#define REPLAY_FRAMES_PER_WRITE 100 // amounts of frames to write per read/write call
enum struct replay_header_t
{
char sReplayFormat[40];
int iReplayVersion;
char sMap[PLATFORM_MAX_PATH];
int iStyle;
int iTrack;
int iPreFrames;
int iFrameCount;
float fTime;
int iSteamID;
int iPostFrames;
float fTickrate;
float fZoneOffset[2];
}
enum struct frame_t
{
float pos[3];
float ang[2];
int buttons;
// iReplayVersion >= 0x02
int flags;
MoveType mt;
// Everything below is generally NOT loaded into memory for playback
// iReplayVersion >= 0x06
int mousexy; // `mousex | (mousey << 16)` // unpack with UnpackSignedShorts
int vel; // basically `forwardmove | (sidemove << 16)` // unpack with UnpackSignedShorts
}
enum struct frame_cache_t
{
int iFrameCount;
float fTime;
bool bNewFormat;
int iReplayVersion;
char sReplayName[MAX_NAME_LENGTH];
int iPreFrames;
ArrayList aFrames;
// iReplayVersion >= 0x05
int iPostFrames;
float fTickrate;
// blah blah not affected by iReplayVersion
int iSteamID;
}
// Can be used to unpack frame_t.mousexy and frame_t.vel
stock void UnpackSignedShorts(int x, int[] out)
{
out[0] = ((x & 0xFFFF) ^ 0x8000) - 0x8000;
out[1] = (((x >> 16) & 0xFFFF) ^ 0x8000) - 0x8000;
}
stock bool LoadReplayCache(frame_cache_t cache, int style, int track, const char[] path, const char[] mapname)
{
bool success = false;
replay_header_t header;
File fFile = ReadReplayHeader(path, header, style, track);
if (fFile != null)
{
if (header.iReplayVersion > REPLAY_FORMAT_SUBVERSION)
{
// not going to try and read it
}
else if (header.iReplayVersion < 0x03 || (StrEqual(header.sMap, mapname, false) && header.iStyle == style && header.iTrack == track))
{
success = ReadReplayFrames(fFile, header, cache);
}
delete fFile;
}
return success;
}
stock bool ReadReplayFrames(File file, replay_header_t header, frame_cache_t cache)
{
int total_cells = 6;
int used_cells = 6;
bool is_btimes = false;
if (header.iReplayVersion > 0x01)
{
total_cells = 8;
used_cells = 8;
}
// We have differing total_cells & used_cells because we want to save memory during playback since the latest two cells added (vel & mousexy) aren't needed and are only useful for replay file anticheat usage stuff....
if (header.iReplayVersion >= 0x06)
{
total_cells = 10;
used_cells = 8;
}
any aReplayData[sizeof(frame_t)];
delete cache.aFrames;
int iTotalSize = header.iFrameCount + header.iPreFrames + header.iPostFrames;
cache.aFrames = new ArrayList(used_cells, iTotalSize);
if (!header.sReplayFormat[0]) // old replay format. no header.
{
char sLine[320];
char sExplodedLine[6][64];
if(!file.Seek(0, SEEK_SET))
{
return false;
}
while (!file.EndOfFile())
{
file.ReadLine(sLine, 320);
int iStrings = ExplodeString(sLine, "|", sExplodedLine, 6, 64);
aReplayData[0] = StringToFloat(sExplodedLine[0]);
aReplayData[1] = StringToFloat(sExplodedLine[1]);
aReplayData[2] = StringToFloat(sExplodedLine[2]);
aReplayData[3] = StringToFloat(sExplodedLine[3]);
aReplayData[4] = StringToFloat(sExplodedLine[4]);
aReplayData[5] = (iStrings == 6) ? StringToInt(sExplodedLine[5]) : 0;
cache.aFrames.PushArray(aReplayData, 6);
}
cache.iFrameCount = cache.aFrames.Length;
}
else // assumes the file position will be at the start of the frames
{
is_btimes = StrEqual(header.sReplayFormat, "btimes");
for (int i = 0; i < iTotalSize; i++)
{
if(file.Read(aReplayData, total_cells, 4) >= 0)
{
cache.aFrames.SetArray(i, aReplayData, used_cells);
if (is_btimes && (aReplayData[5] & IN_BULLRUSH))
{
if (!header.iPreFrames)
{
header.iPreFrames = i;
header.iFrameCount -= i;
}
else if (!header.iPostFrames)
{
header.iPostFrames = header.iFrameCount + header.iPreFrames - i;
header.iFrameCount -= header.iPostFrames;
}
}
}
}
}
if (cache.aFrames.Length <= 10) // worthless replay so it doesn't get to load
{
delete cache.aFrames;
return false;
}
cache.iFrameCount = header.iFrameCount;
cache.fTime = header.fTime;
cache.iReplayVersion = header.iReplayVersion;
cache.bNewFormat = StrEqual(header.sReplayFormat, REPLAY_FORMAT_FINAL) || is_btimes;
cache.sReplayName = "unknown";
cache.iPreFrames = header.iPreFrames;
cache.iPostFrames = header.iPostFrames;
cache.fTickrate = header.fTickrate;
cache.iSteamID = header.iSteamID;
if (cache.iSteamID != 0)
{
FormatEx(cache.sReplayName, sizeof(cache.sReplayName), "[U:1:%u]", cache.iSteamID);
}
return true;
}
stock File ReadReplayHeader(const char[] path, replay_header_t header, int style = 0, int track = 0)
{
replay_header_t empty_header;
header = empty_header;
File file = OpenFile(path, "rb");
if (file == null)
{
return null;
}
char sHeader[64];
if(!file.ReadLine(sHeader, 64))
{
delete file;
return null;
}
TrimString(sHeader);
char sExplodedHeader[2][64];
ExplodeString(sHeader, ":", sExplodedHeader, 2, 64);
strcopy(header.sReplayFormat, sizeof(header.sReplayFormat), sExplodedHeader[1]);
if(StrEqual(header.sReplayFormat, REPLAY_FORMAT_FINAL)) // hopefully, the last of them
{
int version = StringToInt(sExplodedHeader[0]);
header.iReplayVersion = version;
// replay file integrity and PreFrames
if(version >= 0x03)
{
file.ReadString(header.sMap, PLATFORM_MAX_PATH);
file.ReadUint8(header.iStyle);
file.ReadUint8(header.iTrack);
file.ReadInt32(header.iPreFrames);
// In case the replay was from when there could still be negative preframes
if(header.iPreFrames < 0)
{
header.iPreFrames = 0;
}
}
file.ReadInt32(header.iFrameCount);
file.ReadInt32(view_as<int>(header.fTime));
if (header.iReplayVersion < 0x07)
{
header.iFrameCount -= header.iPreFrames;
}
if(version >= 0x04)
{
file.ReadInt32(header.iSteamID);
}
else
{
char sAuthID[32];
file.ReadString(sAuthID, 32);
ReplaceString(sAuthID, 32, "[U:1:", "");
ReplaceString(sAuthID, 32, "]", "");
header.iSteamID = StringToInt(sAuthID);
}
if (version >= 0x05)
{
file.ReadInt32(header.iPostFrames);
file.ReadInt32(view_as<int>(header.fTickrate));
if (header.iReplayVersion < 0x07)
{
header.iFrameCount -= header.iPostFrames;
}
}
if (version >= 0x08)
{
file.ReadInt32(view_as<int>(header.fZoneOffset[0]));
file.ReadInt32(view_as<int>(header.fZoneOffset[1]));
}
}
else if(StrEqual(header.sReplayFormat, REPLAY_FORMAT_V2))
{
header.iFrameCount = StringToInt(sExplodedHeader[0]);
}
else // old, outdated and slow - only used for ancient replays
{
// check for btimes replays
file.Seek(0, SEEK_SET);
any stuff[2];
file.Read(stuff, 2, 4);
int btimes_player_id = stuff[0];
float run_time = stuff[1];
if (btimes_player_id >= 0 && run_time > 0.0 && run_time < (10.0 * 60.0 * 60.0))
{
header.sReplayFormat = "btimes";
header.fTime = run_time;
file.Seek(0, SEEK_END);
header.iFrameCount = (file.Position / 4 - 2) / 6;
file.Seek(2*4, SEEK_SET);
}
}
if (header.iReplayVersion < 0x03)
{
header.iStyle = style;
header.iTrack = track;
}
if (header.iReplayVersion < 0x05)
{
header.fTickrate = (1.0 / GetTickInterval()); // just assume it's our own tickrate...
}
return file;
}
stock void WriteReplayHeader(File fFile, int style, int track, float time, int steamid, int preframes, int postframes, float fZoneOffset[2], int iSize, float tickrate, const char[] sMap)
{
fFile.WriteLine("%d:" ... REPLAY_FORMAT_FINAL, REPLAY_FORMAT_SUBVERSION);
fFile.WriteString(sMap, true);
fFile.WriteInt8(style);
fFile.WriteInt8(track);
fFile.WriteInt32(preframes);
fFile.WriteInt32(iSize - preframes - postframes);
fFile.WriteInt32(view_as<int>(time));
fFile.WriteInt32(steamid);
fFile.WriteInt32(postframes);
fFile.WriteInt32(view_as<int>(tickrate));
fFile.WriteInt32(view_as<int>(fZoneOffset[0]));
fFile.WriteInt32(view_as<int>(fZoneOffset[1]));
}
stock void cell2buf(char[] buf, int& pos, int cell)
{
buf[pos++] = cell & 0xFF;
buf[pos++] = (cell >> 8) & 0xFF;
buf[pos++] = (cell >> 16) & 0xFF;
buf[pos++] = (cell >> 24) & 0xFF;
}
stock int WriteReplayHeaderToBuffer(char[] buf, int style, int track, float time, int steamid, int preframes, int postframes, float fZoneOffset[2], int totalframes, float tickrate, const char[] sMap)
{
int pos = FormatEx(buf, 512, "%d:%s\n%s", REPLAY_FORMAT_SUBVERSION, REPLAY_FORMAT_FINAL, sMap);
pos += 1; // skip past NUL
buf[pos++] = style & 0xFF;
buf[pos++] = track & 0xFF;
cell2buf(buf, pos, preframes);
cell2buf(buf, pos, totalframes - preframes - postframes);
cell2buf(buf, pos, view_as<int>(time));
cell2buf(buf, pos, steamid);
cell2buf(buf, pos, postframes);
cell2buf(buf, pos, view_as<int>(tickrate));
cell2buf(buf, pos, view_as<int>(fZoneOffset[0]));
cell2buf(buf, pos, view_as<int>(fZoneOffset[1]));
return pos;
}
// file_a is usually used as the wr replay file.
// file_b is usually used as the duplicate/backup replay file.
stock void WriteReplayFrames(ArrayList playerrecording, int iSize, File file_a, File file_b)
{
any aFrameData[sizeof(frame_t)];
any aWriteData[sizeof(frame_t) * REPLAY_FRAMES_PER_WRITE];
int iFramesWritten = 0;
for(int i = 0; i < iSize; i++)
{
playerrecording.GetArray(i, aFrameData, sizeof(frame_t));
for(int j = 0; j < sizeof(frame_t); j++)
{
aWriteData[(sizeof(frame_t) * iFramesWritten) + j] = aFrameData[j];
}
if(++iFramesWritten == REPLAY_FRAMES_PER_WRITE || i == iSize - 1)
{
if (file_a)
{
file_a.Write(aWriteData, sizeof(frame_t) * iFramesWritten, 4);
}
if (file_b)
{
file_b.Write(aWriteData, sizeof(frame_t) * iFramesWritten, 4);
}
iFramesWritten = 0;
}
}
}

View File

@ -0,0 +1,501 @@
/*
* shavit's Timer - replay-playback.inc file
* by: shavit, rtldg, carnifex, KiD Fearless
*
* This file is part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#if defined _shavit_replay_playback_included
#endinput
#endif
#define _shavit_replay_playback_included
#include <shavit/replay-file>
enum //ReplayStatus
{
Replay_Start,
Replay_Running,
Replay_End,
Replay_Idle
};
enum //ReplayBotType
{
Replay_Central,
Replay_Looping, // these are the ones that loop styles, tracks, and (eventually) stages...
Replay_Dynamic, // these are bots that spawn on !replay when the central bot is taken
Replay_Prop, // A prop entity that is being used as a replay...
};
/**
* Called when replay playback starts.
* Will be called twice for every replay bot unless the replay is canceled before the second call. Use `delay_elapsed` to check for the first & second time.
*
* @param ent Entity index for the replay.
* @param type The type of replay. Replay_Prop means `ent` is not a fakeclient, but instead a prop.
* @param delay_elapsed `false` when the replay bot just spawned but before the start delay has elapsed. `true` when the start delay has elapsed.
* @noreturn
*/
forward void Shavit_OnReplayStart(int ent, int type, bool delay_elapsed);
/**
* Called when replay playback ends.
* Will be called twice for most replay bots unless the replay bot is canceled before it finishes. See `actually_finished`.
*
* @param ent Entity index for the replay.
* @param type The type of replay. Replay_Prop means `ent` is not a fakeclient, but instead a prop.
* @param actually_finished `false` when the replay runs out of frames and is starting the timer to despawn. `true` when the replay bot is about to despawn. `true` will always run.
* @noreturn
*/
forward void Shavit_OnReplayEnd(int ent, int type, bool actually_finished);
/**
* Called when all replays files have been loaded.
*
* @noreturn
*/
forward void Shavit_OnReplaysLoaded();
/**
* Deletes all replays for the specified map.
* Plugin will refresh if map is currently on.
*
* @param map Map name.
* @noreturn
*/
native void Shavit_Replay_DeleteMap(const char[] map);
/**
* Deletes the specified replay file.
* Replay data will be unloaded if necessary.
*
* @param map Map display name.
* @param style Bhop style.
* @param track Timer track.
* @param accountid Account ID to validate against, 0 to skip validation.
* @return true if replay existed, false if the steam id didn't match or the file didn't exist.
*/
native bool Shavit_DeleteReplay(const char[] map, int style, int track, int accountid = 0);
/**
* Retrieves the engine time of the replay bot's first frame.
*
* @param entity Entity index.
* @return The engine time of the replay bot's first frame.
*/
native float Shavit_GetReplayBotFirstFrameTime(int entity);
/**
* Retrieve the replay bot's entity index.
*
* @param style Style you want. -1 if you want the central bot. If no central bot, the first bot it finds it used.
* @param track Track you want. -1 if you want the central bot. If no central bot, the first bot it finds it used.
* @return Client index for the replay bot. -1 if not found.
*/
native int Shavit_GetReplayBotIndex(int style, int track);
/**
* Retrieve the style being played by the replay bot.
*
* @param entity Entity index.
* @return Style being played by the replay bot. -1 if the replay bot is idle.
*/
native int Shavit_GetReplayBotStyle(int entity);
/**
* Retrieve the timer track being played by the replay bot.
*
* @param entity entity index.
* @return Timer track replayed by the bot. -1 if the replay bot is idle.
*/
native int Shavit_GetReplayBotTrack(int entity);
/**
* Gets the replay bot type setting of the server.
*
* @return See ReplayBotType enum.
*/
native int Shavit_GetReplayBotType();
/**
* Retrieve the replay bot's current played frame.
*
* @param entity Entity index.
* @return Current played frame.
*/
native int Shavit_GetReplayBotCurrentFrame(int entity);
/**
* Retrieves the client who started the replay.
*
* @param Replay entity.
* @return Client index of starter. Can be 0
*/
native int Shavit_GetReplayStarter(int ent);
/**
* Retrieves the replay's buttons for its current tick.
* Really, this is only useful for things like replay props.
*
* @param Replay entity.
* @param anglediff The angle difference between the previous and current y angles.
*
* @return buttons
*/
native int Shavit_GetReplayButtons(int ent, float& anglediff);
/**
* Retrieves the replay's entity flags for its current tick.
* @param Replay entity.
* @return Entity flags
*/
native int Shavit_GetReplayEntityFlags(int ent);
/**
* Retrieves a replay's frame count.
*
* @param style Style.
* @param track Track.
* @return Frame count.
*/
native int Shavit_GetReplayFrameCount(int style, int track);
/**
* Retrieves a replay's pre-run frame count.
*
* @param style Style.
* @param track Track.
* @return Frame count.
*/
native int Shavit_GetReplayPreFrames(int style, int track);
/**
* Retrieves a replay's post-run frame count.
*
* @param style Style.
* @param track Track.
* @return Frame count.
*/
native int Shavit_GetReplayPostFrames(int style, int track);
/**
* Retrieves the frame count from the currently running replay bot's frame_cache_t.
*
* @param bot Replay bot entity.
* @return Frame count.
*/
native int Shavit_GetReplayCacheFrameCount(int bot);
/**
* Retrieves the pre-run frame count from the currently running replay bot's frame_cache_t.
*
* @param bot Replay bot entity.
* @return Frame count.
*/
native int Shavit_GetReplayCachePreFrames(int bot);
/**
* Retrieves the post-run frame count from the currently running replay bot's frame_cache_t.
*
* @param bot Replay bot entity.
* @return Frame count.
*/
native int Shavit_GetReplayCachePostFrames(int bot);
/**
* Retrieves the replay data for the given style and track.
*
* @param style Style.
* @param track Track.
* @param cheapCloneHandle False means we duplicate the frames (ArrayList.Clone). True means we clone the handle to the frames (CloneHandle).
*
* @return ArrayList with proper replay data, or null if there is no recorded data. Delete this handle when you're done with it.
*/
native ArrayList Shavit_GetReplayFrames(int style, int track, bool cheapCloneHandle=false);
/**
* Retrieves a replay's total length in seconds.
*
* @param style Style.
* @param track Track.
* @return Replay length.
*/
native float Shavit_GetReplayLength(int style, int track);
/**
* Retrieves the replay's total length in seconds from the currently running replay bot's frame_cache_t.
*
* @param bot Replay bot entity.
* @return Replay length.
*/
native float Shavit_GetReplayCacheLength(int bot);
/**
* Retrieves an actively playing replay's time.
*
* @param entity Entity index.
* @return The bot's current time in the replay.
*/
native float Shavit_GetReplayTime(int entity);
/**
* Retrieves a replay holder's name.
*
* @param style Style.
* @param track Track.
* @param buffer Buffer string.
* @param length String length.
* @noreturn
*/
native void Shavit_GetReplayName(int style, int track, char[] buffer, int length);
/**
* Retrieves a replay holder's name from an active replay bot.
*
* @param bot Bot.
* @param buffer Buffer string.
* @param length String length.
* @noreturn
*/
native void Shavit_GetReplayCacheName(int bot, char[] buffer, int length);
/**
* Retrieves the folder path where the replay files are saved.
*
* @param buffer Buffer string.
* @param length String length.
* @noreturn
*/
native void Shavit_GetReplayFolderPath(char[] buffer, int length);
/**
* Checks if there's loaded replay data for a bhop style or not.
*
* @param style Style.
* @param track Track.
* @return Boolean value of if there's loaded replay data.
*/
native bool Shavit_IsReplayDataLoaded(int style, int track);
/**
* Checks if the given entity is a replay bot (fakeclient) or replay prop.
*
* @param The entity index to check.
*/
native bool Shavit_IsReplayEntity(int ent);
/**
* Sets the sReplayName value in the bot's frame_cache_t.
* Useful for `Shavit_StartReplayFromFile` and family.
*
* @param bot The replay bot entity.
* @param name The name to use.
*/
native void Shavit_SetReplayCacheName(int bot, char[] name);
/**
* Starts a replay given a style and track.
*
* @param style Bhop style.
* @param track Timer track.
* @param delay Delay until starting. If -1.0, then uses shavit_replay_delay
* @param client Client index.
* @param bot Bot to play on. Should be of type Replay_Central or Replay_Dynamic. -1 to create new replay bot.
* @param type ReplayBotType. Replay_Prop needs `bot` to be -1.
* @param ignorelimit Ignore cvar limit for dynamic bots.
* @return Replay entity. 0 is returned if couldn't be created.
*/
native int Shavit_StartReplay(int style, int track, float delay, int client, int bot, int type, bool ignorelimit);
/**
* Starts a replay with a given set of frames.
* Useful for playing a replay downloaded from a global WR database...
*
* @param style Bhop style.
* @param track Timer track.
* @param delay Delay until starting. If -1.0, then uses shavit_replay_delay
* @param client Client index.
* @param bot Bot to play on. Should be of type Replay_Central or Replay_Dynamic. -1 to create new replay bot.
* @param type ReplayBotType. Replay_Prop needs `bot` to be -1.
* @param ignorelimit Ignore cvar limit for dynamic bots.
* @param cache frame_cache_t filled with replay info and frames.
* @param size sizeof(frame_cache_t). Used to throw errors at you if you don't recompile plugins.
* @return Replay entity. 0 is returned if couldn't be created.
*/
native int Shavit_StartReplayFromFrameCache(int style, int track, float delay, int client, int bot, int type, bool ignorelimit, any[] cache, int size = sizeof(frame_cache_t));
/**
* Starts a replay from a replay file.
* Useful for playing a replay downloaded from a global WR database...
*
* @param style Bhop style.
* @param track Timer track.
* @param delay Delay until starting. If -1.0, then uses shavit_replay_delay
* @param client Client index.
* @param bot Bot to play on. Should be of type Replay_Central or Replay_Dynamic. -1 to create new replay bot.
* @param type ReplayBotType. Replay_Prop needs `bot` to be -1.
* @param ignorelimit Ignore cvar limit for dynamic bots.
* @param path File path to replay
* @return Replay entity. 0 is returned if couldn't be created.
*/
native int Shavit_StartReplayFromFile(int style, int track, float delay, int client, int bot, int type, bool ignorelimit, const char[] path);
/**
* Reloads a specific replay into the replay bot cache.
* Note: Not guaranteed to work with legacy replay bots.
*
* @param style Replay style.
* @param track Replay track.
* @param restart Restart the playback of the replay bot if it's playing?
* @param path Path to the replay file. Use `BuildPath(Path_SM, ...)` to generate one. Leave as empty to use default.
* @return Was the replay loaded?
*/
native bool Shavit_ReloadReplay(int style, int track, bool restart, char[] path = "");
/**
* Reloads all of the replays for the map.
*
* @param restart Restart the playback of the replay bots?
* @return Amount of loaded replays.
*/
native int Shavit_ReloadReplays(bool restart);
/**
* Gets time from replay frame that is closest to client.
*
* @param client Client index.
* @param outlength Fills this variable with the total length of the replay that's being compared to.
*
* @return Replay time.
*/
native float Shavit_GetClosestReplayTime(int client, float &outlength=0.0);
/**
* Gets the style the client is getting the closest replay time from.
*
* @param client Client index.
*
* @return style
*/
native int Shavit_GetClosestReplayStyle(int client);
/**
* Sets the style to grab the closest replay time from.
*
* @param client Client index.
* @param style Style blah.
*
* @param Style to grab replay time from. -1 to use the client's current style.
*
* @noreturn
*/
native void Shavit_SetClosestReplayStyle(int client, int style);
/**
* Gets velocity from replay frame that is closest to client.
*
* @param client Client index.
* @param threeD true for 3D velocity difference. false for 2D velocity difference.
*
* @return Velocity difference from closest replay position.
*/
native float Shavit_GetClosestReplayVelocityDifference(int client, bool threeD);
/**
* Gets the replay status
*
* @param Replay bot (or prop) entity
*
* @return Replay's status
*/
native int Shavit_GetReplayStatus(int ent);
/*
* Used to find a looping replay bot from the loop config name.
*
* @param name Looping bot config name. An example is "Other Styles" from the default set of looping bots in shavit-replay.cfg
*
* @return The client index of the looping replay bot. -1 if could not find the config name. 0 if could not find the replay bot client.
*/
native int Shavit_GetLoopingBotByName(const char[] name);
/*
* Retrieves the playback speed of the replay bot.
*
* @param bot
*
* @return Should be 0.5, 1.0, or 2.0.
*/
native float Shavit_GetReplayPlaybackSpeed(int bot);
public SharedPlugin __pl_shavit_replay_playback =
{
name = "shavit-replay-playback",
file = "shavit-replay-playback.smx",
#if defined REQUIRE_PLUGIN
required = 1
#else
required = 0
#endif
};
#if !defined REQUIRE_PLUGIN
public void __pl_shavit_replay_playback_SetNTVOptional()
{
MarkNativeAsOptional("Shavit_DeleteReplay");
MarkNativeAsOptional("Shavit_GetReplayBotCurrentFrame");
MarkNativeAsOptional("Shavit_GetReplayBotFirstFrameTime");
MarkNativeAsOptional("Shavit_GetReplayBotIndex");
MarkNativeAsOptional("Shavit_GetReplayBotStyle");
MarkNativeAsOptional("Shavit_GetReplayBotTrack");
MarkNativeAsOptional("Shavit_GetReplayBotType");
MarkNativeAsOptional("Shavit_GetReplayStarter");
MarkNativeAsOptional("Shavit_GetReplayFrameCount");
MarkNativeAsOptional("Shavit_GetReplayFrames");
MarkNativeAsOptional("Shavit_GetReplayLength");
MarkNativeAsOptional("Shavit_GetReplayName");
MarkNativeAsOptional("Shavit_GetReplayCacheName");
MarkNativeAsOptional("Shavit_GetReplayStatus");
MarkNativeAsOptional("Shavit_GetReplayTime");
MarkNativeAsOptional("Shavit_IsReplayDataLoaded");
MarkNativeAsOptional("Shavit_ReloadReplay");
MarkNativeAsOptional("Shavit_ReloadReplays");
MarkNativeAsOptional("Shavit_Replay_DeleteMap");
MarkNativeAsOptional("Shavit_StartReplay");
MarkNativeAsOptional("Shavit_GetClosestReplayTime");
MarkNativeAsOptional("Shavit_GetClosestReplayVelocityDifference");
MarkNativeAsOptional("Shavit_IsReplayEntity");
MarkNativeAsOptional("Shavit_GetReplayButtons");
MarkNativeAsOptional("Shavit_GetReplayEntityFlags");
MarkNativeAsOptional("Shavit_GetClosestReplayStyle");
MarkNativeAsOptional("Shavit_SetClosestReplayStyle");
MarkNativeAsOptional("Shavit_GetReplayCacheFrameCount");
MarkNativeAsOptional("Shavit_GetReplayCacheLength");
MarkNativeAsOptional("Shavit_StartReplayFromFrameCache");
MarkNativeAsOptional("Shavit_StartReplayFromFile");
MarkNativeAsOptional("Shavit_GetReplayPreFrames");
MarkNativeAsOptional("Shavit_GetReplayPostFrames");
MarkNativeAsOptional("Shavit_GetReplayCachePreFrames");
MarkNativeAsOptional("Shavit_GetReplayCachePostFrames");
MarkNativeAsOptional("Shavit_GetLoopingBotByName");
MarkNativeAsOptional("Shavit_SetReplayCacheName");
MarkNativeAsOptional("Shavit_GetReplayFolderPath");
MarkNativeAsOptional("Shavit_GetReplayPlaybackSpeed");
}
#endif

View File

@ -0,0 +1,165 @@
/*
* shavit's Timer - replay-recorder.inc file
* by: shavit, rtldg,
*
* This file is part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#if defined _shavit_replay_recorder_included
#endinput
#endif
#define _shavit_replay_recorder_included
/**
* Called when a player finishes a time. Allows you to save a replay even if the run is not a WR.
*
* @param client Client index.
* @param style Style the record was done on.
* @param time Record time.
* @param jumps Jumps amount.
* @param strafes Amount of strafes.
* @param sync Sync percentage (0.0 to 100.0) or -1.0 when not measured.
* @param track Timer track.
* @param oldtime The player's best time on the map before this finish.
* @param perfs Perfect jump percentage (0.0 to 100.0) or 100.0 when not measured.
* @param avgvel Player's average velocity throughout the run.
* @param maxvel Player's highest reached velocity.
* @param timestamp System time of when player finished.
* @param isbestreplay If the time is the new replay.
* @param istoolong If the time is too long to save a replay if the time is a WR. Note: replays WON'T be full length if this is true.
*
* @return Return Plugin_Changed (or higher) to cause a copy of the replay to be saved. Return Plugin_Continue otherwise.
*/
forward Action Shavit_ShouldSaveReplayCopy(int client, int style, float time, int jumps, int strafes, float sync, int track, float oldtime, float perfs, float avgvel, float maxvel, int timestamp, bool isbestreplay, bool istoolong);
/**
* Called when either a WR replay or a copy of a replay has been saved.
* NOTE: Can be called with a delay after a run is finished due to asynchronous replay saving through extensions.
*
* @param client Client index. Can be 0 if the replay was saved asynchronously & the client disconnected super duper quick...
* @param style Style the record was done on.
* @param time Record time.
* @param jumps Jumps amount.
* @param strafes Amount of strafes.
* @param sync Sync percentage (0.0 to 100.0) or -1.0 when not measured.
* @param track Timer track.
* @param oldtime The player's best time on the map before this finish.
* @param perfs Perfect jump percentage (0.0 to 100.0) or 100.0 when not measured.
* @param avgvel Player's average velocity throughout the run.
* @param maxvel Player's highest reached velocity.
* @param timestamp System time of when player finished.
* @param isbestreplay If the time is the new replay.
* @param istoolong If the time is too long to save a replay if the time is a WR. Note: replays WON'T be full length if this is true.
* @param iscopy If the path points to a copy of the replay.
* @param replaypath Path to the saved replay.
* @param frames ArrayList of the player's frames in the replay.
* @param preframes The number of preframes in the replay.
* @param postframes The number of postframes in the replay.
* @param name Player's name at the time of the replay.
*
* @noreturn
*/
forward void Shavit_OnReplaySaved(int client, int style, float time, int jumps, int strafes, float sync, int track, float oldtime, float perfs, float avgvel, float maxvel, int timestamp, bool isbestreplay, bool istoolong, bool iscopy, const char[] replaypath, ArrayList frames, int preframes, int postframes, const char[] name);
/**
* Retrieves a client's frame count.
*
* @param client Client Index.
*
* @return Current number of frames.
*/
native int Shavit_GetClientFrameCount(int client);
/*
* returns the number of preframes in the players current run.
*
* @param client Client index
*
* @return Preframe count
*/
native int Shavit_GetPlayerPreFrames(int client);
/*
* Sets player's preframe length.
*
* @param client Client index
* @param PreFrame PreFrame length
* @param TimerPreFrame Timer start frame length
*
* @noreturn
*/
native void Shavit_SetPlayerPreFrames(int client, int PreFrame);
/**
* Sets a player's replay recording frames from a provided ArrayList.
* To be used by save states/TAS etc.
*
* @param client Client index.
* @param data ArrayList with proper replay data.
* @param cheapCloneHandle False means we duplicate the frames (ArrayList.Clone). True means we clone the handle to the frames (CloneHandle).
*
* @noreturn
*/
native void Shavit_SetReplayData(int client, ArrayList data, bool cheapCloneHandle=false);
/**
* Saves a player's replay recording frames (if exists) into an ArrayList.
* To be used by save states/TAS etc.
*
* @param client Client index.
* @param cheapCloneHandle False means we duplicate the frames (Arraylist.Clone). True means we clone the handle to the frames (CloneHandle). This is going to be used for peristent-data in shavit-misc so we don't allocate duplicate memory needlessly.
*
* @return ArrayList with proper replay data, or null if the player has no recorded data. Delete this handle when you're done with it.
*/
native ArrayList Shavit_GetReplayData(int client, bool cheapCloneHandle=false);
/**
* Hijack the replay data so that this view angle will be used for the next ticks.
* Use case is to make segmented runs look smoother.
*
* @param client Client index.
* @param pitch Vertical view angle.
* @param yaw Horizontal view angle.
* @param ticks The number of ticks to hijack angles for. -1 will calculate the number of ticks based on the client's latency.
* @param keeponstart Whether to continue hijacking angles even after someone restarts.
*
* @noreturn
*/
native void Shavit_HijackAngles(int client, float pitch, float yaw, int ticks = -1, bool keeponstart = false);
public SharedPlugin __pl_shavit_replay_recorder =
{
name = "shavit-replay-recorder",
file = "shavit-replay-recorder.smx",
#if defined REQUIRE_PLUGIN
required = 1
#else
required = 0
#endif
};
#if !defined REQUIRE_PLUGIN
public void __pl_shavit_replay_recorder_SetNTVOptional()
{
MarkNativeAsOptional("Shavit_GetClientFrameCount");
MarkNativeAsOptional("Shavit_GetPlayerPreFrames");
MarkNativeAsOptional("Shavit_SetPlayerPreFrames");
MarkNativeAsOptional("Shavit_GetReplayData");
MarkNativeAsOptional("Shavit_HijackAngles");
MarkNativeAsOptional("Shavit_SetReplayData");
}
#endif

View File

@ -0,0 +1,103 @@
/*
* shavit's Timer - stocks used by the replay plugins
* by: shavit
*
* This file is part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
stock bool Shavit_ReplayEnabledStyle(int style)
{
return !Shavit_GetStyleSettingBool(style, "unranked") && !Shavit_GetStyleSettingBool(style, "noreplay");
}
stock void Shavit_GetReplayFilePath(int style, int track, const char[] mapname, const char[] replayfolder, char sPath[PLATFORM_MAX_PATH])
{
char sTrack[4];
FormatEx(sTrack, 4, "_%d", track);
FormatEx(sPath, PLATFORM_MAX_PATH, "%s/%d/%s%s.replay", replayfolder, style, mapname, (track > 0)? sTrack:"");
}
stock bool Shavit_GetReplayFolderPath_Stock(char buffer[PLATFORM_MAX_PATH])
{
char sPath[PLATFORM_MAX_PATH];
BuildPath(Path_SM, sPath, PLATFORM_MAX_PATH, "configs/shavit-replay.cfg");
KeyValues kv = new KeyValues("shavit-replay");
if (!kv.ImportFromFile(sPath))
{
delete kv;
return false;
}
kv.GetString("replayfolder", buffer, PLATFORM_MAX_PATH, "{SM}/data/replaybot");
if (StrContains(buffer, "{SM}") != -1)
{
ReplaceString(buffer, PLATFORM_MAX_PATH, "{SM}/", "");
BuildPath(Path_SM, buffer, PLATFORM_MAX_PATH, "%s", buffer);
}
delete kv;
return true;
}
stock void Shavit_Replay_CreateDirectories(const char[] sReplayFolder, int styles)
{
if (!DirExists(sReplayFolder) && !CreateDirectory(sReplayFolder, 511))
{
SetFailState("Failed to create replay folder (%s). Make sure you have file permissions", sReplayFolder);
}
char sPath[PLATFORM_MAX_PATH];
FormatEx(sPath, PLATFORM_MAX_PATH, "%s/copy", sReplayFolder);
if (!DirExists(sPath) && !CreateDirectory(sPath, 511))
{
SetFailState("Failed to create replay copy folder (%s). Make sure you have file permissions", sPath);
}
for(int i = 0; i < styles; i++)
{
if (!Shavit_ReplayEnabledStyle(i))
{
continue;
}
FormatEx(sPath, PLATFORM_MAX_PATH, "%s/%d", sReplayFolder, i);
if (!DirExists(sPath) && !CreateDirectory(sPath, 511))
{
SetFailState("Failed to create replay style folder (%s). Make sure you have file permissions", sPath);
}
}
// Test to see if replay file creation works
FormatEx(sPath, sizeof(sPath), "%s/0/faketestfile_69.replay", sReplayFolder);
File fTest = OpenFile(sPath, "wb+");
// Check if the file was opened successfully for writing
if (fTest == null)
{
SetFailState("Failed to write to replay folder (%s). Make sure you have file permissions.", sReplayFolder);
}
else
{
// File was opened successfully, now close it
CloseHandle(fTest);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,97 @@
/*
* Steam ID handling stocks
* by: rtldg
*
* This file is part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#if defined _steamid_stocks_included
#endinput
#endif
#define _steamid_stocks_included
// Retrieves accountid from STEAM_X:Y:Z, [U:1:123], and 765xxxxxxxxxxxxxx
stock int SteamIDToAccountID(const char[] sInput)
{
char sSteamID[32];
strcopy(sSteamID, sizeof(sSteamID), sInput);
ReplaceString(sSteamID, 32, "\"", "");
TrimString(sSteamID);
if (StrContains(sSteamID, "STEAM_") != -1)
{
ReplaceString(sSteamID, 32, "STEAM_", "");
char parts[3][11];
ExplodeString(sSteamID, ":", parts, 3, 11);
// Let X, Y and Z constants be defined by the SteamID: STEAM_X:Y:Z.
// Using the formula W=Z*2+Y, a SteamID can be converted:
return StringToInt(parts[2]) * 2 + StringToInt(parts[1]);
}
else if (StrContains(sSteamID, "U:1:") != -1)
{
ReplaceString(sSteamID, 32, "[", "");
ReplaceString(sSteamID, 32, "U:1:", "");
ReplaceString(sSteamID, 32, "]", "");
return StringToInt(sSteamID);
}
else if (StrContains(sSteamID, "765") == 0)
{
return SteamID64ToAccountID(sSteamID);
}
return 0;
}
stock void AccountIDToSteamID64Num(int accountid, int num[2])
{
num[0] = accountid;
// universe | type | instance
num[1] = (1 << 24) | (1 << 20) | 1; // 0x01100001
}
stock void AccountIDToSteamID64(int accountid, char[] buf, int buflen)
{
int num[2];
AccountIDToSteamID64Num(accountid, num);
SteamID64ToString(num, buf, buflen);
}
stock void AccountIDToSteamID2(int accountid, char[] buf, int buflen)
{
FormatEx(buf, buflen, "STEAM_0:%d:%d", accountid&1, (accountid>>1) & 0x7FFFFFFF);
}
stock void AccountIDToSteamID3(int accountid, char[] buf, int buflen)
{
FormatEx(buf, buflen, "[U:1:%u]", accountid);
}
stock void SteamID64ToString(const int num[2], char[] buf, int buflen)
{
Int64ToString(num, buf, buflen);
}
stock int SteamID64ToAccountID(const char[] steamid64)
{
int num[2];
StringToInt64(steamid64, num);
return num[0];
}

View File

@ -0,0 +1,728 @@
/*
* shavit's Timer - Style settings
* by: shavit, KiD Fearless, rtldg
*
* This file is part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#pragma newdecls required
#pragma semicolon 1
#define SS_VAL_SZ 128
#define SS_KEY_SZ 64
enum struct style_setting_t
{
float f;
char str[SS_VAL_SZ];
}
Handle gH_Forwards_OnStyleConfigLoaded = null;
bool gB_StyleCommandsRegistered = false;
int gI_Styles = 0;
int gI_OrderedStyles[STYLE_LIMIT];
int gI_CurrentParserIndex = 0;
StringMap gSM_StyleKeys[STYLE_LIMIT];
StringMap gSM_StyleCommands = null;
StringMap gSM_StyleKeysSet = null;
int gI_StyleFlag[STYLE_LIMIT];
char gS_StyleOverride[STYLE_LIMIT][32];
void Shavit_Style_Settings_Natives()
{
CreateNative("Shavit_GetOrderedStyles", Native_GetOrderedStyles);
CreateNative("Shavit_GetStyleCount", Native_GetStyleCount);
CreateNative("Shavit_GetStyleSetting", Native_GetStyleSetting);
CreateNative("Shavit_GetStyleSettingInt", Native_GetStyleSettingInt);
CreateNative("Shavit_GetStyleSettingBool", Native_GetStyleSettingBool);
CreateNative("Shavit_GetStyleSettingFloat", Native_GetStyleSettingFloat);
CreateNative("Shavit_HasStyleAccess", Native_HasStyleAccess);
CreateNative("Shavit_HasStyleSetting", Native_HasStyleSetting);
CreateNative("Shavit_SetStyleSetting", Native_SetStyleSetting);
CreateNative("Shavit_SetStyleSettingInt", Native_SetStyleSettingInt);
CreateNative("Shavit_SetStyleSettingBool", Native_SetStyleSettingBool);
CreateNative("Shavit_SetStyleSettingFloat", Native_SetStyleSettingFloat);
CreateNative("Shavit_GetStyleStrings", Native_GetStyleStrings);
CreateNative("Shavit_GetStyleStringsStruct", Native_GetStyleStringsStruct);
gSM_StyleCommands = new StringMap();
}
void Shavit_Style_Settings_Forwards()
{
gH_Forwards_OnStyleConfigLoaded = CreateGlobalForward("Shavit_OnStyleConfigLoaded", ET_Event, Param_Cell);
}
bool LoadStyles()
{
for (int i = 0; i < STYLE_LIMIT; i++)
{
delete gSM_StyleKeys[i];
}
char sPath[PLATFORM_MAX_PATH];
BuildPath(Path_SM, sPath, PLATFORM_MAX_PATH, "configs/shavit-styles.cfg");
SMCParser parser = new SMCParser();
parser.OnEnterSection = OnStyleEnterSection;
parser.OnLeaveSection = OnStyleLeaveSection;
parser.OnKeyValue = OnStyleKeyValue;
parser.ParseFile(sPath);
delete parser;
for (int i = 0; i < gI_Styles; i++)
{
if (gSM_StyleKeys[i] == null)
{
SetFailState("Missing style index %d. Highest index is %d. Fix addons/sourcemod/configs/shavit-styles.cfg", i, gI_Styles-1);
}
}
gB_StyleCommandsRegistered = true;
SortCustom1D(gI_OrderedStyles, gI_Styles, SortAscending_StyleOrder);
Call_StartForward(gH_Forwards_OnStyleConfigLoaded);
Call_PushCell(gI_Styles);
Call_Finish();
return true;
}
public SMCResult OnStyleEnterSection(SMCParser smc, const char[] name, bool opt_quotes)
{
// styles key
if (!IsCharNumeric(name[0]))
{
return SMCParse_Continue;
}
gI_CurrentParserIndex = StringToInt(name);
if (gSM_StyleKeys[gI_CurrentParserIndex] != null)
{
SetFailState("Style index %d (%s) already parsed. Stop using the same index for multiple styles. Fix addons/sourcemod/configs/shavit-styles.cfg", gI_CurrentParserIndex, name);
}
if (gI_CurrentParserIndex >= STYLE_LIMIT)
{
SetFailState("Style index %d (%s) too high (limit %d). Fix addons/sourcemod/configs/shavit-styles.cfg", gI_CurrentParserIndex, name, STYLE_LIMIT);
}
if (gI_Styles <= gI_CurrentParserIndex)
{
gI_Styles = gI_CurrentParserIndex + 1;
}
delete gSM_StyleKeysSet;
gSM_StyleKeysSet = new StringMap();
gSM_StyleKeys[gI_CurrentParserIndex] = new StringMap();
SetStyleSetting(gI_CurrentParserIndex, "name", "<MISSING STYLE NAME>");
SetStyleSetting(gI_CurrentParserIndex, "shortname", "<MISSING SHORT STYLE NAME>");
SetStyleSetting(gI_CurrentParserIndex, "htmlcolor", "<MISSING STYLE HTML COLOR>");
SetStyleSetting(gI_CurrentParserIndex, "command", "");
SetStyleSetting(gI_CurrentParserIndex, "clantag", "<MISSING STYLE CLAN TAG>");
SetStyleSetting(gI_CurrentParserIndex, "specialstring", "");
SetStyleSetting(gI_CurrentParserIndex, "permission", "");
SetStyleSettingInt (gI_CurrentParserIndex, "autobhop", 1);
SetStyleSettingInt (gI_CurrentParserIndex, "easybhop", 1);
SetStyleSettingInt (gI_CurrentParserIndex, "prespeed", 0);
SetStyleSettingFloat(gI_CurrentParserIndex, "prespeed_ez_vel", 0.0);
SetStyleSettingFloat(gI_CurrentParserIndex, "velocity_limit", 0.0);
SetStyleSettingInt (gI_CurrentParserIndex, "bunnyhopping", 1);
SetStyleSettingInt (gI_CurrentParserIndex, "prespeed_type", -1);
SetStyleSettingInt (gI_CurrentParserIndex, "blockprejump", -1);
SetStyleSettingInt (gI_CurrentParserIndex, "nozaxisspeed", -1);
SetStyleSettingInt (gI_CurrentParserIndex, "restrictnoclip", -1);
SetStyleSettingInt (gI_CurrentParserIndex, "startinair", 0);
SetStyleSettingFloat(gI_CurrentParserIndex, "airaccelerate", 1000.0);
SetStyleSettingFloat(gI_CurrentParserIndex, "runspeed", 260.00);
SetStyleSettingFloat(gI_CurrentParserIndex, "maxprestrafe", 0.0);
SetStyleSettingFloat(gI_CurrentParserIndex, "gravity", 1.0);
SetStyleSettingFloat(gI_CurrentParserIndex, "speed", 1.0);
SetStyleSettingInt (gI_CurrentParserIndex, "halftime", 0);
SetStyleSettingFloat(gI_CurrentParserIndex, "timescale", 1.0);
SetStyleSettingInt (gI_CurrentParserIndex, "tas", 0);
SetStyleSettingFloat(gI_CurrentParserIndex, "tas_timescale", 0.0);
SetStyleSettingInt (gI_CurrentParserIndex, "autostrafe", 0);
SetStyleSettingInt (gI_CurrentParserIndex, "autoprestrafe", 0);
SetStyleSettingInt (gI_CurrentParserIndex, "edgejump", 0);
SetStyleSettingInt (gI_CurrentParserIndex, "autojumponstart", 0);
SetStyleSettingInt (gI_CurrentParserIndex, "force_timescale", 0);
SetStyleSettingFloat(gI_CurrentParserIndex, "velocity", 1.0);
SetStyleSettingFloat(gI_CurrentParserIndex, "bonus_velocity", 0.0);
SetStyleSettingFloat(gI_CurrentParserIndex, "min_velocity", 0.0);
SetStyleSettingFloat(gI_CurrentParserIndex, "jump_multiplier", 0.0);
SetStyleSettingFloat(gI_CurrentParserIndex, "jump_bonus", 0.0);
SetStyleSettingInt (gI_CurrentParserIndex, "block_w", 0);
SetStyleSettingInt (gI_CurrentParserIndex, "block_a", 0);
SetStyleSettingInt (gI_CurrentParserIndex, "block_s", 0);
SetStyleSettingInt (gI_CurrentParserIndex, "block_d", 0);
SetStyleSettingInt (gI_CurrentParserIndex, "block_use", 0);
SetStyleSettingBool (gI_CurrentParserIndex, "a_or_d_only", false);
SetStyleSettingInt (gI_CurrentParserIndex, "force_hsw", 0);
SetStyleSettingInt (gI_CurrentParserIndex, "block_pleft", 0);
SetStyleSettingInt (gI_CurrentParserIndex, "block_pright", 0);
SetStyleSettingInt (gI_CurrentParserIndex, "block_pstrafe", 0);
SetStyleSettingInt (gI_CurrentParserIndex, "unranked", 0);
SetStyleSettingInt (gI_CurrentParserIndex, "noreplay", 0);
SetStyleSettingInt (gI_CurrentParserIndex, "sync", 1);
SetStyleSettingInt (gI_CurrentParserIndex, "strafe_count_w", 0);
SetStyleSettingInt (gI_CurrentParserIndex, "strafe_count_a", 1);
SetStyleSettingInt (gI_CurrentParserIndex, "strafe_count_s", 0);
SetStyleSettingInt (gI_CurrentParserIndex, "strafe_count_d", 1);
SetStyleSettingFloat(gI_CurrentParserIndex, "rankingmultiplier", 1.0);
SetStyleSettingInt (gI_CurrentParserIndex, "special", 0);
// bhop_freedompuppies on css auto is like 4.2s. prob lower on csgo so 3.5
SetStyleSettingFloat(gI_CurrentParserIndex, "minimum_time", 3.5);
// bhop_uc_minecraft_beta2 on css auto has a 0.62s time
SetStyleSettingFloat(gI_CurrentParserIndex, "minimum_time_bonus", 0.5);
SetStyleSettingInt(gI_CurrentParserIndex, "ordering", gI_CurrentParserIndex);
SetStyleSettingInt(gI_CurrentParserIndex, "inaccessible", 0);
SetStyleSettingInt(gI_CurrentParserIndex, "enabled", 1);
SetStyleSettingInt(gI_CurrentParserIndex, "kzcheckpoints", 0);
SetStyleSettingInt(gI_CurrentParserIndex, "kzcheckpoints_ladders", 0);
SetStyleSettingInt(gI_CurrentParserIndex, "kzcheckpoints_ontele", -1);
SetStyleSettingInt(gI_CurrentParserIndex, "kzcheckpoints_onstart", -1);
SetStyleSettingInt(gI_CurrentParserIndex, "segments", 0);
SetStyleSettingInt(gI_CurrentParserIndex, "force_groundkeys", 0);
gI_OrderedStyles[gI_CurrentParserIndex] = gI_CurrentParserIndex;
return SMCParse_Continue;
}
public SMCResult OnStyleLeaveSection(SMCParser smc)
{
if (gI_CurrentParserIndex == -1)
{
// OnStyleLeaveSection can be called back to back.
// And does for when hitting the last style!
// So we set gI_CurrentParserIndex to -1 at the end of this function.
return SMCParse_Continue;
}
// if this style is disabled, we will force certain settings
if (GetStyleSettingInt(gI_CurrentParserIndex, "enabled") <= 0)
{
SetStyleSettingInt (gI_CurrentParserIndex, "noreplay", 1);
SetStyleSettingFloat(gI_CurrentParserIndex, "rankingmultiplier", 0.0);
SetStyleSettingInt (gI_CurrentParserIndex, "inaccessible", 1);
}
if (GetStyleSettingInt(gI_CurrentParserIndex, "kzcheckpoints_onstart") != -1)
{
SetStyleSettingInt (gI_CurrentParserIndex, "inaccessible", 1);
}
if (GetStyleSettingBool(gI_CurrentParserIndex, "halftime"))
{
SetStyleSettingFloat(gI_CurrentParserIndex, "timescale", 0.5);
}
if (GetStyleSettingFloat(gI_CurrentParserIndex, "timescale") <= 0.0)
{
SetStyleSettingFloat(gI_CurrentParserIndex, "timescale", 1.0);
}
#if 0
// Setting it here so that we can reference the timescale setting.
if (!HasStyleSetting(gI_CurrentParserIndex, "force_timescale"))
{
if (GetStyleSettingFloat(gI_CurrentParserIndex, "timescale") == 1.0)
{
SetStyleSettingInt(gI_CurrentParserIndex, "force_timescale", 0);
}
else
{
SetStyleSettingInt(gI_CurrentParserIndex, "force_timescale", 1);
}
}
#endif
if (GetStyleSettingInt(gI_CurrentParserIndex, "prespeed") > 0 || GetStyleSettingInt(gI_CurrentParserIndex, "prespeed_type") > 0)
{
bool value;
if (!gSM_StyleKeysSet.GetValue("minimum_time", value))
{
SetStyleSettingFloat(gI_CurrentParserIndex, "minimum_time", 0.01);
}
if (!gSM_StyleKeysSet.GetValue("minimum_time_bonus", value))
{
SetStyleSettingFloat(gI_CurrentParserIndex, "minimum_time_bonus", 0.01);
}
}
char sStyleCommand[SS_VAL_SZ];
GetStyleSetting(gI_CurrentParserIndex, "command", sStyleCommand, sizeof(sStyleCommand));
char sName[64];
GetStyleSetting(gI_CurrentParserIndex, "name", sName, sizeof(sName));
if (!gB_StyleCommandsRegistered && strlen(sStyleCommand) > 0 && !GetStyleSettingBool(gI_CurrentParserIndex, "inaccessible"))
{
char sStyleCommands[32][32];
int iCommands = ExplodeString(sStyleCommand, ";", sStyleCommands, 32, 32, false);
char sDescription[128];
FormatEx(sDescription, 128, "Change style to %s.", sName);
for (int x = 0; x < iCommands; x++)
{
TrimString(sStyleCommands[x]);
StripQuotes(sStyleCommands[x]);
char sCommand[32];
FormatEx(sCommand, 32, "sm_%s", sStyleCommands[x]);
gSM_StyleCommands.SetValue(sCommand, gI_CurrentParserIndex);
RegConsoleCmd(sCommand, Command_StyleChange, sDescription);
}
}
char sPermission[64];
GetStyleSetting(gI_CurrentParserIndex, "permission", sPermission, sizeof(sPermission));
if (StrContains(sPermission, ";") != -1)
{
char sText[2][32];
int iCount = ExplodeString(sPermission, ";", sText, 2, 32);
AdminFlag flag = Admin_Reservation;
if(FindFlagByChar(sText[0][0], flag))
{
gI_StyleFlag[gI_CurrentParserIndex] = FlagToBit(flag);
}
strcopy(gS_StyleOverride[gI_CurrentParserIndex], 32, (iCount >= 2)? sText[1]:"");
}
else if (strlen(sPermission) > 0)
{
AdminFlag flag = Admin_Reservation;
if(FindFlagByChar(sPermission[0], flag))
{
gI_StyleFlag[gI_CurrentParserIndex] = FlagToBit(flag);
}
}
if (HasStyleSetting(gI_CurrentParserIndex, "specialstring"))
{
char value[SS_VAL_SZ];
GetStyleSetting(gI_CurrentParserIndex, "specialstring", value, sizeof(value));
char keys[32][32];
int count = ExplodeString(value, ";", keys, 32, 32, false);
for (int i = 0; i < count; i++)
{
TrimString(keys[i]);
char pair[2][32];
ExplodeString(keys[i], "=", pair, 2, 32, false);
TrimString(pair[0]);
TrimString(pair[1]);
if (!pair[0][0])
{
continue;
}
LowercaseString(pair[0]);
#if 0
if (HasStyleSetting(gI_CurrentParserIndex, pair[0]))
#else
bool x;
if (gSM_StyleKeysSet.GetValue(pair[0], x))
#endif
{
char asdf[SS_VAL_SZ];
GetStyleSetting(gI_CurrentParserIndex, pair[0], asdf, sizeof(asdf));
char name[SS_VAL_SZ];
GetStyleSetting(gI_CurrentParserIndex, "name", name, sizeof(name));
LogError("Style %s (%d) has '%s' set (%s) but is also trying to set it from specialstring (%s).", name, gI_CurrentParserIndex, pair[0], asdf, pair[1][0] ? pair[1] : "1");
continue;
}
if (pair[1][0])
{
SetStyleSetting(gI_CurrentParserIndex, pair[0], pair[1]);
}
else
{
SetStyleSettingBool(gI_CurrentParserIndex, pair[0], true);
}
}
}
if (GetStyleSettingBool(gI_CurrentParserIndex, "tas"))
{
bool x;
if (!gSM_StyleKeysSet.GetValue("tas_timescale", x))
{
SetStyleSettingFloat(gI_CurrentParserIndex, "tas_timescale", -1.0);
}
if (!gSM_StyleKeysSet.GetValue("autostrafe", x))
{
SetStyleSettingInt (gI_CurrentParserIndex, "autostrafe", 1);
}
if (!gSM_StyleKeysSet.GetValue("autoprestrafe", x))
{
SetStyleSettingBool (gI_CurrentParserIndex, "autoprestrafe", true);
}
if (!gSM_StyleKeysSet.GetValue("edgejump", x))
{
SetStyleSettingBool (gI_CurrentParserIndex, "edgejump", true);
}
if (!gSM_StyleKeysSet.GetValue("autojumponstart", x))
{
SetStyleSettingBool (gI_CurrentParserIndex, "autojumponstart", true);
}
}
delete gSM_StyleKeysSet;
gI_CurrentParserIndex = -1;
return SMCParse_Continue;
}
public SMCResult OnStyleKeyValue(SMCParser smc, const char[] key, const char[] value, bool key_quotes, bool value_quotes)
{
SetStyleSetting(gI_CurrentParserIndex, key, value);
gSM_StyleKeysSet.SetValue(key, true);
return SMCParse_Continue;
}
public int SortAscending_StyleOrder(int index1, int index2, const int[] array, Handle hndl)
{
return GetStyleSettingInt(index1, "ordering") - GetStyleSettingInt(index2, "ordering");
}
public Action Command_StyleChange(int client, int args)
{
char sCommand[128];
GetCmdArg(0, sCommand, 128);
int style = 0;
if (gSM_StyleCommands.GetValue(sCommand, style))
{
ChangeClientStyle(client, style, true);
return Plugin_Handled;
}
return Plugin_Continue;
}
public int Native_GetStyleCount(Handle handler, int numParams)
{
return (gI_Styles > 0)? gI_Styles:-1;
}
public int Native_GetOrderedStyles(Handle handler, int numParams)
{
return SetNativeArray(1, gI_OrderedStyles, GetNativeCell(2));
}
public int Native_GetStyleSetting(Handle handler, int numParams)
{
int style = GetNativeCell(1);
char sKey[64];
GetNativeString(2, sKey, sizeof(sKey));
int maxlength = GetNativeCell(4);
char sValue[SS_VAL_SZ];
bool ret = GetStyleSetting(style, sKey, sValue, sizeof(sValue));
SetNativeString(3, sValue, maxlength);
return ret;
}
bool GetStyleSetting(int style, const char[] key, char[] value, int size)
{
style_setting_t ss;
if (gSM_StyleKeys[style].GetArray(key, ss, sizeof(ss)))
{
strcopy(value, size, ss.str);
return true;
}
return false;
}
public int Native_GetStyleSettingInt(Handle handler, int numParams)
{
int style = GetNativeCell(1);
char sKey[64];
GetNativeString(2, sKey, sizeof(sKey));
return GetStyleSettingInt(style, sKey);
}
int GetStyleSettingInt(int style, char[] key)
{
float val[1];
gSM_StyleKeys[style].GetArray(key, val, 1);
return RoundToFloor(val[0]);
}
public int Native_GetStyleSettingBool(Handle handler, int numParams)
{
int style = GetNativeCell(1);
char sKey[256];
GetNativeString(2, sKey, 256);
return GetStyleSettingBool(style, sKey);
}
bool GetStyleSettingBool(int style, char[] key)
{
return GetStyleSettingFloat(style, key) != 0.0;
}
public any Native_GetStyleSettingFloat(Handle handler, int numParams)
{
int style = GetNativeCell(1);
char sKey[SS_KEY_SZ];
GetNativeString(2, sKey, sizeof(sKey));
return GetStyleSettingFloat(style, sKey);
}
float GetStyleSettingFloat(int style, char[] key)
{
float val[1];
gSM_StyleKeys[style].GetArray(key, val, 1);
return val[0];
}
public any Native_HasStyleSetting(Handle handler, int numParams)
{
int style = GetNativeCell(1);
char sKey[SS_KEY_SZ];
GetNativeString(2, sKey, sizeof(sKey));
return HasStyleSetting(style, sKey);
}
bool HasStyleSetting(int style, char[] key)
{
return gSM_StyleKeys[style].ContainsKey(key);
}
bool SetStyleSetting(int style, const char[] key, const char[] value, bool replace=true)
{
style_setting_t ss;
ss.f = StringToFloat(value);
int bytes = 4 + 1 + strcopy(ss.str, sizeof(ss.str), value);
return gSM_StyleKeys[style].SetArray(key, ss, ByteCountToCells(bytes), replace);
}
public any Native_SetStyleSetting(Handle handler, int numParams)
{
int style = GetNativeCell(1);
char sKey[SS_KEY_SZ];
GetNativeString(2, sKey, sizeof(sKey));
char sValue[SS_VAL_SZ];
GetNativeString(3, sValue, sizeof(sValue));
bool replace = GetNativeCell(4);
return SetStyleSetting(style, sKey, sValue, replace);
}
public any Native_SetStyleSettingFloat(Handle handler, int numParams)
{
int style = GetNativeCell(1);
char sKey[SS_KEY_SZ];
GetNativeString(2, sKey, sizeof(sKey));
float fValue = GetNativeCell(3);
bool replace = GetNativeCell(4);
return SetStyleSettingFloat(style, sKey, fValue, replace);
}
bool SetStyleSettingFloat(int style, char[] key, float value, bool replace=true)
{
style_setting_t ss;
ss.f = value;
int strcells = FloatToString(value, ss.str, sizeof(ss.str));
return gSM_StyleKeys[style].SetArray(key, ss, strcells+1, replace);
}
public any Native_SetStyleSettingBool(Handle handler, int numParams)
{
int style = GetNativeCell(1);
char sKey[SS_KEY_SZ];
GetNativeString(2, sKey, sizeof(sKey));
bool value = GetNativeCell(3);
bool replace = GetNativeCell(4);
return SetStyleSettingBool(style, sKey, value, replace);
}
bool SetStyleSettingBool(int style, char[] key, bool value, bool replace=true)
{
return SetStyleSettingFloat(style, key, value ? 1.0 : 0.0, replace);
}
public any Native_SetStyleSettingInt(Handle handler, int numParams)
{
int style = GetNativeCell(1);
char sKey[SS_KEY_SZ];
GetNativeString(2, sKey, sizeof(sKey));
int value = GetNativeCell(3);
bool replace = GetNativeCell(4);
return SetStyleSettingInt(style, sKey, value, replace);
}
bool SetStyleSettingInt(int style, char[] key, int value, bool replace=true)
{
style_setting_t ss;
ss.f = float(value);
int strcells = IntToString(value, ss.str, sizeof(ss.str));
return gSM_StyleKeys[style].SetArray(key, ss, strcells+1, replace);
}
public int Native_GetStyleStrings(Handle handler, int numParams)
{
int style = GetNativeCell(1);
int type = GetNativeCell(2);
int size = GetNativeCell(4);
char sValue[SS_VAL_SZ];
switch(type)
{
case sStyleName:
{
GetStyleSetting(style, "name", sValue, sizeof(stylestrings_t::sStyleName));
}
case sShortName:
{
GetStyleSetting(style, "shortname", sValue, sizeof(stylestrings_t::sShortName));
}
case sHTMLColor:
{
GetStyleSetting(style, "htmlcolor", sValue, sizeof(stylestrings_t::sHTMLColor));
}
case sChangeCommand:
{
GetStyleSetting(style, "command", sValue, sizeof(stylestrings_t::sChangeCommand));
}
case sClanTag:
{
GetStyleSetting(style, "clantag", sValue, sizeof(stylestrings_t::sClanTag));
}
case sSpecialString:
{
GetStyleSetting(style, "specialstring", sValue, sizeof(stylestrings_t::sSpecialString));
}
case sStylePermission:
{
GetStyleSetting(style, "permission", sValue, sizeof(stylestrings_t::sStylePermission));
}
default:
{
return -1;
}
}
return SetNativeString(3, sValue, size);
}
public int Native_GetStyleStringsStruct(Handle plugin, int numParams)
{
int style = GetNativeCell(1);
if (GetNativeCell(3) != sizeof(stylestrings_t))
{
return ThrowNativeError(200, "stylestrings_t does not match latest(got %i expected %i). Please update your includes and recompile your plugins", GetNativeCell(3), sizeof(stylestrings_t));
}
stylestrings_t strings;
GetStyleSetting(style, "name", strings.sStyleName, sizeof(strings.sStyleName));
GetStyleSetting(style, "shortname", strings.sShortName, sizeof(strings.sShortName));
GetStyleSetting(style, "htmlcolor", strings.sHTMLColor, sizeof(strings.sHTMLColor));
GetStyleSetting(style, "command", strings.sChangeCommand, sizeof(strings.sChangeCommand));
GetStyleSetting(style, "clantag", strings.sClanTag, sizeof(strings.sClanTag));
GetStyleSetting(style, "specialstring", strings.sSpecialString, sizeof(strings.sSpecialString));
GetStyleSetting(style, "permission", strings.sStylePermission, sizeof(strings.sStylePermission));
return SetNativeArray(2, strings, sizeof(stylestrings_t));
}
public int Native_HasStyleAccess(Handle handler, int numParams)
{
int style = GetNativeCell(2);
if (GetStyleSettingBool(style, "inaccessible") || GetStyleSettingInt(style, "enabled") <= 0)
{
return false;
}
return CheckCommandAccess(GetNativeCell(1), (strlen(gS_StyleOverride[style]) > 0)? gS_StyleOverride[style]:"<none>", gI_StyleFlag[style]);
}

View File

@ -0,0 +1,269 @@
/*
* tas-oblivious.inc file
* by: oblivious
*
* Originally from autogain (https://github.com/defiy/autogain) Mirror: https://github.com/PMArkive/autogain
* and edited to be part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#if defined _shavit_tas_oblivious_included
#endinput
#endif
#define _shavit_tas_oblivious_included
stock float normalize_yaw(float _yaw)
{
while (_yaw > 180.0) _yaw -= 360.0;
while (_yaw < -180.0) _yaw += 360.0; return _yaw;
}
stock float get_length_2d(float vec[3])
{
return SquareRoot(vec[0] * vec[0] + vec[1] * vec[1]);
}
stock float ground_delta_opt(int client, float angles[3], float move[3], float surface_friction,
float accelerate, float friction, float stopspeed)
{
float fore[3], side[3], wishvel[3];
float wishspeed;
GetAngleVectors(angles, fore, side, ZERO_VECTOR);
fore[2] = 0.0;
side[2] = 0.0;
NormalizeVector(fore, fore);
NormalizeVector(side, side);
wishvel[2] = 0.0;
for(int i = 0; i < 2; i++)
wishvel[i] = fore[i] * move[0] + side[i] * move[1];
wishspeed = GetVectorLength(wishvel);
float flMaxSpeed = Shavit_GetStyleSettingFloat(Shavit_GetBhopStyle(client), "runspeed");
if(wishspeed > flMaxSpeed && flMaxSpeed != 0.0) wishspeed = flMaxSpeed;
float velocity[3];
GetEntPropVector(client, Prop_Data, "m_vecVelocity", velocity);
float speed = GetVectorLength(velocity);
float interval_per_tick = GetTickInterval();
float accelspeed = accelerate * wishspeed * interval_per_tick * surface_friction;
float control = speed;
if (control < stopspeed) control = stopspeed;
float drop = control * friction * interval_per_tick * surface_friction;
float newspeed = speed - drop;
if (newspeed < 0.0) newspeed = 0.0;
float tmp = wishspeed - accelspeed;
if (tmp <= newspeed)
{
float gamma = RadToDeg(ArcCosine(tmp / newspeed));
float vel_dir_ang = RadToDeg(ArcTangent2(velocity[1], velocity[0]));
vel_dir_ang = normalize_yaw(vel_dir_ang);
float accel_yaw = RadToDeg(ArcTangent2(wishvel[1], wishvel[0]));
float diffm = vel_dir_ang - gamma;
float diffp = vel_dir_ang + gamma;
diffm = normalize_yaw(diffm - accel_yaw);
diffp = normalize_yaw(diffp - accel_yaw);
float delta_opt = 0.0;
if (FloatAbs(diffm) <= FloatAbs(diffp))
delta_opt = -diffm;
else
delta_opt = -diffp;
delta_opt = normalize_yaw(delta_opt);
return delta_opt;
}
return 0.0;
}
stock Action ObliviousOnPlayerRunCmd(int client, int& buttons, int& impulse, float vel[3], float angles[3], int& weapon, int& subtype, int& cmdnum, int& tickcount, int& seed, int mouse[2],
float air_accelerate, float surface_friction, float flAirSpeedCap, float flMaxMove,
bool no_speed_loss)
{
float flMaxSpeed = Shavit_GetStyleSettingFloat(Shavit_GetBhopStyle(client), "runspeed");
bool set_back = true;
if (vel[0] != 0.0 || vel[1] != 0.0)
set_back = false;
if (set_back)
vel[1] = flMaxMove;
float velocity[3], velocity_opt[3];
GetEntPropVector(client, Prop_Data, "m_vecVelocity", velocity);
velocity_opt[0] = velocity[0]; velocity_opt[1] = velocity[1]; velocity_opt[2] = velocity[2];
float vel_yaw = ArcTangent2(velocity[1], velocity[0]) * 180.0 / FLOAT_PI;
float delta_opt = -normalize_yaw(angles[1] - vel_yaw);
if (get_length_2d(velocity) == 0.0)
delta_opt = 90.0;
if (vel[0] != 0.0 && vel[1] == 0.0)
{
float sign = vel[0] > 0.0 ? -1.0 : 1.0;
delta_opt = -normalize_yaw(angles[1] - (vel_yaw + (90.0 * sign)));
}
if (vel[0] != 0.0 && vel[1] != 0.0)
{
float sign = vel[1] > 0.0 ? -1.0 : 1.0;
if (vel[0] < 0.0)
sign = -sign;
delta_opt = -normalize_yaw(angles[1] - (vel_yaw + (45.0 * sign)));
}
float frac = 1.0;
if (buttons & IN_DUCK && no_speed_loss)
frac = 0.34;
float _addspeed = 0.0;
if (!set_back)
{
float _fore[3], _side[3], _wishvel[3], _wishdir[3];
float _wishspeed, _wishspd, _currentspeed;
GetAngleVectors(angles, _fore, _side, ZERO_VECTOR);
_fore[2] = 0.0; _side[2] = 0.0;
NormalizeVector(_fore, _fore); NormalizeVector(_side, _side);
for(int i = 0; i < 2; i++)
_wishvel[i] = _fore[i] * vel[0] * frac + _side[i] * vel[1] * frac;
_wishspeed = NormalizeVector(_wishvel, _wishdir);
if(_wishspeed > flMaxSpeed && flMaxSpeed != 0.0) _wishspeed = flMaxSpeed;
_wishspd = _wishspeed;
if (_wishspd > flAirSpeedCap)
_wishspd = flAirSpeedCap;
_currentspeed = GetVectorDotProduct(velocity, _wishdir);
_addspeed = _wishspd - _currentspeed;
if (_addspeed < 0.0)
_addspeed = 0.0;
}
float fore[3], side[3], wishvel[3], wishdir[3];
float wishspeed, wishspd, addspeed, currentspeed;
float tmp[3];
tmp[0] = 0.0; tmp[2] = 0.0;
tmp[1] = normalize_yaw(angles[1] + delta_opt);
GetAngleVectors(tmp, fore, side, ZERO_VECTOR);
fore[2] = 0.0; side[2] = 0.0;
NormalizeVector(fore, fore); NormalizeVector(side, side);
for(int i = 0; i < 2; i++)
wishvel[i] = fore[i] * vel[0] * frac + side[i] * vel[1] * frac;
wishspeed = NormalizeVector(wishvel, wishdir);
if(wishspeed > flMaxSpeed && wishspeed != 0.0) wishspeed = flMaxSpeed;
wishspd = wishspeed;
if (wishspd > flAirSpeedCap)
wishspd = flAirSpeedCap;
currentspeed = GetVectorDotProduct(velocity, wishdir);
addspeed = wishspd - currentspeed;
if (no_speed_loss)
{
if (_addspeed > addspeed)
{
addspeed = _addspeed - addspeed;
}
else
{
addspeed -= _addspeed;
}
}
else
{
addspeed = addspeed - _addspeed;
if (addspeed > flAirSpeedCap)
addspeed = flAirSpeedCap;
}
if (buttons & IN_DUCK)
{
float vel2d[3]; vel2d[0] = velocity[0]; vel2d[1] = velocity[1];
//PrintToChat(client, "%f %f\n", GetVectorLength(vel2d), addspeed);
}
if (addspeed < 0.0)
addspeed = 0.0;
float accelspeed = wishspeed * air_accelerate * GetTickInterval() * surface_friction;
if (accelspeed > addspeed)
accelspeed = addspeed;
for (int i = 0; i < 3; i++)
velocity_opt[i] += accelspeed * wishdir[i];
float new_vel[3];
float numer = velocity_opt[0] * velocity[0] + velocity_opt[1] * velocity[1];
//float denom = SquareRoot(velocity_opt[0] * velocity_opt[0] + velocity_opt[1] * velocity_opt[1]) * SquareRoot(velocity[0] * velocity[0] + velocity[1] * velocity[1]);
float denom = get_length_2d(velocity_opt) * get_length_2d(velocity);
float ang = 0.0;
if (denom > numer)
ang = ArcCosine(numer / denom) * 180.0 / FLOAT_PI;
if (vel[1] < 0.0) ang = -ang;
float st = Sine(ang * FLOAT_PI / 180.0);
float ct = Cosine(ang * FLOAT_PI / 180.0);
new_vel[0] = (velocity_opt[0] * ct) - (velocity_opt[1] * st);
new_vel[1] = (velocity_opt[0] * st) + (velocity_opt[1] * ct);
new_vel[2] = velocity_opt[2];
float base_vel[3];
GetEntPropVector(client, Prop_Data, "m_vecBaseVelocity", base_vel);
//PrintToChat(client, "%.2f, %.2f, %.2f", base_vel[0], base_vel[1], base_vel[2]);
if (GetVectorLength(new_vel) < 99999.0 && GetVectorLength(new_vel) > 0.0)
{
SetEntPropVector(client, Prop_Data, "m_vecVelocity", new_vel);
SetEntPropVector(client, Prop_Data, "m_vecAbsVelocity", new_vel);
}
if (set_back)
vel[1] = 0.0;
return Plugin_Continue;
}

View File

@ -0,0 +1,415 @@
/*
* tas-xutax.inc file
* by: xutaxkamay, KiD Fearless
*
* Retrieved from KiD-TAS (https://github.com/kidfearless/KiD-TAS)
* and edited to be part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#if defined _shavit_tas_xutax_included
#endinput
#endif
#define _shavit_tas_xutax_included
// reference code for CGameMovement::AirAccelerate & CGameMovement::AirMove at:
// https://github.com/ValveSoftware/source-sdk-2013/blob/0d8dceea4310fde5706b3ce1c70609d72a38efdf/mp/src/game/shared/gamemovement.cpp#L1707-L1799
stock float AngleNormalize(float flAngle)
{
if (flAngle > 180.0)
flAngle -= 360.0;
else if (flAngle < -180.0)
flAngle += 360.0;
return flAngle;
}
stock float Vec2DToYaw(float vec[2])
{
float flYaw = 0.0;
if (vec[0] != 0.0 || vec[1] != 0.0)
{
float vecNormalized[2];
float flLength = SquareRoot(vec[0] * vec[0] + vec[1] * vec[1]);
vecNormalized[0] = vec[0] / flLength;
vecNormalized[1] = vec[1] / flLength;
// Credits to Valve.
flYaw = ArcTangent2(vecNormalized[1], vecNormalized[0]) * (180.0 / FLOAT_PI);
flYaw = AngleNormalize(flYaw);
}
return flYaw;
}
/*
* So our problem here is to find a wishdir that no matter the angles we choose, it should go to the direction we want.
* So forward/right vector changing but not sidemove and forwardmove for the case where we modify our angles. (1)
* But in our case we want sidemove and forwardmove values changing and not the forward/right vectors. (2)
* So our unknown variables is fmove and smove to know the (2) case. But we know the (1) case so we can solve this into a linear equation.
* To make it more simplier, we know the wishdir values and forward/right vectors, but we do not know the fowardmove and sidemove variables
* and that's what we want to solve.
* That's what is doing this function, but only in 2D since we can only move forward or side.
* But, for noclip (3D) it's a different story that I will let you discover, same method, but 3 equations and 3 unknown variables (forwardmove, sidemove, upmove).
*/
stock void Solve2DMovementsVars(float vecWishDir[2], float vecForward[2], float vecRight[2], float &flForwardMove, float &flSideMove, float flMaxMove)
{
// wishdir[0] = foward[0] * forwardmove + right[0] * sidemove;
// wishdir[1] = foward[1] * forwardmove + right[1] * sidemove;
// Let's translate this to letters.
// v = a * b + c * d
// w = e * b + f * d
// v = wishdir[0]; w = wishdir[1]...
// Now let's solve it with online solver https://quickmath.com/webMathematica3/quickmath/equations/solve/advanced.jsp
// https://cdn.discordapp.com/attachments/609163806085742622/675477245178937385/c3ca4165c30b3b342e57b903a3ded367-3.png
float v = vecWishDir[0];
float w = vecWishDir[1];
float a = vecForward[0];
float c = vecRight[0];
float e = vecForward[1];
float f = vecRight[1];
float flDivide = (c * e - a * f);
if(flDivide == 0.0)
{
flForwardMove = flMaxMove;
flSideMove = 0.0;
}
else
{
flForwardMove = (c * w - f * v) / flDivide;
flSideMove = (e * v - a * w) / flDivide;
}
}
stock float GetThetaAngleInAir(float flVelocity[2], float flAirAccelerate, float flMaxSpeed, float flSurfaceFriction, float flFrametime, float flAirSpeedCap)
{
// In order to solve this, we must check that accelspeed < 30
// so it applies the correct strafing method.
// So there is basically two cases:
// if 30 - accelspeed <= 0 -> We use the perpendicular of velocity.
// but if 30 - accelspeed > 0 the dot product must be equal to = 30 - accelspeed
// in order to get the best gain.
// First case is theta == 90
// How to solve the second case?
// here we go
// d = velocity2DLength * cos(theta)
// cos(theta) = d / velocity2D
// theta = arcos(d / velocity2D)
float flAccelSpeed = flAirAccelerate * flMaxSpeed * flSurfaceFriction * flFrametime;
float flWantedDotProduct = flAirSpeedCap - flAccelSpeed;
if (flWantedDotProduct > 0.0)
{
float flVelLength2D = SquareRoot(flVelocity[0] * flVelocity[0] + flVelocity[1] * flVelocity[1]);
if(flVelLength2D == 0.0)
{
return 90.0;
}
float flCosTheta = flWantedDotProduct / flVelLength2D;
if (flCosTheta > 1.0)
{
flCosTheta = 1.0;
}
else if(flCosTheta < -1.0)
{
flCosTheta = -1.0;
}
float flTheta = ArcCosine(flCosTheta) * (180.0 / FLOAT_PI);
return flTheta;
}
else
{
return 90.0;
}
}
// Same as above, but this time we calculate max delta angle
// so we can change between normal strafer and autostrafer depending on the player's viewangles difference.
/*float GetMaxDeltaInAir(float flVelocity[2], float flAirAccelerate, float flMaxSpeed, float flSurfaceFriction, float flFrametime)
{
float flAccelSpeed = flAirAccelerate * flMaxSpeed * flSurfaceFriction * flFrametime;
if (flAccelSpeed >= g_flAirSpeedCap)
{
flAccelSpeed = g_flAirSpeedCap;
}
float flVelLength2D = SquareRoot(flVelocity[0] * flVelocity[0] + flVelocity[1] * flVelocity[1]);
float flMaxDelta = ArcTangent2(flAccelSpeed, flVelLength2D) * (180 / FLOAT_PI);
return flMaxDelta;
}*/
stock void SimulateAirAccelerate(float flVelocity[2], float flWishDir[2], float flAirAccelerate, float flMaxSpeed, float flSurfaceFriction, float flFrametime, float flVelocityOutput[2], float flAirSpeedCap)
{
float flWishSpeedCapped = flMaxSpeed;
// Cap speed
if( flWishSpeedCapped > flAirSpeedCap )
flWishSpeedCapped = flAirSpeedCap;
// Determine veer amount
float flCurrentSpeed = flVelocity[0] * flWishDir[0] + flVelocity[1] * flWishDir[1];
// See how much to add
float flAddSpeed = flWishSpeedCapped - flCurrentSpeed;
// If not adding any, done.
if( flAddSpeed <= 0.0 )
{
return;
}
// Determine acceleration speed after acceleration
float flAccelSpeed = flAirAccelerate * flMaxSpeed * flFrametime * flSurfaceFriction;
// Cap it
if( flAccelSpeed > flAddSpeed )
{
flAccelSpeed = flAddSpeed;
}
flVelocityOutput[0] = flVelocity[0] + flAccelSpeed * flWishDir[0];
flVelocityOutput[1] = flVelocity[1] + flAccelSpeed * flWishDir[1];
}
// The idea is to get the maximum angle
stock float GetMaxDeltaInAir(float flVelocity[2], float flMaxSpeed, float flSurfaceFriction, bool bLeft, float flAirAccelerate, float flAirSpeedCap)
{
float flFrametime = GetTickInterval();
float flTheta = GetThetaAngleInAir(flVelocity, flAirAccelerate, flMaxSpeed, flSurfaceFriction, flFrametime, flAirSpeedCap);
// Convert velocity 2D to angle.
float flYawVelocity = Vec2DToYaw(flVelocity);
// Get the best yaw direction on the right.
float flBestYawRight = AngleNormalize(flYawVelocity + flTheta);
// Get the best yaw direction on the left.
float flBestYawLeft = AngleNormalize(flYawVelocity - flTheta);
float flTemp[3], vecBestLeft3D[3], vecBestRight3D[3];
flTemp[0] = 0.0;
flTemp[1] = flBestYawLeft;
flTemp[2] = 0.0;
GetAngleVectors(flTemp, vecBestLeft3D, ZERO_VECTOR, ZERO_VECTOR);
flTemp[0] = 0.0;
flTemp[1] = flBestYawRight;
flTemp[2] = 0.0;
GetAngleVectors(flTemp, vecBestRight3D, ZERO_VECTOR, ZERO_VECTOR);
float vecBestRight[2], vecBestLeft[2];
vecBestRight[0] = vecBestRight3D[0];
vecBestRight[1] = vecBestRight3D[1];
vecBestLeft[0] = vecBestLeft3D[0];
vecBestLeft[1] = vecBestLeft3D[1];
float flCalcVelocityLeft[2], flCalcVelocityRight[2];
// Simulate air accelerate function in order to get the new max gain possible on both side.
SimulateAirAccelerate(flVelocity, vecBestLeft, flAirAccelerate, flMaxSpeed, flFrametime, flSurfaceFriction, flCalcVelocityLeft, flAirSpeedCap);
SimulateAirAccelerate(flVelocity, vecBestRight, flAirAccelerate, flMaxSpeed, flFrametime, flSurfaceFriction, flCalcVelocityRight, flAirSpeedCap);
float flNewBestYawLeft = Vec2DToYaw(flCalcVelocityLeft);
float flNewBestYawRight = Vec2DToYaw(flCalcVelocityRight);
// Then get the difference in order to find the maximum angle.
if (bLeft)
{
return FloatAbs(AngleNormalize(flYawVelocity - flNewBestYawLeft));
}
else
{
return FloatAbs(AngleNormalize(flYawVelocity - flNewBestYawRight));
}
// Do an estimate otherwhise.
// return FloatAbs(AngleNormalize(flNewBestYawLeft - flNewBestYawRight) / 2.0);
}
stock void GetIdealMovementsInAir(float flYawWantedDir, float flVelocity[2], float flMaxSpeed, float flSurfaceFriction, float &flForwardMove, float &flSideMove, bool bPreferRight, float flAirAccelerate, float flMaxMove, float flAirSpeedCap)
{
float flFrametime = GetTickInterval();
float flYawVelocity = Vec2DToYaw(flVelocity);
// Get theta angle
float flTheta = GetThetaAngleInAir(flVelocity, flAirAccelerate, flMaxSpeed, flSurfaceFriction, flFrametime, flAirSpeedCap);
// Get the best yaw direction on the right.
float flBestYawRight = AngleNormalize(flYawVelocity + flTheta);
// Get the best yaw direction on the left.
float flBestYawLeft = AngleNormalize(flYawVelocity - flTheta);
float vecBestDirLeft[3], vecBestDirRight[3];
float tempAngle[3];
tempAngle[0] = 0.0;
tempAngle[1] = flBestYawRight;
tempAngle[2] = 0.0;
GetAngleVectors(tempAngle, vecBestDirRight, ZERO_VECTOR, ZERO_VECTOR);
tempAngle[0] = 0.0;
tempAngle[1] = flBestYawLeft;
tempAngle[2] = 0.0;
GetAngleVectors(tempAngle, vecBestDirLeft, ZERO_VECTOR, ZERO_VECTOR);
// Our wanted direction.
float vecBestDir[2];
// Let's follow the most the wanted direction now with max possible gain.
float flDiffYaw = AngleNormalize(flYawWantedDir - flYawVelocity);
if (flDiffYaw > 0.0)
{
vecBestDir[0] = vecBestDirRight[0];
vecBestDir[1] = vecBestDirRight[1];
}
else if(flDiffYaw < 0.0)
{
vecBestDir[0] = vecBestDirLeft[0];
vecBestDir[1] = vecBestDirLeft[1];
}
else
{
// Going straight.
if (bPreferRight)
{
vecBestDir[0] = vecBestDirRight[0];
vecBestDir[1] = vecBestDirRight[1];
}
else
{
vecBestDir[0] = vecBestDirLeft[0];
vecBestDir[1] = vecBestDirLeft[1];
}
}
float vecForwardWantedDir3D[3], vecRightWantedDir3D[3];
float vecForwardWantedDir[2], vecRightWantedDir[2];
tempAngle[0] = 0.0;
tempAngle[1] = flYawWantedDir;
tempAngle[2] = 0.0;
// Convert our yaw wanted direction to vectors.
GetAngleVectors(tempAngle, vecForwardWantedDir3D, vecRightWantedDir3D, ZERO_VECTOR);
vecForwardWantedDir[0] = vecForwardWantedDir3D[0];
vecForwardWantedDir[1] = vecForwardWantedDir3D[1];
vecRightWantedDir[0] = vecRightWantedDir3D[0];
vecRightWantedDir[1] = vecRightWantedDir3D[1];
// Solve the movement variables from our wanted direction and the best gain direction.
Solve2DMovementsVars(vecBestDir, vecForwardWantedDir, vecRightWantedDir, flForwardMove, flSideMove, flMaxMove);
float flLengthMovements = SquareRoot(flForwardMove * flForwardMove + flSideMove * flSideMove);
if(flLengthMovements != 0.0)
{
flForwardMove /= flLengthMovements;
flSideMove /= flLengthMovements;
}
}
stock Action XutaxOnPlayerRunCmd(int client, int& buttons, int& impulse, float vel[3], float angles[3], int& weapon, int& subtype, int& cmdnum, int& tickcount, int& seed, int mouse[2],
float flAirAccelerate, float flSurfaceFriction, float flAirSpeedCap, float flMaxMove, float flOldYawAngle, float fPower)
{
// clear out forward because Surf_W_Okay is nice...
vel[0] = 0.0;
float flFowardMove, flSideMove;
float flMaxSpeed = Shavit_GetStyleSettingFloat(Shavit_GetBhopStyle(client), "runspeed");
float flVelocity[3], flVelocity2D[2];
GetEntPropVector(client, Prop_Data, "m_vecVelocity", flVelocity);
flVelocity2D[0] = flVelocity[0];
flVelocity2D[1] = flVelocity[1];
// PrintToChat(client, "%f", SquareRoot(flVelocity2D[0] * flVelocity2D[0] + flVelocity2D[1] * flVelocity2D[1]));
GetIdealMovementsInAir(angles[1], flVelocity2D, flMaxSpeed, flSurfaceFriction, flFowardMove, flSideMove, true, flAirAccelerate, flMaxMove, flAirSpeedCap);
float flAngleDifference = AngleNormalize(angles[1] - flOldYawAngle);
float flCurrentAngles = FloatAbs(flAngleDifference);
// Right
if (flAngleDifference < 0.0)
{
float flMaxDelta = GetMaxDeltaInAir(flVelocity2D, flMaxSpeed, flSurfaceFriction, true, flAirAccelerate, flAirSpeedCap);
if (flCurrentAngles <= flMaxDelta * fPower)
{
vel[0] = flFowardMove * flMaxMove;
vel[1] = flSideMove * flMaxMove;
}
else
{
vel[1] = flMaxMove;
}
}
else if (flAngleDifference > 0.0)
{
float flMaxDelta = GetMaxDeltaInAir(flVelocity2D, flMaxSpeed, flSurfaceFriction, false, flAirAccelerate, flAirSpeedCap);
if (flCurrentAngles <= flMaxDelta * fPower)
{
vel[0] = flFowardMove * flMaxMove;
vel[1] = flSideMove * flMaxMove;
}
else
{
vel[1] = -flMaxMove;
}
}
else
{
vel[0] = flFowardMove * flMaxMove;
vel[1] = flSideMove * flMaxMove;
}
return Plugin_Continue;
}

View File

@ -0,0 +1,242 @@
/*
* shavit's Timer - tas.inc file
* by: xutaxkamay, shavit, rtldg
*
* This file is part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#if defined _shavit_tas_included
#endinput
#endif
#define _shavit_tas_included
enum AutostrafeOverride
{
AutostrafeOverride_Normal, // only w/s disables autostrafe
AutostrafeOverride_Surf, // w/s always disables, a/d only over surf ramps
AutostrafeOverride_Surf_W_Okay, // s always disables, a/d only over surf ramps
AutostrafeOverride_All, // all keys disable
AutostrafeOverride_Size // size
};
enum AutostrafeType
{
AutostrafeType_Any = -1,
AutostrafeType_Disabled = 0,
AutostrafeType_1Tick = 1, // xutaxkamay
AutostrafeType_Autogain, // oblivious
AutostrafeType_AutogainNoSpeedLoss, // oblivious
AutostrafeType_Basic, //
AutostrafeType_Size
};
/**
* Sets whether the client has the autostrafe/strafehack enabled.
*
* @param client Client index
* @param value New value to set the autostrafe/strafehack to.
* @noreturn
*/
native void Shavit_SetAutostrafeEnabled(int client, bool value);
/**
* Retrieves whether the client has the autostrafe/strafehack enabled.
*
* @param client Client index
* @return The current autostrafe/strafehack enabled value.
*/
native bool Shavit_GetAutostrafeEnabled(int client);
/**
* Sets the autostrafe/strafehack type on the given client index.
*
* @param client Client index of the player to set the autostrafe/strafehack on.
* @param value New type to set the strafehack to.
* @noreturn
*/
native void Shavit_SetAutostrafeType(int client, AutostrafeType value);
/**
* Retrieves the current strafehack type for the given client index.
*
* @param client Client index of the player to get the strafehack type from.
* @return The current strafehack type.
*/
native AutostrafeType Shavit_GetAutostrafeType(int client);
/**
* Sets the strafehack power on the given client index. Power is the cut off point before it will turn into an autostrafe. 1.0 is the default.
*
* @param client Client index of the player to set the power on.
* @param value New power setting.
* @noreturn
*/
native void Shavit_SetAutostrafePower(int client, float value);
/**
* Retrieves the current strafehack power for the given client index. Default is 1.0
*
* @param client Client index of the player to get the strafehack power.
* @return The current strafehack power.
*/
native float Shavit_GetAutostrafePower(int client);
/**
* Sets the key override type on the given client index.
*
* @param client Client index
* @param value New type to set the key override to.
* @noreturn
*/
native void Shavit_SetAutostrafeKeyOverride(int client, AutostrafeOverride value);
/**
* Retrieves the current key override type for the given client index.
*
* @param client Client index
* @return The current key override type.
*/
native AutostrafeOverride Shavit_GetAutostrafeKeyOverride(int client);
/**
* Sets whether the client has automatic prestrafe enabled.
*
* @param client Client index
* @param value New value to set the automatic prestrafe to.
* @noreturn
*/
native void Shavit_SetAutoPrestrafe(int client, bool value);
/**
* Retrieves whether the client has automatic prestrafe enabled.
*
* @param client Client index
* @return The current auto prestrafe value.
*/
native bool Shavit_GetAutoPrestrafe(int client);
/**
* Sets whether the client automatically jumps when they leave the start zone.
*
* @param client Client index
* @param value New value to set the automatic jump to.
* @noreturn
*/
native void Shavit_SetAutoJumpOnStart(int client, bool value);
/**
* Retrieves whether the client automatically jumps when they leave the start zone.
*
* @param client Client index
* @return The current auto jump value.
*/
native bool Shavit_GetAutoJumpOnStart(int client);
/**
* Sets whether the client uses the autogain basic strafer.
*
* @param client Client index
* @param value New value to set the autogain basic strafer to.
* @noreturn
*/
native void Shavit_SetAutogainBasicStrafer(int client, bool value);
/**
* Retrieves whether the client has has enabled the autogain basic strafer :tm:
*
* @param client Client index
* @return The current autogain basic strafer setting.
*/
native bool Shavit_GetAutogainBasicStrafer(int client);
// taken from shavit's oryx
stock bool IsSurfing(int client)
{
float fPosition[3];
GetClientAbsOrigin(client, fPosition);
float fEnd[3];
fEnd = fPosition;
fEnd[2] -= 64.0;
float fMins[3];
GetEntPropVector(client, Prop_Send, "m_vecMins", fMins);
float fMaxs[3];
GetEntPropVector(client, Prop_Send, "m_vecMaxs", fMaxs);
Handle hTR = TR_TraceHullFilterEx(fPosition, fEnd, fMins, fMaxs, MASK_PLAYERSOLID, TRFilter_NoPlayers, client);
if(TR_DidHit(hTR))
{
float fNormal[3];
TR_GetPlaneNormal(hTR, fNormal);
delete hTR;
// If the plane normal's Z axis is 0.7 or below (alternatively, -0.7 when upside-down) then it's a surf ramp.
// https://github.com/alliedmodders/hl2sdk/blob/92dcf04225a278b75170cc84917f04e98f5d08ec/game/server/physics_main.cpp#L1059
// https://github.com/ValveSoftware/source-sdk-2013/blob/0d8dceea4310fde5706b3ce1c70609d72a38efdf/mp/src/game/server/physics_main.cpp#L1065
return (-0.7 <= fNormal[2] <= 0.7);
}
delete hTR;
return false;
}
stock bool TRFilter_NoPlayers(int entity, int mask, any data)
{
return !(1 <= entity <= MaxClients);
}
public SharedPlugin __pl_shavit_tas =
{
name = "shavit-tas",
file = "shavit-tas.smx",
#if defined REQUIRE_PLUGIN
required = 1
#else
required = 0
#endif
};
#if !defined REQUIRE_PLUGIN
public void __pl_shavit_tas_SetNTVOptional()
{
MarkNativeAsOptional("Shavit_SetAutostrafeEnabled");
MarkNativeAsOptional("Shavit_GetAutostrafeEnabled");
MarkNativeAsOptional("Shavit_SetAutostrafeType");
MarkNativeAsOptional("Shavit_GetAutostrafeType");
MarkNativeAsOptional("Shavit_SetAutostrafePower");
MarkNativeAsOptional("Shavit_GetAutostrafePower");
MarkNativeAsOptional("Shavit_SetAutostrafeKeyOverride");
MarkNativeAsOptional("Shavit_GetAutostrafeKeyOverride");
MarkNativeAsOptional("Shavit_SetAutoPrestrafe");
MarkNativeAsOptional("Shavit_GetAutoPrestrafe");
MarkNativeAsOptional("Shavit_SetAutoJumpOnStart");
MarkNativeAsOptional("Shavit_GetAutoJumpOnStart");
MarkNativeAsOptional("Shavit_SetEdgeJump");
MarkNativeAsOptional("Shavit_GetEdgeJump");
MarkNativeAsOptional("Shavit_SetAutogainBasicStrafer");
MarkNativeAsOptional("Shavit_GetAutogainBasicStrafer");
}
#endif

View File

@ -0,0 +1,116 @@
/*
* shavit's Timer - weapon stocks
* by: shavit, psychonic, Kxnrl, rtldg
*
* This file is part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#if defined _shavit_weapon_stocks_included
#endinput
#endif
#define _shavit_weapon_stocks_included
// based on code by Kxnrl in SurfTimer
// which is based on code by splewis from csgo-deathmatch?
// https://github.com/Maxximou5/csgo-deathmatch/pull/24/commits/207cbfe3f1b9a1082c4a710841c190bb753485dc#diff-2c9694977d0a3fe527ca8b484add6a58f53bab303e5dcaa583cb2917ec04d89cR3122-R3130
// https://github.com/surftimer/SurfTimer/commit/134887a29a396e01a721a78ab69e81a80593411a#diff-0b2bae39ae9de87ea2952bfd12c8777c7301e06ce683acc518229704cf024c33R4894-R4910
stock int GiveSkinnedWeapon(int client, const char[] classname)
{
int target_team = 0;
int current_team = 0;
if (StrContains(classname, "usp") != -1)
{
target_team = 3;
}
else if (StrContains(classname, "glock") != -1)
{
target_team = 2;
}
if (target_team != 0)
{
current_team = GetEntProp(client, Prop_Send, "m_iTeamNum");
if (current_team != target_team)
{
SetEntProp(client, Prop_Send, "m_iTeamNum", target_team);
}
}
int weapon = GivePlayerItem(client, classname);
if (current_team != target_team)
{
SetEntProp(client, Prop_Send, "m_iTeamNum", current_team);
}
return weapon;
}
// based on testsuite code from psychonic
// https://github.com/alliedmodders/sourcemod/blob/c5701503185d7e1cb8411c7347abdd31eee75c4e/plugins/testsuite/entpropelements.sp#L88-L96
stock void RemoveAllWeapons(int client)
{
int weapon = -1, max = GetEntPropArraySize(client, Prop_Send, "m_hMyWeapons");
for (int i = 0; i < max; i++)
{
if ((weapon = GetEntPropEnt(client, Prop_Send, "m_hMyWeapons", i)) == -1)
continue;
if (RemovePlayerItem(client, weapon))
{
AcceptEntityInput(weapon, "Kill");
}
}
}
stock void SetMaxWeaponAmmo(int client, int weapon, bool setClip1)
{
static EngineVersion engine = Engine_Unknown;
if (engine == Engine_Unknown)
{
engine = GetEngineVersion();
}
int iAmmo = GetEntProp(weapon, Prop_Send, "m_iPrimaryAmmoType");
if (iAmmo < 0)
{
return;
}
SetEntProp(client, Prop_Send, "m_iAmmo", 255, 4, iAmmo);
if (engine == Engine_CSGO)
{
SetEntProp(weapon, Prop_Send, "m_iPrimaryReserveAmmoCount", 255);
}
if (setClip1)
{
int amount = GetEntProp(weapon, Prop_Send, "m_iClip1") + 1;
if (HasEntProp(weapon, Prop_Send, "m_bBurstMode") && GetEntProp(weapon, Prop_Send, "m_bBurstMode"))
{
amount += 2;
}
SetEntProp(weapon, Prop_Data, "m_iClip1", amount);
}
}

View File

@ -0,0 +1,279 @@
/*
* shavit's Timer - wr.inc file
* by: shavit, SaengerItsWar, rtldg, KiD Fearless, rtldg, BoomShotKapow
*
* This file is part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#if defined _shavit_wr_included
#endinput
#endif
#define _shavit_wr_included
/**
* Like Shavit_OnFinish, but after the insertion query was called.
* Called from shavit-wr
*
* @param client Client index.
* @param style Style the record was done on.
* @param time Record time.
* @param jumps Jumps amount.
* @param strafes Amount of strafes.
* @param sync Sync percentage (0.0 to 100.0) or -1.0 when not measured.
* @param rank Rank on map.
* @param overwrite 1 - brand new record. 2 - update.
* @param track Timer track.
* @param oldtime The player's best time on the map before this finish.
* @param perfs Perfect jump percentage (0.0 to 100.0) or 100.0 when not measured.
* @param avgvel Player's average velocity throughout the run.
* @param maxvel Player's highest reached velocity.
* @param timestamp System time of when player finished.
* @noreturn
*/
forward void Shavit_OnFinish_Post(int client, int style, float time, int jumps, int strafes, float sync, int rank, int overwrite, int track, float oldtime, float perfs, float avgvel, float maxvel, int timestamp);
/**
* Called when there's a new WR on the map.
*
* @param client Client index.
* @param style Style the record was done on.
* @param time Record time.
* @param jumps Jumps amount.
* @param strafes Amount of strafes.
* @param sync Sync percentage (0.0 to 100.0) or -1.0 when not measured.
* @param track Timer track.
* @param oldwr Time of the old WR. 0.0 if there's none.
* @param oldtime The player's best time on the map before this finish.
* @param perfs Perfect jump percentage (0.0 to 100.0) or 100.0 when not measured.
* @param avgvel Player's average velocity throughout the run.
* @param maxvel Player's highest reached velocity.
* @param timestamp System time of when player finished.
* @noreturn
*/
forward void Shavit_OnWorldRecord(int client, int style, float time, int jumps, int strafes, float sync, int track, float oldwr, float oldtime, float perfs, float avgvel, float maxvel, int timestamp);
/**
* Called when an admin deletes a WR.
*
* @param style Style the record was done on.
* @param id Record ID. -1 if mass deletion.
* @param track Timer track.
* @param accountid The account ID of the wr holder
* @param mapname The map name.
* @noreturn
*/
forward void Shavit_OnWRDeleted(int style, int id, int track, int accountid, const char[] mapname);
/**
* Called after shavit-wr caches the current map's WRs.
*
* @noreturn
*/
forward void Shavit_OnWorldRecordsCached();
/**
* Called before the timer finish message is printed to the users.
*
* @param client Client index.
* @param everyone Is the message printed to everyone, or just the client?
* @param snapshot A snapshot of the client's timer when printing the message.
* @param overwrite Modify the database? 0 - no. 1 - brand new record. 2 - new personal best.
* @param rank Rank on map.
* @param message The finish message.
* @param maxlen Buffer size of message.
* @param message2 A second line of info that is printed on finish.
* @param maxlen2 Buffer size of message2.
*
* @return Plugin_Handled or Plugin_Stop to stop the message. Anything else to use new values.
*/
forward Action Shavit_OnFinishMessage(int client, bool &everyone, timer_snapshot_t snapshot, int overwrite, int rank, char[] message, int maxlen, char[] message2, int maxlen2);
/**
* Retrieves the world record for the given style/track.
*
* @param style Style to get the WR for.
* @param track Timer track.
* @return World record for the specified settings.
*/
native float Shavit_GetWorldRecord(int style, int track);
/**
* Reloads WR leaderboards cache for the current map.
*
* @noreturn
*/
native void Shavit_ReloadLeaderboards();
/**
* Saves the WR's record ID for the current map on a variable.
* Unused in base plugins, as of pre-1.4b.
*
* @param style Style to get the WR for.
* @param time Reference to the time variable. 0.0 will be returned if no records.
* @param track Timer track.
* @noreturn
*/
native void Shavit_GetWRRecordID(int style, int &recordid, int track);
/**
* Saves the WR's player name on the map on a variable.
*
* @param style Style to get the WR for.
* @param wrname Reference to the name variable.
* @param wrmaxlength Max length for the string.
* @param track Timer track.
* @return Returns true if the player's name has been cached. False if it hasn't. `wrname` is filled with the player's name if available, otherwise the steamid if the name isn't cached, and lastly the string "none" if neither the name or steamid is available.
*/
native bool Shavit_GetWRName(int style, char[] wrname, int wrmaxlength, int track);
/**
* Retrieves the best time of a player.
*
* @param client Client index.
* @param style Style to get the PB for.
* @param track Timer track.
* @return Floating number of the player's best time for given style/track.
*/
native float Shavit_GetClientPB(int client, int style, int track);
/**
* Sets the cached pb directly for the given client, style and track.
*
* @param client Client index.
* @param style Style to get the PB for.
* @param track Timer track.
* @param time Time to set
* @noreturn
*/
native void Shavit_SetClientPB(int client, int style, int track, float time);
/**
* Retrieves the completions of a player.
*
* @param client Client index.
* @param style Style to get the Completions for.
* @param track Timer track.
* @return Number of the player's Completions for given style/track.
*/
native int Shavit_GetClientCompletions(int client, int style, int track);
/**
* Get the amount of records on the current map/style on a track.
*
* @param style Style.
* @param track Timer track.
* @return Amount of records.
*/
native int Shavit_GetRecordAmount(int style, int track);
/**
* Calculate potential rank for a given style and time.
*
* @param style Style.
* @param time Time to check for.
* @param track Timer track.
* @return Map rank.
*/
native int Shavit_GetRankForTime(int style, float time, int track);
/**
* Retrieves the time of a record from a specified rank.
*
* @param style Style.
* @param rank Rank to retrieve the time from.
* @param track Timer track.
* @return Record time. 0.0 if none.
*/
native float Shavit_GetTimeForRank(int style, int rank, int track);
/**
* Retrieve the WR's stage time.
*
* @param track Track index.
* @param style Style index.
* @param stage Stage number.
* @return The stage time of the WR run. Can be 0.0 if the WR run didn't hit the stage or if the stage doesn't exist.
*/
native float Shavit_GetStageWR(int track, int style, int stage);
/**
* Retrieve the client's PB stage time.
*
* @param client Client index.
* @param track Track index.
* @param style Style index.
* @param stage Stage number.
* @return The stage time of the PB run. Can be 0.0 if the PB run didn't hit the stage or if the stage doesn't exist.
*/
//native float Shavit_GetStagePB(int client, int track, int style, int stage);
//native float Shavit_GetStageWRCP(int track, int style, int stage);
//native float Shavit_GetStagePBCP(int client, int track, int style, int stage);
/*
* Used to delete a WR. Used to ensure Shavit_OnWRDeleted is ran.
*
* @param style Record style.
* @param track Record track.
* @param map Record map.
* @param accountid -1 if recordid is -1. Otherwise you need the WR holder's Steam account ID. ([U:1:x])
* @param recordid -1 to pull ID & accountid from the database.
* @param delete_sql If this function should delete the record from the database. False might be useful if you're deleting things in bulk like sm_wipeplayer does.
* @param update_cache If this function should update the WR cache & record info. False might be useful if you're deleting things in bulk like sm_wipeplayer does.
* @noreturn
*/
native void Shavit_DeleteWR(int style, int track, const char[] map, int accountid, int recordid, bool delete_sql, bool update_cache);
/**
* Deletes all map records for the specified map.
* Plugin will refresh if map is currently on.
*
* @param map Map name.
* @noreturn
*/
native void Shavit_WR_DeleteMap(const char[] map);
public SharedPlugin __pl_shavit_wr =
{
name = "shavit-wr",
file = "shavit-wr.smx",
#if defined REQUIRE_PLUGIN
required = 1
#else
required = 0
#endif
};
#if !defined REQUIRE_PLUGIN
public void __pl_shavit_wr_SetNTVOptional()
{
MarkNativeAsOptional("Shavit_GetClientCompletions");
MarkNativeAsOptional("Shavit_GetClientPB");
MarkNativeAsOptional("Shavit_SetClientPB");
MarkNativeAsOptional("Shavit_GetRankForTime");
MarkNativeAsOptional("Shavit_GetRecordAmount");
MarkNativeAsOptional("Shavit_GetWorldRecord");
MarkNativeAsOptional("Shavit_GetWRName");
MarkNativeAsOptional("Shavit_GetWRRecordID");
MarkNativeAsOptional("Shavit_ReloadLeaderboards");
MarkNativeAsOptional("Shavit_WR_DeleteMap");
MarkNativeAsOptional("Shavit_GetTimeForRank");
MarkNativeAsOptional("Shavit_DeleteWR");
MarkNativeAsOptional("Shavit_GetStageWR");
MarkNativeAsOptional("Shavit_GetStagePB");
}
#endif

View File

@ -0,0 +1,500 @@
/*
* shavit's Timer - zones.inc file
* by: shavit,
*
* This file is part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#if defined _shavit_zones_included
#endinput
#endif
#define _shavit_zones_included
#define MAX_ZONES 128
#define MAX_STAGES 69
enum
{
Zone_Start, // starts timer
Zone_End, // stops timer
Zone_Respawn, // respawns the player
Zone_Stop, // stops the player's timer
Zone_Slay, // slays (kills) players which come to this zone
Zone_Freestyle, // ignores style physics when at this zone. e.g. WASD when SWing
Zone_CustomSpeedLimit, // overwrites velocity limit in the zone
Zone_Teleport, // teleports to a defined point
Zone_CustomSpawn, // spawn position for a track. not a physical zone.
Zone_Easybhop, // forces easybhop whether if the player is in non-easy styles or if the server has different settings
Zone_Slide, // allows players to slide, in order to fix parts like the 5th stage of bhop_arcane
Zone_Airaccelerate, // custom sv_airaccelerate inside this,
Zone_Stage, // shows time when entering zone
Zone_NoTimerGravity, // prevents the timer from setting gravity while inside this zone
Zone_Gravity, // lets you set a specific gravity while inside this zone
Zone_Speedmod, // creates a player_speedmod
Zone_NoJump, // blocks the player from jumping while inside the zone
Zone_Autobhop, // forces autobhop for the player
ZONETYPES_SIZE
};
enum
{
ZF_ForceRender = (1 << 0),
ZF_Hammerid = (1 << 1), // used by ZoneForm_{trigger_{multiple, teleport}, func_[rot_]button} sometimes
ZF_Solid = (1 << 2), // forces the zone to physically block people...
ZF_Origin = (1 << 4), // sTarget is the entity's origin formatted as "%X %X %X"
};
// Zone Display type
enum
{
ZoneDisplay_Default,
ZoneDisplay_Flat,
ZoneDisplay_Box,
ZoneDisplay_None,
ZoneDisplay_Size
};
// Zone Color, maybe we just let the user decide what color they actually want..? maybe store rgba as hex string but that would be mega long for each track
enum
{
ZoneColor_Default,
ZoneColor_White,
ZoneColor_Red,
ZoneColor_Orange,
ZoneColor_Yellow,
ZoneColor_Green,
ZoneColor_Cyan,
ZoneColor_Blue,
ZoneColor_Purple,
ZoneColor_Pink,
ZoneColor_Size
};
enum
{
ZoneWidth_Default,
ZoneWidth_UltraThin,
ZoneWidth_Thin,
ZoneWidth_Normal,
ZoneWidth_Thick,
ZoneWidth_Size
};
enum
{
ZoneForm_Box,
ZoneForm_trigger_multiple,
ZoneForm_trigger_teleport,
ZoneForm_func_button,
ZoneForm_AreasAndClusters,
};
enum struct zone_cache_t
{
int iType; // The type of zone. Zone_Start, Zone_End, etc...
int iTrack; // 0 - main, 1 - bonus1 etc
int iEntity; // Filled by Shavit_GetZone() if applicable.
int iDatabaseID; // Can be the database ID (> 0) for "sql" sources. Non-sql sources can fill this with whatever.
int iFlags; // The ZF_* flags.
int iData; // Depends on the zone. Zone_Stage stores the stage number in this for example.
float fCorner1[3]; // the hull mins. (or unused if ZoneForm_AreasAndClusters) // TODO, maybe reuse for cluster & areas?
float fCorner2[3]; // the hull maxs. (or unused if ZoneForm_AreasAndClusters)
float fDestination[3]; // Used by Zone_CustomSpawn, Zone_Teleport, and Zone_Stage.
int iForm; // ZoneForm_*
char sSource[16]; // "sql", "autobutton", "autozone", "sourcejump", "http", etc...
char sTarget[64]; // either the hammerid or the targetname
}
stock void GetZoneName(int client, int zoneType, char[] output, int size)
{
static char sTranslationStrings[ZONETYPES_SIZE][] = {
"Zone_Start",
"Zone_End",
"Zone_Respawn",
"Zone_Stop",
"Zone_Slay",
"Zone_Freestyle",
"Zone_CustomSpeedLimit",
"Zone_Teleport",
"Zone_CustomSpawn",
"Zone_Easybhop",
"Zone_Slide",
"Zone_Airaccelerate",
"Zone_Stage",
"Zone_NoTimerGravity",
"Zone_Gravity",
"Zone_Speedmod",
"Zone_NoJump",
"Zone_Autobhop",
};
if (zoneType < 0 || zoneType >= ZONETYPES_SIZE)
FormatEx(output, size, "%T", "Zone_Unknown", client);
else
FormatEx(output, size, "%T", sTranslationStrings[zoneType], client);
}
// Please follow something like this:
// mod_zone_start
// mod_zone_end
// mod_zone_checkpoint_X
// mod_zone_bonus_X_start
// mod_zone_bonus_X_end
// mod_zone_bonus_X_checkpoint_X
//
// climb_startbutton
// climb_endbutton
// climb_bonusX_startbutton
// climb_bonusX_endbutton
//
// climb_startzone
// climb_endzone
// climb_bonusX_startzone
// climb_bonusX_endzone
stock bool Shavit_ParseZoneTargetname(const char[] targetname, bool button, int& type, int& track, int& stage, const char[] mapname_for_log="")
{
track = Track_Main;
type = -1;
stage = 0;
if (strncmp(targetname, "climb_", 6) != 0
&& (button || strncmp(targetname, "mod_zone_", 9) != 0))
{
return false;
}
if (StrContains(targetname, "start") != -1)
{
type = Zone_Start;
}
else if (StrContains(targetname, "end") != -1)
{
type = Zone_End;
}
int bonus = StrContains(targetname, "bonus");
if (bonus != -1)
{
track = Track_Bonus;
bonus += 5; // skip past "bonus"
if (targetname[bonus] == '_') bonus += 1;
if ('1' <= targetname[bonus] <= '9')
{
track = StringToInt(targetname[bonus]);
if (track < Track_Bonus || track > Track_Bonus_Last)
{
if (mapname_for_log[0]) LogError("invalid track in prebuilt map zone (%s) on %s", targetname, mapname_for_log);
return false;
}
}
}
int checkpoint = StrContains(targetname, "checkpoint");
if (checkpoint != -1)
{
if (button)
{
if (mapname_for_log[0]) LogError("invalid button (%s) (has checkpoint) on %s", targetname, mapname_for_log);
return false;
}
if (type != -1)
{
if (mapname_for_log[0]) LogError("invalid type (start/end + checkpoint) in prebuilt map zone (%s) on %s", targetname, mapname_for_log);
return false; // end/start & checkpoint...
}
type = Zone_Stage;
checkpoint += 10; // skip past "checkpoint"
if (targetname[checkpoint] == '_') checkpoint += 1;
if ('1' <= targetname[checkpoint] <= '9')
{
stage = StringToInt(targetname[checkpoint]);
if (stage <= 0 || stage > MAX_STAGES)
{
if (mapname_for_log[0]) LogError("invalid stage number in prebuilt map zone (%s) on %s", targetname, mapname_for_log);
return false;
}
}
}
if (type == -1)
{
if (mapname_for_log[0]) LogError("invalid zone type in prebuilt map zone (%s) on %s", targetname, mapname_for_log);
return false;
}
return true;
}
/**
* Called when a player enters a zone.
*
* @param client Client index.
* @param type Zone type.
* @param track Zone track.
* @param id Zone ID.
* @param entity Zone trigger entity index.
* @param data Zone data if any.
* @noreturn
*/
forward void Shavit_OnEnterZone(int client, int type, int track, int id, int entity, int data);
/**
* Called when a player leaves a zone.
*
* @param client Client index.
* @param type Zone type.
* @param track Zone track.
* @param id Zone ID.
* @param entity Zone trigger entity index.
* @param data Zone data if any.
* @noreturn
*/
forward void Shavit_OnLeaveZone(int client, int type, int track, int id, int entity, int data);
/**
*
*/
forward void Shavit_LoadZonesHere();
/**
* Called when a player leaves a zone.
*
* @param client Client index.
* @param stageNumber Stage number.
* @param message The stage time message that will be printed.
* @param maxlen The buffer size of message.
* @return Plugin_Handled to block the timer from printing msg to the client. Plugin_Continue to let the timer print msg.
*/
forward Action Shavit_OnStageMessage(int client, int stageNumber, char[] message, int maxlen);
/**
* Checks if a mapzone exists.
*
* @param type Mapzone type.
* @param track Mapzone track, -1 to ignore track.
* @return Boolean value.
*/
native bool Shavit_ZoneExists(int type, int track);
/**
* Checks if a player is inside a mapzone.
*
* @param client Client index.
* @param type Mapzone type.
* @param track Mapzone track, -1 to ignore track.
* @return Boolean value.
*/
native bool Shavit_InsideZone(int client, int type, int track);
/**
* Gets the specified zone's data.
*
* @param zoneid ID of the zone we query the data of.
* @return Zone data. 0 if none is specified.
*/
native int Shavit_GetZoneData(int zoneid);
/**
* Gets the specified zone's flags.
*
* @param zoneid ID of the zone we query the flags of.
* @return Zone flags. 0 if none is specified.
*/
native int Shavit_GetZoneFlags(int zoneid);
/**
* Deletes all map zones for the specified map.
* Plugin will refresh if map is currently on.
*
* @param map Map name.
* @noreturn
*/
native void Shavit_Zones_DeleteMap(const char[] map);
/**
* Checks if a player is inside a mapzone.
*
* @param client Client index.
* @param type Mapzone type.
* @param track Mapzone track, -1 to ignore track.
* @param zoneid Reference to variable that will hold the zone's ID.
* @return Boolean value.
*/
native bool Shavit_InsideZoneGetID(int client, int type, int track, int &zoneid);
/**
* Checks if a player is in the process of creating a mapzone.
*
* @param client Client index.
* @return Boolean value.
*/
native bool Shavit_IsClientCreatingZone(int client);
/**
* Retrieve the highest stage number for a given track.
*
* @param track Track number.
* @return Highest stage number...
*/
native int Shavit_GetHighestStage(int track);
/**
* Retrieve the client's current stage number.
*
* @param client Client index.
* @return The client's current stage number.
*/
native int Shavit_GetClientLastStage(int client);
/**
* Returns the zone index for the entity if available.
*
* @param entity Client index.
* @return -1 if not a zone entity. >=0 for a zone index.
*/
native int Shavit_GetZoneID(int entity);
/**
* Returns the zone track.
*
* @param zoneid Zone index.
* @return Zone track.
*/
native int Shavit_GetZoneTrack(int zoneid);
/**
* Returns the zone type.
*
* @param zoneid Zone index.
* @return Zone type.
*/
native int Shavit_GetZoneType(int zoneid);
/**
* Sets the player's current location as their spawn location for the specified track.
*
* @param client Client index.
* @param track Timer track.
* @param anglesonly Whether to save angles only.
* @noreturn
*/
native void Shavit_SetStart(int client, int track, bool anglesonly);
/**
* Deletes the player's current set start position for the specified track.
*
* @param client Client index.
* @param track Timer track.
* @noreturn
*/
native void Shavit_DeleteSetStart(int client, int track);
/**
* Removes all zones from memory and then reloads zones from the database & any plugins.
* @noreturn
*/
native void Shavit_ReloadZones();
/**
* Removes all zones from memory and unhooks any zones and kills any created entities.
* @noreturn
*/
native void Shavit_UnloadZones();
/**
* Returns the number of zones that are currently loaded in memory.
*
* @return The number of zones currently loaded in memory.
*/
native int Shavit_GetZoneCount();
/**
* Retrieves the zone_cache_t for a zone.
*
* @param index The zone index. 0 through Shavit_GetZoneCount()-1.
* @param zonecache The zone_cache_t struct that is retrieved from the zone.
* @param size sizeof(zone_cache_t) to make sure the caller has a matching struct version.
*
* @noreturn
*/
native void Shavit_GetZone(int index, any[] zonecache, int size = sizeof(zone_cache_t));
/**
* Adds a zone to memory. (Does NOT insert into DB).
*
* @param zonecache The zone_cache_t struct that is used to create or hook a zone.
* @param size sizeof(zone_cache_t) to make sure the caller has a matching struct version.
*
* @return The zone index on success (index for a particular zone can change). <0 on failure.
*/
native int Shavit_AddZone(any[] zonecache, int size = sizeof(zone_cache_t));
/**
* Removes a zone from memory. (Does NOT delete from DB).
* WARNING: If there are zones after `index`, then they will be moved down in memory to fill this slot after removal.
* This unhooks the zone's entity too.
*
* @param index The zone's index.
*
* @noreturn
*/
native void Shavit_RemoveZone(int index);
public SharedPlugin __pl_shavit_zones =
{
name = "shavit-zones",
file = "shavit-zones.smx",
#if defined REQUIRE_PLUGIN
required = 1
#else
required = 0
#endif
};
#if !defined REQUIRE_PLUGIN
public void __pl_shavit_zones_SetNTVOptional()
{
MarkNativeAsOptional("Shavit_GetZoneData");
MarkNativeAsOptional("Shavit_GetZoneFlags");
MarkNativeAsOptional("Shavit_GetHighestStage");
MarkNativeAsOptional("Shavit_InsideZone");
MarkNativeAsOptional("Shavit_InsideZoneGetID");
MarkNativeAsOptional("Shavit_IsClientCreatingZone");
MarkNativeAsOptional("Shavit_ZoneExists");
MarkNativeAsOptional("Shavit_Zones_DeleteMap");
MarkNativeAsOptional("Shavit_SetStart");
MarkNativeAsOptional("Shavit_DeleteSetStart");
MarkNativeAsOptional("Shavit_GetClientLastStage");
MarkNativeAsOptional("Shavit_GetZoneTrack");
MarkNativeAsOptional("Shavit_GetZoneType");
MarkNativeAsOptional("Shavit_GetZoneID");
MarkNativeAsOptional("Shavit_ReloadZones");
MarkNativeAsOptional("Shavit_UnloadZones");
MarkNativeAsOptional("Shavit_GetZoneCount");
MarkNativeAsOptional("Shavit_GetZone");
MarkNativeAsOptional("Shavit_AddZone");
MarkNativeAsOptional("Shavit_RemoveZone");
}
#endif

View File

@ -0,0 +1,50 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright 2025 rtldg <rtldg@protonmail.com>
#if defined _srcwrfloppy_included
#endinput
#endif
#define _srcwrfloppy_included
#pragma semicolon 1
typeset ReplaySavedCallback {
function void(bool saved, any value, char[] sPath);
}
// Don't modify the `playerrecording` ArrayList until the ReplaySavedCallback is called... OR ELSE!!!!
native void SRCWRFloppy_AsyncSaveReplay(
ReplaySavedCallback callback // what to call when saved
, any value // what to pass along to the callback
, char[] wrpath
, char[] copypath
, char[] header
, int headersize
, ArrayList playerrecording
, int totalframes
);
public Extension __ext_srcwrfloppy =
{
name = "srcwr💾",
file = "srcwr💾.ext",
#if defined AUTOLOAD_EXTENSIONS
autoload = 1,
#else
autoload = 0,
#endif
#if defined REQUIRE_EXTENSIONS
required = 1,
#else
required = 0,
#endif
};
#if !defined REQUIRE_EXTENSIONS
public void __ext_srcwrfloppy_SetNTVOptional()
{
MarkNativeAsOptional("SRCWRFloppy_AsyncSaveReplay");
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,803 @@
/*
* shavit's Timer - Replay Recorder
* by: shavit, rtldg, KiD Fearless, Ciallo-Ani, BoomShotKapow
*
* This file is part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <sourcemod>
#include <sdktools>
#include <convar_class>
#include <shavit/replay-recorder>
#include <shavit/core>
#undef REQUIRE_PLUGIN
#include <shavit/replay-playback>
#include <shavit/zones>
#include <shavit/replay-file>
#include <shavit/replay-stocks.sp>
#undef REQUIRE_EXTENSIONS
#include <srcwr/floppy>
public Plugin myinfo =
{
name = "[shavit] Replay Recorder",
author = "shavit, rtldg, KiD Fearless, Ciallo-Ani, BoomShotKapow",
description = "A replay recorder for shavit's bhop timer.",
version = SHAVIT_VERSION,
url = "https://github.com/shavitush/bhoptimer"
}
enum struct finished_run_info
{
int iSteamID;
int style;
float time;
int jumps;
int strafes;
float sync;
int track;
float oldtime;
float perfs;
float avgvel;
float maxvel;
int timestamp;
float fZoneOffset[2];
}
bool gB_Late = false;
char gS_Map[PLATFORM_MAX_PATH];
float gF_Tickrate = 0.0;
int gI_Styles = 0;
char gS_ReplayFolder[PLATFORM_MAX_PATH];
Convar gCV_Enabled = null;
Convar gCV_PlaybackPostRunTime = null;
Convar gCV_PlaybackPreRunTime = null;
Convar gCV_PreRunAlways = null;
Convar gCV_TimeLimit = null;
Handle gH_ShouldSaveReplayCopy = null;
Handle gH_OnReplaySaved = null;
bool gB_RecordingEnabled[MAXPLAYERS+1]; // just a simple thing to prevent plugin reloads from recording half-replays
// stuff related to postframes
finished_run_info gA_FinishedRunInfo[MAXPLAYERS+1];
bool gB_GrabbingPostFrames[MAXPLAYERS+1];
Handle gH_PostFramesTimer[MAXPLAYERS+1];
int gI_PlayerFinishFrame[MAXPLAYERS+1];
// we use gI_PlayerFrames instead of grabbing gA_PlayerFrames.Length because the ArrayList is resized to handle 2s worth of extra frames to reduce how often we have to resize it
int gI_PlayerFrames[MAXPLAYERS+1];
int gI_PlayerPrerunFrames[MAXPLAYERS+1];
ArrayList gA_PlayerFrames[MAXPLAYERS+1];
int gI_HijackFrames[MAXPLAYERS+1];
float gF_HijackedAngles[MAXPLAYERS+1][2];
bool gB_HijackFramesKeepOnStart[MAXPLAYERS+1];
bool gB_ReplayPlayback = false;
bool gB_Floppy = false;
//#include <TickRateControl>
forward void TickRate_OnTickRateChanged(float fOld, float fNew);
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
{
CreateNative("Shavit_GetClientFrameCount", Native_GetClientFrameCount);
CreateNative("Shavit_GetPlayerPreFrames", Native_GetPlayerPreFrames);
CreateNative("Shavit_GetReplayData", Native_GetReplayData);
CreateNative("Shavit_HijackAngles", Native_HijackAngles);
CreateNative("Shavit_SetReplayData", Native_SetReplayData);
CreateNative("Shavit_SetPlayerPreFrames", Native_SetPlayerPreFrames);
if (!FileExists("cfg/sourcemod/plugin.shavit-replay-recorder.cfg") && FileExists("cfg/sourcemod/plugin.shavit-replay.cfg"))
{
File source = OpenFile("cfg/sourcemod/plugin.shavit-replay.cfg", "r");
File destination = OpenFile("cfg/sourcemod/plugin.shavit-replay-recorder.cfg", "w");
if (source && destination)
{
char line[512];
while (!source.EndOfFile() && source.ReadLine(line, sizeof(line)))
{
destination.WriteLine("%s", line);
}
}
delete destination;
delete source;
}
RegPluginLibrary("shavit-replay-recorder");
gB_Late = late;
return APLRes_Success;
}
public void OnPluginStart()
{
gH_ShouldSaveReplayCopy = CreateGlobalForward("Shavit_ShouldSaveReplayCopy", ET_Event, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell);
gH_OnReplaySaved = CreateGlobalForward("Shavit_OnReplaySaved", ET_Ignore, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_String, Param_Cell, Param_Cell, Param_Cell, Param_String);
gCV_Enabled = new Convar("shavit_replay_recording_enabled", "1", "Enable replay bot functionality?", 0, true, 0.0, true, 1.0);
gCV_PlaybackPostRunTime = new Convar("shavit_replay_postruntime", "1.5", "Time (in seconds) to record after a player enters the end zone.", 0, true, 0.0, true, 2.0);
gCV_PreRunAlways = new Convar("shavit_replay_prerun_always", "1", "Record prerun frames outside the start zone?", 0, true, 0.0, true, 1.0);
gCV_PlaybackPreRunTime = new Convar("shavit_replay_preruntime", "1.5", "Time (in seconds) to record before a player leaves start zone.", 0, true, 0.0, true, 2.0);
gCV_TimeLimit = new Convar("shavit_replay_timelimit", "7200.0", "Maximum amount of time (in seconds) to allow saving to disk.\nDefault is 7200 (2 hours)\n0 - Disabled (no replays will be recorded)", 0, true, 0.0);
Convar.AutoExecConfig();
gF_Tickrate = (1.0 / GetTickInterval());
gB_ReplayPlayback = LibraryExists("shavit-replay-playback");
gB_Floppy = LibraryExists("srcwr💾");
if (gB_Late)
{
Shavit_OnStyleConfigLoaded(Shavit_GetStyleCount());
for (int i = 1; i <= MaxClients; i++)
{
if (IsValidClient(i) && !IsFakeClient(i))
{
OnClientPutInServer(i);
}
}
}
}
public void OnLibraryAdded(const char[] name)
{
if( StrEqual(name, "shavit-replay-playback"))
{
gB_ReplayPlayback = true;
}
else if (StrEqual(name, "srcwr💾"))
{
gB_Floppy = true;
}
}
public void OnLibraryRemoved(const char[] name)
{
if (StrEqual(name, "shavit-replay-playback"))
{
gB_ReplayPlayback = false;
}
else if (StrEqual(name, "srcwr💾"))
{
gB_Floppy = false;
}
}
public void OnMapStart()
{
GetLowercaseMapName(gS_Map);
}
public void Shavit_OnStyleConfigLoaded(int styles)
{
if (!Shavit_GetReplayFolderPath_Stock(gS_ReplayFolder))
{
SetFailState("Could not load the replay bots' configuration file. Make sure it exists (addons/sourcemod/configs/shavit-replay.cfg) and follows the proper syntax!");
}
gI_Styles = styles;
Shavit_Replay_CreateDirectories(gS_ReplayFolder, gI_Styles);
}
public void OnClientPutInServer(int client)
{
ClearFrames(client);
}
public void OnClientDisconnect(int client)
{
gB_RecordingEnabled[client] = false; // reset a little state...
if (gB_GrabbingPostFrames[client])
{
FinishGrabbingPostFrames(client, gA_FinishedRunInfo[client]);
}
}
public void OnClientDisconnect_Post(int client)
{
// This runs after shavit-misc has cloned the handle
delete gA_PlayerFrames[client];
}
public void TickRate_OnTickRateChanged(float fOld, float fNew)
{
gF_Tickrate = fNew;
}
void ClearFrames(int client)
{
delete gA_PlayerFrames[client];
gA_PlayerFrames[client] = new ArrayList(sizeof(frame_t));
gI_PlayerFrames[client] = 0;
gI_PlayerPrerunFrames[client] = 0;
gI_PlayerFinishFrame[client] = 0;
gI_HijackFrames[client] = 0;
gB_HijackFramesKeepOnStart[client] = false;
}
public Action Shavit_OnStart(int client)
{
gB_RecordingEnabled[client] = true;
if (!gB_HijackFramesKeepOnStart[client])
{
gI_HijackFrames[client] = 0;
}
if (gB_GrabbingPostFrames[client])
{
FinishGrabbingPostFrames(client, gA_FinishedRunInfo[client]);
}
int iMaxPreFrames = RoundToFloor(gCV_PlaybackPreRunTime.FloatValue * gF_Tickrate / Shavit_GetStyleSettingFloat(Shavit_GetBhopStyle(client), "speed"));
bool bInStart = Shavit_InsideZone(client, Zone_Start, Shavit_GetClientTrack(client));
if (bInStart)
{
int iFrameDifference = gI_PlayerFrames[client] - iMaxPreFrames;
if (iFrameDifference > 0)
{
// For too many extra frames, we'll just shift the preframes to the start of the array.
if (iFrameDifference > 100)
{
for (int i = iFrameDifference; i < gI_PlayerFrames[client]; i++)
{
gA_PlayerFrames[client].SwapAt(i, i-iFrameDifference);
}
gI_PlayerFrames[client] = iMaxPreFrames;
}
else // iFrameDifference isn't that bad, just loop through and erase.
{
while (iFrameDifference--)
{
gA_PlayerFrames[client].Erase(0);
gI_PlayerFrames[client]--;
}
}
}
}
else
{
if (!gCV_PreRunAlways.BoolValue)
{
ClearFrames(client);
}
}
gI_PlayerPrerunFrames[client] = gI_PlayerFrames[client];
return Plugin_Continue;
}
public void Shavit_OnStop(int client)
{
if (gB_GrabbingPostFrames[client])
{
FinishGrabbingPostFrames(client, gA_FinishedRunInfo[client]);
}
ClearFrames(client);
}
public Action Timer_PostFrames(Handle timer, int client)
{
gH_PostFramesTimer[client] = null;
FinishGrabbingPostFrames(client, gA_FinishedRunInfo[client]);
return Plugin_Stop;
}
void FinishGrabbingPostFrames(int client, finished_run_info info)
{
gB_GrabbingPostFrames[client] = false;
delete gH_PostFramesTimer[client];
DoReplaySaverCallbacks(info.iSteamID, client, info.style, info.time, info.jumps, info.strafes, info.sync, info.track, info.oldtime, info.perfs, info.avgvel, info.maxvel, info.timestamp, info.fZoneOffset);
}
float ExistingWrReplayLength(int style, int track)
{
if (gB_ReplayPlayback)
{
return Shavit_GetReplayLength(style, track);
}
char sPath[PLATFORM_MAX_PATH];
Shavit_GetReplayFilePath(style, track, gS_Map, gS_ReplayFolder, sPath);
replay_header_t header;
File f = ReadReplayHeader(sPath, header, style, track);
if (f != null)
{
delete f;
return header.fTime;
}
return 0.0;
}
void DoReplaySaverCallbacks(int iSteamID, int client, int style, float time, int jumps, int strafes, float sync, int track, float oldtime, float perfs, float avgvel, float maxvel, int timestamp, float fZoneOffset[2])
{
gA_PlayerFrames[client].Resize(gI_PlayerFrames[client]);
bool isTooLong = (gCV_TimeLimit.FloatValue > 0.0 && time > gCV_TimeLimit.FloatValue);
float length = ExistingWrReplayLength(style, track);
bool isBestReplay = (length == 0.0 || time < length);
Action action = Plugin_Continue;
Call_StartForward(gH_ShouldSaveReplayCopy);
Call_PushCell(client);
Call_PushCell(style);
Call_PushCell(time);
Call_PushCell(jumps);
Call_PushCell(strafes);
Call_PushCell(sync);
Call_PushCell(track);
Call_PushCell(oldtime);
Call_PushCell(perfs);
Call_PushCell(avgvel);
Call_PushCell(maxvel);
Call_PushCell(timestamp);
Call_PushCell(isBestReplay);
Call_PushCell(isTooLong);
Call_Finish(action);
bool makeCopy = (action != Plugin_Continue);
bool makeReplay = (isBestReplay && !isTooLong);
if (!makeCopy && !makeReplay)
{
return;
}
char sName[MAX_NAME_LENGTH];
GetClientName(client, sName, sizeof(sName));
ReplaceString(sName, MAX_NAME_LENGTH, "#", "?");
int postframes = gI_PlayerFrames[client] - gI_PlayerFinishFrame[client];
ArrayList playerrecording = view_as<ArrayList>(CloneHandle(gA_PlayerFrames[client]));
DataPack dp = new DataPack();
dp.WriteCell(GetClientSerial(client));
dp.WriteCell(style);
dp.WriteCell(time);
dp.WriteCell(jumps);
dp.WriteCell(strafes);
dp.WriteCell(sync);
dp.WriteCell(track);
dp.WriteCell(oldtime);
dp.WriteCell(perfs);
dp.WriteCell(avgvel);
dp.WriteCell(maxvel);
dp.WriteCell(timestamp);
dp.WriteCell(isBestReplay);
dp.WriteCell(isTooLong);
dp.WriteCell(makeCopy);
dp.WriteCell(playerrecording);
dp.WriteCell(gI_PlayerPrerunFrames[client]);
dp.WriteCell(postframes);
dp.WriteString(sName);
if (gB_Floppy)
{
char buf[512];
int headersize = WriteReplayHeaderToBuffer(buf, style, track, time, iSteamID, gI_PlayerPrerunFrames[client], postframes, fZoneOffset, gI_PlayerFrames[client], gF_Tickrate, gS_Map);
char wrpath[PLATFORM_MAX_PATH], copypath[PLATFORM_MAX_PATH];
if (makeReplay)
FormatEx(wrpath, sizeof(wrpath),
track>0?"%s/%d/%s_%d.replay" : "%s/%d/%s.replay",
gS_ReplayFolder, style, gS_Map, track
);
if (makeCopy)
FormatEx(copypath, sizeof(copypath), "%s/copy/%d_%d_%s.replay", gS_ReplayFolder, timestamp, iSteamID, gS_Map);
SRCWRFloppy_AsyncSaveReplay(
FloppyAsynchronouslySavedMyReplayWhichWasNiceOfThem
, dp
, wrpath
, copypath
, buf
, headersize
, playerrecording
, gI_PlayerFrames[client]
);
}
else
{
char sPath[PLATFORM_MAX_PATH];
bool saved = SaveReplay(style, track, time, iSteamID, gI_PlayerPrerunFrames[client], playerrecording, gI_PlayerFrames[client], postframes, timestamp, fZoneOffset, makeCopy, makeReplay, sPath, sizeof(sPath));
FloppyAsynchronouslySavedMyReplayWhichWasNiceOfThem(saved, dp, sPath)
}
ClearFrames(client);
}
void FloppyAsynchronouslySavedMyReplayWhichWasNiceOfThem(bool saved, any value, char[] sPath)
{
DataPack dp = value;
dp.Reset();
int client = GetClientFromSerial(dp.ReadCell());
int style = dp.ReadCell();
float time = dp.ReadCell();
int jumps = dp.ReadCell();
int strafes = dp.ReadCell();
float sync = dp.ReadCell();
int track = dp.ReadCell();
float oldtime = dp.ReadCell();
float perfs = dp.ReadCell();
float avgvel = dp.ReadCell();
float maxvel = dp.ReadCell();
int timestamp = dp.ReadCell();
bool isBestReplay = dp.ReadCell();
bool isTooLong = dp.ReadCell();
bool makeCopy = dp.ReadCell();
ArrayList playerrecording = dp.ReadCell();
int preframes = dp.ReadCell();
int postframes = dp.ReadCell();
char sName[MAX_NAME_LENGTH];
dp.ReadString(sName, sizeof(sName));
if (!saved)
{
LogError("Failed to save replay... Skipping OnReplaySaved");
delete playerrecording; // importante!
return;
}
Call_StartForward(gH_OnReplaySaved);
Call_PushCell(client);
Call_PushCell(style);
Call_PushCell(time);
Call_PushCell(jumps);
Call_PushCell(strafes);
Call_PushCell(sync);
Call_PushCell(track);
Call_PushCell(oldtime);
Call_PushCell(perfs);
Call_PushCell(avgvel);
Call_PushCell(maxvel);
Call_PushCell(timestamp);
Call_PushCell(isBestReplay);
Call_PushCell(isTooLong);
Call_PushCell(makeCopy);
Call_PushString(sPath);
Call_PushCell(playerrecording);
Call_PushCell(preframes);
Call_PushCell(postframes);
Call_PushString(sName);
Call_Finish();
delete playerrecording;
}
public void Shavit_OnFinish(int client, int style, float time, int jumps, int strafes, float sync, int track, float oldtime, float perfs, float avgvel, float maxvel, int timestamp)
{
if (Shavit_IsPracticeMode(client) || !gCV_Enabled.BoolValue || (gI_PlayerFrames[client]-gI_PlayerPrerunFrames[client] <= 10))
{
return;
}
// Someone using checkpoints presumably
if (gB_GrabbingPostFrames[client])
{
FinishGrabbingPostFrames(client, gA_FinishedRunInfo[client]);
}
gI_PlayerFinishFrame[client] = gI_PlayerFrames[client];
float fZoneOffset[2];
fZoneOffset[0] = Shavit_GetZoneOffset(client, 0);
fZoneOffset[1] = Shavit_GetZoneOffset(client, 1);
if (gCV_PlaybackPostRunTime.FloatValue > 0.0)
{
finished_run_info info;
info.iSteamID = GetSteamAccountID(client);
info.style = style;
info.time = time;
info.jumps = jumps;
info.strafes = strafes;
info.sync = sync;
info.track = track;
info.oldtime = oldtime;
info.perfs = perfs;
info.avgvel = avgvel;
info.maxvel = maxvel;
info.timestamp = timestamp;
info.fZoneOffset = fZoneOffset;
gA_FinishedRunInfo[client] = info;
gB_GrabbingPostFrames[client] = true;
delete gH_PostFramesTimer[client];
gH_PostFramesTimer[client] = CreateTimer(gCV_PlaybackPostRunTime.FloatValue, Timer_PostFrames, client, TIMER_FLAG_NO_MAPCHANGE);
}
else
{
DoReplaySaverCallbacks(GetSteamAccountID(client), client, style, time, jumps, strafes, sync, track, oldtime, perfs, avgvel, maxvel, timestamp, fZoneOffset);
}
}
bool SaveReplay(int style, int track, float time, int steamid, int preframes, ArrayList playerrecording, int iSize, int postframes, int timestamp, float fZoneOffset[2], bool saveCopy, bool saveWR, char[] sPath, int sPathLen)
{
char sTrack[4];
FormatEx(sTrack, 4, "_%d", track);
File fWR = null;
File fCopy = null;
if (saveCopy)
{
FormatEx(sPath, sPathLen, "%s/copy/%d_%d_%s.replay", gS_ReplayFolder, timestamp, steamid, gS_Map);
if (!(fCopy = OpenFile(sPath, "wb+")))
{
LogError("Failed to open 'copy' replay file for writing. ('%s')", sPath);
}
}
if (saveWR)
{
FormatEx(sPath, sPathLen, "%s/%d/%s%s.replay", gS_ReplayFolder, style, gS_Map, (track > 0)? sTrack:"");
if (!(fWR = OpenFile(sPath, "wb+")))
{
LogError("Failed to open WR replay file for writing. ('%s')", sPath);
}
}
if (!fWR && !fCopy)
{
// I want to try and salvage the replay file so let's write it out to a random
// file and hope people read the error log to figure out what happened...
// I'm not really sure how we could reach this though as
// `Shavit_Replay_CreateDirectories` should have failed if it couldn't create
// a test file.
FormatEx(sPath, sPathLen, "%s/%d_%s%s_%d.replay", gS_ReplayFolder, style, gS_Map, sTrack, iSize-preframes-postframes);
if (!(fWR = OpenFile(sPath, "wb+")))
{
LogError("Couldn't open a WR, 'copy', or 'salvage' replay file....");
return false;
}
LogError("Couldn't open a WR or 'copy' replay file. Writing 'salvage' replay @ (style %d) '%s'", style, sPath);
}
if (fWR)
{
WriteReplayHeader(fWR, style, track, time, steamid, preframes, postframes, fZoneOffset, iSize, gF_Tickrate, gS_Map);
}
if (fCopy)
{
WriteReplayHeader(fCopy, style, track, time, steamid, preframes, postframes, fZoneOffset, iSize, gF_Tickrate, gS_Map);
}
WriteReplayFrames(playerrecording, iSize, fWR, fCopy);
delete fWR;
delete fCopy;
return true;
}
public void OnPlayerRunCmdPost(int client, int buttons, int impulse, const float vel[3], const float angles[3], int weapon, int subtype, int cmdnum, int tickcount, int seed, const int mouse[2])
{
static bool resizeFailed[MAXPLAYERS+1];
if (resizeFailed[client]) // rip
{
resizeFailed[client] = false;
gB_RecordingEnabled[client] = false;
ClearFrames(client);
LogError("failed to resize frames for %N... clearing frames I guess...", client);
return;
}
if (IsFakeClient(client) || !IsPlayerAlive(client))
{
return;
}
if (!gA_PlayerFrames[client] || !gB_RecordingEnabled[client])
{
return;
}
if (!gB_GrabbingPostFrames[client] && !(Shavit_ReplayEnabledStyle(Shavit_GetBhopStyle(client)) && Shavit_GetTimerStatus(client) == Timer_Running))
{
return;
}
if ((gI_PlayerFrames[client] / gF_Tickrate) > gCV_TimeLimit.FloatValue)
{
if (gI_HijackFrames[client])
{
gI_HijackFrames[client] = 0;
}
return;
}
if (!Shavit_ShouldProcessFrame(client))
{
return;
}
if (gA_PlayerFrames[client].Length <= gI_PlayerFrames[client])
{
resizeFailed[client] = true;
// Add about two seconds worth of frames so we don't have to resize so often
gA_PlayerFrames[client].Resize(gI_PlayerFrames[client] + (RoundToCeil(gF_Tickrate) * 2));
//PrintToChat(client, "resizing %d -> %d", gI_PlayerFrames[client], gA_PlayerFrames[client].Length);
resizeFailed[client] = false;
}
frame_t aFrame;
GetClientAbsOrigin(client, aFrame.pos);
if (!gI_HijackFrames[client])
{
float vecEyes[3];
GetClientEyeAngles(client, vecEyes);
aFrame.ang[0] = vecEyes[0];
aFrame.ang[1] = vecEyes[1];
}
else
{
aFrame.ang = gF_HijackedAngles[client];
--gI_HijackFrames[client];
}
aFrame.buttons = buttons;
aFrame.flags = GetEntityFlags(client);
aFrame.mt = GetEntityMoveType(client);
aFrame.mousexy = (mouse[0] & 0xFFFF) | ((mouse[1] & 0xFFFF) << 16);
aFrame.vel = LimitMoveVelFloat(vel[0]) | (LimitMoveVelFloat(vel[1]) << 16);
gA_PlayerFrames[client].SetArray(gI_PlayerFrames[client]++, aFrame, sizeof(frame_t));
}
stock int LimitMoveVelFloat(float vel)
{
int x = RoundToCeil(vel);
return ((x < -666) ? -666 : ((x > 666) ? 666 : x)) & 0xFFFF;
}
public int Native_GetClientFrameCount(Handle handler, int numParams)
{
return gI_PlayerFrames[GetNativeCell(1)];
}
public int Native_GetPlayerPreFrames(Handle handler, int numParams)
{
return gI_PlayerPrerunFrames[GetNativeCell(1)];
}
public int Native_SetPlayerPreFrames(Handle handler, int numParams)
{
int client = GetNativeCell(1);
int preframes = GetNativeCell(2);
gI_PlayerPrerunFrames[client] = preframes;
return 1;
}
public int Native_GetReplayData(Handle plugin, int numParams)
{
int client = GetNativeCell(1);
bool cheapCloneHandle = view_as<bool>(GetNativeCell(2));
Handle cloned = null;
if(gA_PlayerFrames[client] != null)
{
ArrayList frames = cheapCloneHandle ? gA_PlayerFrames[client] : gA_PlayerFrames[client].Clone();
frames.Resize(gI_PlayerFrames[client]);
cloned = CloneHandle(frames, plugin); // set the calling plugin as the handle owner
if (!cheapCloneHandle)
{
// Only hit for .Clone()'d handles. .Clone() != CloneHandle()
CloseHandle(frames);
}
}
return view_as<int>(cloned);
}
public int Native_SetReplayData(Handle handler, int numParams)
{
int client = GetNativeCell(1);
ArrayList data = view_as<ArrayList>(GetNativeCell(2));
bool cheapCloneHandle = view_as<bool>(GetNativeCell(3));
if (gB_GrabbingPostFrames[client])
{
FinishGrabbingPostFrames(client, gA_FinishedRunInfo[client]);
}
// Player starts run, reconnects, savestate reloads, and this needs to be true...
gB_RecordingEnabled[client] = true;
if (cheapCloneHandle)
{
data = view_as<ArrayList>(CloneHandle(data));
}
else
{
data = data.Clone();
}
delete gA_PlayerFrames[client];
gA_PlayerFrames[client] = data;
gI_PlayerFrames[client] = data.Length;
return 1;
}
public int Native_HijackAngles(Handle handler, int numParams)
{
int client = GetNativeCell(1);
gF_HijackedAngles[client][0] = view_as<float>(GetNativeCell(2));
gF_HijackedAngles[client][1] = view_as<float>(GetNativeCell(3));
int ticks = GetNativeCell(4);
if (ticks == -1)
{
float latency = GetClientLatency(client, NetFlow_Both);
if (latency > 0.0)
{
ticks = RoundToCeil(latency / GetTickInterval()) + 1;
//PrintToChat(client, "%f %f %d", latency, GetTickInterval(), ticks);
gI_HijackFrames[client] = ticks;
}
}
else
{
gI_HijackFrames[client] = ticks;
}
gB_HijackFramesKeepOnStart[client] = (numParams < 5) ? false : view_as<bool>(GetNativeCell(5));
return ticks;
}

View File

@ -1,8 +1,9 @@
/*
* shavit's Timer - Sounds
* by: shavit
* by: shavit, KiD Fearless
*
* This file is part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
* This file is part of shavit's Timer.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
@ -16,15 +17,18 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
*/
#include <sourcemod>
#include <sdktools>
#include <convar_class>
#include <dhooks>
#include <shavit/core>
#include <shavit/wr>
#undef REQUIRE_PLUGIN
#include <shavit>
#include <shavit/hud>
#pragma newdecls required
#pragma semicolon 1
@ -47,7 +51,7 @@ Handle gH_OnPlaySound = null;
public Plugin myinfo =
{
name = "[shavit] Sounds",
author = "shavit",
author = "shavit, KiD Fearless",
description = "Play custom sounds when timer-related events happen.",
version = SHAVIT_VERSION,
url = "https://github.com/shavitush/bhoptimer"
@ -61,14 +65,6 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max
return APLRes_Success;
}
public void OnAllPluginsLoaded()
{
if(!LibraryExists("shavit-wr"))
{
SetFailState("shavit-wr is required for the plugin to work.");
}
}
public void OnPluginStart()
{
// cache
@ -126,7 +122,6 @@ public void OnMapStart()
{
SetFailState("Cannot open \"configs/shavit-sounds.cfg\". Make sure this file exists and that the server has read permissions to it.");
}
else
{
char sLine[PLATFORM_MAX_PATH*2];
@ -150,27 +145,22 @@ public void OnMapStart()
{
gA_FirstSounds.PushString(sExploded[1]);
}
else if(StrEqual(sExploded[0], "personal"))
{
gA_PersonalSounds.PushString(sExploded[1]);
}
else if(StrEqual(sExploded[0], "world"))
{
gA_WorldSounds.PushString(sExploded[1]);
}
else if(StrEqual(sExploded[0], "worst"))
{
gA_WorstSounds.PushString(sExploded[1]);
}
else if(StrEqual(sExploded[0], "worse") || StrEqual(sExploded[0], "noimprovement"))
{
gA_NoImprovementSounds.PushString(sExploded[1]);
}
else
{
gSM_RankSounds.SetString(sExploded[0], sExploded[1]);
@ -181,7 +171,6 @@ public void OnMapStart()
FormatEx(sDownloadString, PLATFORM_MAX_PATH, "sound/%s", sExploded[1]);
AddFileToDownloadsTable(sDownloadString);
}
else
{
LogError("\"sound/%s\" could not be accessed.", sExploded[1]);
@ -208,15 +197,13 @@ public void Shavit_OnFinish(int client, int style, float time, int jumps, int st
}
}
public void Shavit_OnFinish_Post(int client, int style, float time, int jumps, int strafes, float sync, int rank, int overwrite, int track)
public void Shavit_OnFinish_Post(int client, int style, float time, int jumps, int strafes, float sync, int rank, int overwrite, int track, float fOldTime)
{
if(!gCV_Enabled.BoolValue)
{
return;
}
float fOldTime = Shavit_GetClientPB(client, style, track);
char sSound[PLATFORM_MAX_PATH];
bool bEveryone = false;
@ -227,19 +214,16 @@ public void Shavit_OnFinish_Post(int client, int style, float time, int jumps, i
{
bEveryone = true;
}
else if(gA_WorldSounds.Length != 0 && rank == 1)
{
bEveryone = true;
gA_WorldSounds.GetString(GetRandomInt(0, gA_WorldSounds.Length - 1), sSound, PLATFORM_MAX_PATH);
}
else if(gA_PersonalSounds.Length != 0 && time < fOldTime)
{
gA_PersonalSounds.GetString(GetRandomInt(0, gA_PersonalSounds.Length - 1), sSound, PLATFORM_MAX_PATH);
}
else if(gA_FirstSounds.Length != 0 && overwrite == 1)
{
gA_FirstSounds.GetString(GetRandomInt(0, gA_FirstSounds.Length - 1), sSound, PLATFORM_MAX_PATH);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,997 @@
/*
* shavit's Timer - TAS
* by: xutaxkamay, KiD Fearless, rtldg
*
* This file is part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <sourcemod>
#include <sdktools>
#include <sdkhooks>
#include <cstrike>
#include <convar_class>
#include <shavit/core>
#include <shavit/tas>
#include <shavit/tas-oblivious>
#include <shavit/tas-xutax>
#undef REQUIRE_PLUGIN
#include <shavit/checkpoints>
#include <shavit/replay-recorder>
#include <shavit/zones>
#pragma newdecls required
#pragma semicolon 1
bool gB_Late = false;
EngineVersion gEV_Type = Engine_Unknown;
float g_flAirSpeedCap = 30.0;
float g_flOldYawAngle[MAXPLAYERS + 1];
int g_iSurfaceFrictionOffset;
float g_fMaxMove = 400.0;
bool gB_Autostrafer[MAXPLAYERS + 1];
AutostrafeType gI_Type[MAXPLAYERS + 1];
AutostrafeOverride gI_Override[MAXPLAYERS + 1];
bool gB_Prestrafe[MAXPLAYERS + 1];
bool gB_AutoJumpOnStart[MAXPLAYERS + 1];
bool gB_EdgeJump[MAXPLAYERS + 1];
float g_fPower[MAXPLAYERS + 1] = {1.0, ...};
bool gB_AutogainBasicStrafer[MAXPLAYERS + 1];
bool gB_ForceJump[MAXPLAYERS+1];
int gI_LastRestart[MAXPLAYERS+1];
ConVar sv_airaccelerate = null;
ConVar sv_accelerate = null;
ConVar sv_friction = null;
ConVar sv_stopspeed = null;
chatstrings_t gS_ChatStrings;
bool gB_GlobalTraceResult = false;
bool gB_ReplayRecorder = false;
public Plugin myinfo =
{
name = "[shavit] TAS",
author = "xutaxkamay, oblivious, KiD Fearless, rtldg",
description = "TAS module for shavit's bhop timer featuring xutaxkamay's autostrafer and oblivious's autogain.",
version = SHAVIT_VERSION,
url = "https://github.com/shavitush/bhoptimer"
};
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
{
CreateNative("Shavit_SetAutostrafeEnabled", Native_SetAutostrafeEnabled);
CreateNative("Shavit_GetAutostrafeEnabled", Native_GetAutostrafeEnabled);
CreateNative("Shavit_SetAutostrafeType", Native_SetAutostrafeType);
CreateNative("Shavit_GetAutostrafeType", Native_GetAutostrafeType);
CreateNative("Shavit_SetAutostrafePower", Native_SetAutostrafePower);
CreateNative("Shavit_GetAutostrafePower", Native_GetAutostrafePower);
CreateNative("Shavit_SetAutostrafeKeyOverride", Native_SetAutostrafeKeyOverride);
CreateNative("Shavit_GetAutostrafeKeyOverride", Native_GetAutostrafeKeyOverride);
CreateNative("Shavit_SetAutoPrestrafe", Native_SetAutoPrestrafe);
CreateNative("Shavit_GetAutoPrestrafe", Native_GetAutoPrestrafe);
CreateNative("Shavit_SetAutoJumpOnStart", Native_SetAutoJumpOnStart);
CreateNative("Shavit_GetAutoJumpOnStart", Native_GetAutoJumpOnStart);
CreateNative("Shavit_SetEdgeJump", Native_SetEdgeJump);
CreateNative("Shavit_GetEdgeJump", Native_GetEdgeJump);
CreateNative("Shavit_SetAutogainBasicStrafer", Native_SetAutogainBasicStrafer);
CreateNative("Shavit_GetAutogainBasicStrafer", Native_GetAutogainBasicStrafer);
gB_Late = late;
RegPluginLibrary("shavit-tas");
return APLRes_Success;
}
public void OnPluginStart()
{
LoadTranslations("shavit-common.phrases");
LoadTranslations("shavit-misc.phrases");
gEV_Type = GetEngineVersion();
sv_airaccelerate = FindConVar("sv_airaccelerate");
sv_accelerate = FindConVar("sv_accelerate");
sv_friction = FindConVar("sv_friction");
sv_stopspeed = FindConVar("sv_stopspeed");
GameData gamedata = new GameData("shavit.games");
Address surfaceFrictionAddress;
if (gEV_Type == Engine_CSGO)
surfaceFrictionAddress = gamedata.GetAddress("m_surfaceFriction");
else
surfaceFrictionAddress = gamedata.GetMemSig("CBasePlayer->m_surfaceFriction");
if (surfaceFrictionAddress == Address_Null)
{
g_iSurfaceFrictionOffset = -1;
LogError("[XUTAX] The address of m_surfaceFriction is null, defaulting friction values");
}
else
{
if (gEV_Type == Engine_CSGO)
{
g_iSurfaceFrictionOffset = view_as<int>(surfaceFrictionAddress);
}
else
{
int instr = LoadFromAddress(surfaceFrictionAddress, NumberType_Int32);
// The lowest two bytes are the beginning of a `mov`.
// The offset is 100% definitely totally always 16-bit.
// We could just put the offset into the gamedata too but SHUT UP!
g_iSurfaceFrictionOffset = instr >> 16;
}
}
delete gamedata;
if (gEV_Type == Engine_CSGO)
{
g_fMaxMove = 450.0;
ConVar sv_air_max_wishspeed = FindConVar("sv_air_max_wishspeed");
sv_air_max_wishspeed.AddChangeHook(OnWishSpeedChanged);
g_flAirSpeedCap = sv_air_max_wishspeed.FloatValue;
}
AddCommandListener(CommandListener_Toggler, "+autostrafer");
AddCommandListener(CommandListener_Toggler, "-autostrafer");
AddCommandListener(CommandListener_Toggler, "+autostrafe");
AddCommandListener(CommandListener_Toggler, "-autostrafe");
AddCommandListener(CommandListener_Toggler, "+autoprestrafe");
AddCommandListener(CommandListener_Toggler, "-autoprestrafe");
AddCommandListener(CommandListener_Toggler, "+autojumponstart");
AddCommandListener(CommandListener_Toggler, "-autojumponstart");
AddCommandListener(CommandListener_Toggler, "+edgejump");
AddCommandListener(CommandListener_Toggler, "-edgejump");
AddCommandListener(CommandListener_Toggler, "+autogainbss");
AddCommandListener(CommandListener_Toggler, "-autogainbss");
RegConsoleCmd("sm_autostrafer", Command_Toggler, "Usage: !autostrafe [1|0]");
RegConsoleCmd("sm_autostrafe", Command_Toggler, "Usage: !autostrafe [1|0]");
RegConsoleCmd("sm_autoprestrafe", Command_Toggler, "Usage: !autoprestrafe [1|0}");
RegConsoleCmd("sm_autojumponstart", Command_Toggler, "Usage: !autojumponstart [1|0}");
RegConsoleCmd("sm_edgejump", Command_Toggler, "Usage: !edgejump [1|0}");
RegConsoleCmd("sm_autogainbss", Command_Toggler, "Usage: !autogainbss [1|0}");
RegConsoleCmd("sm_tasm", Command_TasSettingsMenu, "Opens the TAS settings menu.");
RegConsoleCmd("sm_tasmenu", Command_TasSettingsMenu, "Opens the TAS settings menu.");
//Convar.AutoExecConfig();
if (gB_Late)
{
Shavit_OnChatConfigLoaded();
for (int i = 1; i <= MaxClients; i++)
{
if (IsClientConnected(i))
{
OnClientConnected(i);
if (IsClientInGame(i))
{
OnClientPutInServer(i);
}
}
}
}
gB_ReplayRecorder = LibraryExists("shavit-replay-recorder");
}
public void OnLibraryAdded(const char[] name)
{
if (StrEqual(name, "shavit-replay-recorder"))
{
gB_ReplayRecorder = true;
}
}
public void OnLibraryRemoved(const char[] name)
{
if (StrEqual(name, "shavit-replay-recorder"))
{
gB_ReplayRecorder = false;
}
}
// doesn't exist in css so we have to cache the value
public void OnWishSpeedChanged(ConVar convar, const char[] oldValue, const char[] newValue)
{
g_flAirSpeedCap = StringToFloat(newValue);
}
public void OnClientConnected(int client)
{
gB_Autostrafer[client] = true;
gI_Override[client] = AutostrafeOverride_Surf_W_Okay;
gI_Type[client] = AutostrafeType_1Tick;
gB_AutoJumpOnStart[client] = true;
gB_EdgeJump[client] = true;
gB_Prestrafe[client] = true;
g_fPower[client] = 1.0;
gB_AutogainBasicStrafer[client] = true;
}
public void OnClientPutInServer(int client)
{
if (!IsFakeClient(client))
{
SDKHook(client, SDKHook_PostThinkPost, PostThinkPost);
}
}
public void Shavit_OnChatConfigLoaded()
{
Shavit_GetChatStringsStruct(gS_ChatStrings);
}
public Action Shavit_OnStart(int client, int track)
{
gB_ForceJump[client] = false;
return Plugin_Continue;
}
public void Shavit_OnRestart(int client, int track)
{
gI_LastRestart[client] = GetGameTickCount();
}
public Action Shavit_OnTeleportPre(int client, int index, int target)
{
// to prevent gB_ForceJump when teleporting to a checkpoint in the start zone
gI_LastRestart[client] = GetGameTickCount();
}
public void Shavit_OnEnterZone(int client, int type, int track, int id, int entity, int data)
{
if (!IsValidClient(client, true) || IsFakeClient(client))
{
return;
}
if (type == Zone_Start)
{
if (Shavit_GetClientTrack(client) == track)
{
gB_ForceJump[client] = false;
}
}
}
public void Shavit_OnLeaveZone(int client, int type, int track, int id, int entity, int data)
{
if (type != Zone_Start)
{
return;
}
if (!IsValidClient(client, true) || IsFakeClient(client))
{
return;
}
if (!Shavit_GetStyleSettingBool(Shavit_GetBhopStyle(client), "autojumponstart"))
{
return;
}
if (Shavit_GetTimerStatus(client) != Timer_Running)
{
return;
}
// You can be inside multiple startzones...
if (Shavit_InsideZone(client, type, track))
{
return;
}
// Shavit_OnLeaveZone() will be called a couple times because of the shavit-zones event-clearing thing that happens on restart.
// 5 is a good value that works, but we'll use 6 just-in-case.
if (GetGameTickCount() - gI_LastRestart[client] < 6)
{
return;
}
if (GetEntityFlags(client) & FL_ONGROUND)
{
if (gB_AutoJumpOnStart[client])
{
gB_ForceJump[client] = true;
}
}
}
int FindMenuItem(Menu menu, const char[] info)
{
for (int i = 0; i < menu.ItemCount; i++)
{
char sInfo[64];
menu.GetItem(i, sInfo, sizeof(sInfo));
if (StrEqual(info, sInfo))
{
return i;
}
}
return -1;
}
bool HasAnyTasStyleSettings(int style)
{
if (Shavit_GetStyleSettingBool(style, "tas")
|| Shavit_GetStyleSettingBool(style, "tas_timescale")
|| Shavit_GetStyleSettingBool(style, "autoprestrafe")
|| Shavit_GetStyleSettingBool(style, "edgejump")
|| Shavit_GetStyleSettingBool(style, "autojumponstart"))
{
return true;
}
return false;
}
public Action Shavit_OnCheckpointMenuMade(int client, bool segmented, Menu menu)
{
if (!HasAnyTasStyleSettings(Shavit_GetBhopStyle(client)))
{
return Plugin_Continue;
}
char sDisplay[64];
bool tas_timescale = (Shavit_GetStyleSettingFloat(Shavit_GetBhopStyle(client), "tas_timescale") == -1.0);
FormatEx(sDisplay, 64, "%T\n ", "TasSettings", client);
if (tas_timescale)
{
int pos = FindMenuItem(menu, "del");
menu.InsertItem(pos, "tassettings", sDisplay);
}
else
{
menu.AddItem("tassettings", sDisplay);
}
menu.ExitButton = gEV_Type != Engine_CSGO;
return Plugin_Changed;
}
public Action Shavit_OnCheckpointMenuSelect(int client, int param2, char[] info, int maxlength, int currentCheckpoint, int maxCPs)
{
if (StrEqual(info, "tassettings"))
{
OpenTasSettingsMenu(client);
return Plugin_Stop;
}
return Plugin_Continue;
}
public Action Shavit_OnUserCmdPre(int client, int &buttons, int &impulse, float vel[3], float angles[3], TimerStatus status, int track, int style, int mouse[2])
{
if (!Shavit_ShouldProcessFrame(client))
{
return Plugin_Continue;
}
if (gB_ForceJump[client] && (Shavit_GetStyleSettingBool(style, "edgejump") || Shavit_GetStyleSettingBool(style, "autojumponstart")))
{
buttons |= IN_JUMP;
}
gB_ForceJump[client] = false;
return Plugin_Changed;
}
bool TRFilter_OnlyZones(int entity, any data)
{
int zoneid = Shavit_GetZoneID(entity);
if (zoneid == -1 || Shavit_GetZoneTrack(zoneid) != data)
{
return true;
}
gB_GlobalTraceResult = true;
return false;
}
#if 0
public void OnPlayerRunCmdPost(int client, int buttons, int impulse, const float vel[3], const float angles[3], int weapon, int subtype, int cmdnum, int tickcount, int seed, const int mouse[2])
{
if (IsFakeClient(client))
{
return;
}
#else
public void PostThinkPost(int client)
{
#endif
if (gB_ForceJump[client])
{
return;
}
int style = Shavit_GetBhopStyle(client);
bool edgejump = (gB_EdgeJump[client] && Shavit_GetStyleSettingBool(style, "edgejump"));
bool autojumponstart = (gB_AutoJumpOnStart[client] && Shavit_GetStyleSettingBool(style, "autojumponstart"));
if (!edgejump && !autojumponstart)
{
return;
}
if (!Shavit_ShouldProcessFrame(client))
{
return;
}
if (!IsPlayerAlive(client) || GetEntityMoveType(client) != MOVETYPE_WALK || !(GetEntProp(client, Prop_Data, "m_nWaterLevel") <= 1))
{
return;
}
if (!(GetEntityFlags(client) & FL_ONGROUND))
{
return;
}
float origin[3], absvel[3], nextpos[3];
GetClientAbsOrigin(client, origin);
GetEntPropVector(client, Prop_Data, "m_vecAbsVelocity", absvel);
ScaleVector(absvel, GetTickInterval());
float mins[3], maxs[3];
GetEntPropVector(client, Prop_Send, "m_vecMins", mins);
GetEntPropVector(client, Prop_Send, "m_vecMaxs", maxs);
if (autojumponstart)
{
int track = Shavit_GetClientTrack(client);
if (Shavit_InsideZone(client, Zone_Start, track))
{
float blah[3]; blah = absvel;
ScaleVector(blah, 3.0); // 2 isn't always enough... so 3 it is :)
AddVectors(origin, blah, nextpos);
gB_GlobalTraceResult = false;
TR_EnumerateEntitiesHull(nextpos, nextpos, mins, maxs, PARTITION_TRIGGER_EDICTS, TRFilter_OnlyZones, track);
if (!gB_GlobalTraceResult)
{
gB_ForceJump[client] = true;
}
}
}
if (edgejump && !gB_ForceJump[client])
{
float lower[3];
AddVectors(origin, absvel, nextpos);
AddVectors(nextpos, view_as<float>({0.0, 0.0, -10.0}), lower);
TR_TraceHullFilter(nextpos, lower, mins, maxs, MASK_PLAYERSOLID, TRFilter_NoPlayers, client);
gB_ForceJump[client] = !TR_DidHit();
}
}
public Action OnPlayerRunCmd(int client, int& buttons, int& impulse, float vel[3], float angles[3], int& weapon, int& subtype, int& cmdnum, int& tickcount, int& seed, int mouse[2])
{
if (IsFakeClient(client))
{
return Plugin_Continue;
}
if (!Shavit_ShouldProcessFrame(client))
{
return Plugin_Continue;
}
if (!IsPlayerAlive(client) || GetEntityMoveType(client) == MOVETYPE_NOCLIP || GetEntityMoveType(client) == MOVETYPE_LADDER || !(GetEntProp(client, Prop_Data, "m_nWaterLevel") <= 1))
{
return Plugin_Continue;
}
static int s_iOnGroundCount[MAXPLAYERS+1] = {1, ...};
if (GetEntPropEnt(client, Prop_Send, "m_hGroundEntity") != -1)
{
s_iOnGroundCount[client]++;
}
else
{
s_iOnGroundCount[client] = 0;
#if 0
if (buttons & IN_FORWARD)
{
buttons &= ~IN_FORWARD;
vel[0] = 0.0;
}
#endif
}
float flSurfaceFriction = 1.0;
if (g_iSurfaceFrictionOffset > 0)
{
flSurfaceFriction = GetEntDataFloat(client, g_iSurfaceFrictionOffset);
}
int style = Shavit_GetBhopStyle(client);
AutostrafeType type = view_as<AutostrafeType>(Shavit_GetStyleSettingInt(style, "autostrafe"));
if (type == AutostrafeType_Any)
{
type = gI_Type[client];
}
float oldyaw = g_flOldYawAngle[client];
g_flOldYawAngle[client] = angles[1];
if (s_iOnGroundCount[client] <= 1)
{
if (!type || !gB_Autostrafer[client] || IsSurfing(client))
{
return Plugin_Continue;
}
if (type != AutostrafeType_Autogain && type != AutostrafeType_AutogainNoSpeedLoss)
{
if (!!(buttons & IN_BACK))
{
return Plugin_Continue;
}
if (!!(buttons & IN_FORWARD))
{
if (gI_Override[client] != AutostrafeOverride_Surf_W_Okay)
{
return Plugin_Continue;
}
}
if (!!(buttons & (IN_MOVERIGHT | IN_MOVELEFT)))
{
if (gI_Override[client] == AutostrafeOverride_All)
{
return Plugin_Continue;
}
/*
else if (gI_Override[client] == AutostrafeOverride_Surf && IsSurfing(client))
{
return Plugin_Continue;
}
*/
}
}
if (type == AutostrafeType_1Tick)
{
XutaxOnPlayerRunCmd(client, buttons, impulse, vel, angles, weapon, subtype, cmdnum, tickcount, seed, mouse,
sv_airaccelerate.FloatValue, flSurfaceFriction, g_flAirSpeedCap, g_fMaxMove, oldyaw, g_fPower[client]);
}
else if (type == AutostrafeType_Autogain || type == AutostrafeType_AutogainNoSpeedLoss)
{
if (gB_AutogainBasicStrafer[client])
{
float delta = AngleNormalize(angles[1] - oldyaw);
if (delta < 0.0)
{
vel[1] = g_fMaxMove;
}
else if (delta > 0.0)
{
vel[1] = -g_fMaxMove;
}
}
ObliviousOnPlayerRunCmd(client, buttons, impulse, vel, angles, weapon, subtype, cmdnum, tickcount, seed, mouse,
sv_airaccelerate.FloatValue, flSurfaceFriction, g_flAirSpeedCap, g_fMaxMove,
(type == AutostrafeType_AutogainNoSpeedLoss));
}
else if (type == AutostrafeType_Basic)
{
float delta = AngleNormalize(angles[1] - oldyaw);
if (delta < 0.0)
{
vel[1] = g_fMaxMove;
}
else if (delta > 0.0)
{
vel[1] = -g_fMaxMove;
}
}
}
else
{
if (gB_Prestrafe[client]
&& (vel[0] != 0.0 || vel[1] != 0.0)
&& Shavit_GetStyleSettingBool(style, "autoprestrafe"))
{
float _delta_opt = ground_delta_opt(client, angles, vel, flSurfaceFriction,
sv_accelerate.FloatValue, sv_friction.FloatValue, sv_stopspeed.FloatValue);
float _tmp[3]; _tmp[0] = angles[0]; _tmp[2] = angles[2];
_tmp[1] = normalize_yaw(angles[1] - _delta_opt);
if (gB_ReplayRecorder)
{
Shavit_HijackAngles(client, angles[0], angles[1], 2, true);
}
angles[1] = _tmp[1];
}
}
return Plugin_Continue;
}
void OpenTasSettingsMenu(int client, int pos=0)
{
char display[64];
Menu menu = new Menu(MenuHandler_TasSettings, MENU_ACTIONS_DEFAULT);
menu.SetTitle("%T\n ", "TasSettings", client);
int style = Shavit_GetBhopStyle(client);
bool autostrafe_allowed = Shavit_GetStyleSettingBool(style, "autostrafe");
bool autostrafe = (gB_Autostrafer[client] && autostrafe_allowed);
FormatEx(display, sizeof(display), "[%s] %T", autostrafe ? "":"", "Autostrafer", client);
menu.AddItem("autostrafe", display, autostrafe_allowed ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED);
bool autojumponstart_allowed = Shavit_GetStyleSettingBool(style, "autojumponstart");
bool autojumponstart = (gB_AutoJumpOnStart[client] && autojumponstart_allowed);
FormatEx(display, sizeof(display), "[%s] %T", autojumponstart ? "":"", "AutoJumpOnStart", client);
menu.AddItem("autojump", display, autojumponstart_allowed ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED);
bool autoprestrafe_allowed = Shavit_GetStyleSettingBool(style, "autoprestrafe");
bool autoprestrafe = (gB_Prestrafe[client] && autoprestrafe_allowed);
FormatEx(display, sizeof(display), "[%s] %T\n ", autoprestrafe ? "":"", "AutoPrestrafe", client);
menu.AddItem("prestrafe", display, autoprestrafe_allowed ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED);
AutostrafeType tastype = view_as<AutostrafeType>(Shavit_GetStyleSettingInt(style, "autostrafe"));
bool tastype_editable = (tastype == AutostrafeType_Any);
tastype = tastype_editable ? gI_Type[client] : tastype;
FormatEx(display, sizeof(display), "%T: %T\n ", "Autostrafer_type", client,
(tastype == AutostrafeType_Disabled ? "TASDisabled" : (tastype == AutostrafeType_1Tick ? "Autostrafer_1tick" : (tastype == AutostrafeType_Autogain ? "Autostrafer_autogain" : tastype == AutostrafeType_Basic ? "Autostrafer_basic" : "Autostrafer_autogain_nsl"))), client);
menu.AddItem("type", display, (tastype_editable ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED));
bool tas_timescale = (Shavit_GetStyleSettingFloat(Shavit_GetBhopStyle(client), "tas_timescale") == -1.0);
float ts = Shavit_GetClientTimescale(client);
char buf[10];
PrettyishTimescale(buf, sizeof(buf), ts, 0.1, 1.0, 0.0);
FormatEx(display, sizeof(display), "--%T\n%T: %s", "Timescale", client, "CurrentTimescale", client, buf);
menu.AddItem("tsminus", display, (tas_timescale && ts > 0.1) ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED);
FormatEx(display, sizeof(display), "++%T\n ", "Timescale", client);
menu.AddItem("tsplus", display, (tas_timescale && ts != 1.0) ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED);
bool edgejump_allowed = Shavit_GetStyleSettingBool(style, "edgejump");
bool edgejump = (gB_EdgeJump[client] && edgejump_allowed);
FormatEx(display, sizeof(display), "[%s] %T", edgejump ? "":"", "EdgeJump", client);
menu.AddItem("edgejump", display, edgejump_allowed ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED);
AutostrafeOverride ov = gI_Override[client];
FormatEx(display, sizeof(display), "%T: %T", "AutostrafeOverride", client,
(ov == AutostrafeOverride_Normal ? "AutostrafeOverride_Normal" : (ov == AutostrafeOverride_Surf ? "AutostrafeOverride_Surf" : (ov == AutostrafeOverride_Surf_W_Okay ? "AutostrafeOverride_Surf_W_Okay" : "AutostrafeOverride_All"))), client);
menu.AddItem("override", display);
FormatEx(display, sizeof(display), "[%s] %T", gB_AutogainBasicStrafer[client] ? "":"", "AutogainBasicStrafer", client);
menu.AddItem("autogainbss", display,
(tastype == AutostrafeType_Autogain || tastype == AutostrafeType_AutogainNoSpeedLoss) ?
ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED);
if (Shavit_GetStyleSettingBool(Shavit_GetBhopStyle(client), "segments"))
{
menu.ExitBackButton = true;
}
else
{
menu.ExitButton = true;
}
menu.DisplayAt(client, pos, MENU_TIME_FOREVER);
}
public int MenuHandler_TasSettings(Menu menu, MenuAction action, int param1, int param2)
{
if (action == MenuAction_Select)
{
char info[16];
menu.GetItem(param2, info, sizeof(info));
if (StrEqual(info, "autostrafe"))
{
gB_Autostrafer[param1] = !gB_Autostrafer[param1];
}
else if (StrEqual(info, "autojump"))
{
gB_AutoJumpOnStart[param1] = !gB_AutoJumpOnStart[param1];
}
else if (StrEqual(info, "edgejump"))
{
gB_EdgeJump[param1] = !gB_EdgeJump[param1];
}
else if (StrEqual(info, "prestrafe"))
{
gB_Prestrafe[param1] = !gB_Prestrafe[param1];
}
else if (StrEqual(info, "autogainbss"))
{
gB_AutogainBasicStrafer[param1] = !gB_AutogainBasicStrafer[param1];
}
else if (StrEqual(info, "type"))
{
AutostrafeType tastype = view_as<AutostrafeType>(Shavit_GetStyleSettingInt(Shavit_GetBhopStyle(param1), "autostrafe"));
if (tastype == AutostrafeType_Any)
{
gI_Type[param1] = (gI_Type[param1] == AutostrafeType_1Tick ? AutostrafeType_Autogain : gI_Type[param1] == AutostrafeType_Basic ? AutostrafeType_1Tick : AutostrafeType_Basic);
}
}
else if (StrEqual(info, "override"))
{
if (++gI_Override[param1] >= AutostrafeOverride_Size)
{
gI_Override[param1] = AutostrafeOverride_Normal;
}
}
else if (StrEqual(info, "tsplus"))
{
if (Shavit_GetStyleSettingFloat(Shavit_GetBhopStyle(param1), "tas_timescale") == -1.0)
{
FakeClientCommand(param1, "sm_tsplus");
}
}
else if (StrEqual(info, "tsminus"))
{
if (Shavit_GetStyleSettingFloat(Shavit_GetBhopStyle(param1), "tas_timescale") == -1.0)
{
FakeClientCommand(param1, "sm_tsminus");
}
}
OpenTasSettingsMenu(param1, GetMenuSelectionPosition());
}
else if (action == MenuAction_Cancel && param2 == MenuCancel_ExitBack)
{
FakeClientCommandEx(param1, "sm_cp");
}
else if (action == MenuAction_End)
{
delete menu;
}
return 0;
}
void Command_Toggler_Internal(int client, const char[] asdfcommand, int x)
{
if (!IsValidClient(client))
{
return;
}
char command[32];
strcopy(command, sizeof(command), asdfcommand);
if (StrEqual(command, "autostrafer"))
{
command = "autostrafe";
}
if (!StrEqual(command, "autogainbss"))
{
if (!Shavit_GetStyleSettingBool(Shavit_GetBhopStyle(client), command))
{
return;
}
}
bool set;
char translation[32];
if (StrEqual(command, "autostrafe"))
{
set = gB_Autostrafer[client] = (x == -1) ? !gB_Autostrafer[client] : (x != 0);
translation = "Autostrafer";
}
else if (StrEqual(command, "autoprestrafe"))
{
set = gB_Prestrafe[client] = (x == -1) ? !gB_Prestrafe[client] : (x != 0);
translation = "AutoPrestrafe";
}
else if (StrEqual(command, "autojumponstart"))
{
set = gB_AutoJumpOnStart[client] = (x == -1) ? !gB_AutoJumpOnStart[client] : (x != 0);
translation = "AutoJumpOnStart";
}
else if (StrEqual(command, "edgejump"))
{
set = gB_EdgeJump[client] = (x == -1) ? !gB_EdgeJump[client] : (x != 0);
translation = "EdgeJump";
}
else if (StrEqual(command, "autogainbss"))
{
set = gB_AutogainBasicStrafer[client] = (x == -1) ? !gB_AutogainBasicStrafer[client] : (x != 0);
translation = "AutogainBasicStrafer";
}
Shavit_StopChatSound();
Shavit_PrintToChat(client, "%T: %s%T", translation, client, (set ? gS_ChatStrings.sVariable : gS_ChatStrings.sWarning), (set ? "TASEnabled" : "TASDisabled"), client);
}
public Action CommandListener_Toggler(int client, const char[] command, int args)
{
Command_Toggler_Internal(client, command[1], (command[0] == '+') ? 1 : 0);
return Plugin_Stop;
}
public Action Command_Toggler(int client, int args)
{
char command[32];
GetCmdArg(0, command, sizeof(command));
int x = -1;
if (args > 0)
{
char arg[5];
GetCmdArg(1, arg, sizeof(arg));
x = StringToInt(arg);
}
Command_Toggler_Internal(client, command[3], x);
return Plugin_Handled;
}
public Action Command_TasSettingsMenu(int client, int args)
{
if (IsValidClient(client))
{
OpenTasSettingsMenu(client);
}
return Plugin_Handled;
}
// natives
public any Native_SetAutostrafeEnabled(Handle plugin, int numParams)
{
int client = GetNativeCell(1);
bool value = GetNativeCell(2);
gB_Autostrafer[client] = value;
return 0;
}
public any Native_GetAutostrafeEnabled(Handle plugin, int numParams)
{
int client = GetNativeCell(1);
return gB_Autostrafer[client];
}
public any Native_SetAutostrafeType(Handle plugin, int numParams)
{
int client = GetNativeCell(1);
AutostrafeType value = view_as<AutostrafeType>(GetNativeCell(2));
gI_Type[client] = value;
return 0;
}
public any Native_GetAutostrafeType(Handle plugin, int numParams)
{
int client = GetNativeCell(1);
return gI_Type[client];
}
public any Native_SetAutostrafePower(Handle plugin, int numParams)
{
int client = GetNativeCell(1);
float value = GetNativeCell(2);
g_fPower[client] = value;
return 0;
}
public any Native_GetAutostrafePower(Handle plugin, int numParams)
{
int client = GetNativeCell(1);
return g_fPower[client];
}
public any Native_SetAutostrafeKeyOverride(Handle plugin, int numParams)
{
int client = GetNativeCell(1);
AutostrafeOverride value = view_as<AutostrafeOverride>(GetNativeCell(2));
gI_Override[client] = value;
return 0;
}
public any Native_GetAutostrafeKeyOverride(Handle plugin, int numParams)
{
int client = GetNativeCell(1);
return gI_Override[client];
}
public any Native_SetAutoPrestrafe(Handle plugin, int numParams)
{
int client = GetNativeCell(1);
bool value = GetNativeCell(2);
gB_Prestrafe[client] = value;
return 0;
}
public any Native_GetAutoPrestrafe(Handle plugin, int numParams)
{
int client = GetNativeCell(1);
return gB_Prestrafe[client];
}
public any Native_SetAutoJumpOnStart(Handle plugin, int numParams)
{
int client = GetNativeCell(1);
bool value = GetNativeCell(2);
gB_AutoJumpOnStart[client] = value;
return 0;
}
public any Native_GetAutoJumpOnStart(Handle plugin, int numParams)
{
int client = GetNativeCell(1);
return gB_AutoJumpOnStart[client];
}
public any Native_SetEdgeJump(Handle plugin, int numParams)
{
int client = GetNativeCell(1);
bool value = GetNativeCell(2);
gB_EdgeJump[client] = value;
return 0;
}
public any Native_GetEdgeJump(Handle plugin, int numParams)
{
int client = GetNativeCell(1);
return gB_EdgeJump[client];
}
public any Native_SetAutogainBasicStrafer(Handle plugin, int numParams)
{
int client = GetNativeCell(1);
bool value = GetNativeCell(2);
gB_AutogainBasicStrafer[client] = value;
return 0;
}
public any Native_GetAutogainBasicStrafer(Handle plugin, int numParams)
{
int client = GetNativeCell(1);
return gB_AutogainBasicStrafer[client];
}

View File

@ -1,8 +1,9 @@
/*
* shavit's Timer - Dynamic Timelimits
* by: shavit
* by: shavit, Nickelony, Sirhephaestus, rtldg
*
* This file is part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
* This file is part of shavit's Timer.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
@ -16,7 +17,7 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
*/
// original idea from ckSurf.
@ -24,8 +25,10 @@
#include <convar_class>
#include <dhooks>
#include <shavit/core>
#include <shavit/wr>
#undef REQUIRE_PLUGIN
#include <shavit>
#undef REQUIRE_EXTENSIONS
#include <cstrike>
@ -36,7 +39,7 @@
// #define DEBUG
// database handle
Database2 gH_SQL = null;
Database gH_SQL = null;
// base cvars
ConVar mp_do_warmup_period = null;
@ -66,27 +69,28 @@ bool gB_BlockRoundEndEvent = false;
bool gB_AlternateZeroPrint = false;
Handle gH_Timer = null;
EngineVersion gEV_Type = Engine_Unknown;
chatstrings_t gS_ChatStrings;
Handle gH_Forwards_OnCountdownStart = null;
// table prefix
char gS_MySQLPrefix[32];
bool gB_Late = false;
public Plugin myinfo =
{
name = "[shavit] Dynamic Timelimits",
author = "shavit",
author = "shavit, Nickelony, Sirhephaestus, rtldg",
description = "Sets a dynamic value of mp_timelimit and mp_roundtime, based on average map times on the server.",
version = SHAVIT_VERSION,
url = "https://github.com/shavitush/bhoptimer"
}
public void OnAllPluginsLoaded()
public APLRes AskPluginLoad2(Handle plugin, bool late, char[] error, int maxlength)
{
if(!LibraryExists("shavit-wr"))
{
SetFailState("shavit-wr is required for the plugin to work.");
}
gB_Late = late;
return APLRes_Success;
}
public void OnPluginStart()
@ -102,7 +106,7 @@ public void OnPluginStart()
mp_ignore_round_win_conditions = FindConVar("mp_ignore_round_win_conditions");
mp_timelimit = FindConVar("mp_timelimit");
mp_roundtime = FindConVar("mp_roundtime");
if(mp_roundtime != null)
{
mp_roundtime.SetBounds(ConVarBound_Upper, false);
@ -130,10 +134,16 @@ public void OnPluginStart()
Convar.AutoExecConfig();
RegAdminCmd("sm_extend", Command_Extend, ADMFLAG_CHANGEMAP, "Admin command for extending map");
RegAdminCmd("sm_extendmap", Command_Extend, ADMFLAG_CHANGEMAP, "Admin command for extending map");
HookEvent("round_end", round_end, EventHookMode_Pre);
GetTimerSQLPrefix(gS_MySQLPrefix, 32);
gH_SQL = GetTimerDatabaseHandle2();
gH_SQL = GetTimerDatabaseHandle();
if(gB_Late)
Shavit_OnChatConfigLoaded();
}
public void OnMapStart()
@ -148,7 +158,6 @@ public void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] n
delete gH_Timer;
gH_Timer = CreateTimer(1.0, Timer_PrintToChat, 0, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
}
else
{
delete gH_Timer;
@ -201,7 +210,6 @@ public void OnConfigsExecuted()
{
StartCalculating();
}
else
{
SetLimit(RoundToNearest(gCV_DefaultLimit.FloatValue));
@ -213,6 +221,11 @@ public void OnConfigsExecuted()
}
}
public void Shavit_OnChatConfigLoaded()
{
Shavit_GetChatStringsStruct(gS_ChatStrings);
}
void StartCalculating()
{
char sMap[PLATFORM_MAX_PATH];
@ -225,7 +238,7 @@ void StartCalculating()
PrintToServer("%s", sQuery);
#endif
gH_SQL.Query(SQL_GetMapTimes, sQuery, 0, DBPrio_Low);
QueryLog(gH_SQL, SQL_GetMapTimes, sQuery, 0, DBPrio_Low);
}
public void SQL_GetMapTimes(Database db, DBResultSet results, const char[] error, any data)
@ -276,7 +289,6 @@ public void SQL_GetMapTimes(Database db, DBResultSet results, const char[] error
{
fAverage = gCV_MinimumLimit.FloatValue;
}
else if(fAverage > gCV_MaximumLimit.FloatValue)
{
fAverage = gCV_MaximumLimit.FloatValue;
@ -284,7 +296,6 @@ public void SQL_GetMapTimes(Database db, DBResultSet results, const char[] error
SetLimit(RoundToCeil(fAverage / 10) * 10);
}
else
{
SetLimit(RoundToNearest(gCV_DefaultLimit.FloatValue));
@ -298,6 +309,7 @@ void SetLimit(int time)
if(mp_roundtime != null)
{
mp_roundtime.IntValue = time;
GameRules_SetProp("m_iRoundTime", time * 60);
}
}
@ -318,11 +330,6 @@ public Action Timer_PrintToChat(Handle timer)
int timeleft = 0;
GetMapTimeLeft(timeleft);
if(timeleft <= -1 && timeleft >= -3)
{
Shavit_StopChatSound();
}
if (gCV_InstantMapChange.BoolValue && timeleft <= 5)
{
if (timeleft)
@ -348,17 +355,26 @@ public Action Timer_PrintToChat(Handle timer)
return Plugin_Continue;
}
if(timeleft <= 0 && timeleft >= -3)
{
Shavit_StopChatSound();
}
char timebuf[12];
switch(timeleft)
{
case 3600: Shavit_PrintToChatAll("%T", "Minutes", LANG_SERVER, "60");
case 1800: Shavit_PrintToChatAll("%T", "Minutes", LANG_SERVER, "30");
case 1200: Shavit_PrintToChatAll("%T", "Minutes", LANG_SERVER, "20");
case 600: Shavit_PrintToChatAll("%T", "Minutes", LANG_SERVER, "10");
case 300: Shavit_PrintToChatAll("%T", "Minutes", LANG_SERVER, "5");
case 120: Shavit_PrintToChatAll("%T", "Minutes", LANG_SERVER, "2");
case 60: Shavit_PrintToChatAll("%T", "Seconds", LANG_SERVER, "60");
case 30: Shavit_PrintToChatAll("%T", "Seconds", LANG_SERVER, "30");
case 15: Shavit_PrintToChatAll("%T", "Seconds", LANG_SERVER, "15");
case 3600, 1800, 1200, 600, 300, 120:
{
IntToString(timeleft/60, timebuf, sizeof(timebuf));
Shavit_StopChatSound();
Shavit_PrintToChatAll("%T", "Minutes", LANG_SERVER, timebuf);
}
case 60, 30, 15:
{
IntToString(timeleft, timebuf, sizeof(timebuf));
Shavit_PrintToChatAll("%T", "Seconds", LANG_SERVER, timebuf);
}
case 0: // case 0 is hit twice....
{
@ -368,7 +384,6 @@ public Action Timer_PrintToChat(Handle timer)
Call_Finish();
}
Shavit_StopChatSound();
Shavit_PrintToChatAll("%d..", gB_AlternateZeroPrint ? 4 : 5);
gB_AlternateZeroPrint = !gB_AlternateZeroPrint;
}
@ -421,7 +436,7 @@ public Action CS_OnTerminateRound(float &fDelay, CSRoundEndReason &iReason)
{
return Plugin_Handled;
}
return Plugin_Continue;
}
@ -435,3 +450,28 @@ public Action round_end(Event event, const char[] name, bool dontBroadcast)
return Plugin_Continue;
}
public Action Command_Extend(int client, int args)
{
int extendtime = 10 * 60;
if (args > 0)
{
char sArg[8];
GetCmdArg(1, sArg, sizeof(sArg));
extendtime = RoundFloat(StringToFloat(sArg) * 60);
}
else
{
ConVar smc_mapvote_extend_time = FindConVar("smc_mapvote_extend_time");
if (smc_mapvote_extend_time)
{
extendtime = RoundFloat(smc_mapvote_extend_time.FloatValue * 60.0);
}
}
ExtendMapTimeLimit(extendtime);
Shavit_PrintToChatAll("%T", "Extended", LANG_SERVER, gS_ChatStrings.sVariable2, client, gS_ChatStrings.sText, gS_ChatStrings.sVariable, extendtime / 60, gS_ChatStrings.sText);
return Plugin_Handled;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,706 @@
/*
* shavit's Timer - JSON zones for shavit-zones
* by: rtldg
*
* This file is part of shavit's Timer (https://github.com/shavitush/bhoptimer)
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <sourcemod>
#include <convar_class>
#include <shavit/core>
#include <shavit/zones>
#undef REQUIRE_PLUGIN
#undef REQUIRE_EXTENSIONS
#include <ripext> // https://github.com/ErikMinekus/sm-ripext
#include <json> // https://github.com/clugg/sm-json
#include <SteamWorks> // HTTP stuff
#pragma semicolon 1
#pragma newdecls required
static char gS_ZoneTypes[ZONETYPES_SIZE][18] = {
"start",
"end",
"respawn",
"stop",
"slay",
"freestyle",
"customspeedlimit",
"teleport",
"customspawn",
"easybhop",
"slide",
"airaccel",
"stage",
"notimergravity",
"gravity",
"speedmod",
"nojump",
"autobhop"
};
static char gS_ZoneForms[5][26] = {
"box",
"hook trigger_multiple",
"hook trigger_teleport",
"hook func_button",
"areas and clusters"
};
bool gB_Late = false;
bool gB_YouCanLoadZonesNow = false;
char gS_Map[PLATFORM_MAX_PATH];
char gS_ZonesForMap[PLATFORM_MAX_PATH];
char gS_EngineName[16];
ArrayList gA_Zones = null;
enum struct MapInfoTrack
{
int tier; // 0 = unknown
// -1 = unknown | 0 = false | 1 = true | 2 = really hard
int possible_on_scroll;
int possible_on_400vel;
int possible_on_stamina;
}
static char gS_InfoDescripters[][] = {
"Unknown",
"False",
"True",
"Really hard",
};
int gI_MapInfoTrack[MAXPLAYERS+1];
MapInfoTrack gA_TrackInfo[TRACKS_SIZE];
Convar gCV_Enable = null;
Convar gCV_UseRipext = null;
Convar gCV_ApiUrl = null;
Convar gCV_ApiKey = null;
Convar gCV_Source = null;
Convar gCV_Folder = null;
public Plugin myinfo =
{
name = "[shavit] Map Zones (JSON)",
author = "rtldg",
description = "Retrieves map zones for bhoptimer from an HTTP API.",
version = SHAVIT_VERSION,
url = "https://github.com/shavitush/bhoptimer"
}
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
{
gB_Late = late;
MarkNativeAsOptional("HTTPRequest.HTTPRequest");
MarkNativeAsOptional("HTTPRequest.SetHeader");
MarkNativeAsOptional("HTTPRequest.Get");
MarkNativeAsOptional("HTTPResponse.Status.get");
MarkNativeAsOptional("HTTPResponse.Data.get");
MarkNativeAsOptional("JSONObject.HasKey");
MarkNativeAsOptional("JSONObject.Get");
MarkNativeAsOptional("JSONObject.GetInt");
MarkNativeAsOptional("JSONObject.GetFloat");
MarkNativeAsOptional("JSONObject.GetString");
MarkNativeAsOptional("JSONArray.Get");
MarkNativeAsOptional("JSONArray.Length.get");
MarkNativeAsOptional("JSONArray.GetFloat");
MarkNativeAsOptional("SteamWorks_SetHTTPRequestAbsoluteTimeoutMS");
switch (GetEngineVersion())
{
case Engine_CSGO: gS_EngineName = "csgo";
case Engine_CSS: gS_EngineName = "cstrike";
case Engine_TF2: gS_EngineName = "tf2";
}
char dir[PLATFORM_MAX_PATH];
BuildPath(Path_SM, dir, sizeof(dir), "data/zones-%s", gS_EngineName);
CreateDirectory(dir, 1 | 4 | 8 | 32 | 64 | 128 | 256);
StrCat(dir, sizeof(dir), "/z");
CreateDirectory(dir, 1 | 4 | 8 | 32 | 64 | 128 | 256);
dir[strlen(dir)-1] = 'i';
CreateDirectory(dir, 1 | 4 | 8 | 32 | 64 | 128 | 256);
RegPluginLibrary("shavit-zones-json");
return APLRes_Success;
}
public void OnPluginStart()
{
LoadTranslations("shavit-common.phrases");
gCV_Enable = new Convar("shavit_zones_json_enable", "1", "Whether to enable this or not...", 0, true, 0.0, true, 1.0);
gCV_UseRipext = new Convar("shavit_zones_json_ripext", "1", "Whether to use ripext or steamworks", 0, true, 0.0, true, 1.0);
gCV_ApiUrl = new Convar("shavit_zones_json_url", "http://zones-{engine}.srcwr.com/z/{map}.json", "API URL. Will replace `{map}`, `{key}`, and `{engine}` with the mapname, api key, and engine name....\nOther example urls:\n https://srcwr.github.io/zones-{engine}/z/{map}.json\n https://sourcejump.net/api/v2/maps/{map}/zones", FCVAR_PROTECTED);
gCV_ApiKey = new Convar("shavit_zones_json_key", "", "API key that some APIs might require.", FCVAR_PROTECTED);
gCV_Source = new Convar("shavit_zones_json_src", "http", "A string used by plugins to identify where a zone came from (http, sourcejump, sql, etc)");
gCV_Folder = new Convar("shavit_zones_json_folder", "0", "Whether to use a local folder for json zones instead of the http URL.\n0 - use HTTP stuff...\n1 - use folder of JSON zones at `addons/sourcemod/data/zones-{engine}/z/{map}.json`");
Convar.AutoExecConfig();
RegAdminCmd("sm_dumpzones", Command_DumpZones, ADMFLAG_RCON, "Dumps current map's zones to a json file");
RegAdminCmd("sm_editmi", Command_EditMapInfo, ADMFLAG_RCON, "Edits current map's info and dumps to a json file");
if (gB_Late)
{
gB_YouCanLoadZonesNow = true;
}
}
public void OnMapEnd()
{
gB_YouCanLoadZonesNow = false;
}
public void OnConfigsExecuted()
{
GetLowercaseMapName(gS_Map);
if (!StrEqual(gS_Map, gS_ZonesForMap))
{
RetrieveZones(gS_Map);
}
}
public void Shavit_LoadZonesHere()
{
gB_YouCanLoadZonesNow = true;
if (StrEqual(gS_Map, gS_ZonesForMap))
{
LoadCachedZones();
}
}
void LoadCachedZones()
{
if (!gCV_Enable.BoolValue || !gA_Zones)
return;
Shavit_UnloadZones(); // TODO: fuck it......
for (int i = 0; i < gA_Zones.Length; i++)
{
zone_cache_t cache;
gA_Zones.GetArray(i, cache);
Shavit_AddZone(cache);
}
}
void RetrieveZones(const char[] mapname)
{
if (!gCV_Enable.BoolValue)
return;
if (gCV_Folder.BoolValue)
{
char path[PLATFORM_MAX_PATH];
BuildPath(Path_SM, path, sizeof(path), "data/zones-%s/z/%s.json", gS_EngineName, gS_Map);
JSONArray records = JSONArray.FromFile(path);
if (records)
{
gS_ZonesForMap = gS_Map;
delete gA_Zones;
gA_Zones = EatUpZones(records, true, "folder");
delete records;
if (gB_YouCanLoadZonesNow)
LoadCachedZones();
}
return;
}
char apikey[64], apiurl[512];
gCV_ApiKey.GetString(apikey, sizeof(apikey));
gCV_ApiUrl.GetString(apiurl, sizeof(apiurl));
if (!apiurl[0])
{
LogError("Missing API URL");
return;
}
ReplaceString(apiurl, sizeof(apiurl), "{map}", mapname);
ReplaceString(apiurl, sizeof(apiurl), "{key}", apikey);
ReplaceString(apiurl, sizeof(apiurl), "{engine}", gS_EngineName);
DataPack pack = new DataPack();
pack.WriteString(mapname);
if (gCV_UseRipext.BoolValue)
{
HTTPRequest http = new HTTPRequest(apiurl);
if (apikey[0])
http.SetHeader("api-key", "%s", apikey);
http.SetHeader("map", "%s", mapname);
http.Get(RequestCallback_Ripext, pack);
return;
}
Handle request;
if (!(request = SteamWorks_CreateHTTPRequest(k_EHTTPMethodGET, apiurl))
|| (apikey[0] && !SteamWorks_SetHTTPRequestHeaderValue(request, "api-key", apikey))
|| !SteamWorks_SetHTTPRequestHeaderValue(request, "accept", "application/json")
|| !(!apikey[0] || SteamWorks_SetHTTPRequestHeaderValue(request, "api-key", apikey))
|| !SteamWorks_SetHTTPRequestHeaderValue(request, "map", mapname)
|| !SteamWorks_SetHTTPRequestContextValue(request, pack)
|| !SteamWorks_SetHTTPRequestAbsoluteTimeoutMS(request, 4000)
//|| !SteamWorks_SetHTTPRequestRequiresVerifiedCertificate(request, true)
|| !SteamWorks_SetHTTPCallbacks(request, RequestCompletedCallback_Steamworks)
|| !SteamWorks_SendHTTPRequest(request)
)
{
CloseHandle(request);
LogError("failed to setup & send HTTP request");
return;
}
}
void RequestCallback_Ripext(HTTPResponse response, DataPack pack, const char[] error)
{
if (response.Status != HTTPStatus_OK || response.Data == null)
{
LogError("HTTP API request failed");
delete pack;
return;
}
handlestuff(pack, response.Data, true);
}
public void RequestCompletedCallback_Steamworks(Handle request, bool bFailure, bool bRequestSuccessful, EHTTPStatusCode eStatusCode, DataPack pack)
{
if (bFailure || !bRequestSuccessful || eStatusCode != k_EHTTPStatusCode200OK)
{
pack.Reset();
char mapname[PLATFORM_MAX_PATH];
pack.ReadString(mapname, sizeof(mapname));
delete pack;
LogError("HTTP API failed for '%s'. statuscode=%d", mapname, eStatusCode);
return;
}
SteamWorks_GetHTTPResponseBodyCallback(request, RequestCallback_Steamworks, pack);
}
void RequestCallback_Steamworks(const char[] data, DataPack pack)
{
JSON_Array records = view_as<JSON_Array>(json_decode(data));
if (records)
{
handlestuff(pack, records, false);
json_cleanup(records);
}
}
enum struct JsonThing
{
JSONObject objrip;
JSON_Object objsw;
bool isrip;
bool HasKey(const char[] key)
{
return this.isrip ? this.objrip.HasKey(key) : this.objsw.HasKey(key);
}
int GetInt(const char[] key)
{
return this.isrip ? this.objrip.GetInt(key) : this.objsw.GetInt(key);
}
float GetFloat(const char[] key)
{
return this.isrip ? this.objrip.GetFloat(key) : this.objsw.GetFloat(key);
}
bool GetString(const char[] key, char[] buf, int size)
{
return this.isrip ? this.objrip.GetString(key, buf, size) : this.objsw.GetString(key, buf, size);
}
void GetVec(const char[] key, float vec[3])
{
if (this.isrip)
{
JSONArray arr = view_as<JSONArray>(this.objrip.Get(key));
vec[0] = arr.GetFloat(0);
vec[1] = arr.GetFloat(1);
vec[2] = arr.GetFloat(2);
}
else
{
JSON_Array arr = view_as<JSON_Array>(this.objsw.GetObject(key));
vec[0] = arr.GetFloat(0);
vec[1] = arr.GetFloat(1);
vec[2] = arr.GetFloat(2);
}
}
}
void handlestuff(DataPack pack, any records, bool ripext)
{
pack.Reset();
char mapname[PLATFORM_MAX_PATH];
pack.ReadString(mapname, sizeof(mapname));
delete pack;
if (!StrEqual(mapname, gS_Map))
{
return;
}
char source[16];
gCV_Source.GetString(source, sizeof(source));
if (!source[0]) source = "http";
gS_ZonesForMap = mapname;
delete gA_Zones;
gA_Zones = EatUpZones(records, ripext, source);
if (gB_YouCanLoadZonesNow)
LoadCachedZones();
}
ArrayList EatUpZones(any records, bool ripext, const char source[16])
{
ArrayList zones = new ArrayList(sizeof(zone_cache_t));
int asdf = ripext ? view_as<JSONArray>(records).Length : view_as<JSON_Array>(records).Length;
for (int RN = 0; RN < asdf; RN++)
{
any data = ripext ?
view_as<int>(view_as<JSONArray>(records).Get(RN)) :
view_as<int>(view_as<JSON_Array>(records).GetObject(RN));
JsonThing json;
json.objrip = data;
json.objsw = data;
json.isrip = ripext;
char buf[32];
zone_cache_t cache;
json.GetString("type", buf, sizeof(buf));
cache.iType = -1;
for (int i = 0; i < ZONETYPES_SIZE; i++)
{
if (StrEqual(buf, gS_ZoneTypes[i]))
{
cache.iType = i;
}
}
if (cache.iType == -1)
{
//PrintToServer("");
continue;
}
cache.iTrack = json.GetInt("track");
//cache.iEntity
cache.iDatabaseID = json.GetInt("id");
if (json.HasKey("flags")) cache.iFlags = json.GetInt("flags");
if (json.HasKey("data")) cache.iData = json.GetInt("data");
if (cache.iType == Zone_Stage)
if (json.HasKey("index")) cache.iData = json.GetInt("index");
if (json.HasKey("point_a")) json.GetVec("point_a", cache.fCorner1);
if (json.HasKey("point_b")) json.GetVec("point_b", cache.fCorner2);
if (json.HasKey("dest")) json.GetVec("dest", cache.fDestination);
if (json.HasKey("form")) cache.iForm = json.GetInt("form");
if (json.HasKey("target")) json.GetString("target", cache.sTarget, sizeof(cache.sTarget));
//json.GetString("source", cache.sSource, sizeof(cache.sSource));
cache.sSource = source;
zones.PushArray(cache);
}
if (!zones.Length)
delete zones;
return zones;
}
void FillBoxMinMax(float point1[3], float point2[3], float boxmin[3], float boxmax[3])
{
for (int i = 0; i < 3; i++)
{
float a = point1[i];
float b = point2[i];
if (a < b)
{
boxmin[i] = a;
boxmax[i] = b;
}
else
{
boxmin[i] = b;
boxmax[i] = a;
}
}
}
bool EmptyVector(float vec[3])
{
return vec[0] == 0.0 && vec[1] == 0.0 && vec[2] == 0.0;
}
JSONObject FillYourMom(zone_cache_t cache)
{
// normalize mins & maxs......................................................
FillBoxMinMax(cache.fCorner1, cache.fCorner2, cache.fCorner1, cache.fCorner2);
JSONObject obj = new JSONObject();
obj.SetString("type", gS_ZoneTypes[cache.iType]);
obj.SetInt("track", cache.iTrack);
obj.SetInt("id", cache.iDatabaseID);
if (cache.iFlags) obj.SetInt("flags", cache.iFlags);
if (cache.iData) obj.SetInt("data", cache.iData);
JSONArray a = new JSONArray(), b = new JSONArray(), c = new JSONArray();
for (int i = 0; i < 3; i++) {
a.PushFloat(cache.fCorner1[i]);
b.PushFloat(cache.fCorner2[i]);
c.PushFloat(cache.fDestination[i]);
}
if (!EmptyVector(cache.fCorner1)) obj.Set("point_a", a);
if (!EmptyVector(cache.fCorner2)) obj.Set("point_b", b);
if (!EmptyVector(cache.fDestination)) obj.Set("dest", c);
if (cache.iForm) obj.SetInt("form", cache.iForm);
if (cache.sTarget[0]) obj.SetString("target", cache.sTarget);
delete a;
delete b;
delete c;
return obj;
}
public Action Command_DumpZones(int client, int args)
{
int count = Shavit_GetZoneCount();
if (!count)
{
ReplyToCommand(client, "Map doesn't have any zones...");
return Plugin_Handled;
}
JSONArray wow = new JSONArray();
for (int XXXXXX = 0; XXXXXX < count; XXXXXX++)
{
zone_cache_t cache;
Shavit_GetZone(XXXXXX, cache);
JSONObject obj = FillYourMom(cache);
wow.Push(obj);
delete obj;
}
char path[PLATFORM_MAX_PATH];
BuildPath(Path_SM, path, sizeof(path), "data/zones-%s/z/%s.json", gS_EngineName, gS_Map);
wow.ToFile(path, JSON_SORT_KEYS);
delete wow;
Shavit_PrintToChat(client, "Dumped zones to %s", path);
return Plugin_Handled;
}
int MaybeInt(JSONObject json, const char[] key, int defaultttt=0) // TODO: remove
{
if (json && json.HasKey(key)) return json.GetInt(key);
return defaultttt;
}
void JsonToMapInfo(JSONArray arr)
{
for (int i = 0; i < TRACKS_SIZE; i++)
{
JSONObject obj = (arr.Length > i && !arr.IsNull(i)) ? view_as<JSONObject>(arr.Get(i)) : null;
gA_TrackInfo[i].tier = MaybeInt(obj, "tier", 0);
gA_TrackInfo[i].possible_on_scroll = MaybeInt(obj, "possible_on_scroll", -1);
gA_TrackInfo[i].possible_on_400vel = MaybeInt(obj, "possible_on_400vel", -1);
gA_TrackInfo[i].possible_on_stamina = MaybeInt(obj, "possible_on_stamina", -1);
delete obj;
}
}
JSONObject MapInfoToJson(MapInfoTrack info)
{
JSONObject json = new JSONObject();
if (info.tier > 0) json.SetInt("tier", info.tier);
if (info.possible_on_scroll > -1) json.SetInt("possible_on_scroll", info.possible_on_scroll);
if (info.possible_on_400vel > -1) json.SetInt("possible_on_400vel", info.possible_on_400vel);
if (info.possible_on_stamina > -1) json.SetInt("possible_on_stamina", info.possible_on_stamina);
if (json.Size < 1) delete json;
return json;
}
int MenuHandler_MapInfo(Menu menu, MenuAction action, int param1, int param2)
{
if (action == MenuAction_Select)
{
char info[32];
menu.GetItem(param2, info, sizeof(info));
int track = gI_MapInfoTrack[param1];
if (StrEqual(info, "save"))
{
JSONArray arr = new JSONArray();
JSONObject empty = new JSONObject();
for (int i, empties; i < TRACKS_SIZE; i++)
{
JSONObject obj = MapInfoToJson(gA_TrackInfo[i]);
if (!obj)
{
++empties;
continue;
}
for (; empties; --empties)
arr.Push(empty);
arr.Push(obj);
delete obj;
}
delete empty;
if (!arr.Length)
{
delete arr;
Shavit_PrintToChat(param1, "Empty map info array... doing nothing");
return 0;
}
char path[PLATFORM_MAX_PATH];
BuildPath(Path_SM, path, sizeof(path), "data/zones-%s/i/%s.json", gS_EngineName, gS_Map);
arr.ToFile(path);
char buff[512];
arr.ToString(buff, sizeof(buff));
PrintToServer("%s", buff);
delete arr;
Shavit_PrintToChat(param1, "Wrote mapinfo to %s", path);
return 0;
}
else if (StrEqual(info, "back2main"))
{
gI_MapInfoTrack[param1] = 0;
}
else if (StrEqual(info, "trackiter"))
{
gI_MapInfoTrack[param1] = (track + 1) % TRACKS_SIZE;
}
else if (StrEqual(info, "tier"))
{
gA_TrackInfo[track].tier = (gA_TrackInfo[track].tier + 1) % 11; // hardcode 10 lol
}
else if (StrEqual(info, "scroll"))
{
gA_TrackInfo[track].possible_on_scroll += 1;
if (gA_TrackInfo[track].possible_on_scroll > 2)
gA_TrackInfo[track].possible_on_scroll = -1;
}
else if (StrEqual(info, "400vel"))
{
gA_TrackInfo[track].possible_on_400vel += 1;
if (gA_TrackInfo[track].possible_on_400vel > 2)
gA_TrackInfo[track].possible_on_400vel = -1;
}
else if (StrEqual(info, "stamina"))
{
gA_TrackInfo[track].possible_on_stamina += 1;
if (gA_TrackInfo[track].possible_on_stamina > 2)
gA_TrackInfo[track].possible_on_stamina = -1;
}
CreateMapInfoMenu(param1);
}
else if (action == MenuAction_End)
{
delete menu;
}
return 0;
}
void CreateMapInfoMenu(int client)
{
Menu menu = new Menu(MenuHandler_MapInfo);
menu.SetTitle("Map info\n ");
char display[128];
int track = gI_MapInfoTrack[client];
int tier = gA_TrackInfo[track].tier;
menu.AddItem("save", "Save\n ");
menu.AddItem("back2main", "Back to Main track",
track > 0 ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED);
GetTrackName(client, track, display, sizeof(display), true);
Format(display, sizeof(display), "Track: %s\n ", display);
menu.AddItem("trackiter", display);
FormatEx(display, sizeof(display), "Track Tier: %d%s", tier, tier < 1 ? " (unknown)" : "");
menu.AddItem("tier", display);
FormatEx(display, sizeof(display), "Possible on Scroll: %s", gS_InfoDescripters[1 + gA_TrackInfo[track].possible_on_scroll]);
menu.AddItem("scroll", display);
FormatEx(display, sizeof(display), "Possible on 400vel: %s", gS_InfoDescripters[1 + gA_TrackInfo[track].possible_on_400vel]);
menu.AddItem("400vel", display);
FormatEx(display, sizeof(display), "Possible on Stamina: %s\n ", gS_InfoDescripters[1 + gA_TrackInfo[track].possible_on_stamina]);
menu.AddItem("stamina", display);
menu.ExitButton = true;
menu.Display(client, MENU_TIME_FOREVER);
}
public Action Command_EditMapInfo(int client, int args)
{
if (!client)
{
ReplyToCommand(client, "You're not real");
return Plugin_Handled;
}
char path[PLATFORM_MAX_PATH];
BuildPath(Path_SM, path, sizeof(path), "data/zones-%s/i/%s.json", gS_EngineName, gS_Map);
JSONArray arr = JSONArray.FromFile(path);
if (!arr) arr = new JSONArray();
JsonToMapInfo(arr);
delete arr;
int empty[MAXPLAYERS+1];
gI_MapInfoTrack = empty;
CreateMapInfoMenu(client);
return Plugin_Handled;
}

File diff suppressed because it is too large Load Diff

View File

@ -22,6 +22,11 @@
{
"en" "Check your console."
}
"CCAccessGrantedToPlayer"
{
"#format" "{1:s},{2:s}"
"en" "You've been given access to custom chat! Use {1}!cchelp{2} for more info."
}
"CCHelp_Intro"
{
"en" "- You have access to custom chat.\nUsage information:"
@ -51,6 +56,18 @@
{
"en" "Select chat rank:\n"
}
"SelectChatRankType"
{
"en" "Which chat ranks do you want to see?\n"
}
"SelectChatRankUnlocked"
{
"en" "Unlocked chat ranks\n"
}
"SelectChatRankAll"
{
"en" "All chat ranks\n"
}
"AutoAssign"
{
"en" "Auto-assign\nAutomatically assign using your rank."
@ -63,90 +80,6 @@
{
"en" "Obtainable chat ranks:\nSelect an entry to preview.\n"
}
"ChatRanksMenu_Unranked"
{
"en" "Unranked"
}
"ChatRanksMenu_Points"
{
"#format" "{1:.0f}"
"en" "Have {1} points"
}
"ChatRanksMenu_Points_1"
{
"#format" "{1:.0f}"
"en" "Have {1} point"
}
"ChatRanksMenu_Points_Ranged"
{
"#format" "{1:.0f},{2:.0f}"
"en" "Have between {1} and {2} points"
}
"ChatRanksMenu_Flat"
{
"#format" "{1:.0f}"
"en" "Ranked #{1} or better"
}
"ChatRanksMenu_Flat_1"
{
"#format" "{1:.0f}"
"en" "Ranked #{1}"
}
"ChatRanksMenu_Flat_Ranged"
{
"#format" "{1:.0f},{2:.0f}"
"en" "Ranked between #{1} and #{2}"
}
"ChatRanksMenu_Percentage"
{
"#format" "{1:.1f},{2:.0f},{3:c}"
"en" "Top {1}{3}"
}
"ChatRanksMenu_Percentage_Ranged"
{
"#format" "{1:.1f},{2:.1f},{3:c},{4:c}"
"en" "Between top {1}{3} and {2}{4}"
}
"ChatRanksMenu_WR_Count"
{
"#format" "{1:.0f}"
"en" "Have {1} WRs"
}
"ChatRanksMenu_WR_Count_1"
{
"#format" "{1:.0f}"
"en" "Have {1} WR"
}
"ChatRanksMenu_WR_Count_Ranged"
{
"#format" "{1:.0f},{2:.0f}"
"en" "Have between {1} and {2} WRs"
}
"ChatRanksMenu_WR_Rank"
{
"#format" "{1:.0f}"
"en" "Ranked #{1} or better from WR holders"
}
"ChatRanksMenu_WR_Rank_1"
{
"#format" "{1:.0f}"
"en" "Ranked #{1} out of WRs held"
}
"ChatRanksMenu_WR_Rank_Ranged"
{
"#format" "{1:.0f},{2:.0f}"
"en" "Ranked between #{1} and #{2} out of WRs held"
}
"ChatRanksMenu_WR_Rank_Percentage"
{
"#format" "{1:.0f},{2:.0f},{3:c}"
"en" "Top {1}{3} out of WRs held"
}
"ChatRanksMenu_WR_Rank_Percentage_Ranged"
{
"#format" "{1:.0f},{2:.0f},{3:c},{4:c}"
"en" "Between Top {1}{3} and {2}{4} out of WRs held"
}
"ChatRanksMenu_SampleText"
{
"en" "The quick brown fox jumps over the lazy dog"

View File

@ -18,6 +18,10 @@
"#format" "{1:d}"
"en" "Bonus {1}"
}
"Track_Bonus_NoNum"
{
"en" "Bonus"
}
// ---------- Commands ---------- //
"NoCommandAccess"
{
@ -41,10 +45,37 @@
{
"#format" "{1:s}"
"en" "{1} minutes remaining."
}
}
"Seconds"
{
"#format" "{1:s}"
"en" "{1} seconds remaining."
}
"Extended"
{
"#format" "{1:s},{2:N},{3:s},{4:s},{5:d},{6:s}"
"en" "{1}{2}{3} extended the map by {4}{5}{6} minutes."
}
// ----------- Random ----------- //
"TimerLoading"
{
"en" "Loading.."
}
"Timescale"
{
"en" "Timescale"
}
"CurrentTimescale"
{
"en" "Current Timescale"
}
"OpenSteamProfile"
{
"en" "Open Steam profile"
}
"ReRolling Maps"
{
"#format" "{1:i},{2:i}"
"en" "Voting for next map has restarted. Reroll complete. (Received {1}%% of {2} votes)"
}
}

View File

@ -26,11 +26,25 @@
"#format" "{1:s},{2:s}"
"en" "You lack the {1}permissions{2} for this style."
}
"NoEditingTimescale"
{
"en" "This style doesn't allow you to change timescale."
}
// ---------- Errors ---------- //
"VerificationFailed"
{
"en" "Couldn't verify your, or the server's connection to Steam."
}
"TimeUnderMinimumTime"
{
"#format" "{1:f},{2:f},{3:s}"
"en" "Your time ({2}) was faster than the style's {3} setting ({1}) and did not count."
}
"TimeUnderMinimumTime2"
{
"#format" "{1:f},{2:f}"
"en" "Your time ({2}) was faster or equal to the timer's minimum ({1}) and did not count."
}
// ---------- Menus ---------- //
"StyleMenuTitle"
{

View File

@ -16,10 +16,15 @@
"#format" "{1:d}"
"en" "In Start Zone\n\n{1}"
}
"HudInStartZoneNoSpeed"
{
"#format" "{1:d}"
"en" "In Start Zone"
}
"HudInStartZoneCSGO"
{
"#format" "{1:d}"
"en" "In Start Zone\n\n\t\t\t{1}"
"en" "In Start Zone"
}
"HudEndZone"
{
@ -30,10 +35,15 @@
"#format" "{1:d}"
"en" "In End Zone\n\n{1}"
}
"HudInEndZoneNoSpeed"
{
"#format" "{1:d}"
"en" "In End Zone"
}
"HudInEndZoneCSGO"
{
"#format" "{1:d}"
"en" "In End Zone\n\n\t\t\t{1}"
"en" "In End Zone"
}
"HudPaused"
{
@ -75,6 +85,22 @@
{
"en" "Perfect jumps"
}
"HudPerfsCenter"
{
"en" "Perfect jumps (center hud)"
}
"HudDefaultPistol"
{
"en" "Default Pistol: 1=USP 2=Glock"
}
"HudUSPSilencer"
{
"en" "Spawn USPs with a silencer attached"
}
"HudGlockBurst"
{
"en" "Spawn Glocks with Burst"
}
"HudPracticeMode"
{
"en" "[PRACTICE]"
@ -88,6 +114,10 @@
"#format" "{1:d}"
"en" "(Speed Limit: {1})"
}
"HudCenterKeys"
{
"en" "!keys in the center"
}
// ---------- Menus ---------- //
"HUDMenuTitle"
{
@ -113,6 +143,10 @@
{
"en" "Spectator list"
}
"HudSpectatorsDead"
{
"en" "Spectator list (only when dead)"
}
"HudKeyOverlay"
{
"en" "Key display"
@ -165,6 +199,10 @@
{
"en" "Velocity Difference"
}
"HudDebugTargetname"
{
"en" "Debug targetname"
}
// ---------- Record Bots ---------- //
"ReplayText"
{

View File

@ -48,6 +48,26 @@
"#format" "{1:s},{2:s}"
"en" "You are now {1}not hiding{2} players."
}
"AutoRestartEnabled"
{
"#format" "{1:s},{2:s}"
"en" "You will now {1}automatically restart{2} if you are slower than your PB."
}
"AutoRestartDisabled"
{
"#format" "{1:s},{2:s}"
"en" "You will no longer {1}automatically restart{2}."
}
"AutoRestartTriggered1"
{
"#format" "{1:s},{2:s}"
"en" "You were {1}automatically restarted{2} due to being slower than your PB."
}
"AutoRestartTriggered2"
{
"#format" "{1:s},{2:s}"
"en" "Use {1}!autorestart{2} to disable this."
}
"LackingAccess"
{
"#format" "{1:s},{2:s}"
@ -99,10 +119,14 @@
{
"en" "Unable to save due to checkpoint overflow."
}
"MiscCheckpointOwnerInvalid"
{
"en" "The checkpoint's owner is invalid or has disconnected."
}
"MiscSegmentedCommand"
{
"#format" "{1:s},{2:s}"
"en" "Use {1}!cp{2} to re-open the segmented checkpoints menu."
"en" "Use {1}!cp{2} to re-open the checkpoints menu."
}
// ---------- Menus ---------- //
"StopTimerWarning"
@ -129,6 +153,10 @@
{
"en" "No."
}
"MiscCheckpointNoOtherPlayers"
{
"en" "You are alone (also, the server is empty)"
}
"TeleportMenuTitle"
{
"en" "Teleport to:"
@ -152,8 +180,13 @@
}
"MiscCheckpointSave"
{
"#format" "{1:d}"
"en" "Save checkpoint ({1})"
"#format" "{1:d},{2:d}"
"en" "Save checkpoint ({1}/{2})"
}
"MiscCheckpointDuplicate"
{
"#format" "{1:d},{2:d}"
"en" "Duplicate checkpoint ({1}/{2})"
}
"MiscCheckpointTeleport"
{
@ -168,6 +201,14 @@
{
"en" "Next"
}
"MiscCheckpointUseOthers"
{
"en" "Use another player's checkpoints"
}
"MiscCheckpointBack"
{
"en" "Back to your checkpoints"
}
"MiscCheckpointReset"
{
"en" "Reset checkpoints"
@ -188,6 +229,78 @@
{
"en" "Use velocity"
}
"TasSettings"
{
"en" "TAS Settings"
}
"Autostrafer"
{
"en" "Autostrafer"
}
"AutoJumpOnStart"
{
"en" "Jump on start-zone exit"
}
"EdgeJump"
{
"en" "Edge jump"
}
"AutogainBasicStrafer"
{
"en" "Autogain basic strafer"
}
"AutoPrestrafe"
{
"en" "Auto Prestrafe"
}
"Autostrafer_type"
{
"en" "Type"
}
"Autostrafer_1tick"
{
"en" "1Tick (xutaxkamay)"
}
"Autostrafer_autogain"
{
"en" "Velocity/autogain (oblivious)"
}
"Autostrafer_autogain_nsl"
{
"en" "Velocity/autogain (No speed loss) (oblivious)"
}
"Autostrafer_basic"
{
"en" "Basic"
}
"TASEnabled"
{
"en" "Enabled"
}
"TASDisabled"
{
"en" "Disabled"
}
"AutostrafeOverride"
{
"en" "Key Override"
}
"AutostrafeOverride_Normal"
{
"en" "W/S"
}
"AutostrafeOverride_Surf"
{
"en" "W/S (and A/D on surf ramps)"
}
"AutostrafeOverride_Surf_W_Okay"
{
"en" "S (and A/D on surf ramps)"
}
"AutostrafeOverride_All"
{
"en" "W/S A/D"
}
// ---------- Misc ---------- //
"BHStartZoneDisallowed"
{

View File

@ -107,6 +107,11 @@
"#format" "{1:s}"
"en" "[{1}] Toggle 2x speed"
}
"Menu_PlaybackSpeed"
{
"#format" "{1:.1f}"
"en" "Playback speed: {1}x"
}
"Menu_RefreshReplay"
{
"en" "Refresh"

View File

@ -6,11 +6,20 @@
"#format" "{1:s},{2:s}"
"en" "{1}ERROR: {2}Could not open the stats menu."
}
"StatsMenuUnknownPlayer"
{
"#format" "{1:s},{2:s},{3:s},{4:d}"
"en" "{1}ERROR: {2}Unknown player {3}[U:1:{4}]"
}
// ---------- Map Completions ---------- //
"SelectTrack"
{
"en" "Select timer track:"
}
"SelectTier"
{
"en" "Select map tier:"
}
"MapsDone"
{
"en" "Maps done"
@ -69,6 +78,10 @@
{
"en" "Last Login"
}
"FirstLogin"
{
"en" "First Login"
}
"MapCompletions"
{
"en" "Map completions"

View File

@ -25,6 +25,11 @@
"#format" "{1:s},{2:s}"
"en" "Records for {1}:\n({2})"
}
"ListPersonalBest"
{
"#format" "{1:s},{2:s}"
"en" "Personal best for {1} on {2}"
}
// ---------- Completion Messages ---------- //
"FirstCompletion"
{
@ -132,12 +137,38 @@
"#format" "{1:s},{2:s}"
"en" "{1}FATAL ERROR: {2}No styles are available. Contact the server owner immediately!"
}
// ---------- WR Menu ---------- //
"NoPB"
{
"#format" "{1:s},{2:s},{3:s},{4:s},{5:s},{6:s}"
"en" "No PB records were found for {1}{2}{3} on map {4}{5}{6}."
}
// ---------- RR Menu ---------- //
"RecentRecords"
{
"#format" "{1:d}"
"en" "Recent {1} record(s)"
}
"RecentRecordsFirstMenuTitle"
{
"en" "Recent records"
}
"RecentRecordsStyleSelectionMenuTitle"
{
"en" "Recent records (by style)"
}
"RecentRecordsAll"
{
"en" "All recent records"
}
"RecentRecordsByStyle"
{
"en" "Sorted by style"
}
"RecentRecordsMainOnly"
{
"en" "Main only"
}
// ---------- WR Menu ---------- //
"WRDate"
{
"en" "Date"

View File

@ -24,16 +24,42 @@
"#format" "{1:s},{2:s}"
"en" "You have to be {1}alive{2} to set your start position."
}
"SetStartNotInStartZone"
{
"#format" "{1:s},{2:s},{3:s},{4:s}"
"en" "You {1}must{2} be in the {3}start zone{4} to use set start."
}
"DeleteSetStart"
{
"#format" "{1:s},{2:s}"
"en" "Start position has been {1}deleted{2}."
}
"DeleteSetStartMenuTitle"
{
"en" "Start position to delete"
}
// ---------- ZoneHook ---------- //
"ZoneHook_Crosshair"
{
"en" "Entity under crosshair"
}
"ZoneHook_Tpto"
{
"en" "Teleport to (stops timer)"
}
"ZoneHook_Draw"
{
"en" "Draw beams around entity"
}
"ZoneHook_Zonetype"
{
"#format" "{1:s}"
"en" "Zone type: {1}"
}
"ZoneHook_Hooktype"
{
"#format" "{1:s},{2:s}"
"en" "Hook type: {1} ({2})"
}
"ZoneHook_Confirm"
{
"en" "Go to confirm"
}
// ---------- Commands ---------- //
"StageCommandAlive"
{
@ -57,6 +83,11 @@
"#format" "{1:s},{2:s}"
"en" "You {1}cannot{2} setup mapzones when you're dead."
}
"ZonesNotSQL"
{
"#format" "{1:s},{2:s}"
"en" "You {1}cannot{2} add/edit/delete non-sql zones."
}
"ZoneCustomSpawnMenuTitle"
{
"en" "Add custom spawn for track:"
@ -122,7 +153,7 @@
}
"ZoneAxis"
{
"en" "axis"
"en" "Change Axis"
}
"ZoneCustomSpawnSuccess"
{
@ -229,11 +260,26 @@
"#format" "{1:d}"
"en" "Custom speed limit: {1} (No Limit)"
}
"ZoneSetSpeedLimitDefault"
{
"#format" "{1:d}"
"en" "Custom speed limit: {1} (Default Speedcap)"
}
"ZoneSetStage"
{
"#format" "{1:d}"
"en" "Stage: {1}"
}
"ZoneSetGravity"
{
"#format" "{1:f}"
"en" "Gravity scale: {1}"
}
"ZoneSetSpeedmod"
{
"#format" "{1:f}"
"en" "Speedmod: {1}"
}
"ZoneEnterDataChat"
{
"en" "Input your desired data in chat."
@ -281,6 +327,15 @@
{
"en" "Edit a map zone"
}
"HookZone"
{
"en" "Hook a trigger, teleporter, or button."
}
"HookZone2"
{
"#format" "{1:s}"
"en" "Hook {1}"
}
"ZoneEditTitle"
{
"en" "Choose a zone to edit:"
@ -293,6 +348,103 @@
{
"en" "Refresh menu"
}
"TpToZone"
{
"en" "Teleport to a zone"
}
// ---------- Custom Zone ---------- //
"CustomZone_MainMenuTitle"
{
"en" "Select the zone you want to customize"
}
"CustomZone_SubMenuTitle"
{
"#format" "{1:s},{2:s}"
"en" "Customizing {1} - {2}"
}
"CustomZone_DisplayType"
{
"en" "Zone display type"
}
"CustomZone_Color"
{
"en" "Zone color"
}
"CustomZone_Width"
{
"en" "Zone width"
}
"CustomZone_Default"
{
"en" "Default"
}
"CustomZone_DisplayType_None"
{
"en" "None"
}
"CustomZone_DisplayType_Box"
{
"en" "Box"
}
"CustomZone_DisplayType_Flat"
{
"en" "Flat"
}
"CustomZone_Color_White"
{
"en" "White"
}
"CustomZone_Color_Red"
{
"en" "Red"
}
"CustomZone_Color_Orange"
{
"en" "Orange"
}
"CustomZone_Color_Yellow"
{
"en" "Yellow"
}
"CustomZone_Color_Green"
{
"en" "Green"
}
"CustomZone_Color_Cyan"
{
"en" "Cyan"
}
"CustomZone_Color_Blue"
{
"en" "Blue"
}
"CustomZone_Color_Purple"
{
"en" "Purple"
}
"CustomZone_Color_Pink"
{
"en" "Pink"
}
"CustomZone_Width_UltraThin"
{
"en" "Ultra thin"
}
"CustomZone_Width_Thin"
{
"en" "Thin"
}
"CustomZone_Width_Normal"
{
"en" "Normal"
}
"CustomZone_Width_Thick"
{
"en" "Thick"
}
// ---------- Messages ---------- //
"ZoneSlayEnter"
{
@ -307,6 +459,82 @@
"ZoneStageEnter"
{
"#format" "{1:s},{2:s},{3:d},{4:s},{5:s},{6:s}{7:s}"
"en" "{1}You have reached stage {2}{3}{4} with a time of {5}{6}{7}."
"en" "{1}Stage {2}{3}{4} @ {5}{6}{7} "
}
}
"Zone_Start"
{
"en" "Start zone"
}
"Zone_End"
{
"en" "End zone"
}
"Zone_Respawn"
{
"en" "Glitch Zone (Respawn Player)"
}
"Zone_Stop"
{
"en" "Glitch Zone (Stop Timer)"
}
"Zone_Slay"
{
"en" "Slay Player"
}
"Zone_Freestyle"
{
"en" "Freestyle Zone"
}
"Zone_CustomSpeedLimit"
{
"en" "Custom Speed Limit"
}
"Zone_Teleport"
{
"en" "Teleport Zone"
}
"Zone_CustomSpawn"
{
"en" "SPAWN POINT"
}
"Zone_Easybhop"
{
"en" "Easybhop Zone"
}
"Zone_Slide"
{
"en" "Slide Zone"
}
"Zone_Airaccelerate"
{
"en" "Custom Airaccelerate"
}
"Zone_Stage"
{
"en" "Stage Zone"
}
"Zone_NoTimerGravity"
{
"en" "No Timer Gravity Zone"
}
"Zone_Gravity"
{
"en" "Gravity Zone"
}
"Zone_Speedmod"
{
"en" "Speedmod Zone"
}
"Zone_NoJump"
{
"en" "No Jump Zone"
}
"Zone_Autobhop"
{
"en" "Autobhop Zone"
}
"Zone_Unknown"
{
"en" "UNKNOWN ZONE"
}
}

View File

@ -0,0 +1,5 @@
;; removes empty classname entity that crashes servers
filter:
{
"hammerid" "396"
}

View File

@ -0,0 +1,8 @@
remove:
{
"targetname" "mod_zone_start"
}
remove:
{
"targetname" "mod_zone_end"
}

View File

@ -0,0 +1,21 @@
;; empty classname entities
filter:
{
"model" "*57"
"hammerid" "197699"
}
filter:
{
"model" "*58"
"hammerid" "197718"
}
filter:
{
"model" "*59"
"hammerid" "197727"
}
filter:
{
"model" "*60"
"hammerid" "197743"
}

View File

@ -0,0 +1,21 @@
; empty classnames crash server
filter:
{
"model" "*57"
"hammerid" "197699"
}
filter:
{
"model" "*58"
"hammerid" "197718"
}
filter:
{
"model" "*59"
"hammerid" "197727"
}
filter:
{
"model" "*60"
"hammerid" "197743"
}

View File

@ -0,0 +1,6 @@
;; empty entity classname
filter:
{
"origin" "1708.02 696.406 64"
"hammerid" "716"
}

View File

@ -0,0 +1,9 @@
;; shitty small zones that are shit
filter:
{
"targetname" "mod_zone_start"
}
filter:
{
"targetname" "mod_zone_end"
}

View File

@ -0,0 +1,25 @@
;; fix missing empty classnames
modify:
{
match:
{
"origin" "3019.49 1646.03 1.73"
"hammerid" "9981"
}
replace:
{
"classname" "trigger_teleport"
}
}
modify:
{
match:
{
"origin" "3019.49 1646.03 3.24"
"hammerid" "9984"
}
replace:
{
"classname" "trigger_multiple"
}
}

View File

@ -0,0 +1,5 @@
;; shit zone
filter:
{
"targetname" "mod_zone_start"
}

View File

@ -0,0 +1,6 @@
;; empty entity classname
filter:
{
"model" "*18"
"hammerid" "5005"
}

View File

@ -0,0 +1,6 @@
;; empty entity classname
filter:
{
"model" "*215"
"hammerid" "79725"
}

View File

@ -0,0 +1,12 @@
modify:
{
match:
{
"targetname" "filter_activator"
"classname" "filter_activator_name"
}
insert:
{
"filtername" "activator"
}
}

View File

@ -0,0 +1,12 @@
modify:
{
match:
{
"targetname" "filter_activator"
"classname" "filter_activator_name"
}
insert:
{
"filtername" "bhop"
}
}

View File

@ -0,0 +1,12 @@
modify:
{
match:
{
"targetname" "filter_activator"
"classname" "filter_activator_name"
}
insert:
{
"filtername" "activator"
}
}

View File

@ -1,17 +1,20 @@
Plugin(source='addons/sourcemod/scripting/shavit-chat.sp')
Plugin(source='addons/sourcemod/scripting/shavit-core.sp')
Plugin(source='addons/sourcemod/scripting/shavit-hud.sp')
Plugin(source='addons/sourcemod/scripting/shavit-mapchooser.sp')
Plugin(source='addons/sourcemod/scripting/shavit-misc.sp')
Plugin(source='addons/sourcemod/scripting/shavit-rankings.sp')
Plugin(source='addons/sourcemod/scripting/shavit-replay.sp')
Plugin(source='addons/sourcemod/scripting/shavit-replay-playback.sp')
Plugin(source='addons/sourcemod/scripting/shavit-replay-recorder.sp')
Plugin(source='addons/sourcemod/scripting/shavit-sounds.sp')
Plugin(source='addons/sourcemod/scripting/shavit-stats.sp')
Plugin(source='addons/sourcemod/scripting/shavit-tas.sp')
Plugin(source='addons/sourcemod/scripting/shavit-timelimit.sp')
Plugin(source='addons/sourcemod/scripting/shavit-wr.sp')
Plugin(source='addons/sourcemod/scripting/shavit-zones.sp')
Package(name='bhoptimer',
plugins=['shavit-chat', 'shavit-core', 'shavit-hud', 'shavit-misc', 'shavit-rankings', 'shavit-replay', 'shavit-sounds', 'shavit-stats', 'shavit-timelimit', 'shavit-wr', 'shavit-zones'],
plugins=['shavit-chat', 'shavit-core', 'shavit-hud', 'shavit-misc', 'shavit-mapchooser', 'shavit-rankings', 'shavit-replay-playback', 'shavit-replay-recorder', 'shavit-sounds', 'shavit-stats', 'shavit-tas', 'shavit-timelimit', 'shavit-wr', 'shavit-zones'],
filegroups={
'.': ['README.md', 'LICENSE'],
},