diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 35d851a0c..64cd3d3d3 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -73,7 +73,7 @@ jobs:
testdemos:
name: 'Test demos'
- runs-on: ubuntu-latest
+ runs-on: ubuntu-20.04
container: s1lentq/testdemos:latest
needs: [windows]
@@ -140,7 +140,7 @@ jobs:
linux:
name: 'Linux'
- runs-on: ubuntu-latest
+ runs-on: ubuntu-20.04
container: s1lentq/linux86buildtools:latest
steps:
@@ -173,7 +173,11 @@ jobs:
fi
shell: bash
- - name: Build using Intel C++ Compiler 19.0
+ - name: Build using Intel C++ Compiler 19.0 (only for release)
+ if: |
+ github.event_name == 'release' &&
+ github.event.action == 'published' &&
+ startsWith(github.ref, 'refs/tags/')
run: |
rm -rf build-icc && CC=icc CXX=icpc cmake -B build-icc && cmake --build build-icc -j8
@@ -189,7 +193,7 @@ jobs:
- name: Move files
run: |
mkdir -p publish/bin/linux32/cstrike/dlls
- mv build-icc/regamedll/cs.so publish/bin/linux32/cstrike/dlls/cs.so
+ mv build-icc/regamedll/cs.so publish/bin/linux32/cstrike/dlls/cs.so 2>/dev/null || true
mv build-gcc/regamedll/cs.so publish/cs-gcc.so
mv regamedll/version/appversion.h publish/appversion.h
mv dist/ publish/
@@ -221,7 +225,7 @@ jobs:
publish:
name: 'Publish'
- runs-on: ubuntu-latest
+ runs-on: ubuntu-20.04
needs: [windows, testdemos, linux]
steps:
diff --git a/.gitignore b/.gitignore
index dc6d161e8..6aa9bce05 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
*.bat
*.log
*.lnk
+*.aps
**/msvc/Debug*
**/msvc/Release*
**/msvc/Tests
diff --git a/README.md b/README.md
index 85a5f2246..30a282525 100644
--- a/README.md
+++ b/README.md
@@ -45,6 +45,8 @@ This means that plugins that do binary code analysis (Orpheu for example) probab
| mp_round_restart_delay | 5 | - | - | Number of seconds to delay before restarting a round after a win. |
| mp_hegrenade_penetration | 0 | 0 | 1 | Disable grenade damage through walls.
`0` disabled
`1` enabled |
| mp_nadedrops | 0 | 0 | 2 | Drop a grenade after player death.
`0` disabled
`1` drop first available grenade
`2` drop all grenades |
+| mp_weapondrop | 1 | 0 | 3 | Drop player weapon after death.
`0` do not drop weapons after death
`1` drop best/heaviest weapon after death
`2` drop active weapon after death
`3` drop all weapons after death (primary and secondary) |
+| mp_ammodrop | 1 | 0 | 2 | Drop ammo on weapon boxes on death or manual drop.
`0` always keep ammo on player
`1` drop all ammo only after death
`2` drop all ammo whenever player drops a weapon |
| mp_roundrespawn_time | 20 | 0 | - | Player cannot respawn until next round if more than N seconds has elapsed since the beginning round.
`-1` means no time limit
|
| mp_auto_reload_weapons | 0 | 0 | 1 | Automatically reload each weapon on player spawn.
`0` disabled
`1` enabled |
| mp_refill_bpammo_weapons | 0 | 0 | 2 | Refill amount of backpack ammo up to the max.
`0` disabled
`1` refill backpack ammo on player spawn
`2` refill backpack ammo on player spawn and on the purchase of the item |
@@ -98,6 +100,7 @@ This means that plugins that do binary code analysis (Orpheu for example) probab
| mp_give_player_c4 | 1 | 0 | 1 | Whether this map should spawn a C4 bomb for a player or not.
`0` disabled
`1` enabled |
| mp_weapons_allow_map_placed | 1 | 0 | 1 | When set, map weapons (located on the floor by map) will be shown.
`0` hide all map weapons.
`1` enabled
`NOTE`: Effect will work after round restart. |
| mp_free_armor | 0 | 0 | 2 | Give free armor on player spawn.
`0` disabled
`1` Give Kevlar
`2` Give Kevlar + Helmet |
+| mp_team_flash | 1 | -1 | 1 | Sets the behaviour for Flashbangs on teammates.
`-1` Don't affect teammates neither flash owner
`0` Don't affect teammates
`1` Affects teammates |
| mp_fadetoblack | 0 | 0 | 2 | Observer's screen will fade to black on kill event or permanent.
`0` No fade.
`1` Fade to black and won't be able to watch anybody.
`2` fade to black only on kill moment. |
| mp_falldamage | 1 | 0 | 1 | Damage from falling.
`0` disabled
`1` enabled |
| sv_allchat | 1 | 0 | 1 | Players can receive all other players text chat, team restrictions apply
`0` disabled
`1` enabled |
@@ -110,6 +113,11 @@ This means that plugins that do binary code analysis (Orpheu for example) probab
| mp_max_alive_name_changes | -1 | -1 | - | Maximum amount of nickname changes when alive
`-1` unlimited
`0` Blocks name changes `>0` Allow to change arbitrary amount of nicks |
| sv_legacy_restart_entities | 0 | 0 | 1 | Legacy restart of entities on new round
`0` disabled
`1` enabled |
| sv_block_vote_commands | 0 | 0 | 1 | When set, blocks `vote` and `votemap` commands.
`0` disabled
`1` enabled |
+| mp_dying_time | 3.0 | 0.0 | - | Time for switch to free observing after death.
`0` - disable spectating around death.
`>0.00001` - time delay to start spectate.
`NOTE`: The countdown starts when the player’s death animation is finished. |
+| mp_deathmsg_flags | abc | 0 | - | Sets a flags for extra information in the player's death message.
`0` disabled
`a` position where the victim died
`b` index of the assistant who helped the attacker kill the victim
`c` rarity classification bits, e.g., `blinkill`, `noscope`, `penetrated`, etc. |
+| mp_assist_damage_threshold | 40 | 0 | 100 | Sets the percentage of damage needed to score an assist. |
+| mp_freezetime_duck | 1 | 0 | 1 | Allow players to duck during freezetime.
`0` disabled
`1` enabled |
+| mp_freezetime_jump | 1 | 0 | 1 | Allow players to jump during freezetime.
`0` disabled
`1` enabled |
## How to install zBot for CS 1.6?
diff --git a/dep/cppunitlite/msvc/cppunitlite.vcxproj b/dep/cppunitlite/msvc/cppunitlite.vcxproj
index fbda29b7b..9d0a3f21f 100644
--- a/dep/cppunitlite/msvc/cppunitlite.vcxproj
+++ b/dep/cppunitlite/msvc/cppunitlite.vcxproj
@@ -40,6 +40,7 @@
v140
v141
v142
+ v143
MultiByte
@@ -49,6 +50,7 @@
v140
v141
v142
+ v143
true
MultiByte
diff --git a/dist/delta.lst b/dist/delta.lst
new file mode 100644
index 000000000..7da4af32a
--- /dev/null
+++ b/dist/delta.lst
@@ -0,0 +1,262 @@
+// structure name
+// none == no conditional encode routine
+// gamedll routine_name : before transmitting data, invoke the named function from the game .dll to reset fields as needed
+// clientdll routine_name : same as above, except the routine is called via the client.dll
+
+clientdata_t none
+{
+ DEFINE_DELTA( flTimeStepSound, DT_INTEGER, 10, 1.0 ),
+ DEFINE_DELTA( origin[0], DT_SIGNED | DT_FLOAT, 24, 1024.0 ),
+ DEFINE_DELTA( origin[1], DT_SIGNED | DT_FLOAT, 24, 1024.0 ),
+ DEFINE_DELTA( velocity[0], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
+ DEFINE_DELTA( velocity[1], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
+
+ DEFINE_DELTA( m_flNextAttack, DT_FLOAT | DT_SIGNED, 22, 1000.0 ),
+
+ DEFINE_DELTA( origin[2], DT_SIGNED | DT_FLOAT, 24, 1024.0 ),
+ DEFINE_DELTA( velocity[2], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
+
+ DEFINE_DELTA( ammo_nails, DT_SIGNED | DT_INTEGER, 10, 1.0 ),
+ DEFINE_DELTA( ammo_shells, DT_SIGNED | DT_INTEGER, 10, 1.0 ),
+ DEFINE_DELTA( ammo_cells, DT_SIGNED | DT_INTEGER, 10, 1.0 ),
+ DEFINE_DELTA( ammo_rockets, DT_SIGNED | DT_INTEGER, 10, 1.0 ),
+
+ DEFINE_DELTA( m_iId, DT_INTEGER, 5, 1.0 ),
+
+ DEFINE_DELTA( punchangle[2], DT_SIGNED | DT_FLOAT, 21, 8.0 ),
+ DEFINE_DELTA( flags, DT_INTEGER, 32, 1.0 ), // Cut to 3 bits?
+ DEFINE_DELTA( weaponanim, DT_INTEGER, 8, 1.0 ),
+ DEFINE_DELTA( health, DT_FLOAT, 17, 1.0 ), // Cut # of bits?
+ DEFINE_DELTA( maxspeed, DT_FLOAT, 16, 10.0 ),
+ DEFINE_DELTA( flDuckTime, DT_INTEGER, 10, 1.0 ),
+ DEFINE_DELTA( view_ofs[2], DT_SIGNED | DT_FLOAT, 10, 4.0 ),
+ DEFINE_DELTA( punchangle[0], DT_SIGNED | DT_FLOAT, 26, 8192.0 ),
+ DEFINE_DELTA( punchangle[1], DT_SIGNED | DT_FLOAT, 26, 8192.0 ),
+ DEFINE_DELTA( viewmodel, DT_INTEGER, 10, 1.0 ),
+ DEFINE_DELTA( weapons, DT_INTEGER, 32, 1.0 ),
+
+ DEFINE_DELTA( pushmsec, DT_INTEGER, 11, 1.0 ),
+ DEFINE_DELTA( deadflag, DT_INTEGER, 3, 1.0 ),
+ DEFINE_DELTA( fov, DT_FLOAT, 8, 1.0 ),
+ DEFINE_DELTA( physinfo, DT_STRING, 1, 1.0 ),
+ DEFINE_DELTA( bInDuck, DT_INTEGER, 1, 1.0 ),
+ DEFINE_DELTA( flSwimTime, DT_INTEGER, 10, 1.0 ),
+ DEFINE_DELTA( waterjumptime, DT_INTEGER, 15, 1.0 ),
+ DEFINE_DELTA( waterlevel, DT_INTEGER, 2, 1.0 ),
+
+ DEFINE_DELTA( iuser1, DT_INTEGER, 3, 1.0 ),
+ DEFINE_DELTA( iuser2, DT_INTEGER, 6, 1.0 ),
+ DEFINE_DELTA( iuser3, DT_INTEGER, 8, 1.0 ),
+ DEFINE_DELTA( iuser4, DT_INTEGER, 2, 1.0 ),
+
+ DEFINE_DELTA( vuser2[0], DT_FLOAT, 9, 1.0 ),
+ DEFINE_DELTA( vuser2[1], DT_FLOAT, 9, 1.0 ),
+ DEFINE_DELTA( vuser2[2], DT_FLOAT, 9, 1.0 ),
+
+ DEFINE_DELTA( vuser3[0], DT_FLOAT, 9, 1.0 ),
+ DEFINE_DELTA( vuser3[1], DT_FLOAT, 9, 1.0 ),
+ DEFINE_DELTA( vuser3[2], DT_FLOAT, 9, 1.0 ),
+
+ DEFINE_DELTA( vuser4[0], DT_FLOAT, 9, 1.0 ),
+ DEFINE_DELTA( vuser4[1], DT_FLOAT, 9, 1.0 ),
+
+ DEFINE_DELTA( fuser1, DT_FLOAT, 9, 1.0 ),
+ DEFINE_DELTA( fuser2, DT_FLOAT, 14, 1.0 ),
+ DEFINE_DELTA( fuser3, DT_FLOAT, 10, 1.0 )
+}
+
+entity_state_t gamedll Entity_Encode
+{
+ DEFINE_DELTA( animtime, DT_TIMEWINDOW_8, 8, 1.0 ),
+ DEFINE_DELTA( frame, DT_FLOAT, 8, 1.0 ),
+ DEFINE_DELTA( origin[0], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
+ DEFINE_DELTA( angles[0], DT_ANGLE, 16, 1.0 ),
+ DEFINE_DELTA( angles[1], DT_ANGLE, 16, 1.0 ),
+ DEFINE_DELTA( origin[1], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
+ DEFINE_DELTA( origin[2], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
+ DEFINE_DELTA( sequence, DT_INTEGER, 8, 1.0 ),
+ DEFINE_DELTA( modelindex, DT_INTEGER, 10, 1.0 ),
+ DEFINE_DELTA( movetype, DT_INTEGER, 4, 1.0 ),
+ DEFINE_DELTA( solid, DT_SHORT, 3, 1.0 ),
+ DEFINE_DELTA( mins[0], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
+ DEFINE_DELTA( mins[1], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
+ DEFINE_DELTA( mins[2], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
+ DEFINE_DELTA( maxs[0], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
+ DEFINE_DELTA( maxs[1], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
+ DEFINE_DELTA( maxs[2], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
+
+ DEFINE_DELTA( endpos[0], DT_SIGNED | DT_FLOAT, 13, 1.0 ),
+ DEFINE_DELTA( endpos[1], DT_SIGNED | DT_FLOAT, 13, 1.0 ),
+ DEFINE_DELTA( endpos[2], DT_SIGNED | DT_FLOAT, 13, 1.0 ),
+ DEFINE_DELTA( startpos[0], DT_SIGNED | DT_FLOAT, 13, 1.0 ),
+ DEFINE_DELTA( startpos[1], DT_SIGNED | DT_FLOAT, 13, 1.0 ),
+ DEFINE_DELTA( startpos[2], DT_SIGNED | DT_FLOAT, 13, 1.0 ),
+ DEFINE_DELTA( impacttime, DT_TIMEWINDOW_BIG, 13, 100.0 ),
+ DEFINE_DELTA( starttime, DT_TIMEWINDOW_BIG, 13, 100.0 ),
+
+ DEFINE_DELTA( weaponmodel, DT_INTEGER, 10, 1.0 ),
+ DEFINE_DELTA( owner, DT_INTEGER, 5, 1.0 ),
+ DEFINE_DELTA( effects, DT_INTEGER, 8, 1.0 ),
+ DEFINE_DELTA( eflags, DT_INTEGER, 1, 1.0 ),
+ DEFINE_DELTA( angles[2], DT_ANGLE, 16, 1.0 ),
+ DEFINE_DELTA( colormap, DT_INTEGER, 16, 1.0 ),
+ DEFINE_DELTA( framerate, DT_SIGNED | DT_FLOAT, 8, 16.0 ),
+ DEFINE_DELTA( skin, DT_SHORT | DT_SIGNED, 9, 1.0 ),
+ DEFINE_DELTA( controller[0], DT_BYTE, 8, 1.0 ),
+ DEFINE_DELTA( controller[1], DT_BYTE, 8, 1.0 ),
+ DEFINE_DELTA( controller[2], DT_BYTE, 8, 1.0 ),
+ DEFINE_DELTA( controller[3], DT_BYTE, 8, 1.0 ),
+ DEFINE_DELTA( blending[0], DT_BYTE, 8, 1.0 ),
+ DEFINE_DELTA( blending[1], DT_BYTE, 8, 1.0 ),
+ DEFINE_DELTA( body, DT_INTEGER, 18, 1.0 ),
+ DEFINE_DELTA( rendermode, DT_INTEGER, 8, 1.0 ),
+ DEFINE_DELTA( renderamt, DT_INTEGER, 8, 1.0 ),
+ DEFINE_DELTA( renderfx, DT_INTEGER, 8, 1.0 ),
+ DEFINE_DELTA( scale, DT_FLOAT, 16, 256.0 ),
+ DEFINE_DELTA( rendercolor.r, DT_BYTE, 8, 1.0 ),
+ DEFINE_DELTA( rendercolor.g, DT_BYTE, 8, 1.0 ),
+ DEFINE_DELTA( rendercolor.b, DT_BYTE, 8, 1.0 ),
+ DEFINE_DELTA( aiment, DT_INTEGER, 11, 1.0 ),
+ DEFINE_DELTA( basevelocity[0], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
+ DEFINE_DELTA( basevelocity[1], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
+ DEFINE_DELTA( basevelocity[2], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
+
+ DEFINE_DELTA( iuser4, DT_INTEGER, 2, 1.0 )
+}
+
+entity_state_player_t gamedll Player_Encode
+{
+ DEFINE_DELTA( animtime, DT_TIMEWINDOW_8, 8, 1.0 ),
+ DEFINE_DELTA( frame, DT_FLOAT, 8, 1.0 ),
+ DEFINE_DELTA( origin[0], DT_SIGNED | DT_FLOAT, 24, 32.0 ),
+ DEFINE_DELTA( angles[0], DT_ANGLE, 16, 1.0 ),
+ DEFINE_DELTA( angles[1], DT_ANGLE, 16, 1.0 ),
+ DEFINE_DELTA( origin[1], DT_SIGNED | DT_FLOAT, 24, 32.0 ),
+ DEFINE_DELTA( origin[2], DT_SIGNED | DT_FLOAT, 24, 32.0 ),
+ DEFINE_DELTA( gaitsequence, DT_INTEGER, 8, 1.0 ),
+ DEFINE_DELTA( sequence, DT_INTEGER, 8, 1.0 ),
+ DEFINE_DELTA( modelindex, DT_INTEGER, 10, 1.0 ),
+ DEFINE_DELTA( movetype, DT_INTEGER, 4, 1.0 ),
+ DEFINE_DELTA( solid, DT_SHORT, 3, 1.0 ),
+ DEFINE_DELTA( mins[0], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
+ DEFINE_DELTA( mins[1], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
+ DEFINE_DELTA( mins[2], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
+ DEFINE_DELTA( maxs[0], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
+ DEFINE_DELTA( maxs[1], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
+ DEFINE_DELTA( maxs[2], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
+ DEFINE_DELTA( weaponmodel, DT_INTEGER, 10, 1.0 ),
+ // DEFINE_DELTA( team, DT_INTEGER, 4, 1.0 )
+ // DEFINE_DELTA( playerclass, DT_INTEGER, 4, 1.0 )
+ DEFINE_DELTA( owner, DT_INTEGER, 5, 1.0 ),
+ DEFINE_DELTA( effects, DT_INTEGER, 16, 1.0 ),
+ DEFINE_DELTA( angles[2], DT_ANGLE, 16, 1.0 ),
+ DEFINE_DELTA( colormap, DT_INTEGER, 16, 1.0 ),
+ DEFINE_DELTA( framerate, DT_SIGNED | DT_FLOAT, 8, 16.0 ),
+ DEFINE_DELTA( skin, DT_SHORT | DT_SIGNED, 9, 1.0 ),
+ DEFINE_DELTA( controller[0], DT_BYTE, 8, 1.0 ),
+ DEFINE_DELTA( controller[1], DT_BYTE, 8, 1.0 ),
+ DEFINE_DELTA( controller[2], DT_BYTE, 8, 1.0 ),
+ DEFINE_DELTA( controller[3], DT_BYTE, 8, 1.0 ),
+ DEFINE_DELTA( blending[0], DT_BYTE, 8, 1.0 ),
+ DEFINE_DELTA( blending[1], DT_BYTE, 8, 1.0 ),
+ DEFINE_DELTA( body, DT_INTEGER, 9, 1.0 ),
+ DEFINE_DELTA( rendermode, DT_INTEGER, 8, 1.0 ),
+ DEFINE_DELTA( renderamt, DT_INTEGER, 8, 1.0 ),
+ DEFINE_DELTA( renderfx, DT_INTEGER, 8, 1.0 ),
+ DEFINE_DELTA( scale, DT_FLOAT, 16, 256.0 ),
+ DEFINE_DELTA( rendercolor.r, DT_BYTE, 8, 1.0 ),
+ DEFINE_DELTA( rendercolor.g, DT_BYTE, 8, 1.0 ),
+ DEFINE_DELTA( rendercolor.b, DT_BYTE, 8, 1.0 ),
+ DEFINE_DELTA( friction, DT_SIGNED | DT_FLOAT, 16, 8.0 ),
+ DEFINE_DELTA( usehull, DT_INTEGER, 1, 1.0 ),
+ DEFINE_DELTA( gravity, DT_SIGNED | DT_FLOAT, 16, 32.0 ),
+ DEFINE_DELTA( aiment, DT_INTEGER, 11, 1.0 ),
+ DEFINE_DELTA( basevelocity[0], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
+ DEFINE_DELTA( basevelocity[1], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
+ DEFINE_DELTA( basevelocity[2], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
+ DEFINE_DELTA( spectator, DT_INTEGER, 1, 1.0 )
+
+ DEFINE_DELTA( iuser4, DT_INTEGER, 2, 1.0 )
+}
+
+custom_entity_state_t gamedll Custom_Encode
+{
+ DEFINE_DELTA( rendermode, DT_INTEGER, 8, 1.0 ),
+ DEFINE_DELTA( origin[0], DT_SIGNED | DT_FLOAT, 17, 8.0 ),
+ DEFINE_DELTA( origin[1], DT_SIGNED | DT_FLOAT, 17, 8.0 ),
+ DEFINE_DELTA( origin[2], DT_SIGNED | DT_FLOAT, 17, 8.0 ),
+ DEFINE_DELTA( angles[0], DT_SIGNED | DT_FLOAT, 17, 8.0 ),
+ DEFINE_DELTA( angles[1], DT_SIGNED | DT_FLOAT, 17, 8.0 ),
+ DEFINE_DELTA( angles[2], DT_SIGNED | DT_FLOAT, 17, 8.0 ),
+ DEFINE_DELTA( sequence, DT_INTEGER, 16, 1.0 ),
+ DEFINE_DELTA( skin, DT_INTEGER, 16, 1.0 ),
+ DEFINE_DELTA( modelindex, DT_INTEGER, 16, 1.0 ),
+ DEFINE_DELTA_POST( scale, DT_FLOAT, 8, 1.0, 0.1 ),
+ DEFINE_DELTA( body, DT_INTEGER, 8, 1.0 ),
+ DEFINE_DELTA( rendercolor.r, DT_BYTE, 8, 1.0 ),
+ DEFINE_DELTA( rendercolor.g, DT_BYTE, 8, 1.0 ),
+ DEFINE_DELTA( rendercolor.b, DT_BYTE, 8, 1.0 ),
+ DEFINE_DELTA( renderfx, DT_INTEGER, 8, 1.0 ),
+ DEFINE_DELTA( renderamt, DT_INTEGER, 8, 1.0 ),
+ DEFINE_DELTA( frame, DT_FLOAT, 8, 1.0 ),
+ DEFINE_DELTA_POST( animtime, DT_FLOAT, 8, 1.0, 0.1 )
+}
+
+usercmd_t none
+{
+ DEFINE_DELTA( lerp_msec, DT_SHORT, 9, 1.0 ),
+ DEFINE_DELTA( msec, DT_BYTE, 8, 1.0 ),
+ DEFINE_DELTA( viewangles[1], DT_ANGLE, 16, 1.0 ),
+ DEFINE_DELTA( viewangles[0], DT_ANGLE, 16, 1.0 ),
+ DEFINE_DELTA( buttons, DT_SHORT, 16, 1.0 ),
+ DEFINE_DELTA( forwardmove, DT_SIGNED | DT_FLOAT, 12, 1.0 ),
+ DEFINE_DELTA( lightlevel, DT_BYTE, 8, 1.0 ),
+ DEFINE_DELTA( sidemove, DT_SIGNED | DT_FLOAT, 12, 1.0 ),
+ DEFINE_DELTA( upmove, DT_SIGNED | DT_FLOAT, 12, 1.0 ),
+ DEFINE_DELTA( impulse, DT_BYTE, 8, 1.0 ),
+ DEFINE_DELTA( viewangles[2], DT_ANGLE, 16, 1.0 ),
+ DEFINE_DELTA( impact_index, DT_INTEGER, 6, 1.0 ),
+ DEFINE_DELTA( impact_position[0], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
+ DEFINE_DELTA( impact_position[1], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
+ DEFINE_DELTA( impact_position[2], DT_SIGNED | DT_FLOAT, 16, 8.0 )
+}
+
+weapon_data_t none
+{
+ DEFINE_DELTA( m_flTimeWeaponIdle, DT_FLOAT | DT_SIGNED, 22, 1000.0 ),
+ DEFINE_DELTA( m_flNextPrimaryAttack, DT_FLOAT | DT_SIGNED, 22, 1000.0 ),
+ DEFINE_DELTA( m_flNextReload, DT_FLOAT | DT_SIGNED, 22, 1000.0 ),
+ DEFINE_DELTA( m_fNextAimBonus, DT_FLOAT | DT_SIGNED, 22, 1000.0 ),
+ DEFINE_DELTA( m_flNextSecondaryAttack, DT_FLOAT | DT_SIGNED, 22, 1000.0 ),
+ DEFINE_DELTA( m_iClip, DT_SIGNED | DT_INTEGER, 10, 1.0 ),
+ DEFINE_DELTA( m_flPumpTime, DT_FLOAT | DT_SIGNED, 22, 1000.0 ),
+ DEFINE_DELTA( m_fInSpecialReload, DT_INTEGER, 2, 1.0 ),
+ DEFINE_DELTA( m_fReloadTime, DT_FLOAT, 16, 100.0 ),
+ DEFINE_DELTA( m_fInReload, DT_INTEGER, 1, 1.0 ),
+ DEFINE_DELTA( m_fAimedDamage, DT_FLOAT, 22, 1000.0 ),
+ DEFINE_DELTA( m_fInZoom, DT_INTEGER, 8, 1.0 ),
+ DEFINE_DELTA( m_iWeaponState, DT_INTEGER, 7, 1.0 )
+ DEFINE_DELTA( m_iId, DT_INTEGER, 5, 1.0 )
+ DEFINE_DELTA( fuser1, DT_SIGNED | DT_FLOAT, 22, 1000.0 ),
+ DEFINE_DELTA( fuser2, DT_SIGNED | DT_FLOAT, 22, 128.0 ),
+ DEFINE_DELTA( fuser3, DT_SIGNED | DT_FLOAT, 22, 128.0 ),
+ DEFINE_DELTA( iuser1, DT_SIGNED | DT_INTEGER, 16, 128.0 )
+}
+
+event_t none
+{
+ DEFINE_DELTA( entindex, DT_INTEGER, 11, 1.0 ),
+ DEFINE_DELTA( bparam1, DT_INTEGER, 1, 1.0 ),
+ DEFINE_DELTA( bparam2, DT_INTEGER, 1, 1.0 ),
+ DEFINE_DELTA( origin[0], DT_SIGNED | DT_FLOAT, 26, 8192.0 ),
+ DEFINE_DELTA( origin[1], DT_SIGNED | DT_FLOAT, 26, 8192.0 ),
+ DEFINE_DELTA( origin[2], DT_SIGNED | DT_FLOAT, 26, 8192.0 ),
+ DEFINE_DELTA( fparam1, DT_FLOAT | DT_SIGNED, 20, 100.0 ),
+ DEFINE_DELTA( fparam2, DT_FLOAT | DT_SIGNED, 20, 100.0 ),
+ DEFINE_DELTA( iparam1, DT_INTEGER | DT_SIGNED, 18, 1.0 ),
+ DEFINE_DELTA( iparam2, DT_INTEGER | DT_SIGNED, 18, 1.0 ),
+ DEFINE_DELTA( angles[0], DT_SIGNED | DT_FLOAT, 26, 8192.0 ),
+ DEFINE_DELTA( angles[1], DT_SIGNED | DT_FLOAT, 26, 8192.0 ),
+ DEFINE_DELTA( angles[2], DT_SIGNED | DT_FLOAT, 26, 8192.0 ),
+ DEFINE_DELTA( ducking, DT_INTEGER, 1, 1.0 )
+}
diff --git a/dist/game.cfg b/dist/game.cfg
index 364ec57bf..f7cb92c2f 100644
--- a/dist/game.cfg
+++ b/dist/game.cfg
@@ -78,6 +78,24 @@ mp_hegrenade_penetration "0"
// Default value: "0"
mp_nadedrops "0"
+// Drop player weapon after death
+// 0 - do not drop weapons after death
+// 1 - drop best/heaviest weapon after death (default behaviour)
+// 2 - drop active weapon after death
+// 3 - drop all weapons after death (primary and secondary)
+// NOTE: Grenades are dropped separately depending on mp_nadedrops value
+//
+// Default value: "1"
+mp_weapondrop "1"
+
+// Drop ammo on weapon boxes on death or manual drop
+// 0 - always keep ammo on player
+// 1 - drop all ammo only after death (default behaviour)
+// 2 - drop all ammo whenever player drops a weapon (NOTE: Other weapons may remain without ammo due to same ammo sharing)
+//
+// Default value: "1"
+mp_ammodrop "1"
+
// Player cannot respawn until next round
// if more than N seconds has elapsed since the beginning round
// -1 - means no time limit
@@ -456,6 +474,14 @@ mp_ct_default_weapons_secondary "usp"
// Default value: "0"
mp_free_armor "0"
+// Sets the behaviour for Flashbangs on teammates.
+// -1 - Don't affect teammates neither flash owner
+// 0 - Don't affect teammates
+// 1 - Affects teammates (default behaviour)
+//
+// Default value: "1"
+mp_team_flash 1
+
// Players can receive all other players text chat, team restrictions apply.
// 0 - disabled (default behaviour)
// 1 - enabled
@@ -503,7 +529,6 @@ mp_hostages_rescued_ratio "1.0"
//
// Default value: "1"
mp_legacy_vehicle_block "1"
-
// Maximum amount of nickname changes before next respawn.
// -1 - unlimited (default behaviour)
// 0 - Blocks name changes
@@ -525,3 +550,41 @@ sv_legacy_restart_entities 0
//
// Default value: "0"
sv_block_vote_commands 0
+
+// Time for switch to free observing after death.
+// NOTE: The countdown starts when the player’s death animation is finished.
+// 0 - disable spectating around death
+// >0.00001 - time delay to start spectate
+//
+// Default value: "3.0"
+mp_dying_time "3.0"
+
+// Sets a flags for extra information in the player's death message
+//
+// a - Position where the victim died
+// b - Index of the assistant who helped the attacker kill the victim
+// c - Rarity classification bits, e.g., blinkill, noscope, penetrated, etc
+//
+// Set to "0" to send no extra information about death
+//
+// Default value: "abc"
+mp_deathmsg_flags "abc"
+
+// Sets the percentage of damage needed to score an assist
+//
+// Default value: "40"
+mp_assist_damage_threshold "40"
+
+// Allow players to duck during freezetime
+// 0 - disabled
+// 1 - enabled (default behaviour)
+//
+// Default value: "1"
+mp_freezetime_duck "1"
+
+// Allow players to jump during freezetime
+// 0 - disabled
+// 1 - enabled (default behaviour)
+//
+// Default value: "1"
+mp_freezetime_jump "1"
diff --git a/regamedll/CMakeLists.txt b/regamedll/CMakeLists.txt
index 1b329ca95..69f710b31 100644
--- a/regamedll/CMakeLists.txt
+++ b/regamedll/CMakeLists.txt
@@ -161,6 +161,9 @@ set(SHARED_SRCS
"public/FileSystem.cpp"
"public/interface.cpp"
"public/MemPool.cpp"
+ "public/MemPool.cpp"
+ "public/tier0/dbg.cpp"
+ "public/tier0/platform_posix.cpp"
)
set(GAMEDLL_SRCS
@@ -226,6 +229,7 @@ set(GAMEDLL_SRCS
"dlls/API/CSEntity.cpp"
"dlls/API/CSPlayer.cpp"
"dlls/API/CSPlayerItem.cpp"
+ "dlls/API/CSPlayerWeapon.cpp"
"dlls/addons/item_airbox.cpp"
"dlls/addons/point_command.cpp"
"dlls/addons/trigger_random.cpp"
diff --git a/regamedll/common/const.h b/regamedll/common/const.h
index 3c9873114..024a2a3d5 100644
--- a/regamedll/common/const.h
+++ b/regamedll/common/const.h
@@ -96,6 +96,12 @@
// Goes into globalvars_t.trace_flags
#define FTRACE_SIMPLEBOX BIT(0) // Traceline with a simple box
+// Custom flags that we can retrive in pfnShouldCollide
+// Starting from BIT(16) to reserve space for more flags for Engine
+#define FTRACE_BULLET BIT(16)
+#define FTRACE_FLASH BIT(17)
+#define FTRACE_KNIFE BIT(18)
+
// walkmove modes
#define WALKMOVE_NORMAL 0 // normal walkmove
#define WALKMOVE_WORLDONLY 1 // doesn't hit ANY entities, no matter what the solid type
diff --git a/regamedll/dlls/API/CAPI_Impl.cpp b/regamedll/dlls/API/CAPI_Impl.cpp
index 0fe10a490..5bb6b3940 100644
--- a/regamedll/dlls/API/CAPI_Impl.cpp
+++ b/regamedll/dlls/API/CAPI_Impl.cpp
@@ -30,40 +30,133 @@
CReGameHookchains g_ReGameHookchains;
-int EXT_FUNC Cmd_Argc_api() {
+void EXT_FUNC Regamedll_ChangeString_api(char *&dest, const char *source)
+{
+ size_t len = Q_strlen(source);
+ if (dest == nullptr || Q_strlen(dest) != len) {
+ delete [] dest;
+ dest = new char [len + 1];
+ }
+
+ Q_strcpy(dest, source);
+}
+
+void EXT_FUNC RadiusDamage_api(Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, float flRadius, int iClassIgnore, int bitsDamageType)
+{
+ RadiusDamage(vecSrc, pevInflictor, pevAttacker, flDamage, flRadius, iClassIgnore, bitsDamageType);
+}
+
+void EXT_FUNC ClearMultiDamage_api()
+{
+ ClearMultiDamage();
+}
+
+void EXT_FUNC ApplyMultiDamage_api(entvars_t *pevInflictor, entvars_t *pevAttacker)
+{
+ ApplyMultiDamage(pevInflictor, pevAttacker);
+}
+
+void EXT_FUNC AddMultiDamage_api(entvars_t *pevInflictor, CBaseEntity *pEntity, float flDamage, int bitsDamageType)
+{
+ AddMultiDamage(pevInflictor, pEntity, flDamage, bitsDamageType);
+}
+
+int EXT_FUNC Cmd_Argc_api()
+{
return CMD_ARGC_();
}
-const char *EXT_FUNC Cmd_Argv_api(int i) {
+const char *EXT_FUNC Cmd_Argv_api(int i)
+{
return CMD_ARGV_(i);
}
-CGrenade *PlantBomb_api(entvars_t *pevOwner, Vector &vecStart, Vector &vecVelocity) {
+CGrenade *EXT_FUNC PlantBomb_api(entvars_t *pevOwner, Vector &vecStart, Vector &vecVelocity)
+{
return CGrenade::ShootSatchelCharge(pevOwner, vecStart, vecVelocity);
}
-CGib *SpawnHeadGib_api(entvars_t *pevVictim) {
+CGib *EXT_FUNC SpawnHeadGib_api(entvars_t *pevVictim)
+{
return CGib::SpawnHeadGib(pevVictim);
}
-void SpawnRandomGibs_api(entvars_t *pevVictim, int cGibs, int human) {
+void EXT_FUNC SpawnRandomGibs_api(entvars_t *pevVictim, int cGibs, int human)
+{
CGib::SpawnRandomGibs(pevVictim, cGibs, human);
}
+void EXT_FUNC UTIL_RestartOther_api(const char *szClassname)
+{
+ UTIL_RestartOther(szClassname);
+}
+
+void EXT_FUNC UTIL_ResetEntities_api()
+{
+ UTIL_ResetEntities();
+}
+
+void EXT_FUNC UTIL_RemoveOther_api(const char *szClassname, int nCount)
+{
+ UTIL_RemoveOther(szClassname, nCount);
+}
+
+void EXT_FUNC UTIL_DecalTrace_api(TraceResult *pTrace, int decalNumber)
+{
+ UTIL_DecalTrace(pTrace, decalNumber);
+}
+
+void EXT_FUNC UTIL_Remove_api(CBaseEntity *pEntity)
+{
+ UTIL_Remove(pEntity);
+}
+
+int EXT_FUNC AddAmmoNameToAmmoRegistry_api(const char *szAmmoname)
+{
+ return AddAmmoNameToAmmoRegistry(szAmmoname);
+}
+
+void EXT_FUNC TextureTypePlaySound_api(TraceResult *ptr, Vector vecSrc, Vector vecEnd, int iBulletType)
+{
+ TEXTURETYPE_PlaySound(ptr, vecSrc, vecEnd, iBulletType);
+}
+
+CWeaponBox *EXT_FUNC CreateWeaponBox_api(CBasePlayerItem *pItem, CBasePlayer *pPlayerOwner, const char *modelName, Vector &origin, Vector &angles, Vector &velocity, float lifeTime, bool packAmmo)
+{
+ return CreateWeaponBox(pItem, pPlayerOwner, modelName, origin, angles, velocity, lifeTime < 0.0 ? CGameRules::GetItemKillDelay() : lifeTime, packAmmo);
+}
+
+CGrenade *EXT_FUNC SpawnGrenade_api(WeaponIdType weaponId, entvars_t *pevOwner, Vector &vecSrc, Vector &vecThrow, float time, int iTeam, unsigned short usEvent)
+{
+ switch (weaponId)
+ {
+ case WEAPON_HEGRENADE:
+ return CGrenade::ShootTimed2(pevOwner, vecSrc, vecThrow, time, iTeam, usEvent);
+ case WEAPON_FLASHBANG:
+ return CGrenade::ShootTimed(pevOwner, vecSrc, vecThrow, time);
+ case WEAPON_SMOKEGRENADE:
+ return CGrenade::ShootSmokeGrenade(pevOwner, vecSrc, vecThrow, time, usEvent);
+ case WEAPON_C4:
+ return CGrenade::ShootSatchelCharge(pevOwner, vecSrc, vecThrow);
+ }
+
+ return nullptr;
+}
+
ReGameFuncs_t g_ReGameApiFuncs = {
- &CREATE_NAMED_ENTITY,
+ CREATE_NAMED_ENTITY,
- &Regamedll_ChangeString_api,
+ Regamedll_ChangeString_api,
- &RadiusDamage_api,
- &ClearMultiDamage_api,
- &ApplyMultiDamage_api,
- &AddMultiDamage_api,
+ RadiusDamage_api,
+ ClearMultiDamage_api,
+ ApplyMultiDamage_api,
+ AddMultiDamage_api,
- &UTIL_FindEntityByString,
+ UTIL_FindEntityByString,
- &AddEntityHashValue,
- &RemoveEntityHashValue,
+ AddEntityHashValue,
+ RemoveEntityHashValue,
Cmd_Argc_api,
Cmd_Argv_api,
@@ -71,7 +164,18 @@ ReGameFuncs_t g_ReGameApiFuncs = {
PlantBomb_api,
SpawnHeadGib_api,
- SpawnRandomGibs_api
+ SpawnRandomGibs_api,
+
+ UTIL_RestartOther_api,
+ UTIL_ResetEntities_api,
+ UTIL_RemoveOther_api,
+ UTIL_DecalTrace_api,
+ UTIL_Remove_api,
+
+ AddAmmoNameToAmmoRegistry_api,
+ TextureTypePlaySound_api,
+ CreateWeaponBox_api,
+ SpawnGrenade_api,
};
GAMEHOOK_REGISTRY(CBasePlayer_Spawn);
@@ -204,6 +308,34 @@ GAMEHOOK_REGISTRY(CBasePlayer_Pain);
GAMEHOOK_REGISTRY(CBasePlayer_DeathSound);
GAMEHOOK_REGISTRY(CBasePlayer_JoiningThink);
+GAMEHOOK_REGISTRY(FreeGameRules);
+GAMEHOOK_REGISTRY(PM_LadderMove);
+GAMEHOOK_REGISTRY(PM_WaterJump);
+GAMEHOOK_REGISTRY(PM_CheckWaterJump);
+GAMEHOOK_REGISTRY(PM_Jump);
+GAMEHOOK_REGISTRY(PM_Duck);
+GAMEHOOK_REGISTRY(PM_UnDuck);
+GAMEHOOK_REGISTRY(PM_PlayStepSound);
+GAMEHOOK_REGISTRY(PM_AirAccelerate);
+GAMEHOOK_REGISTRY(ClearMultiDamage);
+GAMEHOOK_REGISTRY(AddMultiDamage);
+GAMEHOOK_REGISTRY(ApplyMultiDamage);
+GAMEHOOK_REGISTRY(BuyItem);
+GAMEHOOK_REGISTRY(CSGameRules_Think);
+GAMEHOOK_REGISTRY(CSGameRules_TeamFull);
+GAMEHOOK_REGISTRY(CSGameRules_TeamStacked);
+GAMEHOOK_REGISTRY(CSGameRules_PlayerGotWeapon);
+GAMEHOOK_REGISTRY(CBotManager_OnEvent);
+GAMEHOOK_REGISTRY(CBasePlayer_CheckTimeBasedDamage);
+GAMEHOOK_REGISTRY(CBasePlayer_EntSelectSpawnPoint);
+GAMEHOOK_REGISTRY(CBasePlayerWeapon_ItemPostFrame);
+GAMEHOOK_REGISTRY(CBasePlayerWeapon_KickBack);
+GAMEHOOK_REGISTRY(CBasePlayerWeapon_SendWeaponAnim);
+GAMEHOOK_REGISTRY(CSGameRules_SendDeathMessage);
+
+GAMEHOOK_REGISTRY(CBasePlayer_PlayerDeathThink);
+GAMEHOOK_REGISTRY(CBasePlayer_Observer_Think);
+
int CReGameApi::GetMajorVersion() {
return REGAMEDLL_API_VERSION_MAJOR;
}
@@ -265,35 +397,4 @@ bool CReGameApi::BGetIGameRules(const char *pchVersion) const
return false;
}
-EXT_FUNC void Regamedll_ChangeString_api(char *&dest, const char *source)
-{
- size_t len = Q_strlen(source);
- if (dest == nullptr || Q_strlen(dest) != len) {
- delete [] dest;
- dest = new char [len + 1];
- }
-
- Q_strcpy(dest, source);
-}
-
-EXT_FUNC void RadiusDamage_api(Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, float flRadius, int iClassIgnore, int bitsDamageType)
-{
- RadiusDamage(vecSrc, pevInflictor, pevAttacker, flDamage, flRadius, iClassIgnore, bitsDamageType);
-}
-
-EXT_FUNC void ClearMultiDamage_api()
-{
- ClearMultiDamage();
-}
-
-EXT_FUNC void ApplyMultiDamage_api(entvars_t *pevInflictor, entvars_t *pevAttacker)
-{
- ApplyMultiDamage(pevInflictor, pevAttacker);
-}
-
-EXT_FUNC void AddMultiDamage_api(entvars_t *pevInflictor, CBaseEntity *pEntity, float flDamage, int bitsDamageType)
-{
- AddMultiDamage(pevInflictor, pEntity, flDamage, bitsDamageType);
-}
-
EXPOSE_SINGLE_INTERFACE(CReGameApi, IReGameApi, VRE_GAMEDLL_API_VERSION);
diff --git a/regamedll/dlls/API/CAPI_Impl.h b/regamedll/dlls/API/CAPI_Impl.h
index 1be3dd232..0548a841f 100644
--- a/regamedll/dlls/API/CAPI_Impl.h
+++ b/regamedll/dlls/API/CAPI_Impl.h
@@ -458,8 +458,8 @@ typedef IHookChainClassImpl CReGameHook_CSGameRu
typedef IHookChainRegistryClassEmptyImpl CReGameHookRegistry_CSGameRules_RemoveGuns;
// CHalfLifeMultiplay::GiveC4 hook
-typedef IHookChainClassImpl CReGameHook_CSGameRules_GiveC4;
-typedef IHookChainRegistryClassEmptyImpl CReGameHookRegistry_CSGameRules_GiveC4;
+typedef IHookChainClassImpl CReGameHook_CSGameRules_GiveC4;
+typedef IHookChainRegistryClassEmptyImpl CReGameHookRegistry_CSGameRules_GiveC4;
// CHalfLifeMultiplay::ChangeLevel hook
typedef IHookChainClassImpl CReGameHook_CSGameRules_ChangeLevel;
@@ -641,6 +641,110 @@ typedef IHookChainRegistryClassImpl CReGameHookRegistry_CBase
typedef IHookChainClassImpl CReGameHook_CBasePlayer_JoiningThink;
typedef IHookChainRegistryClassImpl CReGameHookRegistry_CBasePlayer_JoiningThink;
+// FreeGameRules hook
+typedef IHookChainImpl CReGameHook_FreeGameRules;
+typedef IHookChainRegistryImpl CReGameHookRegistry_FreeGameRules;
+
+// PM_LadderMove hook
+typedef IHookChainImpl CReGameHook_PM_LadderMove;
+typedef IHookChainRegistryImpl CReGameHookRegistry_PM_LadderMove;
+
+// PM_WaterJump hook
+typedef IHookChainImpl CReGameHook_PM_WaterJump;
+typedef IHookChainRegistryImpl CReGameHookRegistry_PM_WaterJump;
+
+// PM_CheckWaterJump hook
+typedef IHookChainImpl CReGameHook_PM_CheckWaterJump;
+typedef IHookChainRegistryImpl CReGameHookRegistry_PM_CheckWaterJump;
+
+// PM_Jump hook
+typedef IHookChainImpl CReGameHook_PM_Jump;
+typedef IHookChainRegistryImpl CReGameHookRegistry_PM_Jump;
+
+// PM_Duck hook
+typedef IHookChainImpl CReGameHook_PM_Duck;
+typedef IHookChainRegistryImpl CReGameHookRegistry_PM_Duck;
+
+// PM_UnDuck hook
+typedef IHookChainImpl CReGameHook_PM_UnDuck;
+typedef IHookChainRegistryImpl CReGameHookRegistry_PM_UnDuck;
+
+// PM_PlayStepSound hook
+typedef IHookChainImpl CReGameHook_PM_PlayStepSound;
+typedef IHookChainRegistryImpl CReGameHookRegistry_PM_PlayStepSound;
+
+// PM_AirAccelerate hook
+typedef IHookChainImpl CReGameHook_PM_AirAccelerate;
+typedef IHookChainRegistryImpl CReGameHookRegistry_PM_AirAccelerate;
+
+// ClearMultiDamage hook
+typedef IHookChainImpl CReGameHook_ClearMultiDamage;
+typedef IHookChainRegistryImpl CReGameHookRegistry_ClearMultiDamage;
+
+// AddMultiDamage hook
+typedef IHookChainImpl CReGameHook_AddMultiDamage;
+typedef IHookChainRegistryImpl CReGameHookRegistry_AddMultiDamage;
+
+// ApplyMultiDamage hook
+typedef IHookChainImpl CReGameHook_ApplyMultiDamage;
+typedef IHookChainRegistryImpl CReGameHookRegistry_ApplyMultiDamage;
+
+// BuyItem hook
+typedef IHookChainImpl CReGameHook_BuyItem;
+typedef IHookChainRegistryImpl CReGameHookRegistry_BuyItem;
+
+// CHalfLifeMultiplay::Think hook
+typedef IHookChainClassImpl CReGameHook_CSGameRules_Think;
+typedef IHookChainRegistryClassEmptyImpl CReGameHookRegistry_CSGameRules_Think;
+
+// CHalfLifeMultiplay::TeamFull hook
+typedef IHookChainClassImpl CReGameHook_CSGameRules_TeamFull;
+typedef IHookChainRegistryClassEmptyImpl CReGameHookRegistry_CSGameRules_TeamFull;
+
+// CHalfLifeMultiplay::TeamStacked hook
+typedef IHookChainClassImpl CReGameHook_CSGameRules_TeamStacked;
+typedef IHookChainRegistryClassEmptyImpl CReGameHookRegistry_CSGameRules_TeamStacked;
+
+// CHalfLifeMultiplay::PlayerGotWeapon hook
+typedef IHookChainClassImpl CReGameHook_CSGameRules_PlayerGotWeapon;
+typedef IHookChainRegistryClassEmptyImpl CReGameHookRegistry_CSGameRules_PlayerGotWeapon;
+
+// CHalfLifeMultiplay::SendDeathMessage hook
+typedef IHookChainClassImpl CReGameHook_CSGameRules_SendDeathMessage;
+typedef IHookChainRegistryClassEmptyImpl CReGameHookRegistry_CSGameRules_SendDeathMessage;
+
+// CBotManager::OnEvent hook
+typedef IHookChainClassImpl CReGameHook_CBotManager_OnEvent;
+typedef IHookChainRegistryClassEmptyImpl CReGameHookRegistry_CBotManager_OnEvent;
+
+// CBasePlayer::CheckTimeBasedDamage hook
+typedef IHookChainClassImpl CReGameHook_CBasePlayer_CheckTimeBasedDamage;
+typedef IHookChainRegistryClassImpl CReGameHookRegistry_CBasePlayer_CheckTimeBasedDamage;
+
+// CBasePlayer::EntSelectSpawnPoint hook
+typedef IHookChainClassImpl CReGameHook_CBasePlayer_EntSelectSpawnPoint;
+typedef IHookChainRegistryClassImpl CReGameHookRegistry_CBasePlayer_EntSelectSpawnPoint;
+
+// CBasePlayerWeapon::ItemPostFrame hook
+typedef IHookChainClassImpl CReGameHook_CBasePlayerWeapon_ItemPostFrame;
+typedef IHookChainRegistryClassImpl CReGameHookRegistry_CBasePlayerWeapon_ItemPostFrame;
+
+// CBasePlayerWeapon::KickBack hook
+typedef IHookChainClassImpl CReGameHook_CBasePlayerWeapon_KickBack;
+typedef IHookChainRegistryClassImpl CReGameHookRegistry_CBasePlayerWeapon_KickBack;
+
+// CBasePlayerWeapon::SendWeaponAnim hook
+typedef IHookChainClassImpl CReGameHook_CBasePlayerWeapon_SendWeaponAnim;
+typedef IHookChainRegistryClassImpl CReGameHookRegistry_CBasePlayerWeapon_SendWeaponAnim;
+
+// CBasePlayer::PlayerDeathThink hook
+typedef IHookChainClassImpl CReGameHook_CBasePlayer_PlayerDeathThink;
+typedef IHookChainRegistryClassImpl CReGameHookRegistry_CBasePlayer_PlayerDeathThink;
+
+// CBasePlayer::Observer_Think hook
+typedef IHookChainClassImpl CReGameHook_CBasePlayer_Observer_Think;
+typedef IHookChainRegistryClassImpl CReGameHookRegistry_CBasePlayer_Observer_Think;
+
class CReGameHookchains: public IReGameHookchains {
public:
// CBasePlayer virtual
@@ -774,6 +878,34 @@ class CReGameHookchains: public IReGameHookchains {
CReGameHookRegistry_CBasePlayer_DeathSound m_CBasePlayer_DeathSound;
CReGameHookRegistry_CBasePlayer_JoiningThink m_CBasePlayer_JoiningThink;
+ CReGameHookRegistry_FreeGameRules m_FreeGameRules;
+ CReGameHookRegistry_PM_LadderMove m_PM_LadderMove;
+ CReGameHookRegistry_PM_WaterJump m_PM_WaterJump;
+ CReGameHookRegistry_PM_CheckWaterJump m_PM_CheckWaterJump;
+ CReGameHookRegistry_PM_Jump m_PM_Jump;
+ CReGameHookRegistry_PM_Duck m_PM_Duck;
+ CReGameHookRegistry_PM_UnDuck m_PM_UnDuck;
+ CReGameHookRegistry_PM_PlayStepSound m_PM_PlayStepSound;
+ CReGameHookRegistry_PM_AirAccelerate m_PM_AirAccelerate;
+ CReGameHookRegistry_ClearMultiDamage m_ClearMultiDamage;
+ CReGameHookRegistry_AddMultiDamage m_AddMultiDamage;
+ CReGameHookRegistry_ApplyMultiDamage m_ApplyMultiDamage;
+ CReGameHookRegistry_BuyItem m_BuyItem;
+ CReGameHookRegistry_CSGameRules_Think m_CSGameRules_Think;
+ CReGameHookRegistry_CSGameRules_TeamFull m_CSGameRules_TeamFull;
+ CReGameHookRegistry_CSGameRules_TeamStacked m_CSGameRules_TeamStacked;
+ CReGameHookRegistry_CSGameRules_PlayerGotWeapon m_CSGameRules_PlayerGotWeapon;
+ CReGameHookRegistry_CBotManager_OnEvent m_CBotManager_OnEvent;
+ CReGameHookRegistry_CBasePlayer_CheckTimeBasedDamage m_CBasePlayer_CheckTimeBasedDamage;
+ CReGameHookRegistry_CBasePlayer_EntSelectSpawnPoint m_CBasePlayer_EntSelectSpawnPoint;
+ CReGameHookRegistry_CBasePlayerWeapon_ItemPostFrame m_CBasePlayerWeapon_ItemPostFrame;
+ CReGameHookRegistry_CBasePlayerWeapon_KickBack m_CBasePlayerWeapon_KickBack;
+ CReGameHookRegistry_CBasePlayerWeapon_SendWeaponAnim m_CBasePlayerWeapon_SendWeaponAnim;
+ CReGameHookRegistry_CSGameRules_SendDeathMessage m_CSGameRules_SendDeathMessage;
+
+ CReGameHookRegistry_CBasePlayer_PlayerDeathThink m_CBasePlayer_PlayerDeathThink;
+ CReGameHookRegistry_CBasePlayer_Observer_Think m_CBasePlayer_Observer_Think;
+
public:
virtual IReGameHookRegistry_CBasePlayer_Spawn *CBasePlayer_Spawn();
virtual IReGameHookRegistry_CBasePlayer_Precache *CBasePlayer_Precache();
@@ -904,6 +1036,34 @@ class CReGameHookchains: public IReGameHookchains {
virtual IReGameHookRegistry_CBasePlayer_Pain *CBasePlayer_Pain();
virtual IReGameHookRegistry_CBasePlayer_DeathSound *CBasePlayer_DeathSound();
virtual IReGameHookRegistry_CBasePlayer_JoiningThink *CBasePlayer_JoiningThink();
+
+ virtual IReGameHookRegistry_FreeGameRules *FreeGameRules();
+ virtual IReGameHookRegistry_PM_LadderMove *PM_LadderMove();
+ virtual IReGameHookRegistry_PM_WaterJump *PM_WaterJump();
+ virtual IReGameHookRegistry_PM_CheckWaterJump *PM_CheckWaterJump();
+ virtual IReGameHookRegistry_PM_Jump *PM_Jump();
+ virtual IReGameHookRegistry_PM_Duck *PM_Duck();
+ virtual IReGameHookRegistry_PM_UnDuck *PM_UnDuck();
+ virtual IReGameHookRegistry_PM_PlayStepSound *PM_PlayStepSound();
+ virtual IReGameHookRegistry_PM_AirAccelerate *PM_AirAccelerate();
+ virtual IReGameHookRegistry_ClearMultiDamage *ClearMultiDamage();
+ virtual IReGameHookRegistry_AddMultiDamage *AddMultiDamage();
+ virtual IReGameHookRegistry_ApplyMultiDamage *ApplyMultiDamage();
+ virtual IReGameHookRegistry_BuyItem *BuyItem();
+ virtual IReGameHookRegistry_CSGameRules_Think *CSGameRules_Think();
+ virtual IReGameHookRegistry_CSGameRules_TeamFull *CSGameRules_TeamFull();
+ virtual IReGameHookRegistry_CSGameRules_TeamStacked *CSGameRules_TeamStacked();
+ virtual IReGameHookRegistry_CSGameRules_PlayerGotWeapon *CSGameRules_PlayerGotWeapon();
+ virtual IReGameHookRegistry_CBotManager_OnEvent *CBotManager_OnEvent();
+ virtual IReGameHookRegistry_CBasePlayer_CheckTimeBasedDamage *CBasePlayer_CheckTimeBasedDamage();
+ virtual IReGameHookRegistry_CBasePlayer_EntSelectSpawnPoint *CBasePlayer_EntSelectSpawnPoint();
+ virtual IReGameHookRegistry_CBasePlayerWeapon_ItemPostFrame *CBasePlayerWeapon_ItemPostFrame();
+ virtual IReGameHookRegistry_CBasePlayerWeapon_KickBack *CBasePlayerWeapon_KickBack();
+ virtual IReGameHookRegistry_CBasePlayerWeapon_SendWeaponAnim *CBasePlayerWeapon_SendWeaponAnim();
+ virtual IReGameHookRegistry_CSGameRules_SendDeathMessage *CSGameRules_SendDeathMessage();
+
+ virtual IReGameHookRegistry_CBasePlayer_PlayerDeathThink *CBasePlayer_PlayerDeathThink();
+ virtual IReGameHookRegistry_CBasePlayer_Observer_Think *CBasePlayer_Observer_Think();
};
extern CReGameHookchains g_ReGameHookchains;
@@ -930,10 +1090,3 @@ class CReGameApi: public IReGameApi {
EXT_FUNC virtual bool BGetICSEntity(const char *pchVersion) const;
EXT_FUNC virtual bool BGetIGameRules(const char *pchVersion) const;
};
-
-void Regamedll_ChangeString_api(char *&dest, const char *source);
-void RadiusDamage_api(Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, float flRadius, int iClassIgnore, int bitsDamageType);
-
-void ClearMultiDamage_api();
-void ApplyMultiDamage_api(entvars_t *pevInflictor, entvars_t *pevAttacker);
-void AddMultiDamage_api(entvars_t *pevInflictor, CBaseEntity *pEntity, float flDamage, int bitsDamageType);
diff --git a/regamedll/dlls/API/CSEntity.cpp b/regamedll/dlls/API/CSEntity.cpp
index 0e037d29e..00f7badc6 100644
--- a/regamedll/dlls/API/CSEntity.cpp
+++ b/regamedll/dlls/API/CSEntity.cpp
@@ -30,15 +30,15 @@
void CCSEntity::FireBullets(int iShots, Vector &vecSrc, Vector &vecDirShooting, Vector &vecSpread, float flDistance, int iBulletType, int iTracerFreq, int iDamage, entvars_t *pevAttacker)
{
- m_pContainingEntity->FireBullets(iShots, vecSrc, vecDirShooting, vecSpread, flDistance, iBulletType, iTracerFreq, iDamage, pevAttacker);
+ BaseEntity()->FireBullets(iShots, vecSrc, vecDirShooting, vecSpread, flDistance, iBulletType, iTracerFreq, iDamage, pevAttacker);
}
void CCSEntity::FireBuckshots(ULONG cShots, Vector &vecSrc, Vector &vecDirShooting, Vector &vecSpread, float flDistance, int iTracerFreq, int iDamage, entvars_t *pevAttacker)
{
- m_pContainingEntity->FireBuckshots(cShots, vecSrc, vecDirShooting, vecSpread, flDistance, iTracerFreq, iDamage, pevAttacker);
+ BaseEntity()->FireBuckshots(cShots, vecSrc, vecDirShooting, vecSpread, flDistance, iTracerFreq, iDamage, pevAttacker);
}
Vector CCSEntity::FireBullets3(Vector &vecSrc, Vector &vecDirShooting, float vecSpread, float flDistance, int iPenetration, int iBulletType, int iDamage, float flRangeModifier, entvars_t *pevAttacker, bool bPistol, int shared_rand)
{
- return m_pContainingEntity->FireBullets3(vecSrc, vecDirShooting, vecSpread, flDistance, iPenetration, iBulletType, iDamage, flRangeModifier, pevAttacker, bPistol, shared_rand);
+ return BaseEntity()->FireBullets3(vecSrc, vecDirShooting, vecSpread, flDistance, iPenetration, iBulletType, iDamage, flRangeModifier, pevAttacker, bPistol, shared_rand);
}
diff --git a/regamedll/dlls/API/CSPlayer.cpp b/regamedll/dlls/API/CSPlayer.cpp
index 96fab9054..ad368bbb9 100644
--- a/regamedll/dlls/API/CSPlayer.cpp
+++ b/regamedll/dlls/API/CSPlayer.cpp
@@ -43,8 +43,10 @@ EXT_FUNC bool CCSPlayer::JoinTeam(TeamName team)
pPlayer->pev->deadflag = DEAD_DEAD;
pPlayer->pev->health = 0;
+ if (pPlayer->m_bHasC4)
+ pPlayer->DropPlayerItem("weapon_c4");
+
pPlayer->RemoveAllItems(TRUE);
- pPlayer->m_bHasC4 = false;
pPlayer->m_iTeam = SPECTATOR;
pPlayer->m_iJoiningState = JOINED;
@@ -58,7 +60,7 @@ EXT_FUNC bool CCSPlayer::JoinTeam(TeamName team)
pPlayer->StartObserver(pentSpawnSpot->v.origin, pentSpawnSpot->v.angles);
// do we have fadetoblack on? (need to fade their screen back in)
- if (fadetoblack.value)
+ if (fadetoblack.value == FADETOBLACK_STAY)
{
UTIL_ScreenFade(pPlayer, Vector(0, 0, 0), 0.001, 0, 0, FFADE_IN);
}
@@ -110,19 +112,16 @@ EXT_FUNC bool CCSPlayer::JoinTeam(TeamName team)
}
}
+ bool bAddFrags = false;
if (pPlayer->pev->deadflag == DEAD_NO)
{
- ClientKill(pPlayer->edict());
- pPlayer->pev->frags++;
+ if (pPlayer->Kill())
+ {
+ bAddFrags = true;
+ }
}
- MESSAGE_BEGIN(MSG_ALL, gmsgScoreInfo);
- WRITE_BYTE(ENTINDEX(pPlayer->edict()));
- WRITE_SHORT(int(pPlayer->pev->frags));
- WRITE_SHORT(pPlayer->m_iDeaths);
- WRITE_SHORT(0);
- WRITE_SHORT(0);
- MESSAGE_END();
+ pPlayer->AddPoints(bAddFrags, TRUE);
// Switch their actual team...
pPlayer->m_bTeamChanged = true;
@@ -151,15 +150,7 @@ EXT_FUNC bool CCSPlayer::RemovePlayerItemEx(const char* pszItemName, bool bRemov
if (!pPlayer->m_bHasDefuser)
return false;
- pPlayer->m_bHasDefuser = false;
- pPlayer->pev->body = 0;
-
- MESSAGE_BEGIN(MSG_ONE, gmsgStatusIcon, nullptr, pPlayer->pev);
- WRITE_BYTE(STATUSICON_HIDE);
- WRITE_STRING("defuser");
- MESSAGE_END();
-
- pPlayer->SendItemStatus();
+ pPlayer->RemoveDefuser();
}
// item_longjump
else if (FStrEq(pszItemName, "longjump"))
@@ -209,39 +200,34 @@ EXT_FUNC bool CCSPlayer::RemovePlayerItemEx(const char* pszItemName, bool bRemov
auto pItem = GetItemByName(pszItemName);
if (pItem)
{
- if (FClassnameIs(pItem->pev, "weapon_c4")) {
- pPlayer->m_bHasC4 = false;
- pPlayer->pev->body = 0;
- pPlayer->SetBombIcon(FALSE);
- pPlayer->SetProgressBarTime(0);
- }
-
if (pItem->IsWeapon())
{
- if (pItem == pPlayer->m_pActiveItem) {
- ((CBasePlayerWeapon *)pItem)->RetireWeapon();
+ // These weapons have a unique type of ammo that is used only by them
+ // If a weapon is removed, its ammo is also reduced, unless the ammo can be used by another weapon
+ if (!bRemoveAmmo && (IsGrenadeWeapon(pItem->m_iId) || pItem->m_iId == WEAPON_C4))
+ {
+ if (pPlayer->m_rgAmmo[pItem->PrimaryAmmoIndex()] > 0)
+ pPlayer->m_rgAmmo[pItem->PrimaryAmmoIndex()]--;
+
+ // Hold the weapon until it runs out of ammo
+ if (pPlayer->m_rgAmmo[pItem->PrimaryAmmoIndex()] > 0)
+ return true; // ammo was reduced, this will be considered a successful result
}
if (bRemoveAmmo) {
- pPlayer->m_rgAmmo[ pItem->PrimaryAmmoIndex() ] = 0;
- }
- }
-
- if (pPlayer->RemovePlayerItem(pItem)) {
- pPlayer->pev->weapons &= ~(1 << pItem->m_iId);
- // No more weapon
- if ((pPlayer->pev->weapons & ~(1 << WEAPON_SUIT)) == 0) {
- pPlayer->m_iHideHUD |= HIDEHUD_WEAPONS;
+ pPlayer->m_rgAmmo[pItem->PrimaryAmmoIndex()] = 0;
}
- pItem->Kill();
+ if (pItem == pPlayer->m_pActiveItem) {
+ ((CBasePlayerWeapon *)pItem)->RetireWeapon();
- if (!pPlayer->m_rgpPlayerItems[PRIMARY_WEAPON_SLOT]) {
- pPlayer->m_bHasPrimary = false;
+ if (pItem->CanHolster() && pItem != pPlayer->m_pActiveItem && !(pPlayer->pev->weapons &(1 << pItem->m_iId))) {
+ return true;
+ }
}
-
- return true;
}
+
+ return pItem->DestroyItem();
}
return false;
@@ -258,11 +244,13 @@ EXT_FUNC CBaseEntity *CCSPlayer::GiveNamedItemEx(const char *pszName)
if (FStrEq(pszName, "weapon_c4")) {
pPlayer->m_bHasC4 = true;
- pPlayer->SetBombIcon();
if (pPlayer->m_iTeam == TERRORIST) {
pPlayer->pev->body = 1;
}
+
+ pPlayer->SetBombIcon();
+
} else if (FStrEq(pszName, "weapon_shield")) {
pPlayer->DropPrimary();
pPlayer->DropPlayerItem("weapon_elite");
@@ -275,7 +263,7 @@ EXT_FUNC CBaseEntity *CCSPlayer::GiveNamedItemEx(const char *pszName)
EXT_FUNC bool CCSPlayer::IsConnected() const
{
- return m_pContainingEntity->has_disconnected == false;
+ return BaseEntity()->has_disconnected == false;
}
EXT_FUNC void CCSPlayer::SetAnimation(PLAYER_ANIM playerAnim)
@@ -303,14 +291,14 @@ EXT_FUNC void CCSPlayer::GiveShield(bool bDeploy)
BasePlayer()->GiveShield(bDeploy);
}
-EXT_FUNC void CCSPlayer::DropShield(bool bDeploy)
+EXT_FUNC CBaseEntity *CCSPlayer::DropShield(bool bDeploy)
{
- BasePlayer()->DropShield(bDeploy);
+ return BasePlayer()->DropShield(bDeploy);
}
-EXT_FUNC void CCSPlayer::DropPlayerItem(const char *pszItemName)
+EXT_FUNC CBaseEntity *CCSPlayer::DropPlayerItem(const char *pszItemName)
{
- BasePlayer()->DropPlayerItem(pszItemName);
+ return BasePlayer()->DropPlayerItem(pszItemName);
}
EXT_FUNC bool CCSPlayer::RemoveShield()
@@ -514,6 +502,21 @@ EXT_FUNC bool CCSPlayer::HintMessageEx(const char *pMessage, float duration, boo
return BasePlayer()->HintMessageEx(pMessage, duration, bDisplayIfPlayerDead, bOverride);
}
+EXT_FUNC void CCSPlayer::Reset()
+{
+ BasePlayer()->Reset();
+}
+
+EXT_FUNC void CCSPlayer::OnSpawnEquip(bool addDefault, bool equipGame)
+{
+ BasePlayer()->OnSpawnEquip(addDefault, equipGame);
+}
+
+EXT_FUNC void CCSPlayer::SetScoreboardAttributes(CBasePlayer *destination)
+{
+ BasePlayer()->SetScoreboardAttributes(destination);
+}
+
EXT_FUNC bool CCSPlayer::CheckActivityInGame()
{
const CBasePlayer* pPlayer = BasePlayer();
@@ -526,7 +529,7 @@ EXT_FUNC bool CCSPlayer::CheckActivityInGame()
return (fabs(deltaYaw) >= 0.1f && fabs(deltaPitch) >= 0.1f);
}
-void CCSPlayer::Reset()
+void CCSPlayer::ResetVars()
{
m_szModel[0] = '\0';
@@ -542,6 +545,18 @@ void CCSPlayer::Reset()
m_bAutoBunnyHopping = false;
m_bMegaBunnyJumping = false;
m_iAliveNameChanges = 0;
+ m_bSpawnProtectionEffects = false;
+}
+
+// Resets all stats
+void CCSPlayer::ResetAllStats()
+{
+ // Resets the kill history for this player
+ for (int i = 0; i < MAX_CLIENTS; i++)
+ {
+ m_iNumKilledByUnanswered[i] = 0;
+ m_bPlayerDominated[i] = false;
+ }
}
void CCSPlayer::OnSpawn()
@@ -549,6 +564,7 @@ void CCSPlayer::OnSpawn()
m_bGameForcingRespawn = false;
m_flRespawnPending = 0.0f;
m_iAliveNameChanges = 0;
+ m_DamageList.Clear();
}
void CCSPlayer::OnKilled()
@@ -566,3 +582,33 @@ void CCSPlayer::OnKilled()
}
#endif
}
+
+void CCSPlayer::OnConnect()
+{
+ ResetVars();
+ m_iUserID = GETPLAYERUSERID(BasePlayer()->edict());
+}
+
+// Remember this amount of damage that we dealt for stats
+void CCSPlayer::RecordDamage(CBasePlayer *pAttacker, float flDamage, float flFlashDurationTime)
+{
+ if (!pAttacker || !pAttacker->IsPlayer())
+ return;
+
+ int attackerIndex = pAttacker->entindex() - 1;
+ if (attackerIndex < 0 || attackerIndex >= MAX_CLIENTS)
+ return;
+
+ CCSPlayer *pCSAttacker = pAttacker->CSPlayer();
+
+ // Accumulate damage
+ CDamageRecord_t &record = m_DamageList[attackerIndex];
+ if (record.flDamage > 0 && record.userId != pCSAttacker->m_iUserID)
+ record.flDamage = 0; // reset damage if attacker became another client
+
+ record.flDamage += flDamage;
+ record.userId = pCSAttacker->m_iUserID;
+
+ if (flFlashDurationTime > 0)
+ record.flFlashDurationTime = gpGlobals->time + flFlashDurationTime;
+}
diff --git a/regamedll/dlls/API/CSPlayerWeapon.cpp b/regamedll/dlls/API/CSPlayerWeapon.cpp
new file mode 100644
index 000000000..51a5fd806
--- /dev/null
+++ b/regamedll/dlls/API/CSPlayerWeapon.cpp
@@ -0,0 +1,54 @@
+/*
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 of the License, or (at
+* your option) any later version.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+* In addition, as a special exception, the author gives permission to
+* link the code of this program with the Half-Life Game Engine ("HL
+* Engine") and Modified Game Libraries ("MODs") developed by Valve,
+* L.L.C ("Valve"). You must obey the GNU General Public License in all
+* respects for all of the code used other than the HL Engine and MODs
+* from Valve. If you modify this file, you may extend this exception
+* to your version of the file, but you are not obligated to do so. If
+* you do not wish to do so, delete this exception statement from your
+* version.
+*
+*/
+
+#include "precompiled.h"
+
+EXT_FUNC BOOL CCSPlayerWeapon::DefaultDeploy(char *szViewModel, char *szWeaponModel, int iAnim, char *szAnimExt, int skiplocal)
+{
+ return BasePlayerWeapon()->DefaultDeploy(szViewModel, szWeaponModel, iAnim, szAnimExt, skiplocal);
+}
+
+EXT_FUNC int CCSPlayerWeapon::DefaultReload(int iClipSize, int iAnim, float fDelay)
+{
+ return BasePlayerWeapon()->DefaultReload(iClipSize, iAnim, fDelay);
+}
+
+EXT_FUNC bool CCSPlayerWeapon::DefaultShotgunReload(int iAnim, int iStartAnim, float fDelay, float fStartDelay, const char *pszReloadSound1, const char *pszReloadSound2)
+{
+ return BasePlayerWeapon()->DefaultShotgunReload(iAnim, iStartAnim, fDelay, fStartDelay, pszReloadSound1, pszReloadSound2);
+}
+
+EXT_FUNC void CCSPlayerWeapon::KickBack(float up_base, float lateral_base, float up_modifier, float lateral_modifier, float up_max, float lateral_max, int direction_change)
+{
+ BasePlayerWeapon()->KickBack(up_base, lateral_base, up_modifier, lateral_modifier, up_max, lateral_max, direction_change);
+}
+
+EXT_FUNC void CCSPlayerWeapon::SendWeaponAnim(int iAnim, int skiplocal)
+{
+ BasePlayerWeapon()->SendWeaponAnim(iAnim, skiplocal);
+}
diff --git a/regamedll/dlls/animating.cpp b/regamedll/dlls/animating.cpp
index 8e7d84334..9e104f22e 100644
--- a/regamedll/dlls/animating.cpp
+++ b/regamedll/dlls/animating.cpp
@@ -179,6 +179,11 @@ NOXREF int CBaseAnimating::GetBodygroup(int iGroup)
return ::GetBodygroup(GET_MODEL_PTR(ENT(pev)), pev, iGroup);
}
+float CBaseAnimating::GetSequenceDuration() const
+{
+ return ::GetSequenceDuration(GET_MODEL_PTR(ENT(pev)), pev);
+}
+
int CBaseAnimating::ExtractBbox(int sequence, float *mins, float *maxs)
{
return ::ExtractBbox(GET_MODEL_PTR(ENT(pev)), sequence, mins, maxs);
diff --git a/regamedll/dlls/animation.cpp b/regamedll/dlls/animation.cpp
index 83c0bd403..7d5df6f07 100644
--- a/regamedll/dlls/animation.cpp
+++ b/regamedll/dlls/animation.cpp
@@ -12,7 +12,7 @@ server_studio_api_t IEngineStudio;
studiohdr_t *g_pstudiohdr;
float (*g_pRotationMatrix)[3][4];
-float (*g_pBoneTransform)[128][3][4];
+float (*g_pBoneTransform)[MAXSTUDIOBONES][3][4];
int ExtractBbox(void *pmodel, int sequence, float *mins, float *maxs)
{
@@ -246,6 +246,21 @@ void GetSequenceInfo(void *pmodel, entvars_t *pev, float *pflFrameRate, float *p
*pflGroundSpeed = *pflGroundSpeed * pseqdesc->fps / (pseqdesc->numframes - 1);
}
+float GetSequenceDuration(void *pmodel, entvars_t *pev)
+{
+ studiohdr_t *pstudiohdr = (studiohdr_t *)pmodel;
+ if (!pstudiohdr)
+ return 0; // model ptr is not valid
+
+ if (pev->sequence < 0 || pev->sequence >= pstudiohdr->numseq)
+ return 0; // sequence is not valid
+
+ // get current sequence time
+ mstudioseqdesc_t *pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + int(pev->sequence);
+
+ return pseqdesc->numframes / pseqdesc->fps;
+}
+
int GetSequenceFlags(void *pmodel, entvars_t *pev)
{
studiohdr_t *pstudiohdr = (studiohdr_t *)pmodel;
@@ -522,7 +537,7 @@ C_DLLEXPORT int Server_GetBlendingInterface(int version, struct sv_blending_inte
IEngineStudio.Mod_Extradata = ((struct server_studio_api_s *)pstudio)->Mod_Extradata;
g_pRotationMatrix = (float (*)[3][4])rotationmatrix;
- g_pBoneTransform = (float (*)[128][3][4])bonetransform;
+ g_pBoneTransform = (float (*)[MAXSTUDIOBONES][3][4])bonetransform;
return 1;
}
diff --git a/regamedll/dlls/animation.h b/regamedll/dlls/animation.h
index 54af21a8c..7889a140b 100644
--- a/regamedll/dlls/animation.h
+++ b/regamedll/dlls/animation.h
@@ -42,6 +42,7 @@ int LookupActivity(void *pmodel, entvars_t *pev, int activity);
int LookupActivityHeaviest(void *pmodel, entvars_t *pev, int activity);
int LookupSequence(void *pmodel, const char *label);
void GetSequenceInfo(void *pmodel, entvars_t *pev, float *pflFrameRate, float *pflGroundSpeed);
+float GetSequenceDuration(void *pmodel, entvars_t *pev);
int GetSequenceFlags(void *pmodel, entvars_t *pev);
float SetController(void *pmodel, entvars_t *pev, int iController, float flValue);
float SetBlending(void *pmodel, entvars_t *pev, int iBlender, float flValue);
diff --git a/regamedll/dlls/basemonster.cpp b/regamedll/dlls/basemonster.cpp
index a134d99c7..bfa9a1e14 100644
--- a/regamedll/dlls/basemonster.cpp
+++ b/regamedll/dlls/basemonster.cpp
@@ -451,17 +451,13 @@ BOOL CBaseMonster::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, f
if (pev->health <= 0.0f)
{
- g_pevLastInflictor = pevInflictor;
-
if (bitsDamageType & DMG_ALWAYSGIB)
- Killed(pevAttacker, GIB_ALWAYS);
-
+ KilledInflicted(pevInflictor, pevAttacker, GIB_ALWAYS);
else if (bitsDamageType & DMG_NEVERGIB)
- Killed(pevAttacker, GIB_NEVER);
+ KilledInflicted(pevInflictor, pevAttacker, GIB_NEVER);
else
- Killed(pevAttacker, GIB_NORMAL);
+ KilledInflicted(pevInflictor, pevAttacker, GIB_NORMAL);
- g_pevLastInflictor = nullptr;
return FALSE;
}
if ((pev->flags & FL_MONSTER) && !FNullEnt(pevAttacker))
diff --git a/regamedll/dlls/basemonster.h b/regamedll/dlls/basemonster.h
index dbdc22c66..63f8d8d41 100644
--- a/regamedll/dlls/basemonster.h
+++ b/regamedll/dlls/basemonster.h
@@ -34,7 +34,7 @@
enum
{
- ITBD_PARALLYZE = 0,
+ ITBD_PARALYZE = 0,
ITBD_NERVE_GAS,
ITBD_POISON,
ITBD_RADIATION,
diff --git a/regamedll/dlls/bot/cs_bot.h b/regamedll/dlls/bot/cs_bot.h
index 27d8bd59e..345e11fbd 100644
--- a/regamedll/dlls/bot/cs_bot.h
+++ b/regamedll/dlls/bot/cs_bot.h
@@ -42,9 +42,6 @@ enum
BOT_PROGGRESS_HIDE, // hide status bar progress
};
-extern int _navAreaCount;
-extern int _currentIndex;
-
class CCSBot;
class BotChatterInterface;
@@ -970,7 +967,6 @@ class CCSBot: public CBot
const CNavNode *m_navNodeList;
CNavNode *m_currentNode;
NavDirType m_generationDir;
- NavAreaList::iterator m_analyzeIter;
enum ProcessType
{
diff --git a/regamedll/dlls/bot/cs_bot_learn.cpp b/regamedll/dlls/bot/cs_bot_learn.cpp
index bb6df51d2..76edded7a 100644
--- a/regamedll/dlls/bot/cs_bot_learn.cpp
+++ b/regamedll/dlls/bot/cs_bot_learn.cpp
@@ -30,8 +30,7 @@
const float updateTimesliceDuration = 0.5f;
-int _navAreaCount = 0;
-int _currentIndex = 0;
+unsigned int _generationIndex = 0; // used for iterating nav areas during generation process
inline CNavNode *LadderEndSearch(CBaseEntity *pEntity, const Vector *pos, NavDirType mountDir)
{
@@ -385,11 +384,8 @@ void CCSBot::UpdateLearnProcess()
void CCSBot::StartAnalyzeAlphaProcess()
{
- m_processMode = PROCESS_ANALYZE_ALPHA;
- m_analyzeIter = TheNavAreaList.begin();
-
- _navAreaCount = TheNavAreaList.size();
- _currentIndex = 0;
+ m_processMode = PROCESS_ANALYZE_ALPHA;
+ _generationIndex = 0;
ApproachAreaAnalysisPrep();
DestroyHidingSpots();
@@ -400,15 +396,18 @@ void CCSBot::StartAnalyzeAlphaProcess()
bool CCSBot::AnalyzeAlphaStep()
{
- _currentIndex++;
- if (m_analyzeIter == TheNavAreaList.end())
+ _generationIndex++;
+
+ if (_generationIndex < 0 || _generationIndex >= TheNavAreaList.size())
return false;
- CNavArea *area = (*m_analyzeIter);
+ // TODO: Pretty ugly and very slow way to access element by index
+ // There is no reason not to use a vector instead of a linked list
+ const NavAreaList::const_iterator &iter = std::next(TheNavAreaList.begin(), _generationIndex - 1);
+
+ CNavArea *area = (*iter);
area->ComputeHidingSpots();
area->ComputeApproachAreas();
- m_analyzeIter++;
-
return true;
}
@@ -426,29 +425,30 @@ void CCSBot::UpdateAnalyzeAlphaProcess()
}
}
- float progress = (double(_currentIndex) / double(_navAreaCount)) * 0.5f;
+ float progress = (double(_generationIndex) / double(TheNavAreaList.size())) * 0.5f;
drawProgressMeter(progress, "#CZero_AnalyzingHidingSpots");
}
void CCSBot::StartAnalyzeBetaProcess()
{
- m_processMode = PROCESS_ANALYZE_BETA;
- m_analyzeIter = TheNavAreaList.begin();
-
- _navAreaCount = TheNavAreaList.size();
- _currentIndex = 0;
+ m_processMode = PROCESS_ANALYZE_BETA;
+ _generationIndex = 0;
}
bool CCSBot::AnalyzeBetaStep()
{
- _currentIndex++;
- if (m_analyzeIter == TheNavAreaList.end())
+ _generationIndex++;
+
+ if (_generationIndex < 0 || _generationIndex >= TheNavAreaList.size())
return false;
- CNavArea *area = (*m_analyzeIter);
+ // TODO: Pretty ugly and very slow way to access element by index
+ // There is no reason not to use a vector instead of a linked list
+ const NavAreaList::const_iterator &iter = std::next(TheNavAreaList.begin(), _generationIndex - 1);
+
+ CNavArea *area = (*iter);
area->ComputeSpotEncounters();
area->ComputeSniperSpots();
- m_analyzeIter++;
return true;
}
@@ -466,7 +466,7 @@ void CCSBot::UpdateAnalyzeBetaProcess()
}
}
- float progress = (double(_currentIndex) / double(_navAreaCount) + 1.0f) * 0.5f;
+ float progress = (double(_generationIndex) / double(TheNavAreaList.size()) + 1.0f) * 0.5f;
drawProgressMeter(progress, "#CZero_AnalyzingApproachPoints");
}
diff --git a/regamedll/dlls/bot/cs_bot_manager.cpp b/regamedll/dlls/bot/cs_bot_manager.cpp
index 786a3f08f..7793e8151 100644
--- a/regamedll/dlls/bot/cs_bot_manager.cpp
+++ b/regamedll/dlls/bot/cs_bot_manager.cpp
@@ -78,7 +78,7 @@ CCSBotManager::CCSBotManager()
char *dataPointer = (char *)LOAD_FILE_FOR_ME((char *)filename, &dataLength);
if (!dataPointer)
{
- TheBotProfiles->Init("BotProfile.db");
+ TheBotProfiles->Init(cv_bot_profile_db.string);
}
else
{
@@ -410,11 +410,7 @@ void CCSBotManager::ServerCommand(const char *pcmd)
{
if (killThemAll || FStrEq(name, msg))
{
-#ifdef REGAMEDLL_FIXES
- ClientKill(pPlayer->edict());
-#else
- pPlayer->TakeDamage(pPlayer->pev, pPlayer->pev, 9999.9f, DMG_CRUSH);
-#endif
+ pPlayer->Kill();
}
}
}
@@ -634,11 +630,15 @@ void CCSBotManager::ServerCommand(const char *pcmd)
{
CONSOLE_ECHO("Ambiguous\n");
}
- else
+ else if (found)
{
CONSOLE_ECHO("Current place set to '%s'\n", found->GetName());
SetNavPlace(found->GetID());
}
+ else
+ {
+ CONSOLE_ECHO("Error - place name '%s' no exists in phrases BotChatter.db\n", msg);
+ }
}
}
else if (FStrEq(pcmd, "bot_nav_toggle_place_mode"))
diff --git a/regamedll/dlls/bot/cs_bot_pathfind.cpp b/regamedll/dlls/bot/cs_bot_pathfind.cpp
index 3b733ea14..00386be7b 100644
--- a/regamedll/dlls/bot/cs_bot_pathfind.cpp
+++ b/regamedll/dlls/bot/cs_bot_pathfind.cpp
@@ -1294,7 +1294,7 @@ CCSBot::PathResult CCSBot::UpdatePathMovement(bool allowSpeedChange)
if (IsOnLadder())
Jump(MUST_JUMP);
- assert(m_pathIndex < m_pathLength);
+ Assert(m_pathIndex < m_pathLength);
// Check if reached the end of the path
bool nearEndOfPath = false;
diff --git a/regamedll/dlls/bot/cs_bot_update.cpp b/regamedll/dlls/bot/cs_bot_update.cpp
index 635360d03..37d496659 100644
--- a/regamedll/dlls/bot/cs_bot_update.cpp
+++ b/regamedll/dlls/bot/cs_bot_update.cpp
@@ -437,7 +437,6 @@ void CCSBot::Update()
}
else
{
- const int dada = offsetof(CCSBot, m_visibleEnemyParts);
// check LOS to current enemy (chest & head), in case he's dead (GetNearestEnemy() only returns live players)
// note we're not checking FOV - once we've acquired an enemy (which does check FOV), assume we know roughly where he is
if (IsVisible(m_enemy, false, &m_visibleEnemyParts))
diff --git a/regamedll/dlls/bot/states/cs_bot_idle.cpp b/regamedll/dlls/bot/states/cs_bot_idle.cpp
index 125d5fee4..e38bde885 100644
--- a/regamedll/dlls/bot/states/cs_bot_idle.cpp
+++ b/regamedll/dlls/bot/states/cs_bot_idle.cpp
@@ -353,7 +353,7 @@ void IdleState::OnUpdate(CCSBot *me)
}
}
- assert((0, "A CT bot doesn't know what to do while the bomb is planted!\n"));
+ DbgAssert(!"A CT bot doesn't know what to do while the bomb is planted!\n");
}
// if we have a sniper rifle, we like to camp, whether rogue or not
diff --git a/regamedll/dlls/buttons.cpp b/regamedll/dlls/buttons.cpp
index c559f8c03..8e38b369f 100644
--- a/regamedll/dlls/buttons.cpp
+++ b/regamedll/dlls/buttons.cpp
@@ -671,7 +671,7 @@ void CBaseButton::ButtonActivate()
PlayLockSounds(pev, &m_ls, FALSE, TRUE);
}
- assert(m_toggle_state == TS_AT_BOTTOM);
+ DbgAssert(m_toggle_state == TS_AT_BOTTOM);
m_toggle_state = TS_GOING_UP;
SetMoveDone(&CBaseButton::TriggerAndWait);
@@ -688,7 +688,7 @@ void CBaseButton::ButtonActivate()
// Button has reached the "in/up" position. Activate its "targets", and pause before "popping out".
void CBaseButton::TriggerAndWait()
{
- assert(m_toggle_state == TS_GOING_UP);
+ DbgAssert(m_toggle_state == TS_GOING_UP);
if (!UTIL_IsMasterTriggered(m_sMaster, m_hActivator))
return;
@@ -724,7 +724,7 @@ void CBaseButton::TriggerAndWait()
// Starts the button moving "out/down".
void CBaseButton::ButtonReturn()
{
- //assert(m_toggle_state == TS_AT_TOP);
+ DbgAssert(m_toggle_state == TS_AT_TOP);
m_toggle_state = TS_GOING_DOWN;
SetMoveDone(&CBaseButton::ButtonBackHome);
@@ -763,7 +763,7 @@ void CBaseButton::Restart()
// Button has returned to start state. Quiesce it.
void CBaseButton::ButtonBackHome()
{
- assert(m_toggle_state == TS_GOING_DOWN);
+ DbgAssert(m_toggle_state == TS_GOING_DOWN);
m_toggle_state = TS_AT_BOTTOM;
if (pev->spawnflags & SF_BUTTON_TOGGLE
@@ -776,7 +776,11 @@ void CBaseButton::ButtonBackHome()
SUB_UseTargets(m_hActivator, USE_TOGGLE, 0);
}
- if (!FStringNull(pev->target))
+ if (!FStringNull(pev->target)
+#ifdef REGAMEDLL_FIXES
+ && m_hActivator
+#endif
+)
{
edict_t *pentTarget = nullptr;
while ((pentTarget = FIND_ENTITY_BY_TARGETNAME(pentTarget, STRING(pev->target))))
@@ -880,7 +884,7 @@ void CRotButton::Spawn()
m_vecAngle1 = pev->angles;
m_vecAngle2 = pev->angles + pev->movedir * m_flMoveDistance;
- assert(("rotating button start/end positions are equal", m_vecAngle1 != m_vecAngle2));
+ DbgAssertMsg(m_vecAngle1 != m_vecAngle2, "rotating button start/end positions are equal");
m_fStayPushed = (m_flWait == -1 ? TRUE : FALSE);
m_fRotating = TRUE;
diff --git a/regamedll/dlls/career_tasks.cpp b/regamedll/dlls/career_tasks.cpp
index 0b0c45a56..200c67558 100644
--- a/regamedll/dlls/career_tasks.cpp
+++ b/regamedll/dlls/career_tasks.cpp
@@ -136,10 +136,14 @@ void CCareerTask::OnWeaponKill(int weaponId, int weaponClassId, bool headshot, b
if (!pHostage->IsAlive())
continue;
+#ifndef REGAMEDLL_FIXES
if (!pHostage->IsFollowingSomeone())
continue;
if (pHostage->m_target == pVictim)
+#else
+ if (pHostage->IsFollowing(pVictim))
+#endif
hostagesCount++;
}
@@ -211,11 +215,14 @@ void CCareerTask::OnEvent(GameEventType event, CBasePlayer *pVictim, CBasePlayer
{
if (!pHostage->IsAlive())
continue;
-
+#ifndef REGAMEDLL_FIXES
if (!pHostage->IsFollowingSomeone())
continue;
if (pHostage->m_target == pAttacker)
+#else
+ if (pHostage->IsFollowing(pAttacker))
+#endif
hostagesCount++;
}
diff --git a/regamedll/dlls/cbase.cpp b/regamedll/dlls/cbase.cpp
index 9bf5abef0..1d706299b 100644
--- a/regamedll/dlls/cbase.cpp
+++ b/regamedll/dlls/cbase.cpp
@@ -63,6 +63,10 @@ NEW_DLL_FUNCTIONS gNewDLLFunctions =
nullptr
};
+#ifndef REGAMEDLL_API
+entvars_t *g_pevLastInflictor = nullptr;
+#endif
+
CMemoryPool hashItemMemPool(sizeof(hash_item_t), 64);
int CaseInsensitiveHash(const char *string, int iBounds)
@@ -697,7 +701,11 @@ BOOL CBaseEntity::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, fl
pev->health -= flDamage;
if (pev->health <= 0)
{
+#ifdef REGAMEDLL_FIXES
+ KilledInflicted(pevInflictor, pevAttacker, GIB_NORMAL);
+#else
Killed(pevAttacker, GIB_NORMAL);
+#endif
return FALSE;
}
@@ -866,6 +874,17 @@ BOOL CBaseEntity::IsInWorld()
}
// speed
+#ifdef REGAMEDLL_FIXES
+ float maxvel = g_psv_maxvelocity->value;
+ if (pev->velocity.x > maxvel || pev->velocity.y > maxvel || pev->velocity.z > maxvel)
+ {
+ return FALSE;
+ }
+ if (pev->velocity.x < -maxvel || pev->velocity.y < -maxvel || pev->velocity.z < -maxvel)
+ {
+ return FALSE;
+ }
+#else
if (pev->velocity.x >= 2000.0 || pev->velocity.y >= 2000.0 || pev->velocity.z >= 2000.0)
{
return FALSE;
@@ -874,6 +893,7 @@ BOOL CBaseEntity::IsInWorld()
{
return FALSE;
}
+#endif
return TRUE;
}
@@ -1039,6 +1059,9 @@ void CBaseEntity::__API_HOOK(FireBullets)(ULONG cShots, VectorRef vecSrc, Vector
vecDir = vecDirShooting + x * vecSpread.x * vecRight + y * vecSpread.y * vecUp;
vecEnd = vecSrc + vecDir * flDistance;
+#ifdef REGAMEDLL_ADD
+ gpGlobals->trace_flags = FTRACE_BULLET;
+#endif
UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, ENT(pev), &tr);
tracer = 0;
@@ -1182,6 +1205,9 @@ void CBaseEntity::__API_HOOK(FireBuckshots)(ULONG cShots, VectorRef vecSrc, Vect
vecDir = vecDirShooting + x * vecSpread.x * vecRight + y * vecSpread.y * vecUp;
vecEnd = vecSrc + vecDir * flDistance;
+#ifdef REGAMEDLL_ADD
+ gpGlobals->trace_flags = FTRACE_BULLET;
+#endif
UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, ENT(pev), &tr);
tracer = 0;
@@ -1236,7 +1262,7 @@ bool EXT_FUNC IsPenetrableEntity_default(Vector &vecSrc, Vector &vecEnd, entvars
LINK_HOOK_CLASS_CHAIN(VectorRef, CBaseEntity, FireBullets3, (VectorRef vecSrc, VectorRef vecDirShooting, float vecSpread, float flDistance, int iPenetration, int iBulletType, int iDamage, float flRangeModifier, entvars_t *pevAttacker, bool bPistol, int shared_rand), vecSrc, vecDirShooting, vecSpread, flDistance, iPenetration, iBulletType, iDamage, flRangeModifier, pevAttacker, bPistol, shared_rand)
-
+
// Go to the trouble of combining multiple pellets into a single damage call.
// This version is used by Players, uses the random seed generator to sync client and server side shots.
VectorRef CBaseEntity::__API_HOOK(FireBullets3)(VectorRef vecSrc, VectorRef vecDirShooting, float vecSpread, float flDistance, int iPenetration, int iBulletType, int iDamage, float flRangeModifier, entvars_t *pevAttacker, bool bPistol, int shared_rand)
@@ -1334,9 +1360,14 @@ VectorRef CBaseEntity::__API_HOOK(FireBullets3)(VectorRef vecSrc, VectorRef vecD
float flDamageModifier = 0.5;
+ int iStartPenetration = iPenetration;
while (iPenetration != 0)
{
ClearMultiDamage();
+
+#ifdef REGAMEDLL_ADD
+ gpGlobals->trace_flags = FTRACE_BULLET;
+#endif
UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, ENT(pev), &tr);
if (TheBots && tr.flFraction != 1.0f)
@@ -1390,9 +1421,11 @@ VectorRef CBaseEntity::__API_HOOK(FireBullets3)(VectorRef vecSrc, VectorRef vecD
default:
break;
}
+
if (tr.flFraction != 1.0f)
{
CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit);
+ int iPenetrationCur = iPenetration;
iPenetration--;
flCurrentDistance = tr.flFraction * flDistance;
@@ -1449,6 +1482,7 @@ VectorRef CBaseEntity::__API_HOOK(FireBullets3)(VectorRef vecSrc, VectorRef vecD
flDistance = (flDistance - flCurrentDistance) * flDistanceModifier;
vecEnd = vecSrc + (vecDir * flDistance);
+ pEntity->SetDmgPenetrationLevel(iStartPenetration - iPenetrationCur);
pEntity->TraceAttack(pevAttacker, iCurrentDamage, vecDir, &tr, (DMG_BULLET | DMG_NEVERGIB));
iCurrentDamage *= flDamageModifier;
}
diff --git a/regamedll/dlls/cbase.h b/regamedll/dlls/cbase.h
index 1e11bbeef..8149356fa 100644
--- a/regamedll/dlls/cbase.h
+++ b/regamedll/dlls/cbase.h
@@ -242,8 +242,16 @@ class CBaseEntity {
void SetBlocked(void (T::*pfn)(CBaseEntity *pOther));
void SetBlocked(std::nullptr_t);
+ void SetDmgPenetrationLevel(int iPenetrationLevel);
+ void ResetDmgPenetrationLevel();
+ int GetDmgPenetrationLevel() const;
+
+ void KilledInflicted(entvars_t *pevInflictor, entvars_t *pevAttacker, int iGib);
+ entvars_t *GetLastInflictor();
+
#ifdef REGAMEDLL_API
CCSEntity *m_pEntity;
+ CCSEntity *CSEntity() const;
#else
// We use this variables to store each ammo count.
// let's sacrifice this unused member, for its own needs in favor of m_pEntity
@@ -328,6 +336,26 @@ inline void CBaseEntity::SetBlocked(std::nullptr_t)
m_pfnBlocked = nullptr;
}
+#ifdef REGAMEDLL_API
+inline CCSEntity *CBaseEntity::CSEntity() const
+{
+ return m_pEntity;
+}
+#else // !REGAMEDLL_API
+
+extern entvars_t *g_pevLastInflictor;
+inline void CBaseEntity::SetDmgPenetrationLevel(int iPenetrationLevel) {}
+inline void CBaseEntity::ResetDmgPenetrationLevel() {}
+inline int CBaseEntity::GetDmgPenetrationLevel() const { return 0; }
+inline entvars_t *CBaseEntity::GetLastInflictor() { return g_pevLastInflictor; }
+inline void CBaseEntity::KilledInflicted(entvars_t *pevInflictor, entvars_t *pevAttacker, int iGib)
+{
+ g_pevLastInflictor = pevInflictor;
+ Killed(pevAttacker, iGib);
+ g_pevLastInflictor = nullptr;
+}
+#endif // !REGAMEDLL_API
+
class CPointEntity: public CBaseEntity {
public:
virtual void Spawn();
@@ -369,6 +397,7 @@ class CBaseAnimating: public CBaseDelay {
float SetBoneController(int iController, float flValue = 0.0f);
void InitBoneControllers();
+ float GetSequenceDuration() const;
float SetBlending(int iBlender, float flValue);
void GetBonePosition(int iBone, Vector &origin, Vector &angles);
void GetAutomovement(Vector &origin, Vector &angles, float flInterval = 0.1f);
diff --git a/regamedll/dlls/client.cpp b/regamedll/dlls/client.cpp
index 0440308d5..2cf9dbd63 100644
--- a/regamedll/dlls/client.cpp
+++ b/regamedll/dlls/client.cpp
@@ -375,29 +375,13 @@ void EXT_FUNC ClientKill(edict_t *pEntity)
entvars_t *pev = &pEntity->v;
CBasePlayer *pPlayer = CBasePlayer::Instance(pev);
- if (pPlayer->GetObserverMode() != OBS_NONE)
- return;
-
- if (pPlayer->m_iJoiningState != JOINED)
- return;
-
// prevent suiciding too often
if (pPlayer->m_fNextSuicideTime > gpGlobals->time)
return;
- pPlayer->m_LastHitGroup = HITGROUP_GENERIC;
-
// don't let them suicide for 1 second after suiciding
pPlayer->m_fNextSuicideTime = gpGlobals->time + 1.0f;
-
- // have the player kill themself
- pEntity->v.health = 0;
- pPlayer->Killed(pev, GIB_NEVER);
-
- if (CSGameRules()->m_pVIP == pPlayer)
- {
- CSGameRules()->m_iConsecutiveVIP = 10;
- }
+ pPlayer->Kill();
}
LINK_HOOK_VOID_CHAIN(ShowMenu, (CBasePlayer *pPlayer, int bitsValidSlots, int nDisplayTime, BOOL fNeedMore, char *pszText), pPlayer, bitsValidSlots, nDisplayTime, fNeedMore, pszText)
@@ -637,6 +621,9 @@ void EXT_FUNC ClientPutInServer(edict_t *pEntity)
return;
}
+#ifdef REGAMEDLL_FIXES
+ pPlayer->m_bHasDefuser = false;
+#endif
pPlayer->m_bNotKilled = true;
pPlayer->m_iIgnoreGlobalChat = IGNOREMSG_NONE;
pPlayer->m_iTeamKills = 0;
@@ -686,10 +673,12 @@ void EXT_FUNC ClientPutInServer(edict_t *pEntity)
CBaseEntity *pTarget = nullptr;
pPlayer->m_pIntroCamera = UTIL_FindEntityByClassname(nullptr, "trigger_camera");
+#ifndef REGAMEDLL_FIXES
if (g_pGameRules && g_pGameRules->IsMultiplayer())
{
CSGameRules()->m_bMapHasCameras = (pPlayer->m_pIntroCamera != nullptr);
}
+#endif
if (pPlayer->m_pIntroCamera)
{
@@ -707,7 +696,12 @@ void EXT_FUNC ClientPutInServer(edict_t *pEntity)
pPlayer->pev->angles = CamAngles;
pPlayer->pev->v_angle = pPlayer->pev->angles;
- pPlayer->m_fIntroCamTime = gpGlobals->time + 6;
+ pPlayer->m_fIntroCamTime =
+#ifdef REGAMEDLL_FIXES
+ (CSGameRules()->m_bMapHasCameras <= 1) ? 0.0 : // no need to refresh cameras if map has only one
+#endif
+ gpGlobals->time + 6;
+
pPlayer->pev->view_ofs = g_vecZero;
}
#ifndef REGAMEDLL_FIXES
@@ -743,7 +737,7 @@ void EXT_FUNC ClientPutInServer(edict_t *pEntity)
}
#ifdef REGAMEDLL_API
- pPlayer->CSPlayer()->Reset();
+ pPlayer->CSPlayer()->OnConnect();
#endif
UTIL_ClientPrintAll(HUD_PRINTNOTIFY, "#Game_connected", (sName[0] != '\0') ? sName : "");
@@ -1210,7 +1204,9 @@ void BuyMachineGun(CBasePlayer *pPlayer, int iSlot)
BuyWeaponByWeaponID(pPlayer, WEAPON_M249);
}
-void BuyItem(CBasePlayer *pPlayer, int iSlot)
+LINK_HOOK_VOID_CHAIN(BuyItem, (CBasePlayer *pPlayer, int iSlot), pPlayer, iSlot)
+
+void EXT_FUNC __API_HOOK(BuyItem)(CBasePlayer *pPlayer, int iSlot)
{
int iItemPrice = 0;
const char *pszItem = nullptr;
@@ -1451,28 +1447,13 @@ void BuyItem(CBasePlayer *pPlayer, int iSlot)
if (pPlayer->m_iAccount >= DEFUSEKIT_PRICE)
{
bEnoughMoney = true;
- pPlayer->m_bHasDefuser = true;
-
- MESSAGE_BEGIN(MSG_ONE, gmsgStatusIcon, nullptr, pPlayer->pev);
- WRITE_BYTE(STATUSICON_SHOW);
- WRITE_STRING("defuser");
- WRITE_BYTE(0);
- WRITE_BYTE(160);
- WRITE_BYTE(0);
- MESSAGE_END();
-
- pPlayer->pev->body = 1;
+ pPlayer->GiveDefuser();
pPlayer->AddAccount(-DEFUSEKIT_PRICE, RT_PLAYER_BOUGHT_SOMETHING);
#ifdef REGAMEDLL_FIXES
EMIT_SOUND(ENT(pPlayer->pev), CHAN_VOICE, "items/kevlar.wav", VOL_NORM, ATTN_NORM);
#else
EMIT_SOUND(ENT(pPlayer->pev), CHAN_ITEM, "items/kevlar.wav", VOL_NORM, ATTN_NORM);
-#endif
- pPlayer->SendItemStatus();
-
-#ifdef BUILD_LATEST
- pPlayer->SetScoreboardAttributes();
#endif
}
break;
@@ -1490,7 +1471,6 @@ void BuyItem(CBasePlayer *pPlayer, int iSlot)
if (pPlayer->m_iAccount >= SHIELDGUN_PRICE)
{
bEnoughMoney = true;
-
pPlayer->DropPrimary();
pPlayer->GiveShield();
pPlayer->AddAccount(-SHIELDGUN_PRICE, RT_PLAYER_BOUGHT_SOMETHING);
@@ -1774,6 +1754,9 @@ BOOL EXT_FUNC __API_HOOK(HandleMenu_ChooseTeam)(CBasePlayer *pPlayer, int slot)
}
TeamName team = UNASSIGNED;
+#ifdef REGAMEDLL_FIXES
+ bool bAddFrags = false;
+#endif
switch (slot)
{
@@ -1856,10 +1839,15 @@ BOOL EXT_FUNC __API_HOOK(HandleMenu_ChooseTeam)(CBasePlayer *pPlayer, int slot)
{
if (pPlayer->m_iTeam != UNASSIGNED && pPlayer->pev->deadflag == DEAD_NO)
{
- ClientKill(pPlayer->edict());
-
- // add 1 to frags to balance out the 1 subtracted for killing yourself
- pPlayer->pev->frags++;
+ if (pPlayer->Kill())
+ {
+ // add 1 to frags to balance out the 1 subtracted for killing yourself
+#ifdef REGAMEDLL_FIXES
+ bAddFrags = true;
+#else
+ pPlayer->pev->frags++;
+#endif
+ }
}
pPlayer->RemoveAllItems(TRUE);
@@ -1895,15 +1883,15 @@ BOOL EXT_FUNC __API_HOOK(HandleMenu_ChooseTeam)(CBasePlayer *pPlayer, int slot)
#ifndef REGAMEDLL_FIXES
MESSAGE_BEGIN(MSG_BROADCAST, gmsgScoreInfo);
-#else
- MESSAGE_BEGIN(MSG_ALL, gmsgScoreInfo);
-#endif
WRITE_BYTE(ENTINDEX(pPlayer->edict()));
WRITE_SHORT(int(pPlayer->pev->frags));
WRITE_SHORT(pPlayer->m_iDeaths);
WRITE_SHORT(0);
WRITE_SHORT(0);
MESSAGE_END();
+#else
+ pPlayer->AddPoints(bAddFrags, TRUE);
+#endif
pPlayer->m_pIntroCamera = nullptr;
pPlayer->m_bTeamChanged = true;
@@ -1926,7 +1914,7 @@ BOOL EXT_FUNC __API_HOOK(HandleMenu_ChooseTeam)(CBasePlayer *pPlayer, int slot)
MESSAGE_END();
#endif
// do we have fadetoblack on? (need to fade their screen back in)
- if (fadetoblack.value)
+ if (fadetoblack.value == FADETOBLACK_STAY)
{
UTIL_ScreenFade(pPlayer, Vector(0, 0, 0), 0.001, 0, 0, FFADE_IN);
}
@@ -2087,10 +2075,10 @@ BOOL EXT_FUNC __API_HOOK(HandleMenu_ChooseTeam)(CBasePlayer *pPlayer, int slot)
pPlayer->m_iMenu = Menu_ChooseAppearance;
// Show the appropriate Choose Appearance menu
- // This must come before ClientKill() for CheckWinConditions() to function properly
+ // This must come before pPlayer->Kill() for CheckWinConditions() to function properly
if (pPlayer->pev->deadflag == DEAD_NO)
{
- ClientKill(pPlayer->edict());
+ pPlayer->Kill();
}
}
@@ -2277,7 +2265,7 @@ bool EXT_FUNC __API_HOOK(BuyGunAmmo)(CBasePlayer *pPlayer, CBasePlayerItem *weap
if (pPlayer->m_iAccount >= info->clipCost)
{
#ifdef REGAMEDLL_FIXES
- if (pPlayer->GiveAmmo(info->buyClipSize, info->ammoName2, weapon->iMaxAmmo1()) == -1)
+ if (pPlayer->GiveAmmo(info->buyClipSize, weapon->pszAmmo1(), weapon->iMaxAmmo1()) == -1)
return false;
EMIT_SOUND(ENT(weapon->pev), CHAN_ITEM, "items/9mmclip1.wav", VOL_NORM, ATTN_NORM);
@@ -4840,6 +4828,16 @@ int EXT_FUNC GetWeaponData(edict_t *pEdict, struct weapon_data_s *info)
item->fuser2 = weapon->m_flStartThrow;
item->fuser3 = weapon->m_flReleaseThrow;
item->iuser1 = weapon->m_iSwing;
+
+#ifdef REGAMEDLL_FIXES
+ if (pPlayerItem == pPlayer->m_pActiveItem && !weapon->m_fInReload && weapon->m_iClip == II.iMaxClip)
+ {
+ const WeaponInfoStruct *wpnInfo = GetDefaultWeaponInfo(II.iId);
+
+ if (wpnInfo && wpnInfo->gunClipSize != II.iMaxClip)
+ item->m_iClip = wpnInfo->gunClipSize;
+ }
+#endif
}
}
@@ -4872,7 +4870,12 @@ void EXT_FUNC UpdateClientData(const edict_t *ent, int sendweapons, struct clien
}
cd->flags = pev->flags;
+#ifdef REGAMEDLL_FIXES
+ cd->health = max(pev->health, 0.0f);
+#else
cd->health = pev->health;
+#endif
+
cd->viewmodel = MODEL_INDEX(STRING(pev->viewmodel));
cd->waterlevel = pev->waterlevel;
cd->watertype = pev->watertype;
diff --git a/regamedll/dlls/client.h b/regamedll/dlls/client.h
index ee98ddbca..68586b2a4 100644
--- a/regamedll/dlls/client.h
+++ b/regamedll/dlls/client.h
@@ -119,6 +119,7 @@ extern unsigned short g_iShadowSprite;
void HandleMenu_ChooseAppearance_OrigFunc(CBasePlayer *pPlayer, int slot);
BOOL HandleMenu_ChooseTeam_OrigFunc(CBasePlayer *pPlayer, int slot);
bool BuyGunAmmo_OrigFunc(CBasePlayer *pPlayer, CBasePlayerItem *weapon, bool bBlinkMoney);
+void BuyItem_OrigFunc(CBasePlayer *pPlayer, int iSlot);
CBaseEntity *BuyWeaponByWeaponID_OrigFunc(CBasePlayer *pPlayer, WeaponIdType weaponID);
void ShowMenu_OrigFunc(CBasePlayer *pPlayer, int bitsValidSlots, int nDisplayTime, BOOL fNeedMore, char *pszText);
void ShowVGUIMenu_OrigFunc(CBasePlayer *pPlayer, int MenuType, int BitMask, char *szOldMenu);
diff --git a/regamedll/dlls/combat.cpp b/regamedll/dlls/combat.cpp
index f5ec1ce15..4cbc485dc 100644
--- a/regamedll/dlls/combat.cpp
+++ b/regamedll/dlls/combat.cpp
@@ -4,7 +4,7 @@ void PlayerBlind(CBasePlayer *pPlayer, entvars_t *pevInflictor, entvars_t *pevAt
{
UTIL_ScreenFade(pPlayer, color, fadeTime, fadeHold, alpha, 0);
- if (!fadetoblack.value)
+ if (fadetoblack.value != FADETOBLACK_STAY)
{
for (int i = 1; i <= gpGlobals->maxClients; i++)
{
@@ -16,16 +16,30 @@ void PlayerBlind(CBasePlayer *pPlayer, entvars_t *pevInflictor, entvars_t *pevAt
}
}
- pPlayer->Blind(fadeTime * 0.33, fadeHold, fadeTime, alpha);
+ float flDurationTime = fadeTime * 0.33;
+ pPlayer->Blind(flDurationTime, fadeHold, fadeTime, alpha);
if (TheBots)
{
TheBots->OnEvent(EVENT_PLAYER_BLINDED_BY_FLASHBANG, pPlayer);
}
+
+#if defined(REGAMEDLL_API) && defined(REGAMEDLL_ADD)
+ float flAdjustedDamage;
+ if (alpha > 200)
+ flAdjustedDamage = fadeTime / 3;
+ else
+ flAdjustedDamage = fadeTime / 1.75;
+
+ pPlayer->CSPlayer()->RecordDamage(CBasePlayer::Instance(pevAttacker), flAdjustedDamage * 16.0f, flDurationTime);
+#endif
}
void RadiusFlash_TraceLine_hook(CBasePlayer *pPlayer, entvars_t *pevInflictor, entvars_t *pevAttacker, Vector &vecSrc, Vector &vecSpot, TraceResult *tr)
{
+#ifdef REGAMEDLL_ADD
+ gpGlobals->trace_flags = FTRACE_FLASH;
+#endif
UTIL_TraceLine(vecSrc, vecSpot, dont_ignore_monsters, ENT(pevInflictor), tr);
}
@@ -87,6 +101,19 @@ void RadiusFlash(Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker,
if (tr2.flFraction >= 1.0)
{
+#ifdef REGAMEDLL_ADD
+ switch ((int)teamflash.value)
+ {
+ case 0:
+ if (pPlayer->pev != pevAttacker && g_pGameRules->PlayerRelationship(pPlayer, CBaseEntity::Instance(pevAttacker)) == GR_TEAMMATE)
+ continue;
+ break;
+ case -1:
+ if (pPlayer->pev == pevAttacker || g_pGameRules->PlayerRelationship(pPlayer, CBaseEntity::Instance(pevAttacker)) == GR_TEAMMATE)
+ continue;
+ break;
+ }
+#endif
if (tr.fStartSolid)
{
tr.vecEndPos = vecSrc;
@@ -94,7 +121,6 @@ void RadiusFlash(Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker,
}
flAdjustedDamage = flDamage - (vecSrc - tr.vecEndPos).Length() * falloff;
-
if (flAdjustedDamage < 0)
flAdjustedDamage = 0;
@@ -287,6 +313,8 @@ void RadiusDamage(Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker
if (tr.flFraction != 1.0f)
flAdjustedDamage = 0.0f;
+ else
+ pEntity->SetDmgPenetrationLevel(1);
}
#endif
}
diff --git a/regamedll/dlls/doors.cpp b/regamedll/dlls/doors.cpp
index c16fe0083..ada7e6a82 100644
--- a/regamedll/dlls/doors.cpp
+++ b/regamedll/dlls/doors.cpp
@@ -215,7 +215,7 @@ void CBaseDoor::Spawn()
// Subtract 2 from size because the engine expands bboxes by 1 in all directions making the size too big
m_vecPosition2 = m_vecPosition1 + (pev->movedir * (Q_fabs(real_t(pev->movedir.x * (pev->size.x - 2))) + Q_fabs(real_t(pev->movedir.y * (pev->size.y - 2))) + Q_fabs(real_t(pev->movedir.z * (pev->size.z - 2))) - m_flLip));
- assert(("door start/end positions are equal", m_vecPosition1 != m_vecPosition2));
+ DbgAssertMsg(m_vecPosition1 != m_vecPosition2, "door start/end positions are equal");
if (pev->spawnflags & SF_DOOR_START_OPEN)
{
@@ -494,7 +494,7 @@ void CBaseDoor::DoorGoUp()
bool isReversing = (m_toggle_state == TS_GOING_DOWN);
// It could be going-down, if blocked.
- assert(m_toggle_state == TS_AT_BOTTOM || m_toggle_state == TS_GOING_DOWN);
+ DbgAssert(m_toggle_state == TS_AT_BOTTOM || m_toggle_state == TS_GOING_DOWN);
// emit door moving and stop sounds on CHAN_STATIC so that the multicast doesn't
// filter them out and leave a client stuck with looping door sounds!
@@ -634,7 +634,7 @@ void CBaseDoor::DoorHitTop()
EMIT_SOUND(ENT(pev), CHAN_STATIC, (char *)STRING(pev->noiseArrived), VOL_NORM, ATTN_NORM);
}
- assert(m_toggle_state == TS_GOING_UP);
+ DbgAssert(m_toggle_state == TS_GOING_UP);
m_toggle_state = TS_AT_TOP;
// toggle-doors don't come down automatically, they wait for refire.
@@ -696,7 +696,7 @@ void CBaseDoor::DoorGoDown()
}
#ifdef DOOR_ASSERT
- assert(m_toggle_state == TS_AT_TOP);
+ DbgAssert(m_toggle_state == TS_AT_TOP);
#endif
m_toggle_state = TS_GOING_DOWN;
@@ -724,7 +724,7 @@ void CBaseDoor::DoorHitBottom()
EMIT_SOUND(ENT(pev), CHAN_STATIC, (char *)STRING(pev->noiseArrived), VOL_NORM, ATTN_NORM);
}
- assert(m_toggle_state == TS_GOING_DOWN);
+ DbgAssert(m_toggle_state == TS_GOING_DOWN);
m_toggle_state = TS_AT_BOTTOM;
// Re-instate touch method, cycle is complete
@@ -927,7 +927,7 @@ void CRotDoor::Spawn()
m_vecAngle1 = pev->angles;
m_vecAngle2 = pev->angles + pev->movedir * m_flMoveDistance;
- assert(("rotating door start/end positions are equal", m_vecAngle1 != m_vecAngle2));
+ DbgAssertMsg(m_vecAngle1 != m_vecAngle2, "rotating door start/end positions are equal");
if (pev->spawnflags & SF_DOOR_PASSABLE)
pev->solid = SOLID_NOT;
@@ -1011,7 +1011,7 @@ void CMomentaryDoor::Spawn()
// Subtract 2 from size because the engine expands bboxes by 1 in all directions making the size too big
m_vecPosition2 = m_vecPosition1 + (pev->movedir * (Q_fabs(real_t(pev->movedir.x * (pev->size.x - 2))) + Q_fabs(real_t(pev->movedir.y * (pev->size.y - 2))) + Q_fabs(real_t(pev->movedir.z * (pev->size.z - 2))) - m_flLip));
- assert(("door start/end positions are equal", m_vecPosition1 != m_vecPosition2));
+ DbgAssertMsg(m_vecPosition1 != m_vecPosition2, "door start/end positions are equal");
if (pev->spawnflags & SF_DOOR_START_OPEN)
{
diff --git a/regamedll/dlls/effects.cpp b/regamedll/dlls/effects.cpp
index 16cc2e6ab..f934edd4b 100644
--- a/regamedll/dlls/effects.cpp
+++ b/regamedll/dlls/effects.cpp
@@ -1737,10 +1737,12 @@ Vector CBlood::BloodPosition(CBaseEntity *pActivator)
void CBlood::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value)
{
+ const Vector direction = Direction();
+
if (pev->spawnflags & SF_BLOOD_STREAM)
- UTIL_BloodStream(BloodPosition(pActivator), Direction(), (Color() == BLOOD_COLOR_RED) ? 70 : Color(), int(BloodAmount()));
+ UTIL_BloodStream(BloodPosition(pActivator), direction, (Color() == BLOOD_COLOR_RED) ? 70 : Color(), int(BloodAmount()));
else
- UTIL_BloodDrips(BloodPosition(pActivator), Direction(), Color(), int(BloodAmount()));
+ UTIL_BloodDrips(BloodPosition(pActivator), Color(), int(BloodAmount()));
if (pev->spawnflags & SF_BLOOD_DECAL)
{
diff --git a/regamedll/dlls/ehandle.h b/regamedll/dlls/ehandle.h
index 66897fbbe..9a8717826 100644
--- a/regamedll/dlls/ehandle.h
+++ b/regamedll/dlls/ehandle.h
@@ -176,7 +176,7 @@ inline int EntityHandle::GetSerialNumber() const
template
inline bool EntityHandle::operator==(T *pEntity) const
{
- assert(("EntityHandle::operator==: got a nullptr pointer!", pEntity != nullptr));
+ DbgAssertMsg(pEntity != nullptr, "EntityHandle::operator==: got a nullptr pointer!");
if (m_serialnumber != pEntity->edict()->serialnumber)
{
@@ -221,10 +221,10 @@ template
inline T *EntityHandle::operator->()
{
edict_t *pEdict = Get();
- assert(("EntityHandle::operator->: pointer is nullptr!", pEdict != nullptr));
+ DbgAssertMsg(pEdict != nullptr, "EntityHandle::operator->: pointer is nullptr!");
T *pEntity = GET_PRIVATE(pEdict);
- assert(("EntityHandle::operator->: pvPrivateData is nullptr!", pEntity != nullptr));
+ DbgAssertMsg(pEntity != nullptr, "EntityHandle::operator->: pvPrivateData is nullptr!");
return pEntity;
}
diff --git a/regamedll/dlls/func_tank.cpp b/regamedll/dlls/func_tank.cpp
index 1ca0e966e..e12c90768 100644
--- a/regamedll/dlls/func_tank.cpp
+++ b/regamedll/dlls/func_tank.cpp
@@ -297,11 +297,11 @@ void CFuncTank::StopControl()
void CFuncTank::ControllerPostFrame()
{
- assert(m_pController != nullptr);
-
if (gpGlobals->time < m_flNextAttack)
return;
+ Assert(m_pController != nullptr);
+
if (m_pController->pev->button & IN_ATTACK)
{
Vector vecForward;
@@ -879,7 +879,7 @@ void CFuncTankControls::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_T
}
// if this fails, most likely means save/restore hasn't worked properly
- assert(m_pTank != nullptr);
+ DbgAssert(m_pTank != nullptr);
}
void CFuncTankControls::Think()
diff --git a/regamedll/dlls/game.cpp b/regamedll/dlls/game.cpp
index fdfd26184..9b3e2f7b2 100644
--- a/regamedll/dlls/game.cpp
+++ b/regamedll/dlls/game.cpp
@@ -9,6 +9,7 @@ cvar_t *g_psv_friction = nullptr;
cvar_t *g_psv_stopspeed = nullptr;
cvar_t *g_psv_stepsize = nullptr;
cvar_t *g_psv_clienttrace = nullptr;
+cvar_t *g_psv_maxvelocity = nullptr;
cvar_t displaysoundlist = { "displaysoundlist", "0", 0, 0.0f, nullptr };
cvar_t timelimit = { "mp_timelimit", "0", FCVAR_SERVER, 0.0f, nullptr };
@@ -109,6 +110,8 @@ cvar_t maxmoney = { "mp_maxmoney", "16000", FCVAR_SERVER, 0.0f, nul
cvar_t round_infinite = { "mp_round_infinite", "0", FCVAR_SERVER, 0.0f, nullptr };
cvar_t hegrenade_penetration = { "mp_hegrenade_penetration", "0", 0, 0.0f, nullptr };
cvar_t nadedrops = { "mp_nadedrops", "0", 0, 0.0f, nullptr };
+cvar_t weapondrop = { "mp_weapondrop", "1", 0, 1.0f, nullptr };
+cvar_t ammodrop = { "mp_ammodrop", "1", 0, 1.0f, nullptr };
cvar_t roundrespawn_time = { "mp_roundrespawn_time", "20", 0, 20.0f, nullptr };
cvar_t auto_reload_weapons = { "mp_auto_reload_weapons", "0", 0, 0.0f, nullptr };
cvar_t refill_bpammo_weapons = { "mp_refill_bpammo_weapons", "0", 0, 0.0f, nullptr }; // Useful for mods like DeathMatch, GunGame, ZombieMod etc
@@ -158,11 +161,16 @@ cvar_t t_give_player_knife = { "mp_t_give_player_knife", "1", 0, 1
cvar_t t_default_weapons_secondary = { "mp_t_default_weapons_secondary", "glock18", 0, 0.0f, nullptr };
cvar_t t_default_weapons_primary = { "mp_t_default_weapons_primary", "", 0, 0.0f, nullptr };
cvar_t free_armor = { "mp_free_armor", "0", 0, 0.0f, nullptr };
+cvar_t teamflash = { "mp_team_flash", "1", 0, 1.0f, nullptr };
cvar_t allchat = { "sv_allchat", "0", 0, 0.0f, nullptr };
cvar_t sv_autobunnyhopping = { "sv_autobunnyhopping", "0", 0, 0.0f, nullptr };
cvar_t sv_enablebunnyhopping = { "sv_enablebunnyhopping", "0", 0, 0.0f, nullptr };
cvar_t plant_c4_anywhere = { "mp_plant_c4_anywhere", "0", 0, 0.0f, nullptr };
cvar_t give_c4_frags = { "mp_give_c4_frags", "3", 0, 3.0f, nullptr };
+cvar_t deathmsg_flags = { "mp_deathmsg_flags", "abc", 0, 0.0f, nullptr };
+cvar_t assist_damage_threshold = { "mp_assist_damage_threshold", "40", 0, 40.0f, nullptr };
+cvar_t freezetime_duck = { "mp_freezetime_duck", "1", 0, 1.0f, nullptr };
+cvar_t freezetime_jump = { "mp_freezetime_jump", "1", 0, 1.0f, nullptr };
cvar_t hostages_rescued_ratio = { "mp_hostages_rescued_ratio", "1.0", 0, 1.0f, nullptr };
cvar_t legacy_vehicle_block = { "mp_legacy_vehicle_block", "1", 0, 0.0f, nullptr };
@@ -170,6 +178,10 @@ cvar_t max_alive_name_changes = { "mp_max_alive_name_changes", "-1",
cvar_t legacy_restart_entities = { "sv_legacy_restart_entities", "0", 0, 0.0f, nullptr };
cvar_t sv_block_vote_commands = { "sv_block_vote_commands", "0", 0, 0.0f, nullptr };
+cvar_t legacy_vehicle_block = { "mp_legacy_vehicle_block", "1", 0, 0.0f, nullptr };
+
+cvar_t dying_time = { "mp_dying_time", "3.0", 0, 3.0f, nullptr };
+
void GameDLL_Version_f()
{
if (Q_stricmp(CMD_ARGV(1), "version") != 0)
@@ -220,8 +232,13 @@ void GameDLL_SwapTeams_f()
#endif // REGAMEDLL_ADD
+SpewRetval_t GameDLL_SpewHandler(SpewType_t spewType, int level, const char *pMsg);
+
void EXT_FUNC GameDLLInit()
{
+ // By default, direct dbg reporting...
+ SpewOutputFunc(GameDLL_SpewHandler);
+
g_pskill = CVAR_GET_POINTER("skill");
g_psv_gravity = CVAR_GET_POINTER("sv_gravity");
g_psv_aim = CVAR_GET_POINTER("sv_aim");
@@ -231,6 +248,7 @@ void EXT_FUNC GameDLLInit()
g_psv_stopspeed = CVAR_GET_POINTER("sv_stopspeed");
g_psv_stepsize = CVAR_GET_POINTER("sv_stepsize");
g_psv_clienttrace = CVAR_GET_POINTER("sv_clienttrace");
+ g_psv_maxvelocity = CVAR_GET_POINTER("sv_maxvelocity");
CVAR_REGISTER(&displaysoundlist);
CVAR_REGISTER(&timelimit);
@@ -353,6 +371,8 @@ void EXT_FUNC GameDLLInit()
CVAR_REGISTER(&round_infinite);
CVAR_REGISTER(&hegrenade_penetration);
CVAR_REGISTER(&nadedrops);
+ CVAR_REGISTER(&weapondrop);
+ CVAR_REGISTER(&ammodrop);
CVAR_REGISTER(&roundrespawn_time);
CVAR_REGISTER(&auto_reload_weapons);
CVAR_REGISTER(&refill_bpammo_weapons);
@@ -406,6 +426,7 @@ void EXT_FUNC GameDLLInit()
CVAR_REGISTER(&t_default_weapons_secondary);
CVAR_REGISTER(&t_default_weapons_primary);
CVAR_REGISTER(&free_armor);
+ CVAR_REGISTER(&teamflash);
CVAR_REGISTER(&allchat);
CVAR_REGISTER(&sv_autobunnyhopping);
CVAR_REGISTER(&sv_enablebunnyhopping);
@@ -414,6 +435,13 @@ void EXT_FUNC GameDLLInit()
CVAR_REGISTER(&hostages_rescued_ratio);
CVAR_REGISTER(&legacy_vehicle_block);
+ CVAR_REGISTER(&dying_time);
+ CVAR_REGISTER(&deathmsg_flags);
+ CVAR_REGISTER(&assist_damage_threshold);
+
+ CVAR_REGISTER(&freezetime_duck);
+ CVAR_REGISTER(&freezetime_jump);
+
CVAR_REGISTER(&max_alive_name_changes);
CVAR_REGISTER(&legacy_restart_entities);
CVAR_REGISTER(&sv_block_vote_commands);
@@ -438,3 +466,28 @@ void EXT_FUNC GameDLLInit()
#endif
}
+
+SpewRetval_t GameDLL_SpewHandler(SpewType_t spewType, int level, const char *pMsg)
+{
+ bool bSpewPrint = (CVAR_GET_FLOAT("developer") >= level);
+ switch (spewType)
+ {
+ case SPEW_LOG:
+ case SPEW_MESSAGE:
+ if (bSpewPrint) UTIL_ServerPrint("%s", pMsg);
+ break;
+ case SPEW_WARNING:
+ if (bSpewPrint) UTIL_ServerPrint("Warning: %s", pMsg);
+ break;
+ case SPEW_ERROR:
+ Sys_Error("%s", pMsg);
+ return SPEW_ABORT; // fatal error, terminate it!
+ case SPEW_ASSERT:
+ UTIL_ServerPrint("Assert: %s", pMsg);
+ return SPEW_DEBUGGER; // assert always tries to debugger break
+ default:
+ break;
+ }
+
+ return SPEW_CONTINUE; // spew handled, continue on
+}
diff --git a/regamedll/dlls/game.h b/regamedll/dlls/game.h
index d1894aa2a..270ee8019 100644
--- a/regamedll/dlls/game.h
+++ b/regamedll/dlls/game.h
@@ -43,12 +43,13 @@
extern cvar_t *g_pskill;
extern cvar_t *g_psv_gravity;
extern cvar_t *g_psv_aim;
+extern cvar_t *g_footsteps;
extern cvar_t *g_psv_accelerate;
extern cvar_t *g_psv_friction;
extern cvar_t *g_psv_stopspeed;
extern cvar_t *g_psv_stepsize;
extern cvar_t *g_psv_clienttrace;
-extern cvar_t *g_footsteps;
+extern cvar_t *g_psv_maxvelocity;
extern cvar_t displaysoundlist;
extern cvar_t timelimit;
@@ -138,6 +139,8 @@ extern cvar_t maxmoney;
extern cvar_t round_infinite;
extern cvar_t hegrenade_penetration;
extern cvar_t nadedrops;
+extern cvar_t weapondrop;
+extern cvar_t ammodrop;
extern cvar_t roundrespawn_time;
extern cvar_t auto_reload_weapons;
extern cvar_t refill_bpammo_weapons;
@@ -184,6 +187,7 @@ extern cvar_t t_give_player_knife;
extern cvar_t t_default_weapons_secondary;
extern cvar_t t_default_weapons_primary;
extern cvar_t free_armor;
+extern cvar_t teamflash;
extern cvar_t allchat;
extern cvar_t sv_autobunnyhopping;
extern cvar_t sv_enablebunnyhopping;
@@ -191,6 +195,11 @@ extern cvar_t plant_c4_anywhere;
extern cvar_t give_c4_frags;
extern cvar_t hostages_rescued_ratio;
extern cvar_t legacy_vehicle_block;
+extern cvar_t dying_time;
+extern cvar_t deathmsg_flags;
+extern cvar_t assist_damage_threshold;
+extern cvar_t freezetime_duck;
+extern cvar_t freezetime_jump;
extern cvar_t max_alive_name_changes;
extern cvar_t legacy_restart_entities;
diff --git a/regamedll/dlls/gamerules.cpp b/regamedll/dlls/gamerules.cpp
index d31e6b565..45210e212 100644
--- a/regamedll/dlls/gamerules.cpp
+++ b/regamedll/dlls/gamerules.cpp
@@ -141,3 +141,13 @@ CGameRules *EXT_FUNC __API_HOOK(InstallGameRules)()
return new CHalfLifeMultiplay;
}
+
+LINK_HOOK_VOID_CHAIN(FreeGameRules, (CGameRules **pGameRules), pGameRules)
+
+void EXT_FUNC __API_HOOK(FreeGameRules)(CGameRules **pGameRules)
+{
+ if (!pGameRules || !(*pGameRules))
+ return;
+
+ delete (*pGameRules);
+}
diff --git a/regamedll/dlls/gamerules.h b/regamedll/dlls/gamerules.h
index ed0111a50..e29aaba88 100644
--- a/regamedll/dlls/gamerules.h
+++ b/regamedll/dlls/gamerules.h
@@ -46,6 +46,7 @@ const float ROUND_RESPAWN_TIME = 20.0f;
const float ROUND_BEGIN_DELAY = 5.0f; // delay before beginning new round
const float ITEM_KILL_DELAY = 300.0f;
const float RADIO_TIMEOUT = 1.5f;
+const float DEATH_ANIMATION_TIME = 3.0f;
const int MAX_INTERMISSION_TIME = 120; // longest the intermission can last, in seconds
@@ -186,6 +187,10 @@ enum
GR_PLR_DROP_AMMO_ALL,
GR_PLR_DROP_AMMO_ACTIVE,
GR_PLR_DROP_AMMO_NO,
+
+#ifdef REGAMEDLL_ADD
+ GR_PLR_DROP_GUN_BEST,
+#endif
};
// custom enum
@@ -202,7 +207,7 @@ enum
SCENARIO_BLOCK_PRISON_ESCAPE_TIME = BIT(8), // flag "i"
SCENARIO_BLOCK_BOMB_TIME = BIT(9), // flag "j"
SCENARIO_BLOCK_HOSTAGE_RESCUE_TIME = BIT(10), // flag "k"
-
+
};
// Player relationship return codes
@@ -215,6 +220,41 @@ enum
GR_NEUTRAL,
};
+// The number of times you must kill a given player to be dominating them
+// Should always be more than 1
+const int CS_KILLS_FOR_DOMINATION = 4;
+
+// Flags for specifying extra info about player death
+enum DeathMessageFlags
+{
+ // float[3]
+ // Position where the victim was killed by the enemy
+ PLAYERDEATH_POSITION = 0x001,
+
+ // byte
+ // Index of the assistant who helped the attacker kill the victim
+ PLAYERDEATH_ASSISTANT = 0x002,
+
+ // short
+ // Bitsum classification for the rarity of the kill
+ // See enum KillRarity for details
+ PLAYERDEATH_KILLRARITY = 0x004
+};
+
+// Classifying various player kill methods in the game
+enum KillRarity
+{
+ KILLRARITY_HEADSHOT = 0x001, // Headshot
+ KILLRARITY_KILLER_BLIND = 0x002, // Killer was blind
+ KILLRARITY_NOSCOPE = 0x004, // No-scope sniper rifle kill
+ KILLRARITY_PENETRATED = 0x008, // Penetrated kill (through walls)
+ KILLRARITY_THRUSMOKE = 0x010, // Smoke grenade penetration kill (bullets went through smoke)
+ KILLRARITY_ASSISTEDFLASH = 0x020, // Assister helped with a flash
+ KILLRARITY_DOMINATION_BEGAN = 0x040, // Killer player began dominating the victim (NOTE: this flag is set once)
+ KILLRARITY_DOMINATION = 0x080, // Continues domination by the killer
+ KILLRARITY_REVENGE = 0x100 // Revenge by the killer
+};
+
class CItem;
class CGameRules
@@ -332,6 +372,7 @@ class CGameRules
inline void SetGameOver() { m_bGameOver = true; }
static float GetItemKillDelay();
static float GetRadioTimeout();
+ static float GetDyingTime();
public:
BOOL m_bFreezePeriod; // TRUE at beginning of round, set to FALSE when the period expires
@@ -537,7 +578,7 @@ class CHalfLifeMultiplay: public CGameRules
// check if the scenario has been won/lost
virtual void CheckWinConditions();
virtual void RemoveGuns();
- virtual void GiveC4();
+ virtual CBasePlayer *GiveC4();
virtual void ChangeLevel();
virtual void GoToIntermission();
@@ -560,10 +601,15 @@ class CHalfLifeMultiplay: public CGameRules
void RestartRound_OrigFunc();
void CheckWinConditions_OrigFunc();
void RemoveGuns_OrigFunc();
- void GiveC4_OrigFunc();
+ CBasePlayer *GiveC4_OrigFunc();
void ChangeLevel_OrigFunc();
void GoToIntermission_OrigFunc();
void BalanceTeams_OrigFunc();
+ void Think_OrigFunc();
+ BOOL TeamFull_OrigFunc(int team_id);
+ BOOL TeamStacked_OrigFunc(int newTeam_id, int curTeam_id);
+ void PlayerGotWeapon_OrigFunc(CBasePlayer *pPlayer, CBasePlayerItem *pWeapon);
+ void SendDeathMessage_OrigFunc(CBaseEntity *pKiller, CBasePlayer *pVictim, CBasePlayer *pAssister, entvars_t *pevInflictor, const char *killerWeaponName, int iDeathMessageFlags, int iRarityOfKill);
#endif
public:
@@ -688,6 +734,10 @@ class CHalfLifeMultiplay: public CGameRules
VFUNC bool HasRoundTimeExpired();
VFUNC bool IsBombPlanted();
+ void SendDeathMessage(CBaseEntity *pKiller, CBasePlayer *pVictim, CBasePlayer *pAssister, entvars_t *pevInflictor, const char *killerWeaponName, int iDeathMessageFlags, int iRarityOfKill);
+ int GetRarityOfKill(CBaseEntity *pKiller, CBasePlayer *pVictim, CBasePlayer *pAssister, const char *killerWeaponName, bool bFlashAssist);
+ CBasePlayer *CheckAssistsToKill(CBaseEntity *pKiller, CBasePlayer *pVictim, bool &bFlashAssist);
+
private:
void MarkLivingPlayersOnTeamAsNotReceivingMoneyNextRound(int iTeam);
@@ -729,7 +779,7 @@ class CHalfLifeMultiplay: public CGameRules
bool m_bMapHasEscapeZone;
BOOL m_bMapHasVIPSafetyZone; // TRUE = has VIP safety zone, FALSE = does not have VIP safetyzone
- BOOL m_bMapHasCameras;
+ int m_bMapHasCameras;
int m_iC4Timer;
int m_iC4Guy; // The current Terrorist who has the C4.
int m_iLoserBonus; // the amount of money the losing team gets. This scales up as they lose more rounds in a row
@@ -831,9 +881,11 @@ extern CGameRules DLLEXPORT *g_pGameRules;
#ifdef REGAMEDLL_API
CGameRules *InstallGameRules_OrigFunc();
+void FreeGameRules_OrigFunc(CGameRules **pGameRules);
#endif
CGameRules *InstallGameRules();
+void FreeGameRules(CGameRules **pGameRules);
// Gets us at the CS game rules
inline CHalfLifeMultiplay *CSGameRules()
@@ -915,6 +967,15 @@ inline float CGameRules::GetRadioTimeout()
#endif
}
+inline float CGameRules::GetDyingTime()
+{
+#ifdef REGAMEDLL_ADD
+ return dying_time.value;
+#else
+ return DEATH_ANIMATION_TIME;
+#endif
+}
+
bool IsBotSpeaking();
void SV_Continue_f();
void SV_Tutor_Toggle_f();
diff --git a/regamedll/dlls/ggrenade.cpp b/regamedll/dlls/ggrenade.cpp
index 48c52622c..f4b3e8809 100644
--- a/regamedll/dlls/ggrenade.cpp
+++ b/regamedll/dlls/ggrenade.cpp
@@ -600,9 +600,15 @@ void CGrenade::__API_HOOK(SG_Detonate)()
}
m_bDetonated = true;
- PLAYBACK_EVENT_FULL(0, nullptr, m_usEvent, 0, pev->origin, (float *)&g_vecZero, 0, 0, 0, 1, m_bLightSmoke, FALSE);
m_vSmokeDetonate = pev->origin;
+ int flags = 0;
+#ifdef REGAMEDLL_FIXES
+ flags = FEV_RELIABLE;
+#endif
+
+ PLAYBACK_EVENT_FULL(flags, nullptr, m_usEvent, 0, m_vSmokeDetonate, (float *)&g_vecZero, 0, 0, 0, 1, m_bLightSmoke, FALSE);
+
pev->velocity.x = RANDOM_FLOAT(-175, 175);
pev->velocity.y = RANDOM_FLOAT(-175, 175);
pev->velocity.z = RANDOM_FLOAT(250, 350);
@@ -766,6 +772,13 @@ void CGrenade::BounceSound()
void CGrenade::TumbleThink()
{
+#ifdef REGAMEDLL_FIXES
+ if (pev->velocity.IsLengthGreaterThan(g_psv_maxvelocity->value))
+ {
+ pev->velocity = pev->velocity.Normalize() * g_psv_maxvelocity->value;
+ }
+#endif
+
if (!IsInWorld())
{
UTIL_Remove(this);
@@ -803,6 +816,13 @@ void CGrenade::TumbleThink()
void CGrenade::SG_TumbleThink()
{
+#ifdef REGAMEDLL_FIXES
+ if (pev->velocity.IsLengthGreaterThan(g_psv_maxvelocity->value))
+ {
+ pev->velocity = pev->velocity.Normalize() * g_psv_maxvelocity->value;
+ }
+#endif
+
if (!IsInWorld())
{
UTIL_Remove(this);
@@ -1085,7 +1105,7 @@ void CGrenade::__API_HOOK(DefuseBombEnd)(CBasePlayer *pPlayer, bool bDefused)
CSGameRules()->CheckWinConditions();
#ifdef REGAMEDLL_ADD
- m_pBombDefuser->pev->frags += (int)give_c4_frags.value;
+ m_pBombDefuser->AddPoints((int)give_c4_frags.value, TRUE);
#else
// give the defuser credit for defusing the bomb
m_pBombDefuser->pev->frags += 3.0f;
@@ -1316,6 +1336,13 @@ void AnnounceFlashInterval(float interval, float offset)
void CGrenade::C4Think()
{
+#ifdef REGAMEDLL_FIXES
+ if (pev->velocity.IsLengthGreaterThan(g_psv_maxvelocity->value))
+ {
+ pev->velocity = pev->velocity.Normalize() * g_psv_maxvelocity->value;
+ }
+#endif
+
if (!IsInWorld())
{
#ifdef REGAMEDLL_FIXES
@@ -1440,7 +1467,7 @@ void CGrenade::C4Think()
if (pBombOwner)
{
#ifdef REGAMEDLL_ADD
- pBombOwner->pev->frags += (int)give_c4_frags.value;
+ pBombOwner->AddPoints((int)give_c4_frags.value, TRUE);
#else
pBombOwner->pev->frags += 3.0f;
#endif
diff --git a/regamedll/dlls/gib.cpp b/regamedll/dlls/gib.cpp
index 5b9122d04..9301e283f 100644
--- a/regamedll/dlls/gib.cpp
+++ b/regamedll/dlls/gib.cpp
@@ -4,14 +4,14 @@ LINK_ENTITY_TO_CLASS(gib, CGib, CCSGib)
void CGib::LimitVelocity()
{
- float length = pev->velocity.Length();
+ float topspeed = g_psv_maxvelocity->value * 0.75f;
- // ceiling at 1500. The gib velocity equation is not bounded properly. Rather than tune it
+ // ceiling at topspeed. The gib velocity equation is not bounded properly. Rather than tune it
// in 3 separate places again, I'll just limit it here.
- if (length > 1500.0)
+ if (pev->velocity.IsLengthGreaterThan(topspeed))
{
- // This should really be sv_maxvelocity * 0.75 or something
- pev->velocity = pev->velocity.Normalize() * 1500;
+ // DONE: This should really be sv_maxvelocity * 0.75 or something
+ pev->velocity = pev->velocity.Normalize() * topspeed;
}
}
diff --git a/regamedll/dlls/h_export.cpp b/regamedll/dlls/h_export.cpp
index 47189b833..486a3eedf 100644
--- a/regamedll/dlls/h_export.cpp
+++ b/regamedll/dlls/h_export.cpp
@@ -16,22 +16,7 @@ C_DLLEXPORT void WINAPI GiveFnptrsToDll(enginefuncs_t *pEnginefuncsTable, global
Regamedll_Game_Init();
}
-#ifdef _WIN32
-
-// DLL entry point
-BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
-{
- if (fdwReason == DLL_PROCESS_ATTACH)
- {
- }
- else if (fdwReason == DLL_PROCESS_DETACH)
- {
- }
-
- return TRUE;
-}
-
-#else // _WIN32
+#if defined(_LINUX)
void __attribute__((constructor)) DllMainLoad()
{
@@ -41,4 +26,4 @@ void __attribute__((destructor)) DllMainUnload()
{
}
-#endif // _WIN32
+#endif // _LINUX
diff --git a/regamedll/dlls/items.cpp b/regamedll/dlls/items.cpp
index fc67bc57f..03620e362 100644
--- a/regamedll/dlls/items.cpp
+++ b/regamedll/dlls/items.cpp
@@ -481,22 +481,9 @@ BOOL CItemThighPack::MyTouch(CBasePlayer *pPlayer)
return FALSE;
#endif
- pPlayer->m_bHasDefuser = true;
- pPlayer->pev->body = 1;
-
+ pPlayer->GiveDefuser();
ClientPrint(pPlayer->pev, HUD_PRINTCENTER, "#Got_defuser");
- MESSAGE_BEGIN(MSG_ONE, gmsgStatusIcon, nullptr, pPlayer->pev);
- WRITE_BYTE(STATUSICON_SHOW);
- WRITE_STRING("defuser");
- WRITE_BYTE(0);
- WRITE_BYTE(160);
- WRITE_BYTE(0);
- MESSAGE_END();
-
- pPlayer->SendItemStatus();
- pPlayer->SetScoreboardAttributes();
-
EMIT_SOUND(pPlayer->edict(), CHAN_VOICE, "items/kevlar.wav", VOL_NORM, ATTN_NORM);
if (TheTutor)
diff --git a/regamedll/dlls/multiplay_gamerules.cpp b/regamedll/dlls/multiplay_gamerules.cpp
index 19650e257..d16a53970 100644
--- a/regamedll/dlls/multiplay_gamerules.cpp
+++ b/regamedll/dlls/multiplay_gamerules.cpp
@@ -382,7 +382,7 @@ CHalfLifeMultiplay::CHalfLifeMultiplay()
m_iNumTerrorist = 0;
m_iNumSpawnableCT = 0;
m_iNumSpawnableTerrorist = 0;
- m_bMapHasCameras = FALSE;
+ m_bMapHasCameras = -1;
m_iLoserBonus = m_rgRewardAccountRules[RR_LOSER_BONUS_DEFAULT];
m_iNumConsecutiveCTLoses = 0;
@@ -696,9 +696,9 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(CleanUpMap)()
PLAYBACK_EVENT((FEV_GLOBAL | FEV_RELIABLE), 0, m_usResetDecals);
}
-LINK_HOOK_CLASS_VOID_CUSTOM_CHAIN2(CHalfLifeMultiplay, CSGameRules, GiveC4)
+LINK_HOOK_CLASS_CUSTOM_CHAIN2(CBasePlayer *, CHalfLifeMultiplay, CSGameRules, GiveC4)
-void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(GiveC4)()
+CBasePlayer *EXT_FUNC CHalfLifeMultiplay::__API_HOOK(GiveC4)()
{
int iTeamCount;
int iTemp = 0;
@@ -759,7 +759,7 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(GiveC4)()
{
#ifdef REGAMEDLL_FIXES
// we already have bomber
- return;
+ return pPlayer;
#endif
}
}
@@ -787,10 +787,12 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(GiveC4)()
if (pPlayer->pev->deadflag != DEAD_NO || pPlayer->m_iTeam != TERRORIST)
continue;
- pPlayer->MakeBomber();
- return;
+ if (pPlayer->MakeBomber())
+ return pPlayer;
}
}
+
+ return nullptr;
}
void CHalfLifeMultiplay::QueueCareerRoundEndMenu(float tmDelay, int iWinStatus)
@@ -2050,6 +2052,10 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(RestartRound)()
#endif
pPlayer->RoundRespawn();
+
+#ifdef REGAMEDLL_ADD
+ FireTargets("game_entity_restart", pPlayer, nullptr, USE_TOGGLE, 0.0);
+#endif
}
// Gooseman : The following code fixes the HUD icon bug
@@ -2088,6 +2094,10 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(RestartRound)()
m_bTargetBombed = m_bBombDefused = false;
m_bLevelInitialized = false;
m_bCompleteReset = false;
+
+#ifdef REGAMEDLL_ADD
+ FireTargets("game_round_start", nullptr, nullptr, USE_TOGGLE, 0.0);
+#endif
}
BOOL CHalfLifeMultiplay::IsThereABomber()
@@ -2129,7 +2139,9 @@ BOOL CHalfLifeMultiplay::IsThereABomb()
return FALSE;
}
-BOOL CHalfLifeMultiplay::TeamFull(int team_id)
+LINK_HOOK_CLASS_CUSTOM_CHAIN(BOOL, CHalfLifeMultiplay, CSGameRules, TeamFull, (int team_id), team_id)
+
+BOOL EXT_FUNC CHalfLifeMultiplay::__API_HOOK(TeamFull)(int team_id)
{
switch (team_id)
{
@@ -2143,8 +2155,10 @@ BOOL CHalfLifeMultiplay::TeamFull(int team_id)
return FALSE;
}
+LINK_HOOK_CLASS_CUSTOM_CHAIN(BOOL, CHalfLifeMultiplay, CSGameRules, TeamStacked, (int newTeam_id, int curTeam_id), newTeam_id, curTeam_id)
+
// checks to see if the desired team is stacked, returns true if it is
-BOOL CHalfLifeMultiplay::TeamStacked(int newTeam_id, int curTeam_id)
+BOOL EXT_FUNC CHalfLifeMultiplay::__API_HOOK(TeamStacked)(int newTeam_id, int curTeam_id)
{
// players are allowed to change to their own team
if (newTeam_id == curTeam_id)
@@ -2377,7 +2391,9 @@ void CHalfLifeMultiplay::PickNextVIP()
}
}
-void CHalfLifeMultiplay::Think()
+LINK_HOOK_CLASS_VOID_CUSTOM_CHAIN2(CHalfLifeMultiplay, CSGameRules, Think)
+
+void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(Think)()
{
MonitorTutorStatus();
m_VoiceGameMgr.Update(gpGlobals->frametime);
@@ -2400,7 +2416,7 @@ void CHalfLifeMultiplay::Think()
MESSAGE_BEGIN(MSG_ALL, gmsgForceCam);
WRITE_BYTE(forcecamera.value != 0);
WRITE_BYTE(forcechasecam.value != 0);
- WRITE_BYTE(fadetoblack.value != 0);
+ WRITE_BYTE(fadetoblack.value == FADETOBLACK_STAY);
MESSAGE_END();
m_flForceCameraValue = forcecamera.value;
@@ -3085,17 +3101,11 @@ void CHalfLifeMultiplay::CheckLevelInitialized()
{
// Count the number of spawn points for each team
// This determines the maximum number of players allowed on each
- CBaseEntity *pEnt = nullptr;
-
- m_iSpawnPointCount_Terrorist = 0;
- m_iSpawnPointCount_CT = 0;
-
- while ((pEnt = UTIL_FindEntityByClassname(pEnt, "info_player_deathmatch")))
- m_iSpawnPointCount_Terrorist++;
-
- while ((pEnt = UTIL_FindEntityByClassname(pEnt, "info_player_start")))
- m_iSpawnPointCount_CT++;
-
+ m_iSpawnPointCount_Terrorist = UTIL_CountEntities("info_player_deathmatch");
+ m_iSpawnPointCount_CT = UTIL_CountEntities("info_player_start");
+#ifdef REGAMEDLL_FIXES
+ m_bMapHasCameras = UTIL_CountEntities("trigger_camera");
+#endif
m_bLevelInitialized = true;
}
}
@@ -3463,7 +3473,7 @@ void CHalfLifeMultiplay::InitHUD(CBasePlayer *pl)
MESSAGE_BEGIN(MSG_ONE, gmsgForceCam, nullptr, pl->edict());
WRITE_BYTE(forcecamera.value != 0);
WRITE_BYTE(forcechasecam.value != 0);
- WRITE_BYTE(fadetoblack.value != 0);
+ WRITE_BYTE(fadetoblack.value == FADETOBLACK_STAY);
MESSAGE_END();
if (m_bGameOver)
@@ -3588,13 +3598,14 @@ void CHalfLifeMultiplay::ClientDisconnected(edict_t *pClient)
pPlayer->DropPlayerItem("weapon_c4");
}
-#ifndef REGAMEDLL_FIXES
- // Why ? DropPlayerItem didn't handle item_thighpack
if (pPlayer->m_bHasDefuser)
{
- pPlayer->DropPlayerItem("item_thighpack");
- }
+#ifdef REGAMEDLL_FIXES
+ SpawnDefuser(pPlayer->pev->origin, nullptr);
+#else
+ pPlayer->DropPlayerItem("item_thighpack"); // DropPlayerItem didn't handle item_thighpack
#endif
+ }
if (pPlayer->m_bIsVIP)
{
@@ -3881,7 +3892,7 @@ BOOL EXT_FUNC CHalfLifeMultiplay::__API_HOOK(FPlayerCanRespawn)(CBasePlayer *pPl
{
// If this player just connected and fadetoblack is on, then maybe
// the server admin doesn't want him peeking around.
- if (fadetoblack.value != 0.0f)
+ if (fadetoblack.value == FADETOBLACK_STAY)
{
UTIL_ScreenFade(pPlayer, Vector(0, 0, 0), 3, 3, 255, (FFADE_OUT | FFADE_STAYOUT));
}
@@ -3923,7 +3934,9 @@ LINK_HOOK_CLASS_VOID_CUSTOM_CHAIN(CHalfLifeMultiplay, CSGameRules, PlayerKilled,
void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(PlayerKilled)(CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor)
{
DeathNotice(pVictim, pKiller, pInflictor);
-
+#ifdef REGAMEDLL_FIXES
+ pVictim->pev->flags &= ~FL_FROZEN;
+#endif
pVictim->m_afPhysicsFlags &= ~PFLAG_ONTRAIN;
pVictim->m_iDeaths++;
pVictim->m_bNotKilled = false;
@@ -3931,6 +3944,10 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(PlayerKilled)(CBasePlayer *pVictim,
pVictim->m_iTrain = (TRAIN_NEW | TRAIN_OFF);
SET_VIEW(ENT(pVictim->pev), ENT(pVictim->pev));
+#ifdef REGAMEDLL_FIXES
+ int iKillerFrags = 0;
+#endif
+
CBasePlayer *peKiller = nullptr;
CBaseEntity *ktmp = CBaseEntity::Instance(pKiller);
@@ -3953,12 +3970,15 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(PlayerKilled)(CBasePlayer *pVictim,
}
FireTargets("game_playerdie", pVictim, pVictim, USE_TOGGLE, 0);
-
// Did the player kill himself?
if (pVictim->pev == pKiller)
{
// Players lose a frag for killing themselves
+#ifdef REGAMEDLL_FIXES
+ iKillerFrags = -1;
+#else
pKiller->frags -= 1;
+#endif
}
else if (peKiller && peKiller->IsPlayer())
{
@@ -3968,7 +3988,11 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(PlayerKilled)(CBasePlayer *pVictim,
if (g_pGameRules->PlayerRelationship(pVictim, killer) == GR_TEAMMATE)
{
// if a player dies by from teammate
+#ifdef REGAMEDLL_FIXES
+ iKillerFrags = -IPointsForKill(peKiller, pVictim);
+#else
pKiller->frags -= IPointsForKill(peKiller, pVictim);
+#endif
killer->AddAccount(PAYBACK_FOR_KILLED_TEAMMATES, RT_TEAMMATES_KILLED);
killer->m_iTeamKills++;
@@ -4008,7 +4032,11 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(PlayerKilled)(CBasePlayer *pVictim,
else
{
// if a player dies in a deathmatch game and the killer is a client, award the killer some points
+#ifdef REGAMEDLL_FIXES
+ iKillerFrags = IPointsForKill(peKiller, pVictim);
+#else
pKiller->frags += IPointsForKill(peKiller, pVictim);
+#endif
if (pVictim->m_bIsVIP)
{
@@ -4040,7 +4068,11 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(PlayerKilled)(CBasePlayer *pVictim,
else
{
// killed by the world
+#ifdef REGAMEDLL_FIXES
+ iKillerFrags = -1;
+#else
pKiller->frags -= 1;
+#endif
}
// update the scores
@@ -4063,7 +4095,9 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(PlayerKilled)(CBasePlayer *pVictim,
if (ep && ep->Classify() == CLASS_PLAYER)
{
CBasePlayer *PK = static_cast(ep);
-
+#ifdef REGAMEDLL_FIXES
+ PK->AddPoints(iKillerFrags, TRUE);
+#else
MESSAGE_BEGIN(MSG_ALL, gmsgScoreInfo);
WRITE_BYTE(ENTINDEX(PK->edict()));
WRITE_SHORT(int(PK->pev->frags));
@@ -4071,7 +4105,7 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(PlayerKilled)(CBasePlayer *pVictim,
WRITE_SHORT(0);
WRITE_SHORT(PK->m_iTeam);
MESSAGE_END();
-
+#endif
// let the killer paint another decal as soon as he'd like.
PK->m_flNextDecalTime = gpGlobals->time;
}
@@ -4079,102 +4113,60 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(PlayerKilled)(CBasePlayer *pVictim,
LINK_HOOK_CLASS_VOID_CUSTOM_CHAIN(CHalfLifeMultiplay, CSGameRules, DeathNotice, (CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pevInflictor), pVictim, pKiller, pevInflictor)
-void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(DeathNotice)(CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pevInflictor)
+void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(DeathNotice)(CBasePlayer *pVictim, entvars_t *pevKiller, entvars_t *pevInflictor)
{
// by default, the player is killed by the world
- const char *killer_weapon_name = "world";
- int killer_index = 0;
+ CBasePlayer *pKiller = (pevKiller->flags & FL_CLIENT) ? CBasePlayer::Instance(pevKiller) : nullptr;
+ const char *killer_weapon_name = pVictim->GetKillerWeaponName(pevInflictor, pevKiller);
-#ifndef REGAMEDLL_FIXES
- // Hack to fix name change
- char *tau = "tau_cannon";
- char *gluon = "gluon gun";
-#endif
-
- // Is the killer a client?
- if (pKiller->flags & FL_CLIENT)
+ if (!TheTutor)
{
- killer_index = ENTINDEX(ENT(pKiller));
+ int iRarityOfKill = 0;
+ int iDeathMessageFlags = PLAYERDEATH_POSITION; // set default bit
+
+ CBasePlayer *pAssister = nullptr;
- if (pevInflictor)
+ bool bFlashAssist = false;
+ if ((pAssister = CheckAssistsToKill(pKiller, pVictim, bFlashAssist)))
{
- if (pevInflictor == pKiller)
- {
- // If the inflictor is the killer, then it must be their current weapon doing the damage
- CBasePlayer *pAttacker = CBasePlayer::Instance(pKiller);
- if (pAttacker && pAttacker->IsPlayer())
- {
- if (pAttacker->m_pActiveItem)
- {
- killer_weapon_name = pAttacker->m_pActiveItem->pszName();
- }
- }
- }
- else
- {
- // it's just that easy
- killer_weapon_name = STRING(pevInflictor->classname);
- }
+ // Add a flag indicating the presence of an assistant who assisted in the kill
+ iDeathMessageFlags |= PLAYERDEATH_ASSISTANT;
}
- }
- else
-#ifdef REGAMEDLL_FIXES
- if (pevInflictor)
-#endif
- {
- killer_weapon_name = STRING(pevInflictor->classname);
- }
- // strip the monster_* or weapon_* from the inflictor's classname
- const char cut_weapon[] = "weapon_";
- const char cut_monster[] = "monster_";
- const char cut_func[] = "func_";
-
- // replace the code names with the 'real' names
- if (!Q_strncmp(killer_weapon_name, cut_weapon, sizeof(cut_weapon) - 1))
- killer_weapon_name += sizeof(cut_weapon) - 1;
+ iRarityOfKill = GetRarityOfKill(pKiller, pVictim, pAssister, killer_weapon_name, bFlashAssist);
+ if (iRarityOfKill != 0)
+ {
+ // Add a flag indicating that the attacker killed the victim in a rare way
+ iDeathMessageFlags |= PLAYERDEATH_KILLRARITY;
+ }
- else if (!Q_strncmp(killer_weapon_name, cut_monster, sizeof(cut_monster) - 1))
- killer_weapon_name += sizeof(cut_monster) - 1;
+ SendDeathMessage(pKiller, pVictim, pAssister, pevInflictor, killer_weapon_name, iDeathMessageFlags, iRarityOfKill);
- else if (!Q_strncmp(killer_weapon_name, cut_func, sizeof(cut_func) - 1))
- killer_weapon_name += sizeof(cut_func) - 1;
+ // Updates the stats of who has killed whom
+ if (pKiller && pKiller->IsPlayer() && PlayerRelationship(pVictim, pKiller) != GR_TEAMMATE)
+ {
+ int iPlayerIndexKiller = pKiller->entindex();
+ int iPlayerIndexVictim = pVictim->entindex();
- if (!TheTutor)
- {
- MESSAGE_BEGIN(MSG_ALL, gmsgDeathMsg);
- WRITE_BYTE(killer_index); // the killer
- WRITE_BYTE(ENTINDEX(pVictim->edict())); // the victim
- WRITE_BYTE(pVictim->m_bHeadshotKilled); // is killed headshot
- WRITE_STRING(killer_weapon_name); // what they were killed by (should this be a string?)
- MESSAGE_END();
+ pKiller->CSPlayer()->m_iNumKilledByUnanswered[iPlayerIndexVictim - 1] = 0;
+ pVictim->CSPlayer()->m_iNumKilledByUnanswered[iPlayerIndexKiller - 1]++;
+ }
}
- // This weapons from HL isn't it?
-#ifndef REGAMEDLL_FIXES
- if (!Q_strcmp(killer_weapon_name, "egon"))
- killer_weapon_name = gluon;
-
- else if (!Q_strcmp(killer_weapon_name, "gauss"))
- killer_weapon_name = tau;
-#endif
-
// Did he kill himself?
- if (pVictim->pev == pKiller)
+ if (pVictim->pev == pevKiller)
{
// killed self
char *team = GetTeam(pVictim->m_iTeam);
UTIL_LogPrintf("\"%s<%i><%s><%s>\" committed suicide with \"%s\"\n", STRING(pVictim->pev->netname), GETPLAYERUSERID(pVictim->edict()),
GETPLAYERAUTHID(pVictim->edict()), team, killer_weapon_name);
}
- else if (pKiller->flags & FL_CLIENT)
+ else if (pevKiller->flags & FL_CLIENT)
{
- CBasePlayer *pAttacker = CBasePlayer::Instance(pKiller);
-
const char *VictimTeam = GetTeam(pVictim->m_iTeam);
- const char *KillerTeam = (pAttacker && pAttacker->IsPlayer()) ? GetTeam(pAttacker->m_iTeam) : "";
+ const char *KillerTeam = (pKiller && pKiller->IsPlayer()) ? GetTeam(pKiller->m_iTeam) : "";
- UTIL_LogPrintf("\"%s<%i><%s><%s>\" killed \"%s<%i><%s><%s>\" with \"%s\"\n", STRING(pKiller->netname), GETPLAYERUSERID(ENT(pKiller)), GETPLAYERAUTHID(ENT(pKiller)),
+ UTIL_LogPrintf("\"%s<%i><%s><%s>\" killed \"%s<%i><%s><%s>\" with \"%s\"\n", STRING(pevKiller->netname), GETPLAYERUSERID(ENT(pevKiller)), GETPLAYERAUTHID(ENT(pevKiller)),
KillerTeam, STRING(pVictim->pev->netname), GETPLAYERUSERID(pVictim->edict()), GETPLAYERAUTHID(pVictim->edict()), VictimTeam, killer_weapon_name);
}
else
@@ -4197,7 +4189,7 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(DeathNotice)(CBasePlayer *pVictim,
if (pevInflictor)
WRITE_SHORT(ENTINDEX(ENT(pevInflictor))); // index number of secondary entity
else
- WRITE_SHORT(ENTINDEX(ENT(pKiller))); // index number of secondary entity
+ WRITE_SHORT(ENTINDEX(ENT(pevKiller))); // index number of secondary entity
if (pVictim->m_bHeadshotKilled)
WRITE_LONG(9 | DRC_FLAG_DRAMATIC | DRC_FLAG_SLOWMOTION);
@@ -4207,8 +4199,10 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(DeathNotice)(CBasePlayer *pVictim,
MESSAGE_END();
}
+LINK_HOOK_CLASS_VOID_CUSTOM_CHAIN(CHalfLifeMultiplay, CSGameRules, PlayerGotWeapon, (CBasePlayer *pPlayer, CBasePlayerItem *pWeapon), pPlayer, pWeapon)
+
// Player has grabbed a weapon that was sitting in the world
-void CHalfLifeMultiplay::PlayerGotWeapon(CBasePlayer *pPlayer, CBasePlayerItem *pWeapon)
+void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(PlayerGotWeapon)(CBasePlayer *pPlayer, CBasePlayerItem *pWeapon)
{
;
}
@@ -4338,11 +4332,29 @@ LINK_HOOK_CLASS_CUSTOM_CHAIN(int, CHalfLifeMultiplay, CSGameRules, DeadPlayerWea
int EXT_FUNC CHalfLifeMultiplay::__API_HOOK(DeadPlayerWeapons)(CBasePlayer *pPlayer)
{
- return GR_PLR_DROP_GUN_ACTIVE;
+#ifdef REGAMEDLL_ADD
+ switch ((int)weapondrop.value)
+ {
+ case 3:
+ return GR_PLR_DROP_GUN_ALL;
+ case 2:
+ break;
+ case 1:
+ return GR_PLR_DROP_GUN_BEST;
+ default:
+ return GR_PLR_DROP_GUN_NO;
+ }
+#endif
+ return GR_PLR_DROP_GUN_ACTIVE; // keep original value in return
}
int CHalfLifeMultiplay::DeadPlayerAmmo(CBasePlayer *pPlayer)
{
+#ifdef REGAMEDLL_ADD
+ if (ammodrop.value == 0.0f)
+ return GR_PLR_DROP_AMMO_NO;
+#endif
+
return GR_PLR_DROP_AMMO_ACTIVE;
}
@@ -4876,7 +4888,7 @@ void CHalfLifeMultiplay::ProcessMapVote(CBasePlayer *pPlayer, int iVote)
}
}
-LINK_HOOK_CLASS_VOID_CUSTOM_CHAIN2(CHalfLifeMultiplay, CSGameRules, ChangeLevel);
+LINK_HOOK_CLASS_VOID_CUSTOM_CHAIN2(CHalfLifeMultiplay, CSGameRules, ChangeLevel)
// Server is changing to a new level, check mapcycle.txt for map name and setup info
void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(ChangeLevel)()
@@ -4903,7 +4915,7 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(ChangeLevel)()
// find the map to change to
char *mapcfile = (char *)CVAR_GET_STRING("mapcyclefile");
- assert(mapcfile != nullptr);
+ Assert(mapcfile != nullptr);
szCommands[0] = '\0';
szRules[0] = '\0';
@@ -4939,7 +4951,7 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(ChangeLevel)()
{
keeplooking = false;
- assert(item != nullptr);
+ Assert(item != nullptr);
if (item->minplayers != 0)
{
@@ -5156,7 +5168,11 @@ void CHalfLifeMultiplay::ChangePlayerTeam(CBasePlayer *pPlayer, const char *pTea
pPlayer->Killed(pPlayer->pev, bGib ? GIB_ALWAYS : GIB_NEVER);
// add 1 to frags to balance out the 1 subtracted for killing yourself
+#ifdef REGAMEDLL_FIXES
+ pPlayer->AddPoints(1, TRUE);
+#else
pPlayer->pev->frags++;
+#endif
}
pPlayer->m_iTeam = newTeam;
@@ -5184,3 +5200,217 @@ bool CHalfLifeMultiplay::CanPlayerBuy(CBasePlayer *pPlayer) const
return true;
}
+
+//
+// Checks for assists in a kill situation
+//
+// This function analyzes damage records and player actions to determine the player who contributed the most to a kill,
+// considering factors such as damage dealt and the use of flashbang grenades
+//
+// pKiller - The killer entity (Note: The killer may be a non-player)
+// pVictim - The victim player
+// bFlashAssist - A flag indicating whether a flashbang was used in the assist
+// Returns - A pointer to the player who gave the most assistance, or NULL if appropriate assistant is not found
+//
+CBasePlayer *CHalfLifeMultiplay::CheckAssistsToKill(CBaseEntity *pKiller, CBasePlayer *pVictim, bool &bFlashAssist)
+{
+#ifdef REGAMEDLL_ADD
+ CCSPlayer::DamageList_t &victimDamageTakenList = pVictim->CSPlayer()->GetDamageList();
+
+ float maxDamage = 0.0f;
+ int maxDamageIndex = -1;
+ CBasePlayer *maxDamagePlayer = nullptr;
+
+ // Find the best assistant
+ for (int i = 1; i <= gpGlobals->maxClients; i++)
+ {
+ const CCSPlayer::CDamageRecord_t &record = victimDamageTakenList[i - 1];
+ if (record.flDamage == 0)
+ continue; // dealt no damage
+
+ CBasePlayer *pAttackerPlayer = UTIL_PlayerByIndex(i);
+ if (!pAttackerPlayer || pAttackerPlayer->IsDormant())
+ continue; // ignore idle clients
+
+ CCSPlayer *pCSAttackerPlayer = pAttackerPlayer->CSPlayer();
+ if (record.userId != pCSAttackerPlayer->m_iUserID)
+ continue; // another client?
+
+ if (pAttackerPlayer == pKiller || pAttackerPlayer == pVictim)
+ continue; // ignore involved as killer or victim
+
+ if (record.flDamage > maxDamage)
+ {
+ // If the assistant used a flash grenade to aid in the kill,
+ // make sure that the victim was blinded, and that the duration of the flash effect is still preserved
+ if (record.flFlashDurationTime > 0 && (!pVictim->IsBlind() || record.flFlashDurationTime <= gpGlobals->time))
+ continue;
+
+ maxDamage = record.flDamage;
+ maxDamagePlayer = pAttackerPlayer;
+ maxDamageIndex = i;
+ }
+ }
+
+ // Note: Only the highest damaging player can be an assistant
+ // The condition checks if the damage dealt by the player exceeds a certain percentage of the victim's max health
+ // Default threshold is 40%, meaning the assistant must deal at least 40% of the victim's max health as damage
+ if (maxDamagePlayer && maxDamage > (assist_damage_threshold.value / 100.0f) * pVictim->pev->max_health)
+ {
+ bFlashAssist = victimDamageTakenList[maxDamageIndex - 1].flFlashDurationTime > 0; // if performed the flash assist
+ return maxDamagePlayer;
+ }
+#endif
+
+ return nullptr;
+}
+
+//
+// Check the rarity estimation for a kill
+//
+// Estimation to represent the rarity of a kill based on various factors, including assists with flashbang grenades,
+// headshot kills, kills through walls, the killer's blindness, no-scope sniper rifle kills, and kills through smoke
+//
+// pKiller - The entity who committed the kill (Note: The killer may be a non-player)
+// pVictim - The player who was killed
+// pAssister - The assisting player (if any)
+// killerWeaponName - The name of the weapon used by the killer
+// bFlashAssist - A flag indicating whether an assist was made with a flashbang
+// Returns an integer estimation representing the rarity of the kill
+// Use with PLAYERDEATH_KILLRARITY flag to indicate a rare kill in death messages
+//
+int CHalfLifeMultiplay::GetRarityOfKill(CBaseEntity *pKiller, CBasePlayer *pVictim, CBasePlayer *pAssister, const char *killerWeaponName, bool bFlashAssist)
+{
+ int iRarity = 0;
+
+ // The killer player kills the victim with an assistant flashbang grenade
+ if (pAssister && bFlashAssist)
+ iRarity |= KILLRARITY_ASSISTEDFLASH;
+
+ // The killer player kills the victim with a headshot
+ if (pVictim->m_bHeadshotKilled)
+ iRarity |= KILLRARITY_HEADSHOT;
+
+ // The killer player was blind
+ CBasePlayer *pKillerPlayer = static_cast(pKiller);
+ if (pKillerPlayer && pKillerPlayer->IsPlayer())
+ {
+ WeaponClassType weaponClass = AliasToWeaponClass(killerWeaponName);
+ if (pKillerPlayer != pVictim
+ && weaponClass != WEAPONCLASS_NONE
+ && weaponClass != WEAPONCLASS_KNIFE
+ && weaponClass != WEAPONCLASS_GRENADE)
+ {
+ // The killer player kills the victim through the walls
+ if (pVictim->GetDmgPenetrationLevel() > 0)
+ iRarity |= KILLRARITY_PENETRATED;
+
+ if (pKillerPlayer->IsFullyBlind())
+ iRarity |= KILLRARITY_KILLER_BLIND;
+
+ // The killer player kills the victim with a sniper rifle with no scope
+ if (weaponClass == WEAPONCLASS_SNIPERRIFLE && pKillerPlayer->m_iClientFOV == DEFAULT_FOV)
+ iRarity |= KILLRARITY_NOSCOPE;
+
+ // The killer player kills the victim through smoke
+ const Vector inEyePos = pKillerPlayer->EyePosition();
+ if (TheCSBots()->IsLineBlockedBySmoke(&inEyePos, &pVictim->pev->origin))
+ iRarity |= KILLRARITY_THRUSMOKE;
+ }
+
+ // Calculate # of unanswered kills between killer & victim
+ // This is plus 1 as this function gets called before the stat is updated
+ // That is done so that the domination and revenge will be calculated prior
+ // to the death message being sent to the clients
+ int iAttackerEntityIndex = pKillerPlayer->entindex();
+ Assert(iAttackerEntityIndex > 0 && iAttackerEntityIndex <= MAX_CLIENTS);
+
+ int iKillsUnanswered = pVictim->CSPlayer()->m_iNumKilledByUnanswered[iAttackerEntityIndex - 1] + 1;
+ if (iKillsUnanswered == CS_KILLS_FOR_DOMINATION || pKillerPlayer->CSPlayer()->IsPlayerDominated(pVictim->entindex() - 1))
+ {
+ // this is the Nth unanswered kill between killer and victim, killer is now dominating victim
+ iRarity |= KILLRARITY_DOMINATION;
+
+ // set victim to be dominated by killer
+ pKillerPlayer->CSPlayer()->SetPlayerDominated(pVictim, true);
+ }
+ else if (pVictim->CSPlayer()->IsPlayerDominated(pKillerPlayer->entindex() - 1))
+ {
+ // the killer killed someone who was dominating him, gains revenge
+ iRarity |= KILLRARITY_REVENGE;
+
+ // set victim to no longer be dominating the killer
+ pVictim->CSPlayer()->SetPlayerDominated(pKillerPlayer, false);
+ }
+ }
+
+ return iRarity;
+}
+
+LINK_HOOK_CLASS_VOID_CUSTOM_CHAIN(CHalfLifeMultiplay, CSGameRules, SendDeathMessage, (CBaseEntity *pKiller, CBasePlayer *pVictim, CBasePlayer *pAssister, entvars_t *pevInflictor, const char *killerWeaponName, int iDeathMessageFlags, int iRarityOfKill), pKiller, pVictim, pAssister, pevInflictor, killerWeaponName, iDeathMessageFlags, iRarityOfKill)
+
+//
+// Sends death messages to all players, including info about the killer, victim, weapon used,
+// extra death flags, death position, assistant, and kill rarity
+//
+//
+// pKiller - The entity who performed the kill (Note: The killer may be a non-player)
+// pVictim - The player who was killed
+// pAssister - The assisting player (if any)
+// killerWeaponName - The name of the weapon used by the killer
+// iDeathMessageFlags - Flags indicating extra death message info
+// iRarityOfKill - An bitsums representing the rarity classification of the kill
+//
+void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(SendDeathMessage)(CBaseEntity *pKiller, CBasePlayer *pVictim, CBasePlayer *pAssister, entvars_t *pevInflictor, const char *killerWeaponName, int iDeathMessageFlags, int iRarityOfKill)
+{
+ CBasePlayer *pKillerPlayer = (pKiller && pKiller->IsPlayer()) ? static_cast(pKiller) : nullptr;
+
+ // Only the player can dominate the victim
+ if ((iRarityOfKill & KILLRARITY_DOMINATION) && pKillerPlayer && pVictim != pKillerPlayer)
+ {
+ // Sets the beginning of domination over the victim until he takes revenge
+ int iKillsUnanswered = pVictim->CSPlayer()->m_iNumKilledByUnanswered[pKillerPlayer->entindex() - 1] + 1;
+ if (iKillsUnanswered == CS_KILLS_FOR_DOMINATION)
+ iRarityOfKill |= KILLRARITY_DOMINATION_BEGAN;
+ }
+
+ MESSAGE_BEGIN(MSG_ALL, gmsgDeathMsg);
+ WRITE_BYTE((pKiller && pKiller->IsPlayer()) ? pKiller->entindex() : 0); // the killer
+ WRITE_BYTE(pVictim->entindex()); // the victim
+ WRITE_BYTE(pVictim->m_bHeadshotKilled); // is killed headshot
+ WRITE_STRING(killerWeaponName); // what they were killed by (should this be a string?)
+
+#ifdef REGAMEDLL_ADD
+ iDeathMessageFlags &= UTIL_ReadFlags(deathmsg_flags.string); // leave only allowed bitsums for extra info
+
+ // Send the victim's death position only
+ // 1. if it is not a free for all mode
+ // 2. if the attacker is a player and they are not teammates
+ if (IsFreeForAll() || !pKillerPlayer || PlayerRelationship(pKillerPlayer, pVictim) == GR_TEAMMATE)
+ iDeathMessageFlags &= ~PLAYERDEATH_POSITION; // do not send a position
+
+ if (iDeathMessageFlags > 0)
+ {
+ WRITE_LONG(iDeathMessageFlags);
+
+ // Writes the coordinates of the place where the victim died
+ // The victim has just been killed, so this usefully display 'X' dead icon on the HUD radar
+ if (iDeathMessageFlags & PLAYERDEATH_POSITION)
+ {
+ WRITE_COORD(pVictim->pev->origin.x);
+ WRITE_COORD(pVictim->pev->origin.y);
+ WRITE_COORD(pVictim->pev->origin.z);
+ }
+
+ // Writes the index of the teammate who assisted in the kill
+ if (iDeathMessageFlags & PLAYERDEATH_ASSISTANT)
+ WRITE_BYTE(pAssister->entindex());
+
+ // Writes the rarity classification of the kill
+ if (iDeathMessageFlags & PLAYERDEATH_KILLRARITY)
+ WRITE_LONG(iRarityOfKill);
+ }
+#endif
+
+ MESSAGE_END();
+}
diff --git a/regamedll/dlls/observer.cpp b/regamedll/dlls/observer.cpp
index 336b7b3cc..4b3521a6c 100644
--- a/regamedll/dlls/observer.cpp
+++ b/regamedll/dlls/observer.cpp
@@ -6,7 +6,7 @@ int __API_HOOK(GetForceCamera)(CBasePlayer *pObserver)
{
int retVal;
- if (!fadetoblack.value)
+ if (fadetoblack.value != FADETOBLACK_STAY)
{
retVal = int(CVAR_GET_FLOAT("mp_forcechasecam"));
@@ -51,7 +51,7 @@ void UpdateClientEffects(CBasePlayer *pObserver, int oldMode)
{
bool clearProgress = false;
bool clearBlindness = false;
- bool blindnessOk = (fadetoblack.value == 0);
+ bool blindnessOk = (fadetoblack.value != FADETOBLACK_STAY);
bool clearNightvision = false;
if (pObserver->GetObserverMode() == OBS_IN_EYE)
@@ -478,10 +478,19 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Observer_SetMode)(int iMode)
// verify observer target again
if (m_hObserverTarget)
{
+#ifdef REGAMEDLL_FIXES
+ m_hObserverTarget = Observer_IsValidTarget( ENTINDEX(m_hObserverTarget->edict()), forcecamera != CAMERA_MODE_SPEC_ANYONE );
+#else
CBasePlayer *pTarget = m_hObserverTarget;
- if (pTarget == this || !pTarget || pTarget->has_disconnected || pTarget->GetObserverMode() != OBS_NONE || (pTarget->pev->effects & EF_NODRAW) || (forcecamera != CAMERA_MODE_SPEC_ANYONE && pTarget->m_iTeam != m_iTeam))
+ if (pTarget == this
+ || !pTarget
+ || pTarget->has_disconnected
+ || pTarget->GetObserverMode() != OBS_NONE
+ || (pTarget->pev->effects & EF_NODRAW)
+ || (forcecamera != CAMERA_MODE_SPEC_ANYONE && pTarget->m_iTeam != m_iTeam))
m_hObserverTarget = nullptr;
+#endif
}
// set spectator mode
@@ -532,9 +541,11 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Observer_SetMode)(int iMode)
m_bWasFollowing = false;
}
-void CBasePlayer::Observer_Think()
+LINK_HOOK_CLASS_VOID_CHAIN2(CBasePlayer, Observer_Think)
+
+void EXT_FUNC CBasePlayer::__API_HOOK(Observer_Think)()
{
Observer_HandleButtons();
Observer_CheckTarget();
Observer_CheckProperties();
-}
+}
\ No newline at end of file
diff --git a/regamedll/dlls/observer.h b/regamedll/dlls/observer.h
index 722c977a4..743936ff9 100644
--- a/regamedll/dlls/observer.h
+++ b/regamedll/dlls/observer.h
@@ -32,6 +32,12 @@
#define CAMERA_MODE_SPEC_ONLY_TEAM 1
#define CAMERA_MODE_SPEC_ONLY_FIRST_PERSON 2
+enum FadeToBlack {
+ FADETOBLACK_OFF,
+ FADETOBLACK_STAY,
+ FADETOBLACK_AT_DYING,
+};
+
int GetForceCamera(CBasePlayer *pObserver);
void UpdateClientEffects(CBasePlayer *pObserver, int oldMode);
diff --git a/regamedll/dlls/pathcorner.cpp b/regamedll/dlls/pathcorner.cpp
index 062d1716a..306c2819c 100644
--- a/regamedll/dlls/pathcorner.cpp
+++ b/regamedll/dlls/pathcorner.cpp
@@ -23,7 +23,7 @@ void CPathCorner::KeyValue(KeyValueData *pkvd)
void CPathCorner::Spawn()
{
- assert(("path_corner without a targetname", !pev->targetname.IsNull()));
+ DbgAssertMsg(!pev->targetname.IsNull(), "path_corner without a targetname");
}
TYPEDESCRIPTION CPathTrack::m_SaveData[] =
diff --git a/regamedll/dlls/plats.cpp b/regamedll/dlls/plats.cpp
index 75a0e96d9..f0735053b 100644
--- a/regamedll/dlls/plats.cpp
+++ b/regamedll/dlls/plats.cpp
@@ -382,7 +382,7 @@ void CFuncPlat::GoDown()
EMIT_SOUND(ENT(pev), CHAN_STATIC, (char *)STRING(pev->noiseMovement), m_volume, ATTN_NORM);
}
- assert(m_toggle_state == TS_AT_TOP || m_toggle_state == TS_GOING_UP);
+ DbgAssert(m_toggle_state == TS_AT_TOP || m_toggle_state == TS_GOING_UP);
m_toggle_state = TS_GOING_DOWN;
SetMoveDone(&CFuncPlat::CallHitBottom);
LinearMove(m_vecPosition2, pev->speed);
@@ -401,7 +401,7 @@ void CFuncPlat::HitBottom()
EMIT_SOUND(ENT(pev), CHAN_WEAPON, (char *)STRING(pev->noiseStopMoving), m_volume, ATTN_NORM);
}
- assert(m_toggle_state == TS_GOING_DOWN);
+ DbgAssert(m_toggle_state == TS_GOING_DOWN);
m_toggle_state = TS_AT_BOTTOM;
}
@@ -413,7 +413,7 @@ void CFuncPlat::GoUp()
EMIT_SOUND(ENT(pev), CHAN_STATIC, (char *)STRING(pev->noiseMovement), m_volume, ATTN_NORM);
}
- assert(m_toggle_state == TS_AT_BOTTOM || m_toggle_state == TS_GOING_DOWN);
+ DbgAssert(m_toggle_state == TS_AT_BOTTOM || m_toggle_state == TS_GOING_DOWN);
m_toggle_state = TS_GOING_UP;
SetMoveDone(&CFuncPlat::CallHitTop);
LinearMove(m_vecPosition1, pev->speed);
@@ -432,7 +432,7 @@ void CFuncPlat::HitTop()
EMIT_SOUND(ENT(pev), CHAN_WEAPON, (char *)STRING(pev->noiseStopMoving), m_volume, ATTN_NORM);
}
- assert(m_toggle_state == TS_GOING_UP);
+ DbgAssert(m_toggle_state == TS_GOING_UP);
m_toggle_state = TS_AT_TOP;
if (!IsTogglePlat())
@@ -456,7 +456,7 @@ void CFuncPlat::Blocked(CBaseEntity *pOther)
}
// Send the platform back where it came from
- assert(m_toggle_state == TS_GOING_UP || m_toggle_state == TS_GOING_DOWN);
+ DbgAssert(m_toggle_state == TS_GOING_UP || m_toggle_state == TS_GOING_DOWN);
if (m_toggle_state == TS_GOING_UP)
{
diff --git a/regamedll/dlls/player.cpp b/regamedll/dlls/player.cpp
index d86b320ef..3b6671e6e 100644
--- a/regamedll/dlls/player.cpp
+++ b/regamedll/dlls/player.cpp
@@ -82,8 +82,6 @@ const char *CDeadHEV::m_szPoses[] =
"deadtable"
};
-entvars_t *g_pevLastInflictor;
-
LINK_ENTITY_TO_CLASS(player, CBasePlayer, CCSPlayer)
#ifdef REGAMEDLL_API
@@ -761,24 +759,30 @@ void EXT_FUNC CBasePlayer::__API_HOOK(TraceAttack)(entvars_t *pevAttacker, float
AddMultiDamage(pevAttacker, this, flDamage, bitsDamageType);
}
-const char *GetWeaponName(entvars_t *pevInflictor, entvars_t *pKiller)
+const char *CBasePlayer::GetKillerWeaponName(entvars_t *pevInflictor, entvars_t *pevKiller) const
{
// by default, the player is killed by the world
const char *killer_weapon_name = "world";
// Is the killer a client?
- if (pKiller->flags & FL_CLIENT)
+ if (pevKiller->flags & FL_CLIENT)
{
if (pevInflictor)
{
- if (pevInflictor == pKiller)
+ if (pevInflictor == pevKiller)
{
- // If the inflictor is the killer, then it must be their current weapon doing the damage
- CBasePlayer *pAttacker = CBasePlayer::Instance(pKiller);
- if (pAttacker && pAttacker->IsPlayer())
+#ifdef REGAMEDLL_FIXES
+ // Ignore the inflictor's weapon if victim killed self
+ if (pevKiller != pev)
+#endif
{
- if (pAttacker->m_pActiveItem)
- killer_weapon_name = pAttacker->m_pActiveItem->pszName();
+ // If the inflictor is the killer, then it must be their current weapon doing the damage
+ CBasePlayer *pAttacker = CBasePlayer::Instance(pevKiller);
+ if (pAttacker && pAttacker->IsPlayer())
+ {
+ if (pAttacker->m_pActiveItem)
+ killer_weapon_name = pAttacker->m_pActiveItem->pszName();
+ }
}
}
else
@@ -797,10 +801,11 @@ const char *GetWeaponName(entvars_t *pevInflictor, entvars_t *pKiller)
}
// strip the monster_* or weapon_* from the inflictor's classname
- const char cut_weapon[] = "weapon_";
+ const char cut_weapon[] = "weapon_";
const char cut_monster[] = "monster_";
- const char cut_func[] = "func_";
+ const char cut_func[] = "func_";
+ // replace the code names with the 'real' names
if (!Q_strncmp(killer_weapon_name, cut_weapon, sizeof(cut_weapon) - 1))
killer_weapon_name += sizeof(cut_weapon) - 1;
@@ -971,7 +976,7 @@ BOOL EXT_FUNC CBasePlayer::__API_HOOK(TakeDamage)(entvars_t *pevInflictor, entva
m_bKilledByGrenade = true;
}
- LogAttack(pAttack, this, bTeamAttack, int(flDamage), armorHit, pev->health - flDamage, pev->armorvalue, GetWeaponName(pevInflictor, pevAttacker));
+ LogAttack(pAttack, this, bTeamAttack, int(flDamage), armorHit, pev->health - flDamage, pev->armorvalue, GetKillerWeaponName(pevInflictor, pevAttacker));
bTookDamage = CBaseMonster::TakeDamage(pevInflictor, pevAttacker, int(flDamage), bitsDamageType);
if (bTookDamage)
@@ -986,9 +991,13 @@ BOOL EXT_FUNC CBasePlayer::__API_HOOK(TakeDamage)(entvars_t *pevInflictor, entva
CBasePlayer *pPlayerAttacker = CBasePlayer::Instance(pevAttacker);
if (pPlayerAttacker && !pPlayerAttacker->IsBot() && pPlayerAttacker->m_iTeam != m_iTeam)
{
- TheCareerTasks->HandleEnemyInjury(GetWeaponName(pevInflictor, pevAttacker), pPlayerAttacker->HasShield(), pPlayerAttacker);
+ TheCareerTasks->HandleEnemyInjury(GetKillerWeaponName(pevInflictor, pevAttacker), pPlayerAttacker->HasShield(), pPlayerAttacker);
}
}
+
+#ifdef REGAMEDLL_API
+ CSPlayer()->RecordDamage(pAttack, flDamage);
+#endif
}
{
@@ -1049,7 +1058,7 @@ BOOL EXT_FUNC CBasePlayer::__API_HOOK(TakeDamage)(entvars_t *pevInflictor, entva
pAttacker = GetClassPtr((CBaseEntity *)pevAttacker);
- if (pAttacker->IsPlayer())
+ if (pAttacker->IsPlayer() && !(pAttacker == this && (bitsDamageType & DMG_FALL)))
{
pAttack = GetClassPtr((CBasePlayer *)pevAttacker);
@@ -1091,16 +1100,18 @@ BOOL EXT_FUNC CBasePlayer::__API_HOOK(TakeDamage)(entvars_t *pevInflictor, entva
pAttack->m_flLastAttackedTeammate = gpGlobals->time;
}
- }
#ifdef REGAMEDLL_ADD
- // bullets hurt teammates less
- flDamage *= clamp(((bitsDamageType & DMG_BULLET) ?
- ff_damage_reduction_bullets.value :
- ff_damage_reduction_other.value), 0.0f, 1.0f);
-#else
- flDamage *= 0.35;
+ // bullets hurt teammates less
+ flDamage *= clamp(((bitsDamageType & DMG_BULLET) ?
+ ff_damage_reduction_bullets.value :
+ ff_damage_reduction_other.value), 0.0f, 1.0f);
#endif // #ifdef REGAMEDLL_ADD
+ }
+
+#ifndef REGAMEDLL_ADD
+ flDamage *= 0.35;
+#endif
}
if (pAttack->m_pActiveItem)
@@ -1169,9 +1180,6 @@ BOOL EXT_FUNC CBasePlayer::__API_HOOK(TakeDamage)(entvars_t *pevInflictor, entva
}
}
- // keep track of amount of damage last sustained
- m_lastDamageAmount = flDamage;
-
// Armor
// armor doesn't protect against fall or drown damage!
if (pev->armorvalue != 0.0f && !(bitsDamageType & (DMG_DROWN | DMG_FALL)) && IsArmored(m_LastHitGroup))
@@ -1211,7 +1219,10 @@ BOOL EXT_FUNC CBasePlayer::__API_HOOK(TakeDamage)(entvars_t *pevInflictor, entva
Pain(m_LastHitGroup, false);
}
- LogAttack(pAttack, this, bTeamAttack, flDamage, armorHit, pev->health - flDamage, pev->armorvalue, GetWeaponName(pevInflictor, pevAttacker));
+ // keep track of amount of damage last sustained
+ m_lastDamageAmount = flDamage;
+
+ LogAttack(pAttack, this, bTeamAttack, flDamage, armorHit, pev->health - flDamage, pev->armorvalue, GetKillerWeaponName(pevInflictor, pevAttacker));
// this cast to INT is critical!!! If a player ends up with 0.5 health, the engine will get that
// as an int (zero) and think the player is dead! (this will incite a clientside screentilt, etc)
@@ -1229,9 +1240,13 @@ BOOL EXT_FUNC CBasePlayer::__API_HOOK(TakeDamage)(entvars_t *pevInflictor, entva
CBasePlayer *pPlayerAttacker = CBasePlayer::Instance(pevAttacker);
if (pPlayerAttacker && !pPlayerAttacker->IsBot() && pPlayerAttacker->m_iTeam != m_iTeam)
{
- TheCareerTasks->HandleEnemyInjury(GetWeaponName(pevInflictor, pevAttacker), pPlayerAttacker->HasShield(), pPlayerAttacker);
+ TheCareerTasks->HandleEnemyInjury(GetKillerWeaponName(pevInflictor, pevAttacker), pPlayerAttacker->HasShield(), pPlayerAttacker);
}
}
+
+#ifdef REGAMEDLL_API
+ CSPlayer()->RecordDamage(pAttack, flDamage);
+#endif
}
{
@@ -1292,7 +1307,7 @@ LINK_HOOK_CHAIN(CWeaponBox *, CreateWeaponBox, (CBasePlayerItem *pItem, CBasePla
CWeaponBox *EXT_FUNC __API_HOOK(CreateWeaponBox)(CBasePlayerItem *pItem, CBasePlayer *pPlayerOwner, const char *modelName, Vector &origin, Vector &angles, Vector &velocity, float lifeTime, bool packAmmo)
{
// create a box to pack the stuff into.
- CWeaponBox *pWeaponBox = (CWeaponBox *)CBaseEntity::Create("weaponbox", origin, angles, ENT(pPlayerOwner->pev));
+ CWeaponBox *pWeaponBox = (CWeaponBox *)CBaseEntity::Create("weaponbox", origin, angles, pPlayerOwner ? ENT(pPlayerOwner->pev) : nullptr);
if (pWeaponBox)
{
@@ -1306,11 +1321,21 @@ CWeaponBox *EXT_FUNC __API_HOOK(CreateWeaponBox)(CBasePlayerItem *pItem, CBasePl
// pack the ammo
bool exhaustibleAmmo = (pItem->iFlags() & ITEM_FLAG_EXHAUSTIBLE) == ITEM_FLAG_EXHAUSTIBLE;
- if (exhaustibleAmmo || packAmmo)
+ if ((exhaustibleAmmo || packAmmo) && pPlayerOwner)
{
+#ifndef REGAMEDLL_ADD
pWeaponBox->PackAmmo(MAKE_STRING(pItem->pszAmmo1()), pPlayerOwner->m_rgAmmo[pItem->PrimaryAmmoIndex()]);
-
+#else
+ pWeaponBox->GiveAmmo(pPlayerOwner->m_rgAmmo[pItem->PrimaryAmmoIndex()], (char *)pItem->pszAmmo1(), pItem->iMaxAmmo1());
+#endif
+#ifndef REGAMEDLL_FIXES
+ // by removing ammo ONLY on exhaustible weapons (slot 4 and 5)
+ // you are allowing to duplicate ammo whenever:
+ // (1) you have 2 weapons sharing the same ammo type (e.g. mp5navy and glock)
+ // (2) you are dropping a weapon alive and pickup another (with same ammo type) without ammo
+ // and, logically, you throw your ammo with your gun with packing enabled
if (exhaustibleAmmo)
+#endif
{
pPlayerOwner->m_rgAmmo[pItem->PrimaryAmmoIndex()] = 0;
}
@@ -1322,10 +1347,10 @@ CWeaponBox *EXT_FUNC __API_HOOK(CreateWeaponBox)(CBasePlayerItem *pItem, CBasePl
return pWeaponBox;
}
-void PackPlayerItem(CBasePlayer *pPlayer, CBasePlayerItem *pItem, bool packAmmo)
+CWeaponBox *PackPlayerItem(CBasePlayer *pPlayer, CBasePlayerItem *pItem, bool packAmmo)
{
if (!pItem)
- return;
+ return nullptr;
const char *modelName = GetCSModelName(pItem->m_iId);
if (modelName)
@@ -1335,7 +1360,7 @@ void PackPlayerItem(CBasePlayer *pPlayer, CBasePlayerItem *pItem, bool packAmmo)
Vector vecVelocity = pPlayer->pev->velocity * 0.75f;
// create a box to pack the stuff into
- CreateWeaponBox(pItem, pPlayer,
+ return CreateWeaponBox(pItem, pPlayer,
modelName,
vecOrigin,
vecAngles,
@@ -1343,6 +1368,8 @@ void PackPlayerItem(CBasePlayer *pPlayer, CBasePlayerItem *pItem, bool packAmmo)
CGameRules::GetItemKillDelay(), packAmmo
);
}
+
+ return nullptr;
}
#ifdef REGAMEDLL_ADD
@@ -1399,78 +1426,130 @@ void PackPlayerNade(CBasePlayer *pPlayer, CBasePlayerItem *pItem, bool packAmmo)
void CBasePlayer::PackDeadPlayerItems()
{
// get the game rules
- bool bPackGun = (g_pGameRules->DeadPlayerWeapons(this) != GR_PLR_DROP_GUN_NO);
+ int iPackGun = g_pGameRules->DeadPlayerWeapons(this);
bool bPackAmmo = (g_pGameRules->DeadPlayerAmmo(this) != GR_PLR_DROP_AMMO_NO);
- if (bPackGun)
+ if (iPackGun != GR_PLR_DROP_GUN_NO)
{
- bool bShieldDropped = false;
+ bool bSkipPrimSec = false;
if (HasShield())
{
DropShield();
- bShieldDropped = true;
+#ifdef REGAMEDLL_ADD
+ if(iPackGun != GR_PLR_DROP_GUN_ALL)
+#endif
+ {
+ bSkipPrimSec = true;
+ }
}
int nBestWeight = 0;
CBasePlayerItem *pBestItem = nullptr;
- for (int n = 0; n < MAX_ITEM_TYPES; n++)
+#ifdef REGAMEDLL_ADD
+ int iGunsPacked = 0;
+
+ if (iPackGun == GR_PLR_DROP_GUN_ACTIVE)
{
- // there's a weapon here. Should I pack it?
- CBasePlayerItem *pPlayerItem = m_rgpPlayerItems[n];
+ // check if we've just already dropped our active gun
+ if (!bSkipPrimSec && m_pActiveItem && m_pActiveItem->CanDrop() && m_pActiveItem->iItemSlot() < KNIFE_SLOT)
+ {
+ pBestItem = m_pActiveItem;
- while (pPlayerItem)
+ // if active item is undroppable, then nothing is dropped
+ }
+
+ // are we allowing nade drop?
+ if ((int)nadedrops.value >= 1)
{
- ItemInfo info;
- if (pPlayerItem->iItemSlot() < KNIFE_SLOT && !bShieldDropped)
+ // goto item loop but skip guns
+ iPackGun = GR_PLR_DROP_GUN_ALL;
+ bSkipPrimSec = true;
+ }
+ }
+
+ if (iPackGun == GR_PLR_DROP_GUN_ALL || iPackGun == GR_PLR_DROP_GUN_BEST)
+#endif
+ {
+ for (int n = 0; n < MAX_ITEM_TYPES; n++)
+ {
+ // there's a weapon here. Should I pack it?
+ CBasePlayerItem *pPlayerItem = m_rgpPlayerItems[n];
+
+ while (pPlayerItem)
{
+ ItemInfo info;
+ if (pPlayerItem->iItemSlot() < KNIFE_SLOT && !bSkipPrimSec)
+ {
#ifdef REGAMEDLL_API
- if (pPlayerItem->CSPlayerItem()->GetItemInfo(&info))
+ if (pPlayerItem->CSPlayerItem()->GetItemInfo(&info)
#else
- if (pPlayerItem->GetItemInfo(&info))
+ if (pPlayerItem->GetItemInfo(&info)
#endif
- {
- if (info.iWeight > nBestWeight)
+#ifdef REGAMEDLL_FIXES
+ && pPlayerItem->CanDrop() // needs to be droppable
+#endif
+ )
{
- nBestWeight = info.iWeight;
- pBestItem = pPlayerItem;
+#ifdef REGAMEDLL_ADD
+ if (iPackGun == GR_PLR_DROP_GUN_ALL)
+ {
+ CBasePlayerItem *pNext = pPlayerItem->m_pNext;
+
+ CWeaponBox *pWeaponBox = PackPlayerItem(this, pPlayerItem, bPackAmmo);
+ if (pWeaponBox)
+ {
+ // just push a few units in forward to separate them
+ pWeaponBox->pev->velocity = pWeaponBox->pev->velocity * (1.0 + (iGunsPacked * 0.2));
+ iGunsPacked++;
+ }
+
+ pPlayerItem = pNext;
+ continue;
+ }
+#endif
+ if (info.iWeight > nBestWeight)
+ {
+ nBestWeight = info.iWeight;
+ pBestItem = pPlayerItem;
+ }
}
}
- }
- // drop a grenade after death
- else if (pPlayerItem->iItemSlot() == GRENADE_SLOT)
- {
- if (AreRunningCZero())
+ // drop a grenade after death
+ else if (pPlayerItem->iItemSlot() == GRENADE_SLOT)
{
+ if (AreRunningCZero())
+ {
#ifdef REGAMEDLL_FIXES
- if (pPlayerItem->m_flStartThrow == 0.0f && m_rgAmmo[pPlayerItem->PrimaryAmmoIndex()] > 0)
+ if (pPlayerItem->m_flStartThrow == 0.0f && m_rgAmmo[pPlayerItem->PrimaryAmmoIndex()] > 0)
#endif
- {
- PackPlayerItem(this, pPlayerItem, true);
+ {
+ PackPlayerItem(this, pPlayerItem, true);
+ }
}
- }
#ifdef REGAMEDLL_ADD
- else
- {
- switch ((int)nadedrops.value)
- {
- case 1:
- PackPlayerNade(this, pPlayerItem, true);
- break;
- case 2:
+ else
{
- CBasePlayerItem *pNext = pPlayerItem->m_pNext;
- PackPlayerNade(this, pPlayerItem, true);
- pPlayerItem = pNext;
- continue;
- }
+ switch ((int)nadedrops.value)
+ {
+ case 1:
+ PackPlayerNade(this, pPlayerItem, true);
+ break;
+ case 2:
+ {
+ CBasePlayerItem *pNext = pPlayerItem->m_pNext;
+ PackPlayerNade(this, pPlayerItem, true);
+ pPlayerItem = pNext;
+ continue;
+ }
+ }
}
- }
#endif
- }
+ }
- pPlayerItem = pPlayerItem->m_pNext;
+ pPlayerItem = pPlayerItem->m_pNext;
+ }
}
}
@@ -1628,7 +1707,6 @@ void EXT_FUNC CBasePlayer::__API_HOOK(GiveDefaultItems)()
void CBasePlayer::RemoveAllItems(BOOL removeSuit)
{
- bool bKillProgBar = false;
int i;
#ifdef REGAMEDLL_FIXES
@@ -1642,34 +1720,18 @@ void CBasePlayer::RemoveAllItems(BOOL removeSuit)
if (m_bHasDefuser)
{
RemoveDefuser();
-
- MESSAGE_BEGIN(MSG_ONE, gmsgStatusIcon, nullptr, pev);
- WRITE_BYTE(STATUSICON_HIDE);
- WRITE_STRING("defuser");
- MESSAGE_END();
-
- SendItemStatus();
- bKillProgBar = true;
}
if (m_bHasC4)
{
m_bHasC4 = false;
pev->body = 0;
-
- MESSAGE_BEGIN(MSG_ONE, gmsgStatusIcon, nullptr, pev);
- WRITE_BYTE(STATUSICON_HIDE);
- WRITE_STRING("c4");
- MESSAGE_END();
-
- bKillProgBar = true;
+ SetBombIcon(FALSE);
+ SetProgressBarTime(0);
}
RemoveShield();
- if (bKillProgBar)
- SetProgressBarTime(0);
-
if (m_pActiveItem)
{
ResetAutoaim();
@@ -2059,8 +2121,27 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Killed)(entvars_t *pevAttacker, int iGib)
}
TheCareerTasks->HandleDeath(m_iTeam, this);
+
+#ifdef REGAMEDLL_FIXES
+ if (!m_bKilledByBomb)
+ {
+ CBasePlayer *pAttacker = CBasePlayer::Instance(pevAttacker);
+
+ if(pAttacker /*safety*/ && !pAttacker->IsBot() && pAttacker->m_iTeam != m_iTeam)
+ {
+ if (pAttacker->HasShield())
+ killerHasShield = true;
+
+ if (IsBot() && IsBlind()) // dystopm: shouldn't be !IsBot() ?
+ wasBlind = true;
+
+ TheCareerTasks->HandleEnemyKill(wasBlind, GetKillerWeaponName(GetLastInflictor(), pevAttacker), m_bHeadshotKilled, killerHasShield, pAttacker, this); // last 2 param swapped to match function definition
+ }
+ }
+#endif
}
+#ifndef REGAMEDLL_FIXES
if (!m_bKilledByBomb)
{
CBasePlayer *pAttacker = CBasePlayer::Instance(pevAttacker);
@@ -2085,16 +2166,17 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Killed)(entvars_t *pevAttacker, int iGib)
{
if (TheCareerTasks)
{
- TheCareerTasks->HandleEnemyKill(wasBlind, GetWeaponName(g_pevLastInflictor, pevAttacker), m_bHeadshotKilled, killerHasShield, this, pPlayer);
+ TheCareerTasks->HandleEnemyKill(wasBlind, GetKillerWeaponName(GetLastInflictor(), pevAttacker), m_bHeadshotKilled, killerHasShield, this, pPlayer);
}
}
}
}
+#endif
}
if (!m_bKilledByBomb)
{
- g_pGameRules->PlayerKilled(this, pevAttacker, g_pevLastInflictor);
+ g_pGameRules->PlayerKilled(this, pevAttacker, GetLastInflictor());
}
MESSAGE_BEGIN(MSG_ONE, gmsgNVGToggle, nullptr, pev);
@@ -2224,6 +2306,8 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Killed)(entvars_t *pevAttacker, int iGib)
UTIL_ScreenFade(this, Vector(0, 0, 0), 3, 3, 255, (FFADE_OUT | FFADE_STAYOUT));
}
#else
+
+ float flDyingDuration = GetSequenceDuration() + CGameRules::GetDyingTime();
switch ((int)fadetoblack.value)
{
default:
@@ -2239,12 +2323,12 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Killed)(entvars_t *pevAttacker, int iGib)
break;
}
- case 1:
+ case FADETOBLACK_STAY:
{
- UTIL_ScreenFade(this, Vector(0, 0, 0), 3, 3, 255, (FFADE_OUT | FFADE_STAYOUT));
+ UTIL_ScreenFade(this, Vector(0, 0, 0), 0.8f, flDyingDuration, 255, (FFADE_OUT | FFADE_STAYOUT));
break;
}
- case 2:
+ case FADETOBLACK_AT_DYING:
{
pev->iuser1 = OBS_CHASE_FREE;
pev->iuser2 = ENTINDEX(edict());
@@ -2255,15 +2339,7 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Killed)(entvars_t *pevAttacker, int iGib)
MESSAGE_BEGIN(MSG_ONE, gmsgADStop, nullptr, pev);
MESSAGE_END();
- for (int i = 1; i <= gpGlobals->maxClients; i++)
- {
- CBasePlayer* pObserver = UTIL_PlayerByIndex(i);
-
- if (pObserver == this || (pObserver && pObserver->IsObservingPlayer(this)))
- {
- UTIL_ScreenFade(pObserver, Vector(0, 0, 0), 1, 4, 255, (FFADE_OUT));
- }
- }
+ UTIL_ScreenFade(this, Vector(0, 0, 0), 0.8f, flDyingDuration, 255, (FFADE_OUT));
break;
}
@@ -2334,8 +2410,8 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Killed)(entvars_t *pevAttacker, int iGib)
}
SetSuitUpdate(nullptr, SUIT_SENTENCE, SUIT_REPEAT_OK);
- m_iClientHealth = 0;
+ m_iClientHealth = 0;
MESSAGE_BEGIN(MSG_ONE, gmsgHealth, nullptr, pev);
WRITE_BYTE(m_iClientHealth);
MESSAGE_END();
@@ -2363,31 +2439,18 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Killed)(entvars_t *pevAttacker, int iGib)
else if (m_bHasDefuser)
{
RemoveDefuser();
-
#ifdef REGAMEDLL_FIXES
- CItemThighPack *pDefuser = (CItemThighPack *)CBaseEntity::Create("item_thighpack", pev->origin, g_vecZero, ENT(pev));
-
- pDefuser->SetThink(&CBaseEntity::SUB_Remove);
- pDefuser->pev->nextthink = gpGlobals->time + CGameRules::GetItemKillDelay();
- pDefuser->pev->spawnflags |= SF_NORESPAWN;
+ SpawnDefuser(pev->origin, ENT(pev));
#else
GiveNamedItem("item_thighpack");
#endif
-
- MESSAGE_BEGIN(MSG_ONE, gmsgStatusIcon, nullptr, pev);
- WRITE_BYTE(STATUSICON_HIDE);
- WRITE_STRING("defuser");
- MESSAGE_END();
-
- SendItemStatus();
- }
-
- if (m_bIsDefusing)
- {
- SetProgressBarTime(0);
}
+#ifndef REGAMEDLL_FIXES
+ // NOTE: moved to RemoveDefuser
m_bIsDefusing = false;
+#endif
+
BuyZoneIcon_Clear(this);
#ifdef REGAMEDLL_ADD
@@ -2404,7 +2467,7 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Killed)(entvars_t *pevAttacker, int iGib)
HintMessage("#Hint_cannot_play_because_tk", TRUE, TRUE);
}
- if ((pev->health < -9000 && iGib != GIB_NEVER) || iGib == GIB_ALWAYS)
+ if (ShouldGibPlayer(iGib))
{
#ifndef REGAMEDLL_FIXES
@@ -3578,16 +3641,20 @@ void EXT_FUNC CBasePlayer::__API_HOOK(JoiningThink)()
ResetMenu();
m_iJoiningState = SHOWTEAMSELECT;
+#ifndef REGAMEDLL_FIXES
+ // NOTE: client already clears StatusIcon on join
MESSAGE_BEGIN(MSG_ONE, gmsgStatusIcon, nullptr, pev);
WRITE_BYTE(STATUSICON_HIDE);
WRITE_STRING("defuser");
MESSAGE_END();
- m_bHasDefuser = false;
+ m_bHasDefuser = false; // set in ClientPutInServer
+#endif
m_fLastMovement = gpGlobals->time;
m_bMissionBriefing = false;
- SendItemStatus();
+ SendItemStatus(); // NOTE: must be on UpdateClientData
+
break;
}
case READINGLTEXT:
@@ -3611,7 +3678,11 @@ void EXT_FUNC CBasePlayer::__API_HOOK(JoiningThink)()
}
}
- if (m_pIntroCamera && gpGlobals->time >= m_fIntroCamTime)
+ if (m_pIntroCamera && gpGlobals->time >= m_fIntroCamTime
+#ifdef REGAMEDLL_FIXES
+ && m_fIntroCamTime > 0.0 // update only if cameras are available
+#endif
+ )
{
// find the next another camera
m_pIntroCamera = UTIL_FindEntityByClassname(m_pIntroCamera, "trigger_camera");
@@ -3706,18 +3777,11 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Disappear)()
else if (m_bHasDefuser)
{
RemoveDefuser();
-
-#ifndef REGAMEDLL_FIXES
+#ifdef REGAMEDLL_FIXES
+ SpawnDefuser(pev->origin, ENT(pev));
+#else
GiveNamedItem("item_thighpack");
#endif
-
- MESSAGE_BEGIN(MSG_ONE, gmsgStatusIcon, nullptr, pev);
- WRITE_BYTE(STATUSICON_HIDE);
- WRITE_STRING("defuser");
- MESSAGE_END();
-
- SendItemStatus();
- SetProgressBarTime(0);
}
BuyZoneIcon_Clear(this);
@@ -3729,7 +3793,9 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Disappear)()
pev->angles.z = 0;
}
-void CBasePlayer::PlayerDeathThink()
+LINK_HOOK_CLASS_VOID_CHAIN2(CBasePlayer, PlayerDeathThink)
+
+void EXT_FUNC CBasePlayer::__API_HOOK(PlayerDeathThink)()
{
if (m_iJoiningState != JOINED)
return;
@@ -3789,7 +3855,7 @@ void CBasePlayer::PlayerDeathThink()
{
// if the player has been dead for one second longer than allowed by forcerespawn,
// forcerespawn isn't on. Send the player off to an intermission camera until they choose to respawn.
- if (g_pGameRules->IsMultiplayer() && HasTimePassedSinceDeath(3.0f) && !(m_afPhysicsFlags & PFLAG_OBSERVER))
+ if (g_pGameRules->IsMultiplayer() && HasTimePassedSinceDeath(CGameRules::GetDyingTime()) && !(m_afPhysicsFlags & PFLAG_OBSERVER))
{
// Send message to everybody to spawn a corpse.
SpawnClientSideCorpse();
@@ -3878,9 +3944,7 @@ void EXT_FUNC CBasePlayer::__API_HOOK(RoundRespawn)()
#ifdef REGAMEDLL_FIXES
if (m_bPunishedForTK && pev->health > 0)
- {
- ClientKill(ENT(pev));
- }
+ Kill();
#endif
}
@@ -4047,11 +4111,10 @@ void CBasePlayer::PlayerUse()
if (pTrain && pTrain->Classify() == CLASS_VEHICLE)
{
#ifdef REGAMEDLL_ADD
- if (legacy_vehicle_block.value)
- ((CFuncVehicle *)pTrain)->m_pDriver = nullptr;
-#else
- ((CFuncVehicle *)pTrain)->m_pDriver = nullptr;
+ if (legacy_vehicle_block.value == 0)
+ return;
#endif
+ ((CFuncVehicle *)pTrain)->m_pDriver = nullptr;
}
return;
}
@@ -4593,12 +4656,17 @@ void EXT_FUNC CBasePlayer::__API_HOOK(PreThink)()
{
m_afPhysicsFlags &= ~PFLAG_ONTRAIN;
m_iTrain = (TRAIN_NEW | TRAIN_OFF);
+
+#ifdef REGAMEDLL_FIXES
+ if (pTrain && pTrain->Classify() == CLASS_VEHICLE) // ensure func_vehicle's m_pDriver assignation
+#endif
+ {
#ifdef REGAMEDLL_ADD
- if (legacy_vehicle_block.value)
- ((CFuncVehicle *)pTrain)->m_pDriver = nullptr;
-#else
- ((CFuncVehicle *)pTrain)->m_pDriver = nullptr;
+ if (legacy_vehicle_block.value == 0)
+ return;
#endif
+ ((CFuncVehicle *)pTrain)->m_pDriver = nullptr;
+ }
return;
}
}
@@ -4607,12 +4675,17 @@ void EXT_FUNC CBasePlayer::__API_HOOK(PreThink)()
// Turn off the train if you jump, strafe, or the train controls go dead
m_afPhysicsFlags &= ~PFLAG_ONTRAIN;
m_iTrain = (TRAIN_NEW | TRAIN_OFF);
+
+#ifdef REGAMEDLL_FIXES
+ if (pTrain->Classify() == CLASS_VEHICLE) // ensure func_vehicle's m_pDriver assignation
+#endif
+ {
#ifdef REGAMEDLL_ADD
- if (legacy_vehicle_block.value)
- ((CFuncVehicle *)pTrain)->m_pDriver = nullptr;
-#else
- ((CFuncVehicle *)pTrain)->m_pDriver = nullptr;
+ if (legacy_vehicle_block.value == 0)
+ return;
#endif
+ ((CFuncVehicle *)pTrain)->m_pDriver = nullptr;
+ }
return;
}
@@ -4718,6 +4791,8 @@ void EXT_FUNC CBasePlayer::__API_HOOK(PreThink)()
#endif
}
+LINK_HOOK_CLASS_VOID_CHAIN2(CBasePlayer, CheckTimeBasedDamage)
+
// If player is taking time based damage, continue doing damage to player -
// this simulates the effect of being poisoned, gassed, dosed with radiation etc -
// anything that continues to do damage even after the initial contact stops.
@@ -4726,7 +4801,7 @@ void EXT_FUNC CBasePlayer::__API_HOOK(PreThink)()
// The m_bitsDamageType bit MUST be set if any damage is to be taken.
// This routine will detect the initial on value of the m_bitsDamageType
// and init the appropriate counter. Only processes damage every second.
-void CBasePlayer::CheckTimeBasedDamage()
+void EXT_FUNC CBasePlayer::__API_HOOK(CheckTimeBasedDamage)()
{
int i;
byte bDuration = 0;
@@ -4751,7 +4826,7 @@ void CBasePlayer::CheckTimeBasedDamage()
{
switch (i)
{
- case ITBD_PARALLYZE:
+ case ITBD_PARALYZE:
// UNDONE - flag movement as half-speed
bDuration = PARALYZE_DURATION;
break;
@@ -5107,7 +5182,17 @@ void EXT_FUNC CBasePlayer::__API_HOOK(PostThink)()
#endif
{
m_LastHitGroup = HITGROUP_GENERIC;
- TakeDamage(VARS(eoNullEntity), VARS(eoNullEntity), flFallDamage, DMG_FALL);
+
+ // FIXED: The player falling to the ground,
+ // the damage caused by the fall is initiated by himself (and not by the world)
+ entvars_t *pevAttacker =
+#ifdef REGAMEDLL_FIXES
+ pev;
+#else
+ VARS(eoNullEntity);
+#endif
+ TakeDamage(pevAttacker, pevAttacker, flFallDamage, DMG_FALL);
+
pev->punchangle.x = 0;
if (TheBots)
{
@@ -5293,7 +5378,9 @@ CBaseEntity *g_pLastSpawn;
CBaseEntity *g_pLastCTSpawn;
CBaseEntity *g_pLastTerroristSpawn;
-edict_t *CBasePlayer::EntSelectSpawnPoint()
+LINK_HOOK_CLASS_CHAIN2(edict_t *, CBasePlayer, EntSelectSpawnPoint)
+
+edict_t *EXT_FUNC CBasePlayer::__API_HOOK(EntSelectSpawnPoint)()
{
CBaseEntity *pSpot;
@@ -5622,10 +5709,7 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Spawn)()
ReloadWeapons();
#endif
- if (m_bHasDefuser)
- pev->body = 1;
- else
- pev->body = 0;
+ pev->body = m_bHasDefuser ? 1 : 0;
if (m_bMissionBriefing)
{
@@ -5937,6 +6021,8 @@ void CBasePlayer::Reset()
if (CSPlayer()->GetProtectionState() == CCSPlayer::ProtectionSt_Active) {
RemoveSpawnProtection();
}
+
+ CSPlayer()->ResetAllStats();
#endif
}
@@ -6312,6 +6398,11 @@ void CBasePlayer::ForceClientDllUpdate()
#ifdef REGAMEDLL_FIXES
// fix for https://github.com/ValveSoftware/halflife/issues/1567
m_iClientHideHUD = -1;
+ m_flNextSBarUpdateTime = -1;
+ InitStatusBar();
+#ifdef BUILD_LATEST
+ m_tmNextAccountHealthUpdate = -1;
+#endif
#endif
m_iClientHealth = -1;
@@ -6324,6 +6415,84 @@ void CBasePlayer::ForceClientDllUpdate()
// Now force all the necessary messages to be sent.
UpdateClientData();
HandleSignals();
+
+#ifdef REGAMEDLL_FIXES
+ // Update HUD backpack ammo
+ for (int i = 0; i < MAX_AMMO_SLOTS; i++)
+ m_rgAmmoLast[i] = -1;
+
+ // Force update server name
+ MESSAGE_BEGIN(MSG_ONE, gmsgServerName, nullptr, pev);
+ WRITE_STRING(CVAR_GET_STRING("hostname"));
+ MESSAGE_END();
+
+ MESSAGE_BEGIN(MSG_ONE, SVC_ROOMTYPE, nullptr, pev);
+ WRITE_SHORT(int(CVAR_GET_FLOAT("room_type")));
+ MESSAGE_END();
+
+ SendItemStatus();
+
+ // Loop through all active players and update their info to the client who started recording the demo
+ for (int i = 1; i <= gpGlobals->maxClients; i++)
+ {
+ CBasePlayer *pPlayer = UTIL_PlayerByIndex(i);
+ if (!pPlayer || FNullEnt(pPlayer->edict()))
+ continue;
+
+ if (pPlayer->IsDormant())
+ continue;
+
+ if (pev->deadflag == DEAD_NO)
+ {
+ // NOTE: Don't use here PlayerRelationShip,
+ // because we have to send a radar message about the players in the team anyway,
+ // even if they are not teammates
+ bool sameTeam = pPlayer->m_iTeam == m_iTeam;
+ if (sameTeam)
+ {
+ const Vector &vecOrigin = CSGameRules()->IsFreeForAll() ?
+ g_vecZero : pPlayer->pev->origin;
+
+ MESSAGE_BEGIN(MSG_ONE, gmsgRadar, nullptr, pev);
+ WRITE_BYTE(pPlayer->entindex());
+ WRITE_COORD(vecOrigin.x);
+ WRITE_COORD(vecOrigin.y);
+ WRITE_COORD(vecOrigin.z);
+ MESSAGE_END();
+ }
+
+ // Update last location of players
+ if (sameTeam || pPlayer->m_iTeam == SPECTATOR)
+ {
+ if (pPlayer->m_lastLocation[0])
+ {
+ MESSAGE_BEGIN(MSG_ONE, gmsgLocation, nullptr, pev);
+ WRITE_BYTE(pPlayer->entindex());
+ WRITE_STRING(pPlayer->m_lastLocation);
+ MESSAGE_END();
+ }
+ }
+ }
+
+ // Update team info
+ MESSAGE_BEGIN(MSG_ONE, gmsgTeamInfo, nullptr, pev);
+ WRITE_BYTE(pPlayer->entindex());
+ WRITE_STRING(GetTeamName(pPlayer->m_iTeam));
+ MESSAGE_END();
+
+ // Update score info Frags, Deaths, etc
+ MESSAGE_BEGIN(MSG_ONE, gmsgScoreInfo, nullptr, pev);
+ WRITE_BYTE(pPlayer->entindex());
+ WRITE_SHORT(int(pPlayer->pev->frags));
+ WRITE_SHORT(pPlayer->m_iDeaths);
+ WRITE_SHORT(0);
+ WRITE_SHORT(pPlayer->m_iTeam);
+ MESSAGE_END();
+
+ // Update player attributes DEAD, BOMB, VIP etc
+ pPlayer->SetScoreAttrib(this);
+ }
+#endif
}
LINK_HOOK_CLASS_VOID_CHAIN2(CBasePlayer, ImpulseCommands)
@@ -6351,8 +6520,6 @@ void EXT_FUNC CBasePlayer::__API_HOOK(ImpulseCommands)()
else
iOn = 0;
- assert(gmsgLogo > 0);
-
MESSAGE_BEGIN(MSG_ONE, gmsgLogo, nullptr, pev);
WRITE_BYTE(iOn);
MESSAGE_END();
@@ -6530,7 +6697,7 @@ void CBasePlayer::CheatImpulseCommands(int iImpulse)
TraceResult tr;
Vector dir(0, 0, 1);
- UTIL_BloodDrips(pev->origin, dir, BLOOD_COLOR_RED, 2000);
+ UTIL_BloodDrips(pev->origin, BLOOD_COLOR_RED, 2000);
for (int r = 1; r < 4; r++)
{
@@ -6990,9 +7157,6 @@ void CBasePlayer::SendAmmoUpdate()
{
m_rgAmmoLast[i] = m_rgAmmo[i];
- assert(m_rgAmmo[i] >= 0);
- assert(m_rgAmmo[i] <= 255);
-
// send "Ammo" update message
MESSAGE_BEGIN(MSG_ONE, gmsgAmmoX, nullptr, pev);
WRITE_BYTE(i);
@@ -7274,8 +7438,6 @@ void EXT_FUNC CBasePlayer::__API_HOOK(UpdateClientData)()
{
m_iClientBattery = int(pev->armorvalue);
- assert(gmsgBattery > 0);
-
// send "armor" update message
MESSAGE_BEGIN(MSG_ONE, gmsgBattery, nullptr, pev);
WRITE_SHORT(int(pev->armorvalue));
@@ -7297,7 +7459,10 @@ void EXT_FUNC CBasePlayer::__API_HOOK(UpdateClientData)()
if (pEntity)
{
- damageOrigin = pEntity->Center();
+ if (pEntity == this && (m_bitsDamageType & DMG_FALL))
+ damageOrigin = Vector(0, 0, 0); // do not show direction of damage caused by fall
+ else
+ damageOrigin = pEntity->Center();
}
}
@@ -7354,8 +7519,6 @@ void EXT_FUNC CBasePlayer::__API_HOOK(UpdateClientData)()
if (m_iTrain & TRAIN_NEW)
{
- assert(gmsgTrain > 0);
-
// send "train hud" update message
MESSAGE_BEGIN(MSG_ONE, gmsgTrain, nullptr, pev);
WRITE_BYTE(m_iTrain & 0xF);
@@ -7978,8 +8141,10 @@ CBaseEntity *EXT_FUNC CBasePlayer::__API_HOOK(DropPlayerItem)(const char *pszIte
g_pGameRules->GetNextBestWeapon(this, pWeapon);
UTIL_MakeVectors(pev->angles);
+#ifndef REGAMEDLL_FIXES
if (pWeapon->iItemSlot() == PRIMARY_WEAPON_SLOT)
- m_bHasPrimary = false;
+ m_bHasPrimary = false; // I may have more than just 1 primary weapon :)
+#endif
if (FClassnameIs(pWeapon->pev, "weapon_c4"))
{
@@ -8028,19 +8193,33 @@ CBaseEntity *EXT_FUNC CBasePlayer::__API_HOOK(DropPlayerItem)(const char *pszIte
Vector vecAngles = pev->angles;
Vector vecVelocity = gpGlobals->v_forward * 300 + gpGlobals->v_forward * 100;
+ bool bPackAmmo = false;
+
+#ifdef REGAMEDLL_ADD
+ if (ammodrop.value >= 2.0f)
+ bPackAmmo = true;
+#endif
+
CWeaponBox *pWeaponBox = CreateWeaponBox(pWeapon, this,
modelname,
vecOrigin,
vecAngles,
vecVelocity,
CGameRules::GetItemKillDelay(),
- false);
+ bPackAmmo
+ );
if (!pWeaponBox)
{
return nullptr;
}
+#ifdef REGAMEDLL_FIXES
+ if (!m_rgpPlayerItems[PRIMARY_WEAPON_SLOT]) {
+ m_bHasPrimary = false; // ensure value assignation on successful weapon removal
+ }
+#endif
+
if (FClassnameIs(pWeapon->pev, "weapon_c4"))
{
pWeaponBox->m_bIsBomb = true;
@@ -8212,14 +8391,6 @@ void CBasePlayer::__API_HOOK(SwitchTeam)()
{
RemoveDefuser();
- MESSAGE_BEGIN(MSG_ONE, gmsgStatusIcon, nullptr, pev);
- WRITE_BYTE(STATUSICON_HIDE);
- WRITE_STRING("defuser");
- MESSAGE_END();
-
- SendItemStatus();
- SetProgressBarTime(0);
-
#ifndef REGAMEDLL_FIXES
// NOTE: unreachable code - Vaqtincha
for (int i = 0; i < MAX_ITEM_TYPES; i++)
@@ -8448,7 +8619,6 @@ void CStripWeapons::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE
if (slot == ALL_OTHER_ITEMS)
{
- pPlayer->CSPlayer()->RemovePlayerItem("item_thighpack");
pPlayer->CSPlayer()->RemovePlayerItem("item_longjump");
pPlayer->CSPlayer()->RemovePlayerItem("item_assaultsuit");
pPlayer->CSPlayer()->RemovePlayerItem("item_kevlar");
@@ -8737,6 +8907,23 @@ int GetPlayerGaitsequence(const edict_t *pEdict)
return pPlayer->m_iGaitsequence;
}
+float CBasePlayer::GetDyingAnimationDuration() const
+{
+ float animDuration = -1.0f;
+
+ if (CGameRules::GetDyingTime() < DEATH_ANIMATION_TIME) // a short time, timeDiff estimates to be small
+ {
+ float flSequenceDuration = GetSequenceDuration();
+ if (flSequenceDuration > 0)
+ animDuration = flSequenceDuration;
+ }
+
+ if (animDuration <= 0)
+ animDuration = CGameRules::GetDyingTime(); // in case of failure
+
+ return animDuration;
+}
+
void CBasePlayer::SpawnClientSideCorpse()
{
#ifdef REGAMEDLL_FIXES
@@ -8744,9 +8931,7 @@ void CBasePlayer::SpawnClientSideCorpse()
if (pev->effects & EF_NODRAW)
return;
- // do not make a corpse if the player goes to respawn.
- if (pev->deadflag == DEAD_RESPAWNABLE)
- return;
+ // deadflag == DEAD_RESPAWNABLE already checked before
#endif
#ifdef REGAMEDLL_ADD
@@ -8756,6 +8941,27 @@ void CBasePlayer::SpawnClientSideCorpse()
char *infobuffer = GET_INFO_BUFFER(edict());
char *pModel = GET_KEY_VALUE(infobuffer, "model");
+ float timeDiff = pev->animtime - gpGlobals->time;
+
+#ifdef REGAMEDLL_ADD
+ if (CGameRules::GetDyingTime() < DEATH_ANIMATION_TIME) // a short time, timeDiff estimates to be small
+ {
+ float animDuration = GetDyingAnimationDuration();
+
+ // client receives a negative value
+ animDuration *= -1.0;
+
+ if (animDuration < timeDiff) // reasonable way to fix client side unfinished sequence bug
+ {
+ // by some reason, if client receives a value less
+ // than "(negative current sequence time) * 100"
+ // animation will play visually awkward
+ // at this function call time, player death animation
+ // has already finished so we can safely fake it
+ timeDiff = animDuration;
+ }
+ }
+#endif
MESSAGE_BEGIN(MSG_ALL, gmsgSendCorpse);
WRITE_STRING(pModel);
@@ -8765,14 +8971,17 @@ void CBasePlayer::SpawnClientSideCorpse()
WRITE_COORD(pev->angles.x);
WRITE_COORD(pev->angles.y);
WRITE_COORD(pev->angles.z);
- WRITE_LONG((pev->animtime - gpGlobals->time) * 100);
+ WRITE_LONG(timeDiff * 100);
WRITE_BYTE(pev->sequence);
WRITE_BYTE(pev->body);
WRITE_BYTE(m_iTeam);
WRITE_BYTE(entindex());
MESSAGE_END();
+#ifndef REGAMEDLL_FIXES
+ // already defined in StartDeathCam
m_canSwitchObserverModes = true;
+#endif
if (TheTutor)
{
@@ -9821,7 +10030,7 @@ void CBasePlayer::UpdateLocation(bool forceUpdate)
const char *placeName = "";
- if (pev->deadflag == DEAD_NO && AreRunningCZero())
+ if (pev->deadflag == DEAD_NO && AreBotsAllowed())
{
// search the place name where is located the player
Place playerPlace = TheNavAreaGrid.GetPlace(&pev->origin);
@@ -10021,10 +10230,61 @@ void CBasePlayer::RemoveBomb()
}
}
+void CBasePlayer::GiveDefuser()
+{
+ m_bHasDefuser = true;
+ pev->body = 1;
+
+ MESSAGE_BEGIN(MSG_ONE, gmsgStatusIcon, nullptr, pev);
+ WRITE_BYTE(STATUSICON_SHOW);
+ WRITE_STRING("defuser");
+ WRITE_BYTE(0);
+ WRITE_BYTE(160);
+ WRITE_BYTE(0);
+ MESSAGE_END();
+
+ SendItemStatus();
+
+#if defined(REGAMEDLL_FIXES) || defined(BUILD_LATEST)
+ SetScoreboardAttributes();
+#endif
+}
+
void CBasePlayer::RemoveDefuser()
{
m_bHasDefuser = false;
pev->body = 0;
+
+ MESSAGE_BEGIN(MSG_ONE, gmsgStatusIcon, nullptr, pev);
+ WRITE_BYTE(STATUSICON_HIDE);
+ WRITE_STRING("defuser");
+ MESSAGE_END();
+
+ SendItemStatus();
+
+#ifdef REGAMEDLL_FIXES
+ if (m_bIsDefusing)
+ {
+ SetProgressBarTime(0);
+ m_bIsDefusing = false;
+ }
+#else
+ SetProgressBarTime(0);
+#endif
+}
+
+CItemThighPack *SpawnDefuser(const Vector &vecOrigin, edict_t *pentOwner)
+{
+ CItemThighPack *pDefuser = (CItemThighPack *)CBaseEntity::Create("item_thighpack", vecOrigin, g_vecZero, pentOwner);
+
+ if (pDefuser)
+ {
+ pDefuser->SetThink(&CBaseEntity::SUB_Remove);
+ pDefuser->pev->nextthink = gpGlobals->time + CGameRules::GetItemKillDelay();
+ pDefuser->pev->spawnflags |= SF_NORESPAWN;
+ }
+
+ return pDefuser;
}
void CBasePlayer::Disconnect()
@@ -10099,8 +10359,8 @@ bool EXT_FUNC CBasePlayer::__API_HOOK(MakeBomber)()
}
m_bHasC4 = true;
- SetBombIcon();
pev->body = 1;
+ SetBombIcon();
m_flDisplayHistory |= DHF_BOMB_RETRIEVED;
HintMessage("#Hint_you_have_the_bomb", FALSE, TRUE);
@@ -10263,6 +10523,7 @@ void EXT_FUNC CBasePlayer::__API_HOOK(SetSpawnProtection)(float flProtectionTime
#ifdef REGAMEDLL_ADD
if (respawn_immunity_effects.value > 0)
{
+ CSPlayer()->m_bSpawnProtectionEffects = true;
pev->rendermode = kRenderTransAdd;
pev->renderamt = 100.0f;
@@ -10284,12 +10545,11 @@ LINK_HOOK_CLASS_VOID_CHAIN2(CBasePlayer, RemoveSpawnProtection)
void CBasePlayer::__API_HOOK(RemoveSpawnProtection)()
{
#ifdef REGAMEDLL_ADD
- if (respawn_immunity_effects.value > 0)
+ if (CSPlayer()->m_bSpawnProtectionEffects)
{
- if (pev->rendermode == kRenderTransAdd &&
- pev->renderamt == 100.0f)
+ if (pev->rendermode == kRenderTransAdd && pev->renderamt == 100.0f)
{
- pev->renderamt = 255.0f;
+ pev->renderamt = 255.0f;
pev->rendermode = kRenderNormal;
}
@@ -10297,6 +10557,8 @@ void CBasePlayer::__API_HOOK(RemoveSpawnProtection)()
WRITE_BYTE(STATUSICON_HIDE);
WRITE_STRING("suithelmet_full");
MESSAGE_END();
+
+ CSPlayer()->m_bSpawnProtectionEffects = false;
}
CSPlayer()->m_flSpawnProtectionEndTime = 0.0f;
@@ -10327,3 +10589,23 @@ void EXT_FUNC CBasePlayer::__API_HOOK(DropIdlePlayer)(const char *reason)
SERVER_COMMAND(UTIL_VarArgs("kick \"%s\"\n", STRING(pev->netname)));
#endif // #ifdef REGAMEDLL_FIXES
}
+
+bool CBasePlayer::Kill()
+{
+ if (GetObserverMode() != OBS_NONE)
+ return false;
+
+ if (m_iJoiningState != JOINED)
+ return false;
+
+ m_LastHitGroup = HITGROUP_GENERIC;
+
+ // have the player kill himself
+ pev->health = 0.0f;
+ Killed(pev, GIB_NEVER);
+
+ if (CSGameRules()->m_pVIP == this)
+ CSGameRules()->m_iConsecutiveVIP = 10;
+
+ return true;
+}
diff --git a/regamedll/dlls/player.h b/regamedll/dlls/player.h
index e62c1b730..4595bf226 100644
--- a/regamedll/dlls/player.h
+++ b/regamedll/dlls/player.h
@@ -444,6 +444,10 @@ class CBasePlayer: public CBaseMonster {
void Pain_OrigFunc(int iLastHitGroup, bool bHasArmour);
void DeathSound_OrigFunc();
void JoiningThink_OrigFunc();
+ void CheckTimeBasedDamage_OrigFunc();
+ edict_t *EntSelectSpawnPoint_OrigFunc();
+ void PlayerDeathThink_OrigFunc();
+ void Observer_Think_OrigFunc();
CCSPlayer *CSPlayer() const;
#endif // REGAMEDLL_API
@@ -453,6 +457,7 @@ class CBasePlayer: public CBaseMonster {
static CBasePlayer *Instance(entvars_t *pev) { return Instance(ENT(pev)); }
static CBasePlayer *Instance(int offset) { return Instance(ENT(offset)); }
+ float GetDyingAnimationDuration() const;
void SpawnClientSideCorpse();
void Observer_FindNextPlayer(bool bReverse, const char *name = nullptr);
CBasePlayer *Observer_IsValidTarget(int iPlayerIndex, bool bSameTeam);
@@ -585,6 +590,7 @@ class CBasePlayer: public CBaseMonster {
bool IsReloading() const;
bool HasTimePassedSinceDeath(float duration) const;
bool IsBlind() const { return (m_blindUntilTime > gpGlobals->time); }
+ bool IsFullyBlind(const float flPeekTime = 0.6f) const { return m_blindAlpha >= 255 && m_blindFadeTime > (flPeekTime * 2.0f) && (m_blindStartTime + m_blindHoldTime + flPeekTime) > gpGlobals->time; }
bool IsAutoFollowAllowed() const { return (gpGlobals->time > m_allowAutoFollowTime); }
void InhibitAutoFollow(float duration) { m_allowAutoFollowTime = gpGlobals->time + duration; }
void AllowAutoFollow() { m_allowAutoFollowTime = 0; }
@@ -628,12 +634,15 @@ class CBasePlayer: public CBaseMonster {
void DropPrimary();
void OnSpawnEquip(bool addDefault = true, bool equipGame = true);
void RemoveBomb();
+ void GiveDefuser();
void RemoveDefuser();
void HideTimer();
bool MakeBomber();
bool GetIntoGame();
bool ShouldToShowAccount(CBasePlayer *pReceiver) const;
bool ShouldToShowHealthInfo(CBasePlayer *pReceiver) const;
+ const char *GetKillerWeaponName(entvars_t *pevInflictor, entvars_t *pevKiller) const;
+ bool ShouldGibPlayer(int iGib);
CBasePlayerItem *GetItemByName(const char *itemName);
CBasePlayerItem *GetItemById(WeaponIdType weaponID);
@@ -642,6 +651,7 @@ class CBasePlayer: public CBaseMonster {
void RemoveSpawnProtection();
void UseEmpty();
void DropIdlePlayer(const char *reason);
+ bool Kill();
// templates
template
@@ -906,6 +916,7 @@ class CBasePlayer: public CBaseMonster {
CWeaponBox *CreateWeaponBox(CBasePlayerItem *pItem, CBasePlayer *pPlayerOwner, const char *modelName, Vector &origin, Vector &angles, Vector &velocity, float lifeTime, bool packAmmo);
CWeaponBox *CreateWeaponBox_OrigFunc(CBasePlayerItem *pItem, CBasePlayer *pPlayerOwner, const char *modelName, Vector &origin, Vector &angles, Vector &velocity, float lifeTime, bool packAmmo);
+CItemThighPack *SpawnDefuser(const Vector &vecOrigin, edict_t *pentOwner);
class CWShield: public CBaseEntity
{
@@ -945,7 +956,24 @@ inline bool CBasePlayer::HasTimePassedSinceDeath(float duration) const
inline CCSPlayer *CBasePlayer::CSPlayer() const {
return reinterpret_cast(this->m_pEntity);
}
-#endif
+#else // !REGAMEDLL_API
+
+// Determine whether player can be gibbed or not
+inline bool CBasePlayer::ShouldGibPlayer(int iGib)
+{
+ // Always gib the player regardless of incoming damage
+ if (iGib == GIB_ALWAYS)
+ return true;
+
+ // Gib the player if health is below the gib damage threshold
+ if (pev->health < GIB_PLAYER_THRESHOLD && iGib != GIB_NEVER)
+ return true;
+
+ // do not gib the player
+ return false;
+}
+
+#endif // !REGAMEDLL_API
#ifdef REGAMEDLL_FIXES
@@ -967,7 +995,6 @@ inline CBasePlayer *UTIL_PlayerByIndexSafe(int playerIndex)
return pPlayer;
}
-extern entvars_t *g_pevLastInflictor;
extern CBaseEntity *g_pLastSpawn;
extern CBaseEntity *g_pLastCTSpawn;
extern CBaseEntity *g_pLastTerroristSpawn;
@@ -995,7 +1022,6 @@ void SendItemStatus(CBasePlayer *pPlayer);
const char *GetCSModelName(int item_id);
Vector VecVelocityForDamage(float flDamage);
int TrainSpeed(int iSpeed, int iMax);
-const char *GetWeaponName(entvars_t *pevInflictor, entvars_t *pKiller);
void LogAttack(CBasePlayer *pAttacker, CBasePlayer *pVictim, int teamAttack, int healthHit, int armorHit, int newHealth, int newArmor, const char *killer_weapon_name);
bool CanSeeUseable(CBasePlayer *me, CBaseEntity *pEntity);
void FixPlayerCrouchStuck(edict_t *pPlayer);
diff --git a/regamedll/dlls/saverestore.cpp b/regamedll/dlls/saverestore.cpp
index a8e63d126..a3a55c7f6 100644
--- a/regamedll/dlls/saverestore.cpp
+++ b/regamedll/dlls/saverestore.cpp
@@ -955,10 +955,10 @@ void CGlobalState::DumpGlobals()
void CGlobalState::EntityAdd(string_t globalname, string_t mapName, GLOBALESTATE state)
{
- assert(!Find(globalname));
+ DbgAssert(!Find(globalname));
globalentity_t *pNewEntity = (globalentity_t *)calloc(sizeof(globalentity_t), 1);
- assert(pNewEntity != nullptr);
+ DbgAssert(pNewEntity != nullptr);
pNewEntity->pNext = m_pList;
m_pList = pNewEntity;
diff --git a/regamedll/dlls/subs.cpp b/regamedll/dlls/subs.cpp
index ad269c062..4c938c270 100644
--- a/regamedll/dlls/subs.cpp
+++ b/regamedll/dlls/subs.cpp
@@ -330,8 +330,8 @@ void CBaseToggle::KeyValue(KeyValueData *pkvd)
// pev->origin traveling at flSpeed
void CBaseToggle::LinearMove(Vector vecDest, float flSpeed)
{
- assert(("LinearMove: no speed is defined!", flSpeed != 0));
- //assert(("LinearMove: no post-move function defined", m_pfnCallWhenMoveDone != nullptr));
+ DbgAssertMsg(flSpeed != 0, "LinearMove: no speed is defined!");
+ //DbgAssertMsg(m_pfnCallWhenMoveDone != nullptr, "LinearMove: no post-move function defined");
m_vecFinalDest = vecDest;
@@ -382,8 +382,8 @@ NOXREF BOOL CBaseToggle::IsLockedByMaster()
// Just like LinearMove, but rotational.
void CBaseToggle::AngularMove(Vector vecDestAngle, float flSpeed)
{
- assert(("AngularMove: no speed is defined!", flSpeed != 0));
- //assert(("AngularMove: no post-move function defined", m_pfnCallWhenMoveDone != nullptr));
+ DbgAssertMsg(flSpeed != 0, "AngularMove: no speed is defined!");
+ //DbgAssertMsg(m_pfnCallWhenMoveDone != nullptr, "AngularMove: no post-move function defined");
m_vecFinalAngle = vecDestAngle;
diff --git a/regamedll/dlls/triggers.cpp b/regamedll/dlls/triggers.cpp
index f454806ce..c4af258c4 100644
--- a/regamedll/dlls/triggers.cpp
+++ b/regamedll/dlls/triggers.cpp
@@ -468,7 +468,10 @@ void CBaseTrigger::InitTrigger()
pev->movetype = MOVETYPE_NONE;
// set size and link into world
- SET_MODEL(ENT(pev), STRING(pev->model));
+ if (FStringNull(pev->model))
+ UTIL_SetOrigin(pev, pev->origin); // link into the list
+ else
+ SET_MODEL(ENT(pev), STRING(pev->model));
if (CVAR_GET_FLOAT("showtriggers") == 0)
{
@@ -968,7 +971,7 @@ void CTriggerMultiple::Spawn()
InitTrigger();
- assert(("trigger_multiple with health", pev->health == 0));
+ DbgAssertMsg(pev->health == 0, "trigger_multiple with health");
//UTIL_SetOrigin(pev, pev->origin);
//SET_MODEL(ENT(pev), STRING(pev->model));
diff --git a/regamedll/dlls/tutor_base_tutor.cpp b/regamedll/dlls/tutor_base_tutor.cpp
index 8723ca2c8..2268d18b7 100644
--- a/regamedll/dlls/tutor_base_tutor.cpp
+++ b/regamedll/dlls/tutor_base_tutor.cpp
@@ -104,7 +104,7 @@ char *TutorMessageEvent::GetNextParameter(char *buf, int buflen)
Q_strncpy(buf, param->m_data, buflen);
#ifdef REGAMEDLL_FIXES
- buf[buflen] = '\0';
+ buf[buflen - 1] = '\0';
#endif
delete param;
diff --git a/regamedll/dlls/util.cpp b/regamedll/dlls/util.cpp
index 6c10ca406..7c3c3db6c 100644
--- a/regamedll/dlls/util.cpp
+++ b/regamedll/dlls/util.cpp
@@ -1056,7 +1056,7 @@ void UTIL_BloodStream(const Vector &origin, const Vector &direction, int color,
MESSAGE_END();
}
-void UTIL_BloodDrips(const Vector &origin, const Vector &direction, int color, int amount)
+void UTIL_BloodDrips(const Vector &origin, int color, int amount)
{
if (!UTIL_ShouldShowBlood(color))
return;
@@ -1497,6 +1497,10 @@ void UTIL_RestartOther(const char *szClassname)
while ((pEntity = UTIL_FindEntityByClassname(pEntity, szClassname)))
{
pEntity->Restart();
+
+#ifdef REGAMEDLL_ADD
+ FireTargets("game_entity_restart", pEntity, nullptr, USE_TOGGLE, 0.0);
+#endif
}
}
@@ -1727,7 +1731,7 @@ bool UTIL_AreHostagesImprov()
#ifdef REGAMEDLL_ADD
if (g_engfuncs.pfnEngCheckParm == nullptr)
return false;
-
+
// someday in CS 1.6
int improv = ENG_CHECK_PARM("-host-improv", nullptr);
if (improv)
@@ -1754,6 +1758,17 @@ int UTIL_GetNumPlayers()
return nNumPlayers;
}
+int UTIL_CountEntities(const char *szName)
+{
+ int count = 0;
+ CBaseEntity *pEnt = nullptr;
+
+ while ((pEnt = UTIL_FindEntityByClassname(pEnt, szName)))
+ count++;
+
+ return count;
+}
+
bool UTIL_IsSpawnPointOccupied(CBaseEntity *pSpot)
{
if (!pSpot)
@@ -1804,10 +1819,11 @@ void NORETURN Sys_Error(const char *error, ...)
CONSOLE_ECHO("FATAL ERROR (shutting down): %s\n", text);
- //TerminateProcess(GetCurrentProcess(), 1);
- int *null = 0;
- *null = 0;
- exit(-1);
+#if defined(_WIN32)
+ MessageBoxA(NULL, text, "Fatal error", MB_ICONERROR | MB_OK);
+#endif
+
+ exit(EXIT_FAILURE);
}
int UTIL_CountPlayersInBrushVolume(bool bOnlyAlive, CBaseEntity *pBrushEntity, int &playersInCount, int &playersOutCount, CPlayerInVolumeAdapter *pAdapter)
diff --git a/regamedll/dlls/util.h b/regamedll/dlls/util.h
index baeea3634..f96be669b 100644
--- a/regamedll/dlls/util.h
+++ b/regamedll/dlls/util.h
@@ -262,7 +262,7 @@ bool UTIL_IsMasterTriggered(string_t sMaster, CBaseEntity *pActivator);
BOOL UTIL_ShouldShowBlood(int color);
int UTIL_PointContents(const Vector &vec);
void UTIL_BloodStream(const Vector &origin, const Vector &direction, int color, int amount);
-void UTIL_BloodDrips(const Vector &origin, const Vector &direction, int color, int amount);
+void UTIL_BloodDrips(const Vector &origin, int color, int amount);
Vector UTIL_RandomBloodVector();
void UTIL_BloodDecalTrace(TraceResult *pTrace, int bloodColor);
void UTIL_DecalTrace(TraceResult *pTrace, int decalNumber);
@@ -297,6 +297,7 @@ bool UTIL_AreBotsAllowed();
bool UTIL_IsBeta();
bool UTIL_AreHostagesImprov();
int UTIL_GetNumPlayers();
+int UTIL_CountEntities(const char *szName);
bool UTIL_IsSpawnPointOccupied(CBaseEntity *pSpot);
void MAKE_STRING_CLASS(const char *str, entvars_t *pev);
void NORETURN Sys_Error(const char *error, ...);
diff --git a/regamedll/dlls/vehicle.cpp b/regamedll/dlls/vehicle.cpp
index ffd0bc550..3ff84b941 100644
--- a/regamedll/dlls/vehicle.cpp
+++ b/regamedll/dlls/vehicle.cpp
@@ -150,7 +150,7 @@ void CFuncVehicle::Blocked(CBaseEntity *pOther)
if (pOther->Classify() == CLASS_PLAYER)
{
CBasePlayer* playerOther = static_cast(pOther);
- if (!playerDriver || (!friendlyfire.value && playerDriver->m_iTeam == playerOther->m_iTeam))
+ if (!playerDriver || !g_pGameRules->FPlayerCanTakeDamage(playerOther, playerDriver))
{
// Just kick player
return;
diff --git a/regamedll/dlls/weapons.cpp b/regamedll/dlls/weapons.cpp
index b727d38eb..d3877fbba 100644
--- a/regamedll/dlls/weapons.cpp
+++ b/regamedll/dlls/weapons.cpp
@@ -70,27 +70,35 @@ float GetBaseAccuracy(WeaponIdType id)
case WEAPON_MP5N:
return 0.0f;
}
+
+ return 0.0f;
}
+LINK_HOOK_VOID_CHAIN2(ClearMultiDamage)
+
// Resets the global multi damage accumulator
-void ClearMultiDamage()
+void EXT_FUNC __API_HOOK(ClearMultiDamage)()
{
gMultiDamage.pEntity = nullptr;
gMultiDamage.amount = 0;
gMultiDamage.type = 0;
}
+LINK_HOOK_VOID_CHAIN(ApplyMultiDamage, (entvars_t *pevInflictor, entvars_t *pevAttacker), pevInflictor, pevAttacker)
+
// Inflicts contents of global multi damage register on gMultiDamage.pEntity
-void ApplyMultiDamage(entvars_t *pevInflictor, entvars_t *pevAttacker)
+void EXT_FUNC __API_HOOK(ApplyMultiDamage)(entvars_t *pevInflictor, entvars_t *pevAttacker)
{
if (!gMultiDamage.pEntity)
return;
gMultiDamage.pEntity->TakeDamage(pevInflictor, pevAttacker, gMultiDamage.amount, gMultiDamage.type);
-
+ gMultiDamage.pEntity->ResetDmgPenetrationLevel();
}
-void AddMultiDamage(entvars_t *pevInflictor, CBaseEntity *pEntity, float flDamage, int bitsDamageType)
+LINK_HOOK_VOID_CHAIN(AddMultiDamage, (entvars_t *pevInflictor, CBaseEntity *pEntity, float flDamage, int bitsDamageType), pevInflictor, pEntity, flDamage, bitsDamageType)
+
+void EXT_FUNC __API_HOOK(AddMultiDamage)(entvars_t *pevInflictor, CBaseEntity *pEntity, float flDamage, int bitsDamageType)
{
if (!pEntity)
return;
@@ -110,7 +118,7 @@ void AddMultiDamage(entvars_t *pevInflictor, CBaseEntity *pEntity, float flDamag
void SpawnBlood(Vector vecSpot, int bloodColor, float flDamage)
{
- UTIL_BloodDrips(vecSpot, g_vecAttackDir, bloodColor, int(flDamage));
+ UTIL_BloodDrips(vecSpot, bloodColor, int(flDamage));
}
NOXREF int DamageDecal(CBaseEntity *pEntity, int bitsDamageType)
@@ -206,10 +214,16 @@ struct {
#endif
// Precaches the ammo and queues the ammo info for sending to clients
-void AddAmmoNameToAmmoRegistry(const char *szAmmoname)
+int AddAmmoNameToAmmoRegistry(const char *szAmmoname)
{
+ // string validation
+ if (!szAmmoname || !szAmmoname[0])
+ {
+ return -1;
+ }
+
// make sure it's not already in the registry
- for (int i = 0; i < MAX_AMMO_SLOTS; i++)
+ for (int i = 1; i < MAX_AMMO_SLOTS; i++)
{
if (!CBasePlayerItem::m_AmmoInfoArray[i].pszName)
continue;
@@ -217,15 +231,15 @@ void AddAmmoNameToAmmoRegistry(const char *szAmmoname)
if (!Q_stricmp(CBasePlayerItem::m_AmmoInfoArray[i].pszName, szAmmoname))
{
// ammo already in registry, just quite
- return;
+ return i;
}
}
giAmmoIndex++;
- assert(giAmmoIndex < MAX_AMMO_SLOTS);
+ DbgAssert(giAmmoIndex < MAX_AMMO_SLOTS);
if (giAmmoIndex >= MAX_AMMO_SLOTS)
- giAmmoIndex = 0;
+ giAmmoIndex = 1;
#ifdef REGAMEDLL_ADD
for (auto& ammo : ammoIndex)
@@ -244,6 +258,8 @@ void AddAmmoNameToAmmoRegistry(const char *szAmmoname)
// Yes, this info is redundant
CBasePlayerItem::m_AmmoInfoArray[giAmmoIndex].iId = giAmmoIndex;
+
+ return giAmmoIndex;
}
// Precaches the weapon and queues the weapon info for sending to clients
@@ -267,15 +283,8 @@ void UTIL_PrecacheOtherWeapon(const char *szClassname)
{
CBasePlayerItem::m_ItemInfoArray[info.iId] = info;
- if (info.pszAmmo1 && info.pszAmmo1[0] != '\0')
- {
- AddAmmoNameToAmmoRegistry(info.pszAmmo1);
- }
-
- if (info.pszAmmo2 && info.pszAmmo2[0] != '\0')
- {
- AddAmmoNameToAmmoRegistry(info.pszAmmo2);
- }
+ AddAmmoNameToAmmoRegistry(info.pszAmmo1);
+ AddAmmoNameToAmmoRegistry(info.pszAmmo2);
}
}
@@ -689,7 +698,9 @@ bool CBasePlayerWeapon::ShieldSecondaryFire(int iUpAnim, int iDownAnim)
return true;
}
-void CBasePlayerWeapon::KickBack(float up_base, float lateral_base, float up_modifier, float lateral_modifier, float up_max, float lateral_max, int direction_change)
+LINK_HOOK_CLASS_VOID_CHAIN(CBasePlayerWeapon, KickBack, (float up_base, float lateral_base, float up_modifier, float lateral_modifier, float up_max, float lateral_max, int direction_change), up_base, lateral_base, up_modifier, lateral_modifier, up_max, lateral_max, direction_change)
+
+void EXT_FUNC CBasePlayerWeapon::__API_HOOK(KickBack)(float up_base, float lateral_base, float up_modifier, float lateral_modifier, float up_max, float lateral_max, int direction_change)
{
real_t flKickUp;
float flKickLateral;
@@ -759,8 +770,9 @@ void CBasePlayerWeapon::FireRemaining(int &shotsFired, float &shootTime, BOOL bI
if (bIsGlock)
{
vecDir = m_pPlayer->FireBullets3(vecSrc, gpGlobals->v_forward, 0.05, 8192, 1, BULLET_PLAYER_9MM, 18, 0.9, m_pPlayer->pev, true, m_pPlayer->random_seed);
+#ifndef REGAMEDLL_FIXES
--m_pPlayer->ammo_9mm;
-
+#endif
PLAYBACK_EVENT_FULL(flag, m_pPlayer->edict(), m_usFireGlock18, 0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y,
int(m_pPlayer->pev->punchangle.x * 10000), int(m_pPlayer->pev->punchangle.y * 10000), m_iClip == 0, FALSE);
}
@@ -768,7 +780,9 @@ void CBasePlayerWeapon::FireRemaining(int &shotsFired, float &shootTime, BOOL bI
{
vecDir = m_pPlayer->FireBullets3(vecSrc, gpGlobals->v_forward, m_fBurstSpread, 8192, 2, BULLET_PLAYER_556MM, 30, 0.96, m_pPlayer->pev, false, m_pPlayer->random_seed);
+#ifndef REGAMEDLL_FIXES
--m_pPlayer->ammo_556nato;
+#endif
#ifdef REGAMEDLL_ADD
// HACKHACK: client-side weapon prediction fix
@@ -809,6 +823,21 @@ BOOL CanAttack(float attack_time, float curtime, BOOL isPredicted)
bool CBasePlayerWeapon::HasSecondaryAttack()
{
+#ifdef REGAMEDLL_API
+ if (CSPlayerWeapon()->m_iStateSecondaryAttack != WEAPON_SECONDARY_ATTACK_NONE)
+ {
+ switch (CSPlayerWeapon()->m_iStateSecondaryAttack)
+ {
+ case WEAPON_SECONDARY_ATTACK_SET:
+ return true;
+ case WEAPON_SECONDARY_ATTACK_BLOCK:
+ return false;
+ default:
+ break;
+ }
+ }
+#endif
+
if (m_pPlayer && m_pPlayer->HasShield())
{
return true;
@@ -876,7 +905,9 @@ void CBasePlayerWeapon::HandleInfiniteAmmo()
}
}
-void CBasePlayerWeapon::ItemPostFrame()
+LINK_HOOK_CLASS_VOID_CHAIN2(CBasePlayerWeapon, ItemPostFrame)
+
+void EXT_FUNC CBasePlayerWeapon::__API_HOOK(ItemPostFrame)()
{
int usableButtons = m_pPlayer->pev->button;
@@ -1101,8 +1132,10 @@ void CBasePlayerWeapon::ItemPostFrame()
}
}
-void CBasePlayerItem::DestroyItem()
+bool CBasePlayerItem::DestroyItem()
{
+ bool success = false;
+
if (m_pPlayer)
{
// if attached to a player, remove.
@@ -1110,18 +1143,31 @@ void CBasePlayerItem::DestroyItem()
{
#ifdef REGAMEDLL_FIXES
+ if (m_iId == WEAPON_C4) {
+ m_pPlayer->m_bHasC4 = false;
+ m_pPlayer->pev->body = 0;
+ m_pPlayer->SetBombIcon(FALSE);
+ m_pPlayer->SetProgressBarTime(0);
+ }
+
m_pPlayer->pev->weapons &= ~(1 << m_iId);
// No more weapon
if ((m_pPlayer->pev->weapons & ~(1 << WEAPON_SUIT)) == 0) {
m_pPlayer->m_iHideHUD |= HIDEHUD_WEAPONS;
}
-#endif
+ if (!m_pPlayer->m_rgpPlayerItems[PRIMARY_WEAPON_SLOT]) {
+ m_pPlayer->m_bHasPrimary = false;
+ }
+#endif
+ success = true;
}
}
Kill();
+
+ return success;
}
int CBasePlayerItem::AddToPlayer(CBasePlayer *pPlayer)
@@ -1187,8 +1233,6 @@ void CBasePlayerWeapon::Spawn()
if (GetItemInfo(&info)) {
CSPlayerItem()->SetItemInfo(&info);
}
-
- CSPlayerWeapon()->m_bHasSecondaryAttack = HasSecondaryAttack();
#endif
}
@@ -1271,7 +1315,9 @@ int CBasePlayerWeapon::UpdateClientData(CBasePlayer *pPlayer)
return 1;
}
-void CBasePlayerWeapon::SendWeaponAnim(int iAnim, int skiplocal)
+LINK_HOOK_CLASS_VOID_CHAIN(CBasePlayerWeapon, SendWeaponAnim, (int iAnim, int skiplocal), iAnim, skiplocal)
+
+void EXT_FUNC CBasePlayerWeapon::__API_HOOK(SendWeaponAnim)(int iAnim, int skiplocal)
{
m_pPlayer->pev->weaponanim = iAnim;
@@ -1590,7 +1636,17 @@ int CBasePlayerWeapon::ExtractClipAmmo(CBasePlayerWeapon *pWeapon)
iAmmo = m_iClip;
}
- return pWeapon->m_pPlayer->GiveAmmo(iAmmo, pszAmmo1(), iMaxAmmo1());
+ int iIdAmmo = pWeapon->m_pPlayer->GiveAmmo(iAmmo, pszAmmo1(), iMaxAmmo1());
+
+#ifdef REGAMEDLL_FIXES
+ if (iIdAmmo > 0 && IsGrenadeWeapon(m_iId))
+ {
+ // grenades have WEAPON_NOCLIP force play the "got ammo" sound.
+ EMIT_SOUND(pWeapon->m_pPlayer->edict(), CHAN_ITEM, "items/9mmclip1.wav", VOL_NORM, ATTN_NORM);
+ }
+#endif
+
+ return iIdAmmo;
}
// RetireWeapon - no more ammo for this gun, put it away.
@@ -1803,7 +1859,12 @@ void CWeaponBox::Touch(CBaseEntity *pOther)
pPlayer->OnTouchingWeapon(this);
bool bRemove = true;
- bool bEmitSound = false;
+
+#ifdef REGAMEDLL_FIXES
+ CBasePlayerItem *givenItem = nullptr;
+#else
+ bool givenItem = false;
+#endif
// go through my weapons and try to give the usable ones to the player.
// it's important the the player be given ammo first, so the weapons code doesn't refuse
@@ -1863,8 +1924,8 @@ void CWeaponBox::Touch(CBaseEntity *pOther)
MESSAGE_END();
pPlayer->m_bHasC4 = true;
- pPlayer->SetBombIcon(FALSE);
pPlayer->pev->body = 1;
+ pPlayer->SetBombIcon(FALSE);
CBaseEntity *pEntity = nullptr;
while ((pEntity = UTIL_FindEntityByClassname(pEntity, "player")))
@@ -1915,19 +1976,35 @@ void CWeaponBox::Touch(CBaseEntity *pOther)
int playerGrenades = pPlayer->m_rgAmmo[pGrenade->m_iPrimaryAmmoType];
#ifdef REGAMEDLL_FIXES
- auto info = GetWeaponInfo(pGrenade->m_iId);
- if (info && playerGrenades < info->maxRounds)
+ // sorry for hardcode :(
+ const int boxAmmoSlot = 1;
+
+ if (playerGrenades < pGrenade->iMaxAmmo1())
{
- auto pNext = m_rgpPlayerItems[i]->m_pNext;
- if (pPlayer->AddPlayerItem(pItem))
+ if (m_rgAmmo[boxAmmoSlot] > 1 && playerGrenades > 0)
{
- pItem->AttachToPlayer(pPlayer);
- bEmitSound = true;
+ if (!FStringNull(m_rgiszAmmo[boxAmmoSlot])
+ && pPlayer->GiveAmmo(1, STRING(m_rgiszAmmo[boxAmmoSlot]), pGrenade->iMaxAmmo1()) != -1)
+ {
+ m_rgAmmo[boxAmmoSlot]--;
+
+ EMIT_SOUND(pPlayer->edict(), CHAN_ITEM, "items/9mmclip1.wav", VOL_NORM, ATTN_NORM);
+ }
}
+ else
+ {
+ auto pNext = m_rgpPlayerItems[i]->m_pNext;
- // unlink this weapon from the box
- m_rgpPlayerItems[i] = pItem = pNext;
- continue;
+ if (pPlayer->AddPlayerItem(pItem))
+ {
+ pItem->AttachToPlayer(pPlayer);
+ givenItem = pItem;
+ }
+
+ // unlink this weapon from the box
+ m_rgpPlayerItems[i] = pItem = pNext;
+ continue;
+ }
}
#else
@@ -1958,7 +2035,7 @@ void CWeaponBox::Touch(CBaseEntity *pOther)
// there we will see only get one grenade. Next step - pick it up, do check again `entity_dump`,
// but this time we'll see them x2.
- bEmitSound = true;
+ givenItem = true;
pPlayer->GiveNamedItem(grenadeName);
// unlink this weapon from the box
@@ -1980,7 +2057,11 @@ void CWeaponBox::Touch(CBaseEntity *pOther)
if (pPlayer->AddPlayerItem(pItem))
{
pItem->AttachToPlayer(pPlayer);
- bEmitSound = true;
+#ifdef REGAMEDLL_FIXES
+ givenItem = pItem;
+#else
+ givenItem = true;
+#endif
}
// unlink this weapon from the box
@@ -2001,7 +2082,11 @@ void CWeaponBox::Touch(CBaseEntity *pOther)
if (!FStringNull(m_rgiszAmmo[n]))
{
// there's some ammo of this type.
+#ifndef REGAMEDLL_ADD
pPlayer->GiveAmmo(m_rgAmmo[n], (char *)STRING(m_rgiszAmmo[n]), MaxAmmoCarry(m_rgiszAmmo[n]));
+#else
+ pPlayer->GiveAmmo(m_rgAmmo[n], STRING(m_rgiszAmmo[n]), m_rgAmmo[n]);
+#endif
// now empty the ammo from the weaponbox since we just gave it to the player
m_rgiszAmmo[n] = iStringNull;
@@ -2010,9 +2095,21 @@ void CWeaponBox::Touch(CBaseEntity *pOther)
}
}
- if (bEmitSound)
+ if (givenItem)
{
EMIT_SOUND(ENT(pPlayer->pev), CHAN_ITEM, "items/gunpickup2.wav", VOL_NORM, ATTN_NORM);
+
+#ifdef REGAMEDLL_FIXES
+ // BUGBUG: weaponbox links gun to player, then ammo is given
+ // so FShouldSwitchWeapon's CanHolster (which checks ammo) check inside AddPlayerItem
+ // return FALSE, causing an unarmed player to not deploy any weaponbox grenade
+ if (pPlayer->m_pActiveItem != givenItem && CSGameRules()->FShouldSwitchWeapon(pPlayer, givenItem))
+ {
+ // This re-check is done after ammo is given
+ // so it ensures player properly deploys grenade from floor
+ pPlayer->SwitchWeapon(givenItem);
+ }
+#endif
}
if (bRemove)
@@ -2600,3 +2697,4 @@ int CBasePlayerItem::iFlags() const
{
return m_ItemInfoEx.iFlags;
}
+
diff --git a/regamedll/dlls/weapons.h b/regamedll/dlls/weapons.h
index bd22989e3..431284fb9 100644
--- a/regamedll/dlls/weapons.h
+++ b/regamedll/dlls/weapons.h
@@ -296,7 +296,7 @@ class CBasePlayerItem: public CBaseAnimating
virtual int iItemSlot() { return 0; } // return 0 to MAX_ITEMS_SLOTS, used in hud
public:
- void EXPORT DestroyItem();
+ bool EXPORT DestroyItem();
void EXPORT DefaultTouch(CBaseEntity *pOther);
void EXPORT FallThink();
void EXPORT Materialize();
@@ -403,6 +403,9 @@ class CBasePlayerWeapon: public CBasePlayerItem
BOOL DefaultDeploy_OrigFunc(char *szViewModel, char *szWeaponModel, int iAnim, char *szAnimExt, int skiplocal);
BOOL DefaultReload_OrigFunc(int iClipSize, int iAnim, float fDelay);
bool DefaultShotgunReload_OrigFunc(int iAnim, int iStartAnim, float fDelay, float fStartDelay, const char *pszReloadSound1, const char *pszReloadSound2);
+ void KickBack_OrigFunc(float up_base, float lateral_base, float up_modifier, float lateral_modifier, float up_max, float lateral_max, int direction_change);
+ void SendWeaponAnim_OrigFunc(int iAnim, int skiplocal);
+ void ItemPostFrame_OrigFunc();
CCSPlayerWeapon *CSPlayerWeapon() const;
#endif
@@ -534,7 +537,7 @@ enum usp_shield_e
USP_SHIELD_SHOOT_EMPTY,
USP_SHIELD_RELOAD,
USP_SHIELD_DRAW,
- USP_SHIELD_UP_IDLE,
+ USP_SHIELD_IDLE_UP,
USP_SHIELD_UP,
USP_SHIELD_DOWN,
};
@@ -900,6 +903,19 @@ enum deagle_e
DEAGLE_DRAW,
};
+enum deagle_shield_e
+{
+ DEAGLE_SHIELD_IDLE1,
+ DEAGLE_SHIELD_SHOOT,
+ DEAGLE_SHIELD_SHOOT2,
+ DEAGLE_SHIELD_SHOOT_EMPTY,
+ DEAGLE_SHIELD_RELOAD,
+ DEAGLE_SHIELD_DRAW,
+ DEAGLE_SHIELD_IDLE_UP,
+ DEAGLE_SHIELD_UP,
+ DEAGLE_SHIELD_DOWN,
+};
+
class CDEAGLE: public CBasePlayerWeapon
{
public:
@@ -1065,7 +1081,7 @@ enum glock18_shield_e
GLOCK18_SHIELD_SHOOT_EMPTY,
GLOCK18_SHIELD_RELOAD,
GLOCK18_SHIELD_DRAW,
- GLOCK18_SHIELD_IDLE,
+ GLOCK18_SHIELD_IDLE_UP,
GLOCK18_SHIELD_UP,
GLOCK18_SHIELD_DOWN,
};
@@ -1151,15 +1167,16 @@ class CHEGrenade: public CBasePlayerWeapon
};
-const float KNIFE_BODYHIT_VOLUME = 128.0f;
-const float KNIFE_WALLHIT_VOLUME = 512.0f;
-const float KNIFE_MAX_SPEED = 250.0f;
-const float KNIFE_MAX_SPEED_SHIELD = 180.0f;
-const float KNIFE_STAB_DAMAGE = 65.0f;
-const float KNIFE_SWING_DAMAGE = 15.0f;
-const float KNIFE_SWING_DAMAGE_FAST = 20.0f;
-const float KNIFE_STAB_DISTANCE = 32.0f;
-const float KNIFE_SWING_DISTANCE = 48.0f;
+const float KNIFE_BODYHIT_VOLUME = 128.0f;
+const float KNIFE_WALLHIT_VOLUME = 512.0f;
+const float KNIFE_MAX_SPEED = 250.0f;
+const float KNIFE_MAX_SPEED_SHIELD = 180.0f;
+const float KNIFE_STAB_DAMAGE = 65.0f;
+const float KNIFE_SWING_DAMAGE = 15.0f;
+const float KNIFE_SWING_DAMAGE_FAST = 20.0f;
+const float KNIFE_STAB_DISTANCE = 32.0f;
+const float KNIFE_SWING_DISTANCE = 48.0f;
+const float KNIFE_BACKSTAB_MULTIPLIER = 3.0f;
enum knife_e
{
@@ -1179,7 +1196,7 @@ enum knife_shield_e
KNIFE_SHIELD_SLASH,
KNIFE_SHIELD_ATTACKHIT,
KNIFE_SHIELD_DRAW,
- KNIFE_SHIELD_UPIDLE,
+ KNIFE_SHIELD_IDLE_UP,
KNIFE_SHIELD_UP,
KNIFE_SHIELD_DOWN,
};
@@ -1220,19 +1237,41 @@ class CKnife: public CBasePlayerWeapon
void SetPlayerShieldAnim();
void ResetPlayerShieldAnim();
+ float KnifeStabDamage() const;
+ float KnifeSwingDamage(bool fast) const;
+ float KnifeStabDistance() const;
+ float KnifeSwingDistance() const;
+ float KnifeBackStabMultiplier() const;
+
private:
TraceResult m_trHit;
unsigned short m_usKnife;
- // Extra RegameDLL features
+#ifdef REGAMEDLL_API
float m_flStabBaseDamage;
float m_flSwingBaseDamage;
float m_flSwingBaseDamage_Fast;
float m_flStabDistance;
float m_flSwingDistance;
+
+ float m_flBackStabMultiplier;
+#endif
};
+#ifdef REGAMEDLL_API
+inline float CKnife::KnifeStabDamage() const { return m_flStabBaseDamage; }
+inline float CKnife::KnifeSwingDamage(bool fast) const { return fast ? m_flSwingBaseDamage_Fast : m_flSwingBaseDamage; }
+inline float CKnife::KnifeStabDistance() const { return m_flStabDistance; }
+inline float CKnife::KnifeSwingDistance() const { return m_flSwingDistance; }
+inline float CKnife::KnifeBackStabMultiplier() const { return m_flBackStabMultiplier; }
+#else
+inline float CKnife::KnifeStabDamage() const { return KNIFE_STAB_DAMAGE; }
+inline float CKnife::KnifeSwingDamage(bool fast) const { return fast ? KNIFE_SWING_DAMAGE_FAST : KNIFE_SWING_DAMAGE; }
+inline float CKnife::KnifeStabDistance() const { return KNIFE_STAB_DISTANCE; }
+inline float CKnife::KnifeSwingDistance() const { return KNIFE_SWING_DISTANCE; }
+inline float CKnife::KnifeBackStabMultiplier() const { return KNIFE_BACKSTAB_MULTIPLIER; }
+#endif // REGAMEDLL_API
const float M249_MAX_SPEED = 220.0f;
const float M249_DAMAGE = 32.0f;
@@ -1835,6 +1874,19 @@ enum fiveseven_e
FIVESEVEN_DRAW,
};
+enum fiveseven_shield_e
+{
+ FIVESEVEN_SHIELD_IDLE1,
+ FIVESEVEN_SHIELD_SHOOT,
+ FIVESEVEN_SHIELD_SHOOT2,
+ FIVESEVEN_SHIELD_SHOOT_EMPTY,
+ FIVESEVEN_SHIELD_RELOAD,
+ FIVESEVEN_SHIELD_DRAW,
+ FIVESEVEN_SHIELD_IDLE_UP,
+ FIVESEVEN_SHIELD_UP,
+ FIVESEVEN_SHIELD_DOWN,
+};
+
class CFiveSeven: public CBasePlayerWeapon
{
public:
@@ -2113,7 +2165,13 @@ int DamageDecal(CBaseEntity *pEntity, int bitsDamageType);
void DecalGunshot(TraceResult *pTrace, int iBulletType, bool ClientOnly, entvars_t *pShooter, bool bHitMetal);
void EjectBrass(const Vector &vecOrigin, const Vector &vecLeft, const Vector &vecVelocity, float rotation, int model, int soundtype, int entityIndex);
void EjectBrass2(const Vector &vecOrigin, const Vector &vecVelocity, float rotation, int model, int soundtype, entvars_t *pev);
-void AddAmmoNameToAmmoRegistry(const char *szAmmoname);
+int AddAmmoNameToAmmoRegistry(const char *szAmmoname);
void UTIL_PrecacheOtherWeapon(const char *szClassname);
BOOL CanAttack(float attack_time, float curtime, BOOL isPredicted);
float GetBaseAccuracy(WeaponIdType id);
+
+#ifdef REGAMEDLL_API
+void ClearMultiDamage_OrigFunc();
+void ApplyMultiDamage_OrigFunc(entvars_t *pevInflictor, entvars_t *pevAttacker);
+void AddMultiDamage_OrigFunc(entvars_t *pevInflictor, CBaseEntity *pEntity, float flDamage, int bitsDamageType);
+#endif
diff --git a/regamedll/dlls/weapontype.cpp b/regamedll/dlls/weapontype.cpp
index 209c7b89d..2b8ae4458 100644
--- a/regamedll/dlls/weapontype.cpp
+++ b/regamedll/dlls/weapontype.cpp
@@ -529,6 +529,17 @@ WeaponInfoStruct *GetWeaponInfo(const char *weaponName)
return nullptr;
}
+WeaponInfoStruct *GetDefaultWeaponInfo(int weaponID)
+{
+ for (auto& info : g_weaponInfo_default) {
+ if (info.id == weaponID) {
+ return &info;
+ }
+ }
+
+ return nullptr;
+}
+
AmmoInfoStruct *GetAmmoInfo(const char *ammoName)
{
for (auto& info : g_ammoInfo) {
diff --git a/regamedll/dlls/weapontype.h b/regamedll/dlls/weapontype.h
index e3527e5fa..2005b6af7 100644
--- a/regamedll/dlls/weapontype.h
+++ b/regamedll/dlls/weapontype.h
@@ -318,25 +318,12 @@ enum AmmoBuyAmount
AMMO_SMOKEGRENADE_BUY = 1,
};
-enum shieldgun_e
-{
- SHIELDGUN_IDLE,
- SHIELDGUN_SHOOT1,
- SHIELDGUN_SHOOT2,
- SHIELDGUN_SHOOT_EMPTY,
- SHIELDGUN_RELOAD,
- SHIELDGUN_DRAW,
- SHIELDGUN_DRAWN_IDLE,
- SHIELDGUN_UP,
- SHIELDGUN_DOWN,
-};
-
// custom
enum shieldgren_e
{
- SHIELDREN_IDLE = 4,
- SHIELDREN_UP,
- SHIELDREN_DOWN
+ SHIELDGREN_IDLE = 4, // 3 is last grenade viewmodel sequence
+ SHIELDGREN_UP,
+ SHIELDGREN_DOWN
};
enum InventorySlotType
@@ -458,6 +445,8 @@ void WeaponInfoReset();
WeaponInfoStruct *GetWeaponInfo(int weaponID);
WeaponInfoStruct *GetWeaponInfo(const char *weaponName);
+WeaponInfoStruct *GetDefaultWeaponInfo(int weaponID);
+
AmmoInfoStruct *GetAmmoInfo(AmmoType ammoID);
AmmoInfoStruct *GetAmmoInfo(const char *ammoName);
diff --git a/regamedll/dlls/world.cpp b/regamedll/dlls/world.cpp
index efbb4dcf1..55147af09 100644
--- a/regamedll/dlls/world.cpp
+++ b/regamedll/dlls/world.cpp
@@ -288,11 +288,7 @@ void CWorld::Precache()
CVAR_SET_STRING("room_type", "0");
// Set up game rules
- if (g_pGameRules)
- {
- delete g_pGameRules;
- }
-
+ FreeGameRules(&g_pGameRules);
g_pGameRules = InstallGameRules();
// NOTE: What is the essence of soundent in CS 1.6? I think this is for NPC monsters - s1lent
diff --git a/regamedll/dlls/wpn_shared/wpn_aug.cpp b/regamedll/dlls/wpn_shared/wpn_aug.cpp
index c54780f3a..988c74808 100644
--- a/regamedll/dlls/wpn_shared/wpn_aug.cpp
+++ b/regamedll/dlls/wpn_shared/wpn_aug.cpp
@@ -78,21 +78,19 @@ void CAUG::SecondaryAttack()
void CAUG::PrimaryAttack()
{
+ const float flCycleTime = (m_pPlayer->pev->fov == DEFAULT_FOV) ? 0.0825f : 0.135f;
+
if (!(m_pPlayer->pev->flags & FL_ONGROUND))
{
- AUGFire(0.035 + (0.4 * m_flAccuracy), 0.0825, FALSE);
+ AUGFire(0.035 + (0.4 * m_flAccuracy), flCycleTime, FALSE);
}
else if (m_pPlayer->pev->velocity.Length2D() > 140)
{
- AUGFire(0.035 + (0.07 * m_flAccuracy), 0.0825, FALSE);
- }
- else if (m_pPlayer->pev->fov == DEFAULT_FOV)
- {
- AUGFire(0.02 * m_flAccuracy, 0.0825, FALSE);
+ AUGFire(0.035 + (0.07 * m_flAccuracy), flCycleTime, FALSE);
}
else
{
- AUGFire(0.02 * m_flAccuracy, 0.135, FALSE);
+ AUGFire(0.02 * m_flAccuracy, flCycleTime, FALSE);
}
}
diff --git a/regamedll/dlls/wpn_shared/wpn_deagle.cpp b/regamedll/dlls/wpn_shared/wpn_deagle.cpp
index f7a97d5d0..7dbed0c6b 100644
--- a/regamedll/dlls/wpn_shared/wpn_deagle.cpp
+++ b/regamedll/dlls/wpn_shared/wpn_deagle.cpp
@@ -93,7 +93,7 @@ void CDEAGLE::PrimaryAttack()
void CDEAGLE::SecondaryAttack()
{
- ShieldSecondaryFire(SHIELDGUN_UP, SHIELDGUN_DOWN);
+ ShieldSecondaryFire(DEAGLE_SHIELD_UP, DEAGLE_SHIELD_DOWN);
}
void CDEAGLE::DEAGLEFire(float flSpread, float flCycleTime, BOOL fUseSemi)
@@ -204,7 +204,7 @@ void CDEAGLE::WeaponIdle()
if (m_iWeaponState & WPNSTATE_SHIELD_DRAWN)
{
- SendWeaponAnim(SHIELDGUN_DRAWN_IDLE, UseDecrement() != FALSE);
+ SendWeaponAnim(DEAGLE_SHIELD_IDLE_UP, UseDecrement() != FALSE);
}
}
}
diff --git a/regamedll/dlls/wpn_shared/wpn_fiveseven.cpp b/regamedll/dlls/wpn_shared/wpn_fiveseven.cpp
index 67f2f3d57..31f211f08 100644
--- a/regamedll/dlls/wpn_shared/wpn_fiveseven.cpp
+++ b/regamedll/dlls/wpn_shared/wpn_fiveseven.cpp
@@ -92,7 +92,7 @@ void CFiveSeven::PrimaryAttack()
void CFiveSeven::SecondaryAttack()
{
- ShieldSecondaryFire(SHIELDGUN_UP, SHIELDGUN_DOWN);
+ ShieldSecondaryFire(FIVESEVEN_SHIELD_UP, FIVESEVEN_SHIELD_DOWN);
}
void CFiveSeven::FiveSevenFire(float flSpread, float flCycleTime, BOOL fUseSemi)
@@ -208,7 +208,7 @@ void CFiveSeven::WeaponIdle()
if (m_iWeaponState & WPNSTATE_SHIELD_DRAWN)
{
- SendWeaponAnim(SHIELDGUN_DRAWN_IDLE, UseDecrement() != FALSE);
+ SendWeaponAnim(FIVESEVEN_SHIELD_IDLE_UP, UseDecrement() != FALSE);
}
}
else if (m_iClip)
diff --git a/regamedll/dlls/wpn_shared/wpn_flashbang.cpp b/regamedll/dlls/wpn_shared/wpn_flashbang.cpp
index c5462e49b..0443353e8 100644
--- a/regamedll/dlls/wpn_shared/wpn_flashbang.cpp
+++ b/regamedll/dlls/wpn_shared/wpn_flashbang.cpp
@@ -142,7 +142,7 @@ bool CFlashbang::ShieldSecondaryFire(int iUpAnim, int iDownAnim)
void CFlashbang::SecondaryAttack()
{
- ShieldSecondaryFire(SHIELDGUN_DRAW, SHIELDGUN_DRAWN_IDLE);
+ ShieldSecondaryFire(SHIELDGREN_UP, SHIELDGREN_DOWN);
}
void CFlashbang::SetPlayerShieldAnim()
@@ -236,7 +236,7 @@ void CFlashbang::WeaponIdle()
if (m_iWeaponState & WPNSTATE_SHIELD_DRAWN)
{
- SendWeaponAnim(SHIELDREN_IDLE, UseDecrement() != FALSE);
+ SendWeaponAnim(SHIELDGREN_IDLE, UseDecrement() != FALSE);
}
}
else
diff --git a/regamedll/dlls/wpn_shared/wpn_glock18.cpp b/regamedll/dlls/wpn_shared/wpn_glock18.cpp
index b82d5148f..c2f5399d5 100644
--- a/regamedll/dlls/wpn_shared/wpn_glock18.cpp
+++ b/regamedll/dlls/wpn_shared/wpn_glock18.cpp
@@ -295,7 +295,7 @@ void CGLOCK18::WeaponIdle()
if (m_iWeaponState & WPNSTATE_SHIELD_DRAWN)
{
- SendWeaponAnim(GLOCK18_SHIELD_IDLE, UseDecrement() != FALSE);
+ SendWeaponAnim(GLOCK18_SHIELD_IDLE_UP, UseDecrement() != FALSE);
}
}
// only idle if the slid isn't back
diff --git a/regamedll/dlls/wpn_shared/wpn_hegrenade.cpp b/regamedll/dlls/wpn_shared/wpn_hegrenade.cpp
index 3f17e7254..49d8eb7a8 100644
--- a/regamedll/dlls/wpn_shared/wpn_hegrenade.cpp
+++ b/regamedll/dlls/wpn_shared/wpn_hegrenade.cpp
@@ -144,7 +144,7 @@ bool CHEGrenade::ShieldSecondaryFire(int iUpAnim, int iDownAnim)
void CHEGrenade::SecondaryAttack()
{
- ShieldSecondaryFire(SHIELDGUN_DRAW, SHIELDGUN_DRAWN_IDLE);
+ ShieldSecondaryFire(SHIELDGREN_UP, SHIELDGREN_DOWN);
}
void CHEGrenade::SetPlayerShieldAnim()
@@ -247,7 +247,7 @@ void CHEGrenade::WeaponIdle()
if (m_iWeaponState & WPNSTATE_SHIELD_DRAWN)
{
- SendWeaponAnim(SHIELDREN_IDLE, UseDecrement() != FALSE);
+ SendWeaponAnim(SHIELDGREN_IDLE, UseDecrement() != FALSE);
}
}
else
diff --git a/regamedll/dlls/wpn_shared/wpn_knife.cpp b/regamedll/dlls/wpn_shared/wpn_knife.cpp
index 18275c047..fcbf2d949 100644
--- a/regamedll/dlls/wpn_shared/wpn_knife.cpp
+++ b/regamedll/dlls/wpn_shared/wpn_knife.cpp
@@ -12,6 +12,7 @@ void CKnife::Spawn()
m_iWeaponState &= ~WPNSTATE_SHIELD_DRAWN;
m_iClip = WEAPON_NOCLIP;
+#ifdef REGAMEDLL_API
m_flStabBaseDamage = KNIFE_STAB_DAMAGE;
m_flSwingBaseDamage = KNIFE_SWING_DAMAGE;
m_flSwingBaseDamage_Fast = KNIFE_SWING_DAMAGE_FAST;
@@ -19,6 +20,9 @@ void CKnife::Spawn()
m_flStabDistance = KNIFE_STAB_DISTANCE;
m_flSwingDistance = KNIFE_SWING_DISTANCE;
+ m_flBackStabMultiplier = KNIFE_BACKSTAB_MULTIPLIER;
+#endif
+
// Get ready to fall down
FallInit();
@@ -44,12 +48,16 @@ void CKnife::Precache()
m_usKnife = PRECACHE_EVENT(1, "events/knife.sc");
+#ifdef REGAMEDLL_API
m_flStabBaseDamage = KNIFE_STAB_DAMAGE;
m_flSwingBaseDamage = KNIFE_SWING_DAMAGE;
m_flSwingBaseDamage_Fast = KNIFE_SWING_DAMAGE_FAST;
m_flStabDistance = KNIFE_STAB_DISTANCE;
m_flSwingDistance = KNIFE_SWING_DISTANCE;
+
+ m_flBackStabMultiplier = KNIFE_BACKSTAB_MULTIPLIER;
+#endif
}
int CKnife::GetItemInfo(ItemInfo *p)
@@ -121,6 +129,9 @@ void FindHullIntersection(const Vector &vecSrc, TraceResult &tr, float *mins, fl
distance = 1e6f;
vecHullEnd = vecSrc + ((vecHullEnd - vecSrc) * 2);
+#ifdef REGAMEDLL_ADD
+ gpGlobals->trace_flags = FTRACE_KNIFE;
+#endif
UTIL_TraceLine(vecSrc, vecHullEnd, dont_ignore_monsters, pEntity, &tmpTrace);
if (tmpTrace.flFraction < 1.0f)
@@ -139,6 +150,9 @@ void FindHullIntersection(const Vector &vecSrc, TraceResult &tr, float *mins, fl
vecEnd.y = vecHullEnd.y + minmaxs[j][1];
vecEnd.z = vecHullEnd.z + minmaxs[k][2];
+#ifdef REGAMEDLL_ADD
+ gpGlobals->trace_flags = FTRACE_KNIFE;
+#endif
UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, pEntity, &tmpTrace);
if (tmpTrace.flFraction < 1.0f)
@@ -166,14 +180,7 @@ void CKnife::SetPlayerShieldAnim()
if (!m_pPlayer->HasShield())
return;
- if (m_iWeaponState & WPNSTATE_SHIELD_DRAWN)
- {
- Q_strcpy(m_pPlayer->m_szAnimExtention, "shield");
- }
- else
- {
- Q_strcpy(m_pPlayer->m_szAnimExtention, "shieldknife");
- }
+ Q_strcpy(m_pPlayer->m_szAnimExtention, (m_iWeaponState & WPNSTATE_SHIELD_DRAWN) != 0 ? "shield" : "shieldknife");
}
void CKnife::ResetPlayerShieldAnim()
@@ -271,13 +278,23 @@ BOOL CKnife::Swing(BOOL fFirst)
UTIL_MakeVectors(m_pPlayer->pev->v_angle);
vecSrc = m_pPlayer->GetGunPosition();
- vecEnd = vecSrc + gpGlobals->v_forward * m_flSwingDistance;
+ vecEnd = vecSrc + gpGlobals->v_forward * KnifeSwingDistance();
+#ifdef REGAMEDLL_ADD
+ gpGlobals->trace_flags = FTRACE_KNIFE;
+#endif
UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, m_pPlayer->edict(), &tr);
if (tr.flFraction >= 1.0f)
{
+#ifdef REGAMEDLL_ADD
+ gpGlobals->trace_flags = FTRACE_KNIFE;
+#endif
UTIL_TraceHull(vecSrc, vecEnd, dont_ignore_monsters, head_hull, m_pPlayer->edict(), &tr);
+#ifdef REGAMEDLL_ADD
+ // We manually reset it because Engine doesn't unlike TraceLine
+ gpGlobals->trace_flags = 0;
+#endif
if (tr.flFraction < 1.0f)
{
@@ -303,8 +320,8 @@ BOOL CKnife::Swing(BOOL fFirst)
{
switch ((m_iSwing++) % 2)
{
- case 0: SendWeaponAnim(KNIFE_MIDATTACK1HIT, UseDecrement() != FALSE); break;
- case 1: SendWeaponAnim(KNIFE_MIDATTACK2HIT, UseDecrement() != FALSE); break;
+ case 0: SendWeaponAnim(KNIFE_MIDATTACK1HIT, UseDecrement() != FALSE); break;
+ case 1: SendWeaponAnim(KNIFE_MIDATTACK2HIT, UseDecrement() != FALSE); break;
}
// miss
@@ -322,10 +339,15 @@ BOOL CKnife::Swing(BOOL fFirst)
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2.0f;
// play wiff or swish sound
- if (RANDOM_LONG(0, 1))
- EMIT_SOUND_DYN(m_pPlayer->edict(), CHAN_WEAPON, "weapons/knife_slash1.wav", VOL_NORM, ATTN_NORM, 0, 94);
- else
- EMIT_SOUND_DYN(m_pPlayer->edict(), CHAN_WEAPON, "weapons/knife_slash2.wav", VOL_NORM, ATTN_NORM, 0, 94);
+ EMIT_SOUND_DYN(m_pPlayer->edict(),
+ CHAN_WEAPON,
+ RANDOM_LONG(0, 1) ?
+ "weapons/knife_slash1.wav" :
+ "weapons/knife_slash2.wav",
+ VOL_NORM,
+ ATTN_NORM,
+ 0,
+ 94);
// player "shoot" animation
m_pPlayer->SetAnimation(PLAYER_ATTACK1);
@@ -340,8 +362,8 @@ BOOL CKnife::Swing(BOOL fFirst)
{
switch ((m_iSwing++) % 2)
{
- case 0: SendWeaponAnim(KNIFE_MIDATTACK1HIT, UseDecrement() != FALSE); break;
- case 1: SendWeaponAnim(KNIFE_MIDATTACK2HIT, UseDecrement() != FALSE); break;
+ case 0: SendWeaponAnim(KNIFE_MIDATTACK1HIT, UseDecrement() != FALSE); break;
+ case 1: SendWeaponAnim(KNIFE_MIDATTACK2HIT, UseDecrement() != FALSE); break;
}
m_flNextPrimaryAttack = GetNextAttackDelay(0.4);
@@ -368,10 +390,11 @@ BOOL CKnife::Swing(BOOL fFirst)
m_pPlayer->SetAnimation(PLAYER_ATTACK1);
ClearMultiDamage();
- if (m_flNextPrimaryAttack + 0.4f < UTIL_WeaponTimeBase())
- pEntity->TraceAttack(m_pPlayer->pev, m_flSwingBaseDamage_Fast, gpGlobals->v_forward, &tr, (DMG_NEVERGIB | DMG_BULLET));
- else
- pEntity->TraceAttack(m_pPlayer->pev, m_flSwingBaseDamage, gpGlobals->v_forward, &tr, (DMG_NEVERGIB | DMG_BULLET));
+ pEntity->TraceAttack(m_pPlayer->pev,
+ KnifeSwingDamage(m_flNextPrimaryAttack + 0.4f < UTIL_WeaponTimeBase()),
+ gpGlobals->v_forward,
+ &tr,
+ (DMG_NEVERGIB | DMG_BULLET));
ApplyMultiDamage(m_pPlayer->pev, m_pPlayer->pev);
@@ -379,28 +402,27 @@ BOOL CKnife::Swing(BOOL fFirst)
if (pEntity) // -V595
#endif
{
+ if (pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE
#ifdef REGAMEDLL_FIXES
- if (pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE && pEntity->Classify() != CLASS_VEHICLE)
-#else
- if (pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE)
+ && pEntity->Classify() != CLASS_VEHICLE
#endif
+ )
{
// play thwack or smack sound
switch (RANDOM_LONG(0, 3))
{
- case 0: EMIT_SOUND(m_pPlayer->edict(), CHAN_WEAPON, "weapons/knife_hit1.wav", VOL_NORM, ATTN_NORM); break;
- case 1: EMIT_SOUND(m_pPlayer->edict(), CHAN_WEAPON, "weapons/knife_hit2.wav", VOL_NORM, ATTN_NORM); break;
- case 2: EMIT_SOUND(m_pPlayer->edict(), CHAN_WEAPON, "weapons/knife_hit3.wav", VOL_NORM, ATTN_NORM); break;
- case 3: EMIT_SOUND(m_pPlayer->edict(), CHAN_WEAPON, "weapons/knife_hit4.wav", VOL_NORM, ATTN_NORM); break;
+ case 0: EMIT_SOUND(m_pPlayer->edict(), CHAN_WEAPON, "weapons/knife_hit1.wav", VOL_NORM, ATTN_NORM); break;
+ case 1: EMIT_SOUND(m_pPlayer->edict(), CHAN_WEAPON, "weapons/knife_hit2.wav", VOL_NORM, ATTN_NORM); break;
+ case 2: EMIT_SOUND(m_pPlayer->edict(), CHAN_WEAPON, "weapons/knife_hit3.wav", VOL_NORM, ATTN_NORM); break;
+ case 3: EMIT_SOUND(m_pPlayer->edict(), CHAN_WEAPON, "weapons/knife_hit4.wav", VOL_NORM, ATTN_NORM); break;
}
m_pPlayer->m_iWeaponVolume = KNIFE_BODYHIT_VOLUME;
if (!pEntity->IsAlive())
return TRUE;
- else
- flVol = 0.1f;
+ flVol = 0.1f;
fHitWorld = FALSE;
}
}
@@ -449,13 +471,23 @@ BOOL CKnife::Stab(BOOL fFirst)
UTIL_MakeVectors(m_pPlayer->pev->v_angle);
vecSrc = m_pPlayer->GetGunPosition();
- vecEnd = vecSrc + gpGlobals->v_forward * m_flStabDistance;
+ vecEnd = vecSrc + gpGlobals->v_forward * KnifeStabDistance();
+#ifdef REGAMEDLL_ADD
+ gpGlobals->trace_flags = FTRACE_KNIFE;
+#endif
UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, m_pPlayer->edict(), &tr);
if (tr.flFraction >= 1.0f)
{
+#ifdef REGAMEDLL_ADD
+ gpGlobals->trace_flags = FTRACE_KNIFE;
+#endif
UTIL_TraceHull(vecSrc, vecEnd, dont_ignore_monsters, head_hull, m_pPlayer->edict(), &tr);
+#ifdef REGAMEDLL_ADD
+ // We manually reset it because Engine doesn't unlike TraceLine
+ gpGlobals->trace_flags = 0;
+#endif
if (tr.flFraction < 1.0f)
{
@@ -486,10 +518,15 @@ BOOL CKnife::Stab(BOOL fFirst)
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1.0f;
// play wiff or swish sound
- if (RANDOM_LONG(0, 1))
- EMIT_SOUND_DYN(m_pPlayer->edict(), CHAN_WEAPON, "weapons/knife_slash1.wav", VOL_NORM, ATTN_NORM, 0, 94);
- else
- EMIT_SOUND_DYN(m_pPlayer->edict(), CHAN_WEAPON, "weapons/knife_slash2.wav", VOL_NORM, ATTN_NORM, 0, 94);
+ EMIT_SOUND_DYN(m_pPlayer->edict(),
+ CHAN_WEAPON,
+ RANDOM_LONG(0, 1) ?
+ "weapons/knife_slash1.wav" :
+ "weapons/knife_slash2.wav",
+ VOL_NORM,
+ ATTN_NORM,
+ 0,
+ 94);
// player "shoot" animation
m_pPlayer->SetAnimation(PLAYER_ATTACK1);
@@ -517,7 +554,7 @@ BOOL CKnife::Stab(BOOL fFirst)
// player "shoot" animation
m_pPlayer->SetAnimation(PLAYER_ATTACK1);
- float flDamage = m_flStabBaseDamage;
+ float flDamage = KnifeStabDamage();
if (pEntity && pEntity->IsPlayer())
{
@@ -532,10 +569,10 @@ BOOL CKnife::Stab(BOOL fFirst)
flDot = DotProduct(vec2LOS, gpGlobals->v_forward.Make2D());
- //Triple the damage if we are stabbing them in the back.
+ // Multiply the damage if we are stabbing them in the back.
if (flDot > 0.80f)
{
- flDamage *= 3.0f;
+ flDamage *= KnifeBackStabMultiplier();
}
}
@@ -549,11 +586,11 @@ BOOL CKnife::Stab(BOOL fFirst)
if (pEntity) // -V595
#endif
{
+ if (pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE
#ifdef REGAMEDLL_FIXES
- if (pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE && pEntity->Classify() != CLASS_VEHICLE)
-#else
- if (pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE)
+ && pEntity->Classify() != CLASS_VEHICLE
#endif
+ )
{
EMIT_SOUND(m_pPlayer->edict(), CHAN_WEAPON, "weapons/knife_stab.wav", VOL_NORM, ATTN_NORM);
m_pPlayer->m_iWeaponVolume = KNIFE_BODYHIT_VOLUME;
diff --git a/regamedll/dlls/wpn_shared/wpn_p228.cpp b/regamedll/dlls/wpn_shared/wpn_p228.cpp
index 6e2c8d05b..b64f5fcf3 100644
--- a/regamedll/dlls/wpn_shared/wpn_p228.cpp
+++ b/regamedll/dlls/wpn_shared/wpn_p228.cpp
@@ -92,7 +92,7 @@ void CP228::PrimaryAttack()
void CP228::SecondaryAttack()
{
- ShieldSecondaryFire(SHIELDGUN_UP, SHIELDGUN_DOWN);
+ ShieldSecondaryFire(P228_SHIELD_UP, P228_SHIELD_DOWN);
}
void CP228::P228Fire(float flSpread, float flCycleTime, BOOL fUseSemi)
diff --git a/regamedll/dlls/wpn_shared/wpn_sg552.cpp b/regamedll/dlls/wpn_shared/wpn_sg552.cpp
index c95a66878..e86eec412 100644
--- a/regamedll/dlls/wpn_shared/wpn_sg552.cpp
+++ b/regamedll/dlls/wpn_shared/wpn_sg552.cpp
@@ -77,21 +77,19 @@ void CSG552::SecondaryAttack()
void CSG552::PrimaryAttack()
{
+ const float flCycleTime = (m_pPlayer->pev->fov == DEFAULT_FOV) ? 0.0825f : 0.135f;
+
if (!(m_pPlayer->pev->flags & FL_ONGROUND))
{
- SG552Fire(0.035 + (0.45 * m_flAccuracy), 0.0825, FALSE);
+ SG552Fire(0.035 + (0.45 * m_flAccuracy), flCycleTime, FALSE);
}
else if (m_pPlayer->pev->velocity.Length2D() > 140)
{
- SG552Fire(0.035 + (0.075 * m_flAccuracy), 0.0825, FALSE);
- }
- else if (m_pPlayer->pev->fov == DEFAULT_FOV)
- {
- SG552Fire(0.02 * m_flAccuracy, 0.0825, FALSE);
+ SG552Fire(0.035 + (0.075 * m_flAccuracy), flCycleTime, FALSE);
}
else
{
- SG552Fire(0.02 * m_flAccuracy, 0.135, FALSE);
+ SG552Fire(0.02 * m_flAccuracy, flCycleTime, FALSE);
}
}
diff --git a/regamedll/dlls/wpn_shared/wpn_smokegrenade.cpp b/regamedll/dlls/wpn_shared/wpn_smokegrenade.cpp
index d63fe3a69..ae13158b4 100644
--- a/regamedll/dlls/wpn_shared/wpn_smokegrenade.cpp
+++ b/regamedll/dlls/wpn_shared/wpn_smokegrenade.cpp
@@ -145,7 +145,7 @@ bool CSmokeGrenade::ShieldSecondaryFire(int iUpAnim, int iDownAnim)
void CSmokeGrenade::SecondaryAttack()
{
- ShieldSecondaryFire(SHIELDGUN_DRAW, SHIELDGUN_DRAWN_IDLE);
+ ShieldSecondaryFire(SHIELDGREN_UP, SHIELDGREN_DOWN);
}
void CSmokeGrenade::SetPlayerShieldAnim()
@@ -251,7 +251,7 @@ void CSmokeGrenade::WeaponIdle()
if (m_iWeaponState & WPNSTATE_SHIELD_DRAWN)
{
- SendWeaponAnim(SHIELDREN_IDLE, UseDecrement() != FALSE);
+ SendWeaponAnim(SHIELDGREN_IDLE, UseDecrement() != FALSE);
}
}
else
diff --git a/regamedll/dlls/wpn_shared/wpn_usp.cpp b/regamedll/dlls/wpn_shared/wpn_usp.cpp
index 6141baebe..0d830d690 100644
--- a/regamedll/dlls/wpn_shared/wpn_usp.cpp
+++ b/regamedll/dlls/wpn_shared/wpn_usp.cpp
@@ -279,7 +279,7 @@ void CUSP::WeaponIdle()
if (m_iWeaponState & WPNSTATE_SHIELD_DRAWN)
{
- SendWeaponAnim(USP_DRAW, UseDecrement());
+ SendWeaponAnim(USP_SHIELD_IDLE_UP, UseDecrement());
}
}
else if (m_iClip)
diff --git a/regamedll/engine/studio.h b/regamedll/engine/studio.h
index bbd18b47b..b896ccdff 100644
--- a/regamedll/engine/studio.h
+++ b/regamedll/engine/studio.h
@@ -32,195 +32,338 @@
#pragma once
#endif
-#include "studio_event.h"
+#define MAXSTUDIOTRIANGLES 20000 // TODO: tune this
+#define MAXSTUDIOVERTS 2048 // TODO: tune this
+#define MAXSTUDIOSEQUENCES 2048 // total animation sequences
+#define MAXSTUDIOSKINS 100 // total textures
+#define MAXSTUDIOSRCBONES 512 // bones allowed at source movement
+#define MAXSTUDIOBONES 128 // total bones actually used
+#define MAXSTUDIOMODELS 32 // sub-models per model
+#define MAXSTUDIOBODYPARTS 32
+#define MAXSTUDIOGROUPS 16
+#define MAXSTUDIOANIMATIONS 2048 // per sequence
+#define MAXSTUDIOMESHES 256
+#define MAXSTUDIOEVENTS 1024
+#define MAXSTUDIOPIVOTS 256
+#define MAXSTUDIOCONTROLLERS 8
-#define MAXSTUDIOTRIANGLES 20000 // TODO: tune this
-#define MAXSTUDIOVERTS 2048 // TODO: tune this
-#define MAXSTUDIOSEQUENCES 256 // total animation sequences
-#define MAXSTUDIOSKINS 100 // total textures
-#define MAXSTUDIOSRCBONES 512 // bones allowed at source movement
-#define MAXSTUDIOBONES 128 // total bones actually used
-#define MAXSTUDIOMODELS 32 // sub-models per model
-#define MAXSTUDIOBODYPARTS 32
-#define MAXSTUDIOGROUPS 16
-#define MAXSTUDIOANIMATIONS 512 // per sequence
-#define MAXSTUDIOMESHES 256
-#define MAXSTUDIOEVENTS 1024
-#define MAXSTUDIOPIVOTS 256
-#define MAXSTUDIOCONTROLLERS 8
+typedef struct
+{
+ int id;
+ int version;
-// lighting options
-#define STUDIO_NF_FLATSHADE 0x0001
-#define STUDIO_NF_CHROME 0x0002
-#define STUDIO_NF_FULLBRIGHT 0x0004
+ char name[64];
+ int length;
-// motion flags
-#define STUDIO_X 0x0001
-#define STUDIO_Y 0x0002
-#define STUDIO_Z 0x0004
-#define STUDIO_XR 0x0008
-#define STUDIO_YR 0x0010
-#define STUDIO_ZR 0x0020
-#define STUDIO_LX 0x0040
-#define STUDIO_LY 0x0080
-#define STUDIO_LZ 0x0100
-#define STUDIO_AX 0x0200
-#define STUDIO_AY 0x0400
-#define STUDIO_AZ 0x0800
-#define STUDIO_AXR 0x1000
-#define STUDIO_AYR 0x2000
-#define STUDIO_AZR 0x4000
-#define STUDIO_TYPES 0x7FFF
-#define STUDIO_RLOOP 0x8000 // controller that wraps shortest distance
+ vec3_t eyeposition; // ideal eye position
+ vec3_t min; // ideal movement hull size
+ vec3_t max;
-// sequence flags
-#define STUDIO_LOOPING 0x0001
+ vec3_t bbmin; // clipping bounding box
+ vec3_t bbmax;
-// bone flags
-#define STUDIO_HAS_NORMALS 0x0001
-#define STUDIO_HAS_VERTICES 0x0002
-#define STUDIO_HAS_BBOX 0x0004
-#define STUDIO_HAS_CHROME 0x0008 // if any of the textures have chrome on them
+ int flags;
-#define RAD_TO_STUDIO (32768.0/M_PI)
-#define STUDIO_TO_RAD (M_PI/32768.0)
+ int numbones; // bones
+ int boneindex;
-typedef struct
-{
- int id;
- int version;
- char name[64];
- int length;
- vec3_t eyeposition; // ideal eye position
- vec3_t min; // ideal movement hull size
- vec3_t max;
- vec3_t bbmin; // clipping bounding box
- vec3_t bbmax;
- int flags;
- int numbones; // bones
- int boneindex;
- int numbonecontrollers; // bone controllers
- int bonecontrollerindex;
- int numhitboxes; // complex bounding boxes
- int hitboxindex;
- int numseq; // animation sequences
- int seqindex;
- int numseqgroups; // demand loaded sequences
- int seqgroupindex;
- int numtextures; // raw textures
- int textureindex;
- int texturedataindex;
- int numskinref; // replaceable textures
- int numskinfamilies;
- int skinindex;
- int numbodyparts;
- int bodypartindex;
- int numattachments; // queryable attachable points
- int attachmentindex;
- int soundtable;
- int soundindex;
- int soundgroups;
- int soundgroupindex;
- int numtransitions; // animation node to animation node transition graph
- int transitionindex;
+ int numbonecontrollers; // bone controllers
+ int bonecontrollerindex;
+
+ int numhitboxes; // complex bounding boxes
+ int hitboxindex;
+
+ int numseq; // animation sequences
+ int seqindex;
+
+ int numseqgroups; // demand loaded sequences
+ int seqgroupindex;
+ int numtextures; // raw textures
+ int textureindex;
+ int texturedataindex;
+
+ int numskinref; // replaceable textures
+ int numskinfamilies;
+ int skinindex;
+
+ int numbodyparts;
+ int bodypartindex;
+
+ int numattachments; // queryable attachable points
+ int attachmentindex;
+
+ int soundtable;
+ int soundindex;
+ int soundgroups;
+ int soundgroupindex;
+
+ int numtransitions; // animation node to animation node transition graph
+ int transitionindex;
} studiohdr_t;
-// bones
-typedef struct
+// header for demand loaded sequence group data
+typedef struct
{
- char name[32]; // bone name for symbolic links
- int parent; // parent bone
- int flags; // ??
- int bonecontroller[6]; // bone controller index, -1 == none
- float value[6]; // default DoF values
- float scale[6]; // scale for delta DoF values
+ int id;
+ int version;
+ char name[64];
+ int length;
+} studioseqhdr_t;
+
+// bones
+typedef struct
+{
+ char name[32]; // bone name for symbolic links
+ int parent; // parent bone
+ int flags; // ??
+ int bonecontroller[6]; // bone controller index, -1 == none
+ float value[6]; // default DoF values
+ float scale[6]; // scale for delta DoF values
} mstudiobone_t;
+
// bone controllers
-typedef struct
+typedef struct
{
- int bone; // -1 == 0
- int type; // X, Y, Z, XR, YR, ZR, M
- float start;
- float end;
- int rest; // byte index value at rest
- int index; // 0-3 user set controller, 4 mouth
-
+ int bone; // -1 == 0
+ int type; // X, Y, Z, XR, YR, ZR, M
+ float start;
+ float end;
+ int rest; // byte index value at rest
+ int index; // 0-3 user set controller, 4 mouth
} mstudiobonecontroller_t;
-// demand loaded sequence groups
+// intersection boxes
typedef struct
{
- char label[32]; // textual name
- char name[64]; // file name
- int32 unused1; // cache index pointer
- int unused2; // hack for group 0
+ int bone;
+ int group; // intersection group
+ vec3_t bbmin; // bounding box
+ vec3_t bbmax;
+} mstudiobbox_t;
+// demand loaded sequence groups
+typedef struct
+{
+ char label[32]; // textual name
+ char name[64]; // file name
+ int32 unused1; // was "cache" - index pointer
+ int unused2; // was "data" - hack for group 0
} mstudioseqgroup_t;
// sequence descriptions
typedef struct
{
- char label[32]; // sequence label
- float fps; // frames per second
- int flags; // looping/non-looping flags
- int activity;
- int actweight;
- int numevents;
- int eventindex;
- int numframes; // number of frames per sequence
- int numpivots; // number of foot pivots
- int pivotindex;
- int motiontype;
- int motionbone;
- vec3_t linearmovement;
- int automoveposindex;
- int automoveangleindex;
- vec3_t bbmin; // per sequence bounding box
- vec3_t bbmax;
- int numblends;
- int animindex; // mstudioanim_t pointer relative to start of sequence group data
- // [blend][bone][X, Y, Z, XR, YR, ZR]
- int blendtype[2]; // X, Y, Z, XR, YR, ZR
- float blendstart[2]; // starting value
- float blendend[2]; // ending value
- int blendparent;
- int seqgroup; // sequence group for demand loading
- int entrynode; // transition node at entry
- int exitnode; // transition node at exit
- int nodeflags; // transition rules
- int nextseq; // auto advancing sequences
+ char label[32]; // sequence label
+ float fps; // frames per second
+ int flags; // looping/non-looping flags
+
+ int activity;
+ int actweight;
+
+ int numevents;
+ int eventindex;
+
+ int numframes; // number of frames per sequence
+
+ int numpivots; // number of foot pivots
+ int pivotindex;
+
+ int motiontype;
+ int motionbone;
+ vec3_t linearmovement;
+ int automoveposindex;
+ int automoveangleindex;
+
+ vec3_t bbmin; // per sequence bounding box
+ vec3_t bbmax;
+
+ int numblends;
+ int animindex; // mstudioanim_t pointer relative to start of sequence group data
+ // [blend][bone][X, Y, Z, XR, YR, ZR]
+
+ int blendtype[2]; // X, Y, Z, XR, YR, ZR
+ float blendstart[2]; // starting value
+ float blendend[2]; // ending value
+ int blendparent;
+
+ int seqgroup; // sequence group for demand loading
+
+ int entrynode; // transition node at entry
+ int exitnode; // transition node at exit
+ int nodeflags; // transition rules
+
+ int nextseq; // auto advancing sequences
} mstudioseqdesc_t;
-typedef struct
+// events
+#include "studio_event.h"
+/*
+typedef struct
+{
+ int frame;
+ int event;
+ int type;
+ char options[64];
+} mstudioevent_t;
+*/
+
+// pivots
+typedef struct
{
- unsigned short offset[6];
+ vec3_t org; // pivot point
+ int start;
+ int end;
+} mstudiopivot_t;
+// attachment
+typedef struct
+{
+ char name[32];
+ int type;
+ int bone;
+ vec3_t org; // attachment point
+ vec3_t vectors[3];
+} mstudioattachment_t;
+
+typedef struct
+{
+ unsigned short offset[6];
} mstudioanim_t;
// animation frames
-typedef union
+typedef union
{
- struct
- {
- byte valid;
- byte total;
+ struct {
+ byte valid;
+ byte total;
} num;
- short int value;
-
+ short value;
} mstudioanimvalue_t;
+
+
// body part index
typedef struct
{
- char name[64];
- int nummodels;
- int base;
- int modelindex; // index into models array
-
+ char name[64];
+ int nummodels;
+ int base;
+ int modelindex; // index into models array
} mstudiobodyparts_t;
+
+
+// skin info
+typedef struct
+{
+ char name[64];
+ int flags;
+ int width;
+ int height;
+ int index;
+} mstudiotexture_t;
+
+
+// skin families
+// short index[skinfamilies][skinref]
+
+// studio models
+typedef struct
+{
+ char name[64];
+
+ int type;
+
+ float boundingradius;
+
+ int nummesh;
+ int meshindex;
+
+ int numverts; // number of unique vertices
+ int vertinfoindex; // vertex bone info
+ int vertindex; // vertex vec3_t
+ int numnorms; // number of unique surface normals
+ int norminfoindex; // normal bone info
+ int normindex; // normal vec3_t
+
+ int numgroups; // deformation groups
+ int groupindex;
+} mstudiomodel_t;
+
+
+// vec3_t boundingbox[model][bone][2]; // complex intersection info
+
+
+// meshes
+typedef struct
+{
+ int numtris;
+ int triindex;
+ int skinref;
+ int numnorms; // per mesh normals
+ int normindex; // normal vec3_t
+} mstudiomesh_t;
+
+// triangles
+#if 0
+typedef struct
+{
+ short vertindex; // index into vertex array
+ short normindex; // index into normal array
+ short s,t; // s,t position on skin
+} mstudiotrivert_t;
+#endif
+
+#define STUDIO_DYNAMIC_LIGHT 0x0100 // dynamically get lighting from floor or ceil (flying monsters)
+#define STUDIO_TRACE_HITBOX 0x0200 // always use hitbox trace instead of bbox
+
+// lighting options
+#define STUDIO_NF_FLATSHADE 0x0001
+#define STUDIO_NF_CHROME 0x0002
+#define STUDIO_NF_FULLBRIGHT 0x0004
+#define STUDIO_NF_NOMIPS 0x0008
+#define STUDIO_NF_ALPHA 0x0010
+#define STUDIO_NF_ADDITIVE 0x0020
+#define STUDIO_NF_MASKED 0x0040
+
+// motion flags
+#define STUDIO_X 0x0001
+#define STUDIO_Y 0x0002
+#define STUDIO_Z 0x0004
+#define STUDIO_XR 0x0008
+#define STUDIO_YR 0x0010
+#define STUDIO_ZR 0x0020
+#define STUDIO_LX 0x0040
+#define STUDIO_LY 0x0080
+#define STUDIO_LZ 0x0100
+#define STUDIO_AX 0x0200
+#define STUDIO_AY 0x0400
+#define STUDIO_AZ 0x0800
+#define STUDIO_AXR 0x1000
+#define STUDIO_AYR 0x2000
+#define STUDIO_AZR 0x4000
+#define STUDIO_TYPES 0x7FFF
+#define STUDIO_RLOOP 0x8000 // controller that wraps shortest distance
+
+// sequence flags
+#define STUDIO_LOOPING 0x0001
+
+// bone flags
+#define STUDIO_HAS_NORMALS 0x0001
+#define STUDIO_HAS_VERTICES 0x0002
+#define STUDIO_HAS_BBOX 0x0004
+#define STUDIO_HAS_CHROME 0x0008 // if any of the textures have chrome on them
+
+#define RAD_TO_STUDIO (32768.0/M_PI)
+#define STUDIO_TO_RAD (M_PI/32768.0)
+
+
+#define STUDIO_NUM_HULLS 128
+#define STUDIO_NUM_PLANES (STUDIO_NUM_HULLS * 6)
+#define STUDIO_CACHE_SIZE 16
+
#endif // STUDIO_H
diff --git a/regamedll/engine/unicode_strtools.cpp b/regamedll/engine/unicode_strtools.cpp
index e7e113ba6..6dbf19417 100644
--- a/regamedll/engine/unicode_strtools.cpp
+++ b/regamedll/engine/unicode_strtools.cpp
@@ -756,9 +756,8 @@ int Q_UnicodeConvertT(const SrcType *pIn, int nInChars, DstType *pOut, int nOutB
if (bErr)
{
-#ifdef _DEBUG
- AssertMsg(!(ePolicy & _STRINGCONVERTFLAG_ASSERT), "invalid Unicode byte sequence");
-#endif
+ DbgAssertMsg(!(ePolicy & _STRINGCONVERTFLAG_ASSERT), "invalid Unicode byte sequence");
+
if (ePolicy & _STRINGCONVERTFLAG_SKIP)
{
nOut -= EncodeDstLen(uVal);
@@ -793,9 +792,8 @@ int Q_UnicodeConvertT(const SrcType *pIn, int nInChars, DstType *pOut, int nOutB
nOut += EncodeDst(uVal, pOut + nOut);
if (bErr)
{
-#ifdef _DEBUG
- AssertMsg(!(ePolicy & _STRINGCONVERTFLAG_ASSERT), "invalid Unicode byte sequence");
-#endif
+ DbgAssertMsg(!(ePolicy & _STRINGCONVERTFLAG_ASSERT), "invalid Unicode byte sequence");
+
if (ePolicy & _STRINGCONVERTFLAG_SKIP)
{
nOut -= EncodeDstLen(uVal);
diff --git a/regamedll/game_shared/bitvec.h b/regamedll/game_shared/bitvec.h
index 52f91b539..36c6b7384 100644
--- a/regamedll/game_shared/bitvec.h
+++ b/regamedll/game_shared/bitvec.h
@@ -127,7 +127,7 @@ inline CBitVec &CBitVec::operator=(CBitVec const &
template
inline CBitVecAccessor CBitVec::operator[](int i)
{
- assert(i >= 0 && i < GetNumBits());
+ DbgAssert(i >= 0 && i < GetNumBits());
return CBitVecAccessor(m_DWords, i);
}
@@ -152,13 +152,13 @@ inline bool CBitVec::operator!=(CBitVec const &other)
template
inline uint32 CBitVec::GetDWord(int i)
{
- assert(i >= 0 && i < NUM_DWORDS);
+ DbgAssert(i >= 0 && i < NUM_DWORDS);
return m_DWords[i];
}
template
inline void CBitVec::SetDWord(int i, uint32 val)
{
- assert(i >= 0 && i < NUM_DWORDS);
+ DbgAssert(i >= 0 && i < NUM_DWORDS);
m_DWords[i] = val;
}
diff --git a/regamedll/game_shared/bot/bot_manager.cpp b/regamedll/game_shared/bot/bot_manager.cpp
index 6e75cef75..285a26a36 100644
--- a/regamedll/game_shared/bot/bot_manager.cpp
+++ b/regamedll/game_shared/bot/bot_manager.cpp
@@ -213,10 +213,12 @@ const char *CBotManager::GetNavMapFilename() const
return filename;
}
+LINK_HOOK_CLASS_VOID_CHAIN(CBotManager, OnEvent, (GameEventType event, CBaseEntity* pEntity, CBaseEntity* pOther), event, pEntity, pOther)
+
// Invoked when given player does given event (some events have NULL player).
// Events are propogated to all bots.
// TODO: This has become the game-wide event dispatcher. We should restructure this.
-void CBotManager::OnEvent(GameEventType event, CBaseEntity *pEntity, CBaseEntity *pOther)
+void CBotManager::__API_HOOK(OnEvent)(GameEventType event, CBaseEntity* pEntity, CBaseEntity* pOther)
{
// propogate event to all bots
for (int i = 1; i <= gpGlobals->maxClients; i++)
diff --git a/regamedll/game_shared/bot/bot_manager.h b/regamedll/game_shared/bot/bot_manager.h
index 788c54ca9..dfcfd8edc 100644
--- a/regamedll/game_shared/bot/bot_manager.h
+++ b/regamedll/game_shared/bot/bot_manager.h
@@ -81,6 +81,10 @@ class CBotManager
virtual void OnEvent(GameEventType event, CBaseEntity *pEntity = nullptr, CBaseEntity *pOther = nullptr); // Invoked when event occurs in the game (some events have NULL entity).
virtual unsigned int GetPlayerPriority(CBasePlayer *pPlayer) const = 0; // return priority of player (0 = max pri)
+#ifdef REGAMEDLL_API
+ void OnEvent_OrigFunc(GameEventType event, CBaseEntity* pEntity = nullptr, CBaseEntity* pOther = nullptr);
+#endif
+
public:
const char *GetNavMapFilename() const; // return the filename for this map's "nav" file
diff --git a/regamedll/game_shared/bot/bot_util.cpp b/regamedll/game_shared/bot/bot_util.cpp
index d14aaaeba..9b5e2013e 100644
--- a/regamedll/game_shared/bot/bot_util.cpp
+++ b/regamedll/game_shared/bot/bot_util.cpp
@@ -613,6 +613,13 @@ void CONSOLE_ECHO_LOGGED(const char *pszMsg, ...)
void BotPrecache()
{
+#ifdef REGAMEDLL_FIXES
+ // all resources above are used between navarea, improved bots and tutor
+ // you can run cs1.6 with bots so it's not only limited to czero
+ if (!AreRunningCZero() && !AreBotsAllowed())
+ return;
+#endif
+
s_iBeamSprite = PRECACHE_MODEL("sprites/smoke.spr");
PRECACHE_SOUND("buttons/bell1.wav");
@@ -621,7 +628,12 @@ void BotPrecache()
PRECACHE_SOUND("buttons/button11.wav");
PRECACHE_SOUND("buttons/latchunlocked2.wav");
PRECACHE_SOUND("buttons/lightswitch2.wav");
- PRECACHE_SOUND("ambience/quail1.wav");
+
+#ifdef REGAMEDLL_FIXES
+ PRECACHE_GENERIC("sound/ambience/quail1.wav");
+#else
+ PRECACHE_SOUND("ambience/quail1.wav"); // not used internally
+#endif
PRECACHE_SOUND("events/tutor_msg.wav");
PRECACHE_SOUND("events/enemy_died.wav");
diff --git a/regamedll/game_shared/bot/nav_file.cpp b/regamedll/game_shared/bot/nav_file.cpp
index 1e8bf7170..ad04f52c9 100644
--- a/regamedll/game_shared/bot/nav_file.cpp
+++ b/regamedll/game_shared/bot/nav_file.cpp
@@ -15,7 +15,6 @@
#include
#include
-#include
#ifndef _WIN32
#include
@@ -42,7 +41,7 @@ PlaceDirectory::EntryType PlaceDirectory::GetEntry(Place place) const
auto it = std::find(m_directory.begin(), m_directory.end(), place);
if (it == m_directory.end())
{
- assert(false && "PlaceDirectory::GetEntry failure");
+ DbgAssert(false && "PlaceDirectory::GetEntry failure");
return 0;
}
@@ -54,7 +53,7 @@ void PlaceDirectory::AddPlace(Place place)
if (place == UNDEFINED_PLACE)
return;
- assert(place < 1000);
+ DbgAssert(place < 1000);
if (IsKnown(place))
return;
@@ -70,7 +69,7 @@ Place PlaceDirectory::EntryToPlace(EntryType entry) const
unsigned int i = entry - 1;
if (i > m_directory.size())
{
- assert(false && "PlaceDirectory::EntryToPlace: Invalid entry");
+ DbgAssert(false && "PlaceDirectory::EntryToPlace: Invalid entry");
return UNDEFINED_PLACE;
}
diff --git a/regamedll/msvc/ReGameDLL.vcxproj b/regamedll/msvc/ReGameDLL.vcxproj
index 3e882d9e6..57e09e917 100644
--- a/regamedll/msvc/ReGameDLL.vcxproj
+++ b/regamedll/msvc/ReGameDLL.vcxproj
@@ -47,6 +47,10 @@
+
+
+
+
@@ -536,14 +540,9 @@
-
-
-
-
-
- true
- true
-
+
+
+
true
true
@@ -783,6 +782,8 @@
+
+
@@ -805,6 +806,9 @@
false
+
+
+
{70A2B904-B7DB-4C48-8DE0-AF567360D572}
ReGameDLL
@@ -818,7 +822,8 @@
v120
v140
v141
- v142
+ v142
+ v143
DynamicLibrary
@@ -827,7 +832,8 @@
v120
v140
v141
- v142
+ v142
+ v143
true
@@ -837,7 +843,8 @@
v120
v140
v141
- v142
+ v142
+ v143
true
@@ -847,7 +854,8 @@
v120
v140
v141
- v142
+ v142
+ v143
Application
@@ -855,7 +863,8 @@
v120_xp
v140_xp
v141_xp
- v142
+ v142
+ v143
MultiByte
diff --git a/regamedll/msvc/ReGameDLL.vcxproj.filters b/regamedll/msvc/ReGameDLL.vcxproj.filters
index d8c27981d..ef2017ae4 100644
--- a/regamedll/msvc/ReGameDLL.vcxproj.filters
+++ b/regamedll/msvc/ReGameDLL.vcxproj.filters
@@ -540,6 +540,9 @@
dlls\API
+
+ dlls\API
+
regamedll
@@ -552,6 +555,12 @@
public
+
+ public\tier0
+
+
+ public\tier0
+
@@ -1049,5 +1058,16 @@
dlls\addons
+
+ public
+
+
+ public\tier0
+
+
+
+
+ public\tier0
+
\ No newline at end of file
diff --git a/regamedll/pm_shared/pm_shared.cpp b/regamedll/pm_shared/pm_shared.cpp
index 75d4a4909..b41a23927 100644
--- a/regamedll/pm_shared/pm_shared.cpp
+++ b/regamedll/pm_shared/pm_shared.cpp
@@ -12,6 +12,10 @@ char pm_grgchTextureType[MAX_TEXTURES];
playermove_t *pmove = nullptr;
BOOL g_onladder = FALSE;
+#ifdef REGAMEDLL_API
+static CCSPlayer *pmoveplayer = nullptr;
+#endif
+
#ifdef CLIENT_DLL
int iJumpSpectator;
float vJumpOrigin[3];
@@ -134,7 +138,7 @@ char EXT_FUNC PM_FindTextureType(char *name)
int left, right, pivot;
int val;
- assert(pm_shared_initialized);
+ DbgAssert(pm_shared_initialized);
left = 0;
right = pm_gcTextures - 1;
@@ -162,7 +166,9 @@ char EXT_FUNC PM_FindTextureType(char *name)
return CHAR_TEX_CONCRETE;
}
-void PM_PlayStepSound(int step, float fvol)
+LINK_HOOK_VOID_CHAIN(PM_PlayStepSound, (int step, float fvol), step, fvol)
+
+void EXT_FUNC __API_HOOK(PM_PlayStepSound)(int step, float fvol)
{
static int iSkipStep = 0;
int irand;
@@ -365,7 +371,7 @@ void PM_CatagorizeTextureType()
pmove->chtexturetype = PM_FindTextureType(pmove->sztexturename);
}
-LINK_HOOK_VOID_CHAIN2(PM_UpdateStepSound);
+LINK_HOOK_VOID_CHAIN2(PM_UpdateStepSound)
void EXT_FUNC __API_HOOK(PM_UpdateStepSound)()
{
@@ -1127,7 +1133,9 @@ void PM_Friction()
VectorCopy(newvel, pmove->velocity);
}
-void PM_AirAccelerate(vec_t *wishdir, float wishspeed, float accel)
+LINK_HOOK_VOID_CHAIN(PM_AirAccelerate, (vec_t *wishdir, float wishspeed, float accel), wishdir, wishspeed, accel)
+
+void EXT_FUNC __API_HOOK(PM_AirAccelerate)(vec_t *wishdir, float wishspeed, float accel)
{
int i;
float addspeed;
@@ -1274,7 +1282,7 @@ void PM_WaterMove()
PM_FlyMove();
}
-LINK_HOOK_VOID_CHAIN(PM_AirMove, (int playerIndex = 0), pmove->player_index + 1);
+LINK_HOOK_VOID_CHAIN(PM_AirMove, (int playerIndex = 0), pmove->player_index + 1)
void EXT_FUNC __API_HOOK(PM_AirMove)(int playerIndex)
{
@@ -1793,7 +1801,9 @@ void PM_FixPlayerCrouchStuck(int direction)
VectorCopy(test, pmove->origin);
}
-void PM_UnDuck()
+LINK_HOOK_VOID_CHAIN2(PM_UnDuck)
+
+void EXT_FUNC __API_HOOK(PM_UnDuck)()
{
#ifdef REGAMEDLL_ADD
if (unduck_method.value)
@@ -1863,7 +1873,9 @@ void PM_UnDuck()
}
}
-void PM_Duck()
+LINK_HOOK_VOID_CHAIN2(PM_Duck)
+
+void EXT_FUNC __API_HOOK(PM_Duck)()
{
int buttonsChanged = (pmove->oldbuttons ^ pmove->cmd.buttons); // These buttons have changed this frame
int nButtonPressed = buttonsChanged & pmove->cmd.buttons; // The changed ones still down are "pressed"
@@ -1881,8 +1893,8 @@ void PM_Duck()
}
#ifdef REGAMEDLL_ADD
- // Prevent ducking if the iuser3 variable is contain PLAYER_PREVENT_DUCK
- if ((pmove->iuser3 & PLAYER_PREVENT_DUCK) == PLAYER_PREVENT_DUCK)
+ if ((pmove->iuser3 & PLAYER_PREVENT_DUCK) == PLAYER_PREVENT_DUCK // Prevent ducking if the iuser3 variable is contain PLAYER_PREVENT_DUCK
+ || freezetime_duck.value == 0.0f && CSGameRules()->IsFreezePeriod()) // Prevent ducking during freezetime if the freezetime_duck cvar is 0
{
// Try to unduck
if (pmove->flags & FL_DUCKING)
@@ -1899,9 +1911,16 @@ void PM_Duck()
return;
}
- pmove->cmd.forwardmove *= PLAYER_DUCKING_MULTIPLIER;
- pmove->cmd.sidemove *= PLAYER_DUCKING_MULTIPLIER;
- pmove->cmd.upmove *= PLAYER_DUCKING_MULTIPLIER;
+ real_t mult = PLAYER_DUCKING_MULTIPLIER;
+
+#ifdef REGAMEDLL_API
+ if (pmoveplayer->m_flDuckSpeedMultiplier > 0.0)
+ mult = pmoveplayer->m_flDuckSpeedMultiplier;
+#endif
+
+ pmove->cmd.forwardmove *= mult;
+ pmove->cmd.sidemove *= mult;
+ pmove->cmd.upmove *= mult;
if (pmove->cmd.buttons & IN_DUCK)
{
@@ -1967,7 +1986,9 @@ void PM_Duck()
}
}
-void PM_LadderMove(physent_t *pLadder)
+LINK_HOOK_VOID_CHAIN(PM_LadderMove, (physent_t *pLadder), pLadder)
+
+void EXT_FUNC __API_HOOK(PM_LadderMove)(physent_t *pLadder)
{
vec3_t ladderCenter;
trace_t trace;
@@ -2013,7 +2034,16 @@ void PM_LadderMove(physent_t *pLadder)
if (pmove->flags & FL_DUCKING)
{
- flSpeed *= PLAYER_DUCKING_MULTIPLIER;
+#ifdef REGAMEDLL_API
+ if (pmoveplayer->m_flDuckSpeedMultiplier > 0.0)
+ {
+ flSpeed *= pmoveplayer->m_flDuckSpeedMultiplier;
+ }
+ else
+#endif
+ {
+ flSpeed *= PLAYER_DUCKING_MULTIPLIER;
+ }
}
if (pmove->cmd.buttons & IN_BACK)
@@ -2117,7 +2147,9 @@ physent_t *PM_Ladder()
return nullptr;
}
-void PM_WaterJump()
+LINK_HOOK_VOID_CHAIN2(PM_WaterJump)
+
+void EXT_FUNC __API_HOOK(PM_WaterJump)()
{
if (pmove->waterjumptime > 10000)
{
@@ -2342,7 +2374,23 @@ void PM_PreventMegaBunnyJumping()
VectorScale(pmove->velocity, fraction, pmove->velocity);
}
-void PM_Jump()
+inline real_t PM_JumpHeight(bool longjump)
+{
+#ifdef REGAMEDLL_API
+ if (longjump)
+ {
+ if(pmoveplayer->m_flLongJumpHeight > 0.0)
+ return pmoveplayer->m_flLongJumpHeight;
+ }
+ else if (pmoveplayer->m_flJumpHeight > 0.0)
+ return pmoveplayer->m_flJumpHeight;
+#endif
+ return Q_sqrt(2.0 * 800.0f * (longjump ? 56.0f : 45.0f));
+}
+
+LINK_HOOK_VOID_CHAIN2(PM_Jump)
+
+void EXT_FUNC __API_HOOK(PM_Jump)()
{
if (pmove->dead)
{
@@ -2401,8 +2449,8 @@ void PM_Jump()
}
#ifdef REGAMEDLL_ADD
- // Prevent jumping if the iuser3 variable is contain PLAYER_PREVENT_JUMP
- if ((pmove->iuser3 & PLAYER_PREVENT_JUMP) == PLAYER_PREVENT_JUMP)
+ if ((pmove->iuser3 & PLAYER_PREVENT_JUMP) == PLAYER_PREVENT_JUMP // Prevent jumping if the iuser3 variable is contain PLAYER_PREVENT_JUMP
+ || freezetime_jump.value == 0.0f && CSGameRules()->IsFreezePeriod()) // Prevent jumping during freezetime if the freezetime_jump cvar is 0
{
return;
}
@@ -2418,16 +2466,12 @@ void PM_Jump()
return;
}
-#ifdef REGAMEDLL_API
- const CCSPlayer* player = UTIL_PlayerByIndex(pmove->player_index + 1)->CSPlayer();
-#endif
-
// don't pogo stick
if (pmove->oldbuttons & IN_JUMP
#ifdef REGAMEDLL_ADD
&& sv_autobunnyhopping.value <= 0.0
#ifdef REGAMEDLL_API
- && !player->m_bAutoBunnyHopping
+ && !pmoveplayer->m_bAutoBunnyHopping
#endif
#endif
)
@@ -2448,7 +2492,7 @@ void PM_Jump()
#ifdef REGAMEDLL_ADD
if (sv_enablebunnyhopping.value <= 0.0
#ifdef REGAMEDLL_API
- && !player->m_bMegaBunnyJumping
+ && !pmoveplayer->m_bMegaBunnyJumping
#endif
)
#endif
@@ -2478,23 +2522,34 @@ void PM_Jump()
{
pmove->punchangle[0] = -5.0f;
- for (int i = 0; i < 2; i++)
+#ifdef REGAMEDLL_API
+ if (pmoveplayer->m_flLongJumpForce > 0.0)
{
- pmove->velocity[i] = pmove->forward[i] * PLAYER_LONGJUMP_SPEED * 1.6f;
+ fvel = pmoveplayer->m_flLongJumpForce;
+ }
+ else
+#endif
+ {
+ fvel = PLAYER_LONGJUMP_SPEED * 1.6f;
+ }
+
+ for (int i = 0; i < 2; i++)
+ {
+ pmove->velocity[i] = pmove->forward[i] * fvel;
}
- pmove->velocity[2] = Q_sqrt(2 * 800 * 56.0f);
+ pmove->velocity[2] = PM_JumpHeight(true);
}
else
{
- pmove->velocity[2] = Q_sqrt(2 * 800 * 45.0f);
+ pmove->velocity[2] = PM_JumpHeight(false);
}
}
else
#endif
{
// NOTE: don't do it in .f (float)
- pmove->velocity[2] = Q_sqrt(2.0 * 800.0f * 45.0f);
+ pmove->velocity[2] = PM_JumpHeight(false);
}
if (pmove->fuser2 > 0.0f)
@@ -2514,7 +2569,9 @@ void PM_Jump()
pmove->oldbuttons |= IN_JUMP;
}
-void PM_CheckWaterJump()
+LINK_HOOK_VOID_CHAIN2(PM_CheckWaterJump)
+
+void EXT_FUNC __API_HOOK(PM_CheckWaterJump)()
{
vec3_t vecStart, vecEnd;
vec3_t flatforward;
@@ -3207,7 +3264,7 @@ void PM_CreateStuckTable()
}
}
-LINK_HOOK_VOID_CHAIN(PM_Move, (struct playermove_s *ppmove, int server), ppmove, server);
+LINK_HOOK_VOID_CHAIN(PM_Move, (struct playermove_s *ppmove, int server), ppmove, server)
// This module implements the shared player physics code between any particular game and
// the engine. The same PM_Move routine is built into the game .dll and the client .dll and is
@@ -3215,9 +3272,13 @@ LINK_HOOK_VOID_CHAIN(PM_Move, (struct playermove_s *ppmove, int server), ppmove,
// and client. This will ensure that prediction behaves appropriately.
void EXT_FUNC __API_HOOK(PM_Move)(struct playermove_s *ppmove, int server)
{
- assert(pm_shared_initialized);
+ DbgAssert(pm_shared_initialized);
pmove = ppmove;
+
+#ifdef REGAMEDLL_API
+ pmoveplayer = UTIL_PlayerByIndex(pmove->player_index + 1)->CSPlayer();
+#endif
PM_PlayerMove((server != 0) ? TRUE : FALSE);
@@ -3252,11 +3313,11 @@ NOXREF int PM_GetPhysEntInfo(int ent)
return -1;
}
-LINK_HOOK_VOID_CHAIN(PM_Init, (struct playermove_s *ppmove), ppmove);
+LINK_HOOK_VOID_CHAIN(PM_Init, (struct playermove_s *ppmove), ppmove)
void EXT_FUNC __API_HOOK(PM_Init)(struct playermove_s *ppmove)
{
- assert(!pm_shared_initialized);
+ DbgAssert(!pm_shared_initialized);
pmove = ppmove;
diff --git a/regamedll/pm_shared/pm_shared.h b/regamedll/pm_shared/pm_shared.h
index 94113ae0a..2c0385f40 100644
--- a/regamedll/pm_shared/pm_shared.h
+++ b/regamedll/pm_shared/pm_shared.h
@@ -77,12 +77,21 @@ void PM_Init(struct playermove_s *ppmove);
void PM_Move(struct playermove_s *ppmove, int server);
char PM_FindTextureType(char *name);
void PM_AirMove_internal();
+void PM_LadderMove(physent_t *pLadder);
#ifdef REGAMEDLL_API
void PM_Init_OrigFunc(struct playermove_s *ppmove);
void PM_Move_OrigFunc(struct playermove_s *ppmove, int server);
void PM_AirMove_OrigFunc(int playerIndex = 0);
void PM_UpdateStepSound_OrigFunc();
+void PM_LadderMove_OrigFunc(physent_t *pLadder);
+void PM_WaterJump_OrigFunc();
+void PM_CheckWaterJump_OrigFunc();
+void PM_Jump_OrigFunc();
+void PM_Duck_OrigFunc();
+void PM_UnDuck_OrigFunc();
+void PM_PlayStepSound_OrigFunc(int step, float fvol);
+void PM_AirAccelerate_OrigFunc(vec_t *wishdir, float wishspeed, float accel);
#else
void PM_AirMove(int playerIndex = 0);
#endif
diff --git a/regamedll/public/interface.cpp b/regamedll/public/interface.cpp
index 8c6dd0ccc..d1cf92830 100644
--- a/regamedll/public/interface.cpp
+++ b/regamedll/public/interface.cpp
@@ -230,7 +230,7 @@ void *InitializeInterface(char const *interfaceName, CreateInterfaceFn *factoryL
}
// No provider for requested interface!!!
- // assert(!"No provider for requested interface!!!");
+ // Assert(!"No provider for requested interface!!!");
return nullptr;
}
diff --git a/regamedll/public/regamedll/API/CSEntity.h b/regamedll/public/regamedll/API/CSEntity.h
index 92882bd84..4d73075e7 100644
--- a/regamedll/public/regamedll/API/CSEntity.h
+++ b/regamedll/public/regamedll/API/CSEntity.h
@@ -33,8 +33,10 @@ class CCSEntity
{
public:
CCSEntity() :
- m_pContainingEntity(nullptr)
+ m_pContainingEntity(nullptr),
+ m_pevLastInflictor(nullptr)
{
+ m_ucDmgPenetrationLevel = 0;
}
virtual ~CCSEntity() {}
@@ -42,13 +44,19 @@ class CCSEntity
virtual void FireBuckshots(ULONG cShots, Vector &vecSrc, Vector &vecDirShooting, Vector &vecSpread, float flDistance, int iTracerFreq, int iDamage, entvars_t *pevAttacker);
virtual Vector FireBullets3(Vector &vecSrc, Vector &vecDirShooting, float vecSpread, float flDistance, int iPenetration, int iBulletType, int iDamage, float flRangeModifier, entvars_t *pevAttacker, bool bPistol, int shared_rand);
+ CBaseEntity *BaseEntity() const;
+
public:
CBaseEntity *m_pContainingEntity;
+ unsigned char m_ucDmgPenetrationLevel; // penetration level of the damage caused by the inflictor
+ entvars_t *m_pevLastInflictor;
private:
#if defined(_MSC_VER)
-#pragma region reserve_vfuncs_Region
+#pragma region reserve_data_Region
#endif
+ char CCSEntity_Reserve[0x3FF7];
+
virtual void func_reserve1() {};
virtual void func_reserve2() {};
virtual void func_reserve3() {};
@@ -84,28 +92,71 @@ class CCSEntity
#endif
};
+// Inlines
+inline CBaseEntity *CCSEntity::BaseEntity() const
+{
+ return this->m_pContainingEntity;
+}
+
+#ifdef REGAMEDLL_API
+inline void CBaseEntity::SetDmgPenetrationLevel(int iPenetrationLevel)
+{
+ CSEntity()->m_ucDmgPenetrationLevel = iPenetrationLevel;
+}
+
+inline void CBaseEntity::ResetDmgPenetrationLevel()
+{
+ CSEntity()->m_ucDmgPenetrationLevel = 0;
+}
+
+inline int CBaseEntity::GetDmgPenetrationLevel() const
+{
+ return CSEntity()->m_ucDmgPenetrationLevel;
+}
+
+inline void CBaseEntity::KilledInflicted(entvars_t *pevInflictor, entvars_t *pevAttacker, int iGib)
+{
+ CSEntity()->m_pevLastInflictor = pevInflictor;
+ Killed(pevAttacker, iGib);
+ CSEntity()->m_pevLastInflictor = nullptr;
+}
+
+inline entvars_t *CBaseEntity::GetLastInflictor()
+{
+ return CSEntity()->m_pevLastInflictor;
+}
+#endif
+
class CCSDelay: public CCSEntity
{
public:
+private:
+ int CCSDelay_Reserve[0x100];
};
class CCSAnimating: public CCSDelay
{
public:
+private:
+ int CCSAnimating_Reserve[0x100];
};
class CCSToggle: public CCSAnimating
{
public:
+private:
+ int CCSToggle_Reserve[0x100];
};
class CCSMonster: public CCSToggle
{
public:
+private:
+ int CCSMonster_Reserve[0x100];
};
-#define CSENTITY_API_INTERFACE_VERSION "CSENTITY_API_INTERFACE_VERSION002"
+#define CSENTITY_API_INTERFACE_VERSION "CSENTITY_API_INTERFACE_VERSION003"
diff --git a/regamedll/public/regamedll/API/CSPlayer.h b/regamedll/public/regamedll/API/CSPlayer.h
index 9ce4c15d0..18558a433 100644
--- a/regamedll/public/regamedll/API/CSPlayer.h
+++ b/regamedll/public/regamedll/API/CSPlayer.h
@@ -30,6 +30,7 @@
#include
#include
+#include
enum WeaponInfiniteAmmoMode
{
@@ -50,9 +51,23 @@ class CCSPlayer: public CCSMonster {
m_bAutoBunnyHopping(false),
m_bMegaBunnyJumping(false),
m_bPlantC4Anywhere(false),
- m_iAliveNameChanges(0)
+ m_iAliveNameChanges(0),
+ m_bSpawnProtectionEffects(false),
+ m_flJumpHeight(0),
+ m_flLongJumpHeight(0),
+ m_flLongJumpForce(0),
+ m_flDuckSpeedMultiplier(0),
+ m_iUserID(-1),
+ m_iGibDamageThreshold(GIB_PLAYER_THRESHOLD)
{
m_szModel[0] = '\0';
+
+ // Resets the kill history for this player
+ for (int i = 0; i < MAX_CLIENTS; i++)
+ {
+ m_iNumKilledByUnanswered[i] = 0;
+ m_bPlayerDominated[i] = false;
+ }
}
virtual bool IsConnected() const;
@@ -62,8 +77,8 @@ class CCSPlayer: public CCSMonster {
virtual CBaseEntity *GiveNamedItemEx(const char *pszName);
virtual void GiveDefaultItems();
virtual void GiveShield(bool bDeploy = true);
- virtual void DropShield(bool bDeploy = true);
- virtual void DropPlayerItem(const char *pszItemName);
+ virtual CBaseEntity *DropShield(bool bDeploy = true);
+ virtual CBaseEntity* DropPlayerItem(const char *pszItemName);
virtual bool RemoveShield();
virtual void RemoveAllItems(bool bRemoveSuit);
virtual bool RemovePlayerItem(const char* pszItemName);
@@ -100,11 +115,19 @@ class CCSPlayer: public CCSMonster {
virtual void SetSpawnProtection(float flProtectionTime);
virtual void RemoveSpawnProtection();
virtual bool HintMessageEx(const char *pMessage, float duration = 6.0f, bool bDisplayIfPlayerDead = false, bool bOverride = false);
+ virtual void Reset();
+ virtual void OnSpawnEquip(bool addDefault = true, bool equipGame = true);
+ virtual void SetScoreboardAttributes(CBasePlayer *destination = nullptr);
+
+ bool IsPlayerDominated(int iPlayerIndex) const;
+ void SetPlayerDominated(CBasePlayer *pPlayer, bool bDominated);
- void Reset();
+ void ResetVars();
+ void ResetAllStats();
void OnSpawn();
void OnKilled();
+ void OnConnect();
CBasePlayer *BasePlayer() const;
@@ -133,6 +156,27 @@ class CCSPlayer: public CCSMonster {
bool m_bMegaBunnyJumping;
bool m_bPlantC4Anywhere;
int m_iAliveNameChanges;
+ bool m_bSpawnProtectionEffects;
+ double m_flJumpHeight;
+ double m_flLongJumpHeight;
+ double m_flLongJumpForce;
+ double m_flDuckSpeedMultiplier;
+
+ int m_iUserID;
+ struct CDamageRecord_t
+ {
+ float flDamage = 0.0f;
+ float flFlashDurationTime = 0.0f;
+ int userId = -1;
+ };
+ using DamageList_t = CUtlArray;
+ DamageList_t m_DamageList; // A unified array of recorded damage that includes giver and taker in each entry
+ DamageList_t &GetDamageList() { return m_DamageList; }
+ void RecordDamage(CBasePlayer *pAttacker, float flDamage, float flFlashDurationTime = -1);
+ int m_iNumKilledByUnanswered[MAX_CLIENTS]; // [0-31] how many unanswered kills this player has been dealt by each other player
+ bool m_bPlayerDominated[MAX_CLIENTS]; // [0-31] array of state per other player whether player is dominating other players
+
+ int m_iGibDamageThreshold; // negative health to reach to gib player
};
// Inlines
@@ -154,3 +198,37 @@ inline CCSPlayer::EProtectionState CCSPlayer::GetProtectionState() const
// has expired
return ProtectionSt_Expired;
}
+
+// Returns whether this player is dominating the specified other player
+inline bool CCSPlayer::IsPlayerDominated(int iPlayerIndex) const
+{
+ if (iPlayerIndex < 0 || iPlayerIndex >= MAX_CLIENTS)
+ return false;
+
+ return m_bPlayerDominated[iPlayerIndex];
+}
+
+// Sets whether this player is dominating the specified other player
+inline void CCSPlayer::SetPlayerDominated(CBasePlayer *pPlayer, bool bDominated)
+{
+ int iPlayerIndex = pPlayer->entindex();
+ Assert(iPlayerIndex > 0 && iPlayerIndex <= MAX_CLIENTS);
+ m_bPlayerDominated[iPlayerIndex - 1] = bDominated;
+}
+
+#ifdef REGAMEDLL_API
+// Determine whether player can be gibbed or not
+inline bool CBasePlayer::ShouldGibPlayer(int iGib)
+{
+ // Always gib the player regardless of incoming damage
+ if (iGib == GIB_ALWAYS)
+ return true;
+
+ // Gib the player if health is below the gib damage threshold
+ if (pev->health < CSPlayer()->m_iGibDamageThreshold && iGib != GIB_NEVER)
+ return true;
+
+ // do not gib the player
+ return false;
+}
+#endif
diff --git a/regamedll/public/regamedll/API/CSPlayerWeapon.h b/regamedll/public/regamedll/API/CSPlayerWeapon.h
index 70317c931..22c020464 100644
--- a/regamedll/public/regamedll/API/CSPlayerWeapon.h
+++ b/regamedll/public/regamedll/API/CSPlayerWeapon.h
@@ -28,19 +28,32 @@
#pragma once
+enum SecondaryAtkState : uint8_t
+{
+ WEAPON_SECONDARY_ATTACK_NONE = 0,
+ WEAPON_SECONDARY_ATTACK_SET,
+ WEAPON_SECONDARY_ATTACK_BLOCK
+};
+
class CBasePlayerWeapon;
class CCSPlayerWeapon: public CCSPlayerItem
{
public:
CCSPlayerWeapon() :
- m_bHasSecondaryAttack(false)
+ m_iStateSecondaryAttack(WEAPON_SECONDARY_ATTACK_NONE)
{
}
+ virtual BOOL DefaultDeploy(char *szViewModel, char *szWeaponModel, int iAnim, char *szAnimExt, int skiplocal = 0);
+ virtual int DefaultReload(int iClipSize, int iAnim, float fDelay);
+ virtual bool DefaultShotgunReload(int iAnim, int iStartAnim, float fDelay, float fStartDelay, const char *pszReloadSound1 = nullptr, const char *pszReloadSound2 = nullptr);
+ virtual void KickBack(float up_base, float lateral_base, float up_modifier, float lateral_modifier, float up_max, float lateral_max, int direction_change);
+ virtual void SendWeaponAnim(int iAnim, int skiplocal = 0);
+
CBasePlayerWeapon *BasePlayerWeapon() const;
public:
- bool m_bHasSecondaryAttack;
+ SecondaryAtkState m_iStateSecondaryAttack;
float m_flBaseDamage;
};
@@ -49,3 +62,4 @@ inline CBasePlayerWeapon *CCSPlayerWeapon::BasePlayerWeapon() const
{
return reinterpret_cast(this->m_pContainingEntity);
}
+
diff --git a/regamedll/public/regamedll/regamedll_api.h b/regamedll/public/regamedll/regamedll_api.h
index ba7a8517c..4aeb12545 100644
--- a/regamedll/public/regamedll/regamedll_api.h
+++ b/regamedll/public/regamedll/regamedll_api.h
@@ -38,7 +38,7 @@
#include
#define REGAMEDLL_API_VERSION_MAJOR 5
-#define REGAMEDLL_API_VERSION_MINOR 21
+#define REGAMEDLL_API_VERSION_MINOR 26
// CBasePlayer::Spawn hook
typedef IHookChainClass IReGameHook_CBasePlayer_Spawn;
@@ -337,8 +337,8 @@ typedef IHookChain IReGameHook_CSGameRules_RemoveGuns;
typedef IHookChainRegistry IReGameHookRegistry_CSGameRules_RemoveGuns;
// CHalfLifeMultiplay::GiveC4 hook
-typedef IHookChain IReGameHook_CSGameRules_GiveC4;
-typedef IHookChainRegistry IReGameHookRegistry_CSGameRules_GiveC4;
+typedef IHookChain IReGameHook_CSGameRules_GiveC4;
+typedef IHookChainRegistry IReGameHookRegistry_CSGameRules_GiveC4;
// CHalfLifeMultiplay::ChangeLevel hook
typedef IHookChain IReGameHook_CSGameRules_ChangeLevel;
@@ -520,6 +520,110 @@ typedef IHookChainRegistryClass IReGameHookRegistry_CBa
typedef IHookChainClass IReGameHook_CBasePlayer_JoiningThink;
typedef IHookChainRegistryClass IReGameHookRegistry_CBasePlayer_JoiningThink;
+// FreeGameRules hook
+typedef IHookChain IReGameHook_FreeGameRules;
+typedef IHookChainRegistry IReGameHookRegistry_FreeGameRules;
+
+// PM_LadderMove hook
+typedef IHookChain IReGameHook_PM_LadderMove;
+typedef IHookChainRegistry IReGameHookRegistry_PM_LadderMove;
+
+// PM_WaterJump hook
+typedef IHookChain IReGameHook_PM_WaterJump;
+typedef IHookChainRegistry IReGameHookRegistry_PM_WaterJump;
+
+// PM_CheckWaterJump hook
+typedef IHookChain IReGameHook_PM_CheckWaterJump;
+typedef IHookChainRegistry IReGameHookRegistry_PM_CheckWaterJump;
+
+// PM_Jump hook
+typedef IHookChain IReGameHook_PM_Jump;
+typedef IHookChainRegistry IReGameHookRegistry_PM_Jump;
+
+// PM_Duck hook
+typedef IHookChain IReGameHook_PM_Duck;
+typedef IHookChainRegistry IReGameHookRegistry_PM_Duck;
+
+// PM_UnDuck hook
+typedef IHookChain IReGameHook_PM_UnDuck;
+typedef IHookChainRegistry IReGameHookRegistry_PM_UnDuck;
+
+// PM_PlayStepSound hook
+typedef IHookChain IReGameHook_PM_PlayStepSound;
+typedef IHookChainRegistry IReGameHookRegistry_PM_PlayStepSound;
+
+// PM_AirAccelerate hook
+typedef IHookChain IReGameHook_PM_AirAccelerate;
+typedef IHookChainRegistry IReGameHookRegistry_PM_AirAccelerate;
+
+// ClearMultiDamage hook
+typedef IHookChain IReGameHook_ClearMultiDamage;
+typedef IHookChainRegistry IReGameHookRegistry_ClearMultiDamage;
+
+// AddMultiDamage hook
+typedef IHookChain IReGameHook_AddMultiDamage;
+typedef IHookChainRegistry IReGameHookRegistry_AddMultiDamage;
+
+// ApplyMultiDamage hook
+typedef IHookChain IReGameHook_ApplyMultiDamage;
+typedef IHookChainRegistry IReGameHookRegistry_ApplyMultiDamage;
+
+// BuyItem hook
+typedef IHookChain IReGameHook_BuyItem;
+typedef IHookChainRegistry IReGameHookRegistry_BuyItem;
+
+// CHalfLifeMultiplay::Think hook
+typedef IHookChain IReGameHook_CSGameRules_Think;
+typedef IHookChainRegistry IReGameHookRegistry_CSGameRules_Think;
+
+// CHalfLifeMultiplay::TeamFull hook
+typedef IHookChain IReGameHook_CSGameRules_TeamFull;
+typedef IHookChainRegistry IReGameHookRegistry_CSGameRules_TeamFull;
+
+// CHalfLifeMultiplay::TeamStacked hook
+typedef IHookChain IReGameHook_CSGameRules_TeamStacked;
+typedef IHookChainRegistry IReGameHookRegistry_CSGameRules_TeamStacked;
+
+// CHalfLifeMultiplay::PlayerGotWeapon hook
+typedef IHookChain IReGameHook_CSGameRules_PlayerGotWeapon;
+typedef IHookChainRegistry IReGameHookRegistry_CSGameRules_PlayerGotWeapon;
+
+// CBotManager::OnEvent hook
+typedef IHookChain IReGameHook_CBotManager_OnEvent;
+typedef IHookChainRegistry IReGameHookRegistry_CBotManager_OnEvent;
+
+// CBasePlayer::CheckTimeBasedDamage hook
+typedef IHookChainClass IReGameHook_CBasePlayer_CheckTimeBasedDamage;
+typedef IHookChainRegistryClass IReGameHookRegistry_CBasePlayer_CheckTimeBasedDamage;
+
+// CBasePlayer::EntSelectSpawnPoint hook
+typedef IHookChainClass IReGameHook_CBasePlayer_EntSelectSpawnPoint;
+typedef IHookChainRegistryClass IReGameHookRegistry_CBasePlayer_EntSelectSpawnPoint;
+
+// CBasePlayerWeapon::ItemPostFrame hook
+typedef IHookChainClass IReGameHook_CBasePlayerWeapon_ItemPostFrame;
+typedef IHookChainRegistryClass IReGameHookRegistry_CBasePlayerWeapon_ItemPostFrame;
+
+// CBasePlayerWeapon::KickBack hook
+typedef IHookChainClass IReGameHook_CBasePlayerWeapon_KickBack;
+typedef IHookChainRegistryClass IReGameHookRegistry_CBasePlayerWeapon_KickBack;
+
+// CBasePlayerWeapon::SendWeaponAnim hook
+typedef IHookChainClass IReGameHook_CBasePlayerWeapon_SendWeaponAnim;
+typedef IHookChainRegistryClass IReGameHookRegistry_CBasePlayerWeapon_SendWeaponAnim;
+
+// CHalfLifeMultiplay::SendDeathMessage hook
+typedef IHookChain IReGameHook_CSGameRules_SendDeathMessage;
+typedef IHookChainRegistry IReGameHookRegistry_CSGameRules_SendDeathMessage;
+
+// CBasePlayer::PlayerDeathThink hook
+typedef IHookChainClass IReGameHook_CBasePlayer_PlayerDeathThink;
+typedef IHookChainRegistryClass IReGameHookRegistry_CBasePlayer_PlayerDeathThink;
+
+// CBasePlayer::Observer_Think hook
+typedef IHookChainClass IReGameHook_CBasePlayer_Observer_Think;
+typedef IHookChainRegistryClass IReGameHookRegistry_CBasePlayer_Observer_Think;
+
class IReGameHookchains {
public:
virtual ~IReGameHookchains() {}
@@ -653,6 +757,34 @@ class IReGameHookchains {
virtual IReGameHookRegistry_CBasePlayer_Pain *CBasePlayer_Pain() = 0;
virtual IReGameHookRegistry_CBasePlayer_DeathSound *CBasePlayer_DeathSound() = 0;
virtual IReGameHookRegistry_CBasePlayer_JoiningThink *CBasePlayer_JoiningThink() = 0;
+
+ virtual IReGameHookRegistry_FreeGameRules *FreeGameRules() = 0;
+ virtual IReGameHookRegistry_PM_LadderMove *PM_LadderMove() = 0;
+ virtual IReGameHookRegistry_PM_WaterJump *PM_WaterJump() = 0;
+ virtual IReGameHookRegistry_PM_CheckWaterJump *PM_CheckWaterJump() = 0;
+ virtual IReGameHookRegistry_PM_Jump *PM_Jump() = 0;
+ virtual IReGameHookRegistry_PM_Duck *PM_Duck() = 0;
+ virtual IReGameHookRegistry_PM_UnDuck *PM_UnDuck() = 0;
+ virtual IReGameHookRegistry_PM_PlayStepSound *PM_PlayStepSound() = 0;
+ virtual IReGameHookRegistry_PM_AirAccelerate *PM_AirAccelerate() = 0;
+ virtual IReGameHookRegistry_ClearMultiDamage *ClearMultiDamage() = 0;
+ virtual IReGameHookRegistry_AddMultiDamage *AddMultiDamage() = 0;
+ virtual IReGameHookRegistry_ApplyMultiDamage *ApplyMultiDamage() = 0;
+ virtual IReGameHookRegistry_BuyItem *BuyItem() = 0;
+ virtual IReGameHookRegistry_CSGameRules_Think *CSGameRules_Think() = 0;
+ virtual IReGameHookRegistry_CSGameRules_TeamFull *CSGameRules_TeamFull() = 0;
+ virtual IReGameHookRegistry_CSGameRules_TeamStacked *CSGameRules_TeamStacked() = 0;
+ virtual IReGameHookRegistry_CSGameRules_PlayerGotWeapon *CSGameRules_PlayerGotWeapon() = 0;
+ virtual IReGameHookRegistry_CBotManager_OnEvent *CBotManager_OnEvent() = 0;
+ virtual IReGameHookRegistry_CBasePlayer_CheckTimeBasedDamage *CBasePlayer_CheckTimeBasedDamage() = 0;
+ virtual IReGameHookRegistry_CBasePlayer_EntSelectSpawnPoint *CBasePlayer_EntSelectSpawnPoint() = 0;
+ virtual IReGameHookRegistry_CBasePlayerWeapon_ItemPostFrame *CBasePlayerWeapon_ItemPostFrame() = 0;
+ virtual IReGameHookRegistry_CBasePlayerWeapon_KickBack *CBasePlayerWeapon_KickBack() = 0;
+ virtual IReGameHookRegistry_CBasePlayerWeapon_SendWeaponAnim *CBasePlayerWeapon_SendWeaponAnim() = 0;
+ virtual IReGameHookRegistry_CSGameRules_SendDeathMessage *CSGameRules_SendDeathMessage() = 0;
+
+ virtual IReGameHookRegistry_CBasePlayer_PlayerDeathThink *CBasePlayer_PlayerDeathThink() = 0;
+ virtual IReGameHookRegistry_CBasePlayer_Observer_Think *CBasePlayer_Observer_Think() = 0;
};
struct ReGameFuncs_t {
@@ -670,6 +802,15 @@ struct ReGameFuncs_t {
class CGrenade *(*PlantBomb)(entvars_t *pevOwner, Vector &vecStart, Vector &vecVelocity);
class CGib *(*SpawnHeadGib)(entvars_t* pevVictim);
void (*SpawnRandomGibs)(entvars_t* pevVictim, int cGibs, int human);
+ void (*UTIL_RestartOther)(const char *szClassname);
+ void (*UTIL_ResetEntities)();
+ void (*UTIL_RemoveOther)(const char *szClassname, int nCount);
+ void (*UTIL_DecalTrace)(TraceResult *pTrace, int decalNumber);
+ void (*UTIL_Remove)(CBaseEntity *pEntity);
+ int (*AddAmmoNameToAmmoRegistry)(const char *szAmmoname);
+ void (*TextureTypePlaySound)(TraceResult *ptr, Vector vecSrc, Vector vecEnd, int iBulletType);
+ class CWeaponBox *(*CreateWeaponBox)(CBasePlayerItem *pItem, CBasePlayer *pPlayerOwner, const char *modelName, Vector &origin, Vector &angles, Vector &velocity, float lifeTime, bool packAmmo);
+ class CGrenade *(*SpawnGrenade)(WeaponIdType weaponId, entvars_t *pevOwner, Vector &vecSrc, Vector &vecThrow, float time, int iTeam, unsigned short usEvent);
};
class IReGameApi {
diff --git a/regamedll/public/regamedll/regamedll_const.h b/regamedll/public/regamedll/regamedll_const.h
index ddbe62af4..4599c58f2 100644
--- a/regamedll/public/regamedll/regamedll_const.h
+++ b/regamedll/public/regamedll/regamedll_const.h
@@ -106,3 +106,4 @@
#define GIB_NEVER 1 // Never gib, no matter how much death damage is done ( freezing, etc )
#define GIB_ALWAYS 2 // Always gib ( Houndeye Shock, Barnacle Bite )
#define GIB_HEALTH_VALUE -30
+#define GIB_PLAYER_THRESHOLD -9000
diff --git a/regamedll/public/tier0/assert_dialog.cpp b/regamedll/public/tier0/assert_dialog.cpp
new file mode 100644
index 000000000..11bb9442b
--- /dev/null
+++ b/regamedll/public/tier0/assert_dialog.cpp
@@ -0,0 +1,302 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//===========================================================================//
+
+#include "precompiled.h"
+#include "resource.h"
+
+class CDialogInitInfo
+{
+public:
+ const char *m_pFilename;
+ int m_iLine;
+ const char *m_pExpression;
+};
+
+class CAssertDisable
+{
+public:
+ char m_Filename[MAX_OSPATH];
+
+ // If these are not -1, then this CAssertDisable only disables asserts on lines between
+ // these values (inclusive).
+ int m_LineMin;
+ int m_LineMax;
+
+ // Decremented each time we hit this assert and ignore it, until it's 0.
+ // Then the CAssertDisable is removed.
+ // If this is -1, then we always ignore this assert.
+ int m_nIgnoreTimes;
+
+ CAssertDisable *m_pNext;
+};
+
+static CDialogInitInfo g_Info{};
+static bool g_bAssertsEnabled = true;
+static CAssertDisable *g_pAssertDisables = nullptr;
+
+// Set to true if they want to break in the debugger
+static bool g_bBreak = false;
+
+// Internal functions
+static HINSTANCE g_hTier0Instance = nullptr;
+BOOL WINAPI DllMain(
+ HINSTANCE hinstDLL, // handle to the DLL module
+ DWORD fdwReason, // reason for calling function
+ LPVOID lpvReserved // reserved
+)
+{
+ g_hTier0Instance = hinstDLL;
+ return true;
+}
+
+static bool IsDebugBreakEnabled()
+{
+ static bool bResult = (Q_strstr(Plat_GetCommandLine(), "-debugbreak") != nullptr);
+ return bResult;
+}
+
+static bool AreAssertsDisabled()
+{
+ static bool bResult = (Q_strstr(Plat_GetCommandLine(), "-noassert") != nullptr);
+ return bResult;
+}
+
+static bool AreAssertsEnabledInFileLine(const char *pFilename, int iLine)
+{
+ CAssertDisable **pPrev = &g_pAssertDisables;
+ CAssertDisable *pNext = nullptr;
+
+ for (CAssertDisable *pCur = g_pAssertDisables; pCur; pCur = pNext)
+ {
+ pNext = pCur->m_pNext;
+
+ if (Q_stricmp(pFilename, pCur->m_Filename) == 0)
+ {
+ // Are asserts disabled in the whole file?
+ bool bAssertsEnabled = true;
+ if (pCur->m_LineMin == -1 && pCur->m_LineMax == -1)
+ bAssertsEnabled = false;
+
+ // Are asserts disabled on the specified line?
+ if (iLine >= pCur->m_LineMin && iLine <= pCur->m_LineMax)
+ bAssertsEnabled = false;
+
+ if (!bAssertsEnabled)
+ {
+ // If this assert is only disabled for the next N times, then countdown..
+ if (pCur->m_nIgnoreTimes > 0)
+ {
+ pCur->m_nIgnoreTimes--;
+
+ if (pCur->m_nIgnoreTimes == 0)
+ {
+ // Remove this one from the list.
+ *pPrev = pNext;
+ delete pCur;
+ continue;
+ }
+ }
+
+ return false;
+ }
+ }
+
+ pPrev = &pCur->m_pNext;
+ }
+
+ return true;
+}
+
+CAssertDisable *CreateNewAssertDisable(const char *pFilename)
+{
+ CAssertDisable *pDisable = new CAssertDisable;
+ pDisable->m_pNext = g_pAssertDisables;
+ g_pAssertDisables = pDisable;
+
+ pDisable->m_LineMin = pDisable->m_LineMax = -1;
+ pDisable->m_nIgnoreTimes = -1;
+
+ Q_strlcpy(pDisable->m_Filename, g_Info.m_pFilename);
+
+ return pDisable;
+}
+
+void IgnoreAssertsInCurrentFile()
+{
+ CreateNewAssertDisable(g_Info.m_pFilename);
+}
+
+CAssertDisable *IgnoreAssertsNearby(int nRange)
+{
+ CAssertDisable *pDisable = CreateNewAssertDisable(g_Info.m_pFilename);
+ pDisable->m_LineMin = g_Info.m_iLine - nRange;
+ pDisable->m_LineMax = g_Info.m_iLine - nRange;
+ return pDisable;
+}
+
+static int g_iLastLineRange = 5;
+static int g_nLastIgnoreNumTimes = 1;
+
+int CALLBACK AssertDialogProc(
+ HWND hDlg, // handle to dialog box
+ UINT uMsg, // message
+ WPARAM wParam, // first message parameter
+ LPARAM lParam // second message parameter
+)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ SetDlgItemText(hDlg, IDC_ASSERT_MSG_CTRL, g_Info.m_pExpression);
+ SetDlgItemText(hDlg, IDC_FILENAME_CONTROL, g_Info.m_pFilename);
+
+ SetDlgItemInt(hDlg, IDC_LINE_CONTROL, g_Info.m_iLine, false);
+ SetDlgItemInt(hDlg, IDC_IGNORE_NUMLINES, g_iLastLineRange, false);
+ SetDlgItemInt(hDlg, IDC_IGNORE_NUMTIMES, g_nLastIgnoreNumTimes, false);
+
+ // Center the dialog.
+ RECT rcDlg, rcDesktop;
+ GetWindowRect(hDlg, &rcDlg);
+ GetWindowRect(GetDesktopWindow(), &rcDesktop);
+ SetWindowPos(hDlg, HWND_TOP,
+ ((rcDesktop.right - rcDesktop.left) - (rcDlg.right - rcDlg.left)) / 2,
+ ((rcDesktop.bottom - rcDesktop.top) - (rcDlg.bottom - rcDlg.top)) / 2,
+ 0, 0,
+ SWP_NOSIZE
+ );
+
+ return TRUE;
+ }
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ // Ignore this assert N times
+ case IDC_IGNORE_THIS:
+ {
+ BOOL bTranslated = false;
+ UINT value = GetDlgItemInt(hDlg, IDC_IGNORE_NUMTIMES, &bTranslated, false);
+ if (bTranslated && value > 1)
+ {
+ CAssertDisable *pDisable = IgnoreAssertsNearby(0);
+ pDisable->m_nIgnoreTimes = value - 1;
+ g_nLastIgnoreNumTimes = value;
+ }
+
+ EndDialog(hDlg, 0);
+ return TRUE;
+ }
+ case IDC_IGNORE_NEARBY:
+ {
+ BOOL bTranslated = false;
+ UINT value = GetDlgItemInt(hDlg, IDC_IGNORE_NUMLINES, &bTranslated, false);
+ if (!bTranslated || value < 1)
+ return TRUE;
+
+ IgnoreAssertsNearby(value);
+ EndDialog(hDlg, 0);
+ return TRUE;
+ }
+ case IDC_IGNORE_FILE:
+ IgnoreAssertsInCurrentFile();
+ EndDialog(hDlg, 0);
+ return TRUE;
+ // Always ignore this assert
+ case IDC_IGNORE_ALWAYS:
+ IgnoreAssertsNearby(0);
+ EndDialog(hDlg, 0);
+ return TRUE;
+ case IDC_IGNORE_ALL:
+ g_bAssertsEnabled = false;
+ EndDialog(hDlg, 0);
+ return TRUE;
+ case IDC_BREAK:
+ g_bBreak = true;
+ EndDialog(hDlg, 0);
+ return TRUE;
+ }
+ case WM_KEYDOWN:
+ {
+ // Escape?
+ if (wParam == 2)
+ {
+ // Ignore this assert
+ EndDialog(hDlg, 0);
+ return TRUE;
+ }
+
+ break;
+ }
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static HWND g_hBestParentWindow = nullptr;
+
+static BOOL CALLBACK ParentWindowEnumProc(
+ HWND hWnd, // handle to parent window
+ LPARAM lParam // application-defined value
+)
+{
+ if (IsWindowVisible(hWnd))
+ {
+ DWORD procID;
+ GetWindowThreadProcessId(hWnd, &procID);
+ if (procID == (DWORD)lParam)
+ {
+ g_hBestParentWindow = hWnd;
+ return FALSE; // don't iterate any more.
+ }
+ }
+
+ return TRUE;
+}
+
+static HWND FindLikelyParentWindow()
+{
+ // Enumerate top-level windows and take the first visible one with our processID.
+ g_hBestParentWindow = nullptr;
+ EnumWindows(ParentWindowEnumProc, GetCurrentProcessId());
+ return g_hBestParentWindow;
+}
+
+bool DoNewAssertDialog(const char *pFilename, int line, const char *pExpression)
+{
+ if (AreAssertsDisabled())
+ return false;
+
+ // If they have the old mode enabled (always break immediately), then just break right into
+ // the debugger like we used to do.
+ if (IsDebugBreakEnabled())
+ return true;
+
+ // Have ALL Asserts been disabled?
+ if (!g_bAssertsEnabled)
+ return false;
+
+ // Has this specific Assert been disabled?
+ if (!AreAssertsEnabledInFileLine(pFilename, line))
+ return false;
+
+ // Now create the dialog.
+ g_Info.m_pFilename = pFilename;
+ g_Info.m_iLine = line;
+ g_Info.m_pExpression = pExpression;
+
+ g_bBreak = false;
+
+ HWND hParentWindow = FindLikelyParentWindow();
+ DialogBox(g_hTier0Instance, MAKEINTRESOURCE(IDD_ASSERT_DIALOG), hParentWindow, AssertDialogProc);
+
+ return g_bBreak;
+}
diff --git a/regamedll/public/tier0/assert_dialog.rc b/regamedll/public/tier0/assert_dialog.rc
new file mode 100644
index 000000000..e8683cf41
--- /dev/null
+++ b/regamedll/public/tier0/assert_dialog.rc
@@ -0,0 +1,117 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_ASSERT_DIALOG DIALOG DISCARDABLE 0, 0, 268, 158
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Assert"
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "File:",IDC_NOID,7,7,23,9
+ LTEXT "c:/cstrike16/src/blah.cpp",IDC_FILENAME_CONTROL,36,7,217,8
+ LTEXT "Line:",IDC_NOID,7,18,23,9
+ LTEXT "45",IDC_LINE_CONTROL,36,18,217,8
+ LTEXT "Assert:",IDC_NOID,7,29,23,9
+ CONTROL "ASSERT MESSAGE",IDC_ASSERT_MSG_CTRL,"Static",
+ SS_LEFTNOWORDWRAP | SS_NOPREFIX | WS_GROUP,36,29,217,9
+ DEFPUSHBUTTON "&Break in Debugger",IDC_BREAK,7,49,98,14
+ PUSHBUTTON "&Ignore This Assert",IDC_IGNORE_THIS,7,66,98,14
+ EDITTEXT IDC_IGNORE_NUMTIMES,110,66,24,14,ES_AUTOHSCROLL |
+ ES_NUMBER
+ LTEXT "time(s).",IDC_NOID,138,68,23,8
+ PUSHBUTTON "Always Ignore &This Assert",IDC_IGNORE_ALWAYS,7,84,98,
+ 14
+ PUSHBUTTON "Ignore &Nearby Asserts",IDC_IGNORE_NEARBY,7,102,98,14
+ LTEXT "within",IDC_NOID,109,105,19,8
+ EDITTEXT IDC_IGNORE_NUMLINES,131,102,40,14,ES_AUTOHSCROLL |
+ ES_NUMBER
+ LTEXT "lines.",IDC_NOID,175,105,17,8
+ PUSHBUTTON "Ignore Asserts in This &File",IDC_IGNORE_FILE,7,120,98,
+ 14
+ PUSHBUTTON "Ignore &All Asserts",IDC_IGNORE_ALL,7,137,98,14
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_ASSERT_DIALOG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 261
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 151
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/regamedll/public/tier0/dbg.cpp b/regamedll/public/tier0/dbg.cpp
index ebf36c2e4..35c99fe38 100644
--- a/regamedll/public/tier0/dbg.cpp
+++ b/regamedll/public/tier0/dbg.cpp
@@ -1,50 +1,17 @@
-/*
-*
-* This program is free software; you can redistribute it and/or modify it
-* under the terms of the GNU General Public License as published by the
-* Free Software Foundation; either version 2 of the License, or (at
-* your option) any later version.
-*
-* This program is distributed in the hope that it will be useful, but
-* WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software Foundation,
-* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*
-* In addition, as a special exception, the author gives permission to
-* link the code of this program with the Half-Life Game Engine ("HL
-* Engine") and Modified Game Libraries ("MODs") developed by Valve,
-* L.L.C ("Valve"). You must obey the GNU General Public License in all
-* respects for all of the code used other than the HL Engine and MODs
-* from Valve. If you modify this file, you may extend this exception
-* to your version of the file, but you are not obligated to do so. If
-* you do not wish to do so, delete this exception statement from your
-* version.
-*
-*/
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//===========================================================================//
#include "precompiled.h"
-// Internal structures
-enum
-{
- MAX_GROUP_NAME_LENGTH = 48
-};
-
-struct SpewGroup_t
-{
- char m_GroupName[MAX_GROUP_NAME_LENGTH];
- int m_Level;
-};
-
-
// Templates to assist in validating pointers:
void _AssertValidReadPtr(void *ptr, int count)
{
-#ifdef _WIN32
+#if defined(_WIN32)
Assert(!IsBadReadPtr(ptr, count));
#else
Assert(ptr);
@@ -54,7 +21,7 @@ void _AssertValidReadPtr(void *ptr, int count)
void _AssertValidWritePtr(void *ptr, int count)
{
-#ifdef _WIN32
+#if defined(_WIN32)
Assert(!IsBadWritePtr(ptr, count));
#else
Assert(ptr);
@@ -63,26 +30,29 @@ void _AssertValidWritePtr(void *ptr, int count)
void _AssertValidReadWritePtr(void *ptr, int count)
{
-#ifdef _WIN32
+#if defined(_WIN32)
Assert(!(IsBadWritePtr(ptr, count) || IsBadReadPtr(ptr, count)));
#else
Assert(ptr);
#endif
}
+#if defined(DBGFLAG_ASSERT)
void AssertValidStringPtr(const char *ptr, int maxchar)
{
-#ifdef _WIN32
+#if defined(_WIN32)
Assert(!IsBadStringPtr(ptr, maxchar));
#else
Assert(ptr);
#endif
}
+#endif // DBGFLAG_ASSERT
// Globals
-SpewRetval_t DefaultSpewFunc(SpewType_t type, const char *pMsg)
+SpewRetval_t DefaultSpewFunc(SpewType_t type, int level, const char *pMsg)
{
printf("%s", pMsg);
+
if (type == SPEW_ASSERT)
return SPEW_DEBUGGER;
else if (type == SPEW_ERROR)
@@ -93,13 +63,10 @@ SpewRetval_t DefaultSpewFunc(SpewType_t type, const char *pMsg)
static SpewOutputFunc_t s_SpewOutputFunc = DefaultSpewFunc;
-static const char *s_pFileName;
-static int s_Line;
-static SpewType_t s_SpewType;
-
-static SpewGroup_t *s_pSpewGroups = 0;
-static int s_GroupCount = 0;
-static int s_DefaultLevel = 0;
+static const char *s_pMessage = nullptr;
+static const char *s_pFileName = nullptr;
+static int s_Line = 0;
+static SpewType_t s_SpewType = SPEW_MESSAGE;
// Spew output management.
void SpewOutputFunc(SpewOutputFunc_t func)
@@ -119,54 +86,92 @@ SpewOutputFunc_t GetSpewOutputFunc()
}
}
+void _ExitOnFatalAssert()
+{
+ Msg("Fatal assert failed: %s, file %s line %d. Application exiting.\n", s_pMessage, s_pFileName, s_Line);
+
+#if defined(WIN32)
+ TerminateProcess(GetCurrentProcess(), EXIT_FAILURE); // die, die RIGHT NOW! (don't call exit() so destructors will not get run)
+#else
+ exit(EXIT_FAILURE); // forcefully shutdown of the process without destructors running
+#endif
+}
+
// Spew functions
void _SpewInfo(SpewType_t type, const char *pFile, int line)
{
- // Only grab the file name. Ignore the path.
- const char *pSlash = strrchr(pFile, '\\');
- const char *pSlash2 = strrchr(pFile, '/');
+ // Only grab the file name. Ignore the path
+ const char *pSlash = Q_strrchr(pFile, '\\');
+ const char *pSlash2 = Q_strrchr(pFile, '/');
+
if (pSlash < pSlash2) pSlash = pSlash2;
s_pFileName = pSlash ? pSlash + 1 : pFile;
- s_Line = line;
- s_SpewType = type;
+ s_Line = line;
+ s_SpewType = type;
}
-SpewRetval_t _SpewMessage(SpewType_t spewType, const char *pMsgFormat, va_list args)
+SpewRetval_t _SpewMessageV(SpewType_t spewType, int level, const char *pMsgFormat, va_list args)
{
- char pTempBuffer[1024];
+ if (level < 0) level = DBG_DEFAULT_LEVEL;
+
+ static char szTempBuffer[4096]{};
+ szTempBuffer[0] = '\0';
+ s_pMessage = szTempBuffer;
+
+ // check that we won't artifically truncate the string
+ assert(Q_strlen(pMsgFormat) < sizeof(szTempBuffer));
// Printf the file and line for warning + assert only...
int len = 0;
- if ((spewType == SPEW_ASSERT))
+ if (spewType == SPEW_ASSERT)
+ {
+ len = Q_snprintf(szTempBuffer, sizeof(szTempBuffer), "%s (%d) : ", s_pFileName, s_Line);
+ }
+
+ if (len == -1)
{
- len = sprintf(pTempBuffer, "%s (%d) : ", s_pFileName, s_Line);
+ return SPEW_ABORT;
}
// Create the message....
- len += vsprintf(&pTempBuffer[len], pMsgFormat, args);
+ len += Q_vsnprintf(&szTempBuffer[len], sizeof(szTempBuffer) - len, pMsgFormat, args);
+
+ // Use normal assert here; to avoid recursion
+ assert(len < sizeof(szTempBuffer));
// Add \n for warning and assert
if ((spewType == SPEW_ASSERT))
{
- len += sprintf(&pTempBuffer[len], "\n");
+ len += Q_snprintf(&szTempBuffer[len], sizeof(szTempBuffer) - len, "\n");
+ Plat_OutputDebugString(szTempBuffer);
}
- assert(len < 1024); // use normal assert here; to avoid recursion.
+ // use normal assert here; to avoid recursion
+ assert((size_t)len < (sizeof(szTempBuffer) / sizeof(szTempBuffer[0]) - 1));
assert(s_SpewOutputFunc);
// direct it to the appropriate target(s)
- SpewRetval_t ret = s_SpewOutputFunc(spewType, pTempBuffer);
+ SpewRetval_t ret = s_SpewOutputFunc(spewType, level, szTempBuffer);
switch (ret)
{
// Put the break into the macro so it would occur in the right place
- //case SPEW_DEBUGGER:
- // DebuggerBreak();
- // break;
+ case SPEW_DEBUGGER:
+ {
+ if (spewType != SPEW_ASSERT)
+ DebuggerBreakIfDebugging();
+ break;
+ }
case SPEW_ABORT:
- // MessageBox(nullptr, "Error in _SpewMessage", "Error", MB_OK);
- exit(0);
+ {
+#if defined(WIN32)
+ TerminateProcess(GetCurrentProcess(), EXIT_FAILURE); // die, die RIGHT NOW! (don't call exit() so destructors will not get run)
+#else
+ exit(EXIT_FAILURE); // forcefully shutdown of the process without destructors running
+#endif
+ break;
+ }
default:
break;
}
@@ -174,81 +179,52 @@ SpewRetval_t _SpewMessage(SpewType_t spewType, const char *pMsgFormat, va_list a
return ret;
}
-SpewRetval_t _SpewMessage(const char *pMsgFormat, ...)
-{
- va_list args;
- va_start(args, pMsgFormat);
- SpewRetval_t ret = _SpewMessage(s_SpewType, pMsgFormat, args);
- va_end(args);
- return ret;
-}
-
-SpewRetval_t _DSpewMessage(const char *pGroupName, int level, const char *pMsgFormat, ...)
-{
- if (!IsSpewActive(pGroupName, level))
- return SPEW_CONTINUE;
-
- va_list args;
- va_start(args, pMsgFormat);
- SpewRetval_t ret = _SpewMessage(s_SpewType, pMsgFormat, args);
- va_end(args);
- return ret;
-}
+#if defined(_WIN32)
+// Returns true if they want to break in the debugger
+bool DoNewAssertDialog(const char *pFile, int line, const char *pExpression);
+#endif
-void Msg(const char *pMsgFormat, ...)
+bool _SpewAssertDialog()
{
- va_list args;
- va_start(args, pMsgFormat);
- _SpewMessage(SPEW_MESSAGE, pMsgFormat, args);
- va_end(args);
+#if defined(_WIN32)
+ return DoNewAssertDialog(s_pFileName, s_Line, s_pMessage);
+#else
+ return false;
+#endif
}
-void DMsg(const char *pGroupName, int level, const char *pMsgFormat, ...)
+SpewRetval_t _SpewAssert(const char *pFile, int line, int level, const char *pMsgFormat, ...)
{
- if (!IsSpewActive(pGroupName, level))
- return;
+ _SpewInfo(SPEW_ASSERT, pFile, line);
va_list args;
va_start(args, pMsgFormat);
- _SpewMessage(SPEW_MESSAGE, pMsgFormat, args);
- va_end(args);
-}
-
-void Warning(const char *pMsgFormat, ...)
-{
- va_list args;
- va_start(args, pMsgFormat);
- _SpewMessage(SPEW_WARNING, pMsgFormat, args);
+ SpewRetval_t ret = _SpewMessageV(s_SpewType, level, pMsgFormat, args);
va_end(args);
+ return ret;
}
-void DWarning(const char *pGroupName, int level, const char *pMsgFormat, ...)
+void _Msg(int level, const char *pMsgFormat, ...)
{
- if (!IsSpewActive(pGroupName, level))
- return;
-
va_list args;
va_start(args, pMsgFormat);
- _SpewMessage(SPEW_WARNING, pMsgFormat, args);
+ _SpewMessageV(SPEW_MESSAGE, level, pMsgFormat, args);
va_end(args);
}
-void Log(const char *pMsgFormat, ...)
+void _Warning(int level, const char *pMsgFormat, ...)
{
va_list args;
va_start(args, pMsgFormat);
- _SpewMessage(SPEW_LOG, pMsgFormat, args);
+ _SpewMessageV(SPEW_WARNING, level, pMsgFormat, args);
va_end(args);
}
-void DLog(const char *pGroupName, int level, const char *pMsgFormat, ...)
+void _Log(int level, const char *pMsgFormat, ...)
{
- if (!IsSpewActive(pGroupName, level))
- return;
-
va_list args;
va_start(args, pMsgFormat);
- _SpewMessage(SPEW_LOG, pMsgFormat, args);
+ _SpewMessageV(SPEW_LOG, level, pMsgFormat, args);
va_end(args);
}
@@ -256,146 +232,6 @@ void Error(const char *pMsgFormat, ...)
{
va_list args;
va_start(args, pMsgFormat);
- _SpewMessage(SPEW_ERROR, pMsgFormat, args);
+ _SpewMessageV(SPEW_ERROR, DBG_DEFAULT_LEVEL, pMsgFormat, args);
va_end(args);
}
-
-// A couple of super-common dynamic spew messages, here for convenience
-// These looked at the "developer" group, print if it's level 1 or higher
-void DevMsg(int level, char const *pMsgFormat, ...)
-{
- if (!IsSpewActive("developer", level))
- return;
-
- va_list args;
- va_start(args, pMsgFormat);
- _SpewMessage(SPEW_MESSAGE, pMsgFormat, args);
- va_end(args);
-}
-
-void DevWarning(int level, const char *pMsgFormat, ...)
-{
- if (!IsSpewActive("developer", level))
- return;
-
- va_list args;
- va_start(args, pMsgFormat);
- _SpewMessage(SPEW_WARNING, pMsgFormat, args);
- va_end(args);
-}
-
-void DevLog(int level, const char *pMsgFormat, ...)
-{
- if (!IsSpewActive("developer", level))
- return;
-
- va_list args;
- va_start(args, pMsgFormat);
- _SpewMessage(SPEW_LOG, pMsgFormat, args);
- va_end(args);
-}
-
-void DevMsg(const char *pMsgFormat, ...)
-{
- if (!IsSpewActive("developer", 1))
- return;
-
- va_list args;
- va_start(args, pMsgFormat);
- _SpewMessage(SPEW_MESSAGE, pMsgFormat, args);
- va_end(args);
-}
-
-void DevWarning(const char *pMsgFormat, ...)
-{
- va_list args;
- va_start(args, pMsgFormat);
- _SpewMessage(SPEW_WARNING, pMsgFormat, args);
- va_end(args);
-}
-
-void DevLog(const char *pMsgFormat, ...)
-{
- va_list args;
- va_start(args, pMsgFormat);
- _SpewMessage(SPEW_LOG, pMsgFormat, args);
- va_end(args);
-}
-
-// Find a group, return true if found, false if not. Return in ind the
-// index of the found group, or the index of the group right before where the
-// group should be inserted into the list to maintain sorted order.
-bool FindSpewGroup(const char *pGroupName, int *pInd)
-{
- int s = 0;
- if (s_GroupCount)
- {
- int e = (int)(s_GroupCount - 1);
- while (s <= e)
- {
- int m = (s + e) >> 1;
- int cmp = Q_stricmp(pGroupName, s_pSpewGroups[m].m_GroupName);
- if (!cmp)
- {
- *pInd = m;
- return true;
- }
-
- if (cmp < 0)
- e = m - 1;
- else
- s = m + 1;
- }
- }
-
- *pInd = s;
- return false;
-}
-
-// Sets the priority level for a spew group
-void SpewActivate(const char *pGroupName, int level)
-{
- Assert(pGroupName);
-
- // check for the default group first...
- if ((pGroupName[0] == '*') && (pGroupName[1] == '\0'))
- {
- s_DefaultLevel = level;
- return;
- }
-
- // Normal case, search in group list using binary search.
- // If not found, grow the list of groups and insert it into the
- // right place to maintain sorted order. Then set the level.
- int ind;
- if (!FindSpewGroup(pGroupName, &ind))
- {
- // not defined yet, insert an entry.
- s_GroupCount++;
- if (s_pSpewGroups)
- {
- s_pSpewGroups = (SpewGroup_t *)realloc(s_pSpewGroups, s_GroupCount * sizeof(SpewGroup_t));
-
- // shift elements down to preserve order
- int numToMove = s_GroupCount - ind - 1;
- memmove(&s_pSpewGroups[ind + 1], &s_pSpewGroups[ind], numToMove * sizeof(SpewGroup_t));
- }
- else
- s_pSpewGroups = (SpewGroup_t *)malloc(s_GroupCount * sizeof(SpewGroup_t));
-
- Assert(strlen(pGroupName) < MAX_GROUP_NAME_LENGTH);
- strcpy(s_pSpewGroups[ind].m_GroupName, pGroupName);
- }
- s_pSpewGroups[ind].m_Level = level;
-}
-
-// Tests to see if a particular spew is active
-bool IsSpewActive(const char *pGroupName, int level)
-{
- // If we don't find the spew group, use the default level.
- int ind;
- if (FindSpewGroup(pGroupName, &ind))
- return s_pSpewGroups[ind].m_Level >= level;
- else
- return s_DefaultLevel >= level;
-}
diff --git a/regamedll/public/tier0/dbg.h b/regamedll/public/tier0/dbg.h
index 38e992f67..848250414 100644
--- a/regamedll/public/tier0/dbg.h
+++ b/regamedll/public/tier0/dbg.h
@@ -1,30 +1,10 @@
-/*
-*
-* This program is free software; you can redistribute it and/or modify it
-* under the terms of the GNU General Public License as published by the
-* Free Software Foundation; either version 2 of the License, or (at
-* your option) any later version.
-*
-* This program is distributed in the hope that it will be useful, but
-* WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software Foundation,
-* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*
-* In addition, as a special exception, the author gives permission to
-* link the code of this program with the Half-Life Game Engine ("HL
-* Engine") and Modified Game Libraries ("MODs") developed by Valve,
-* L.L.C ("Valve"). You must obey the GNU General Public License in all
-* respects for all of the code used other than the HL Engine and MODs
-* from Valve. If you modify this file, you may extend this exception
-* to your version of the file, but you are not obligated to do so. If
-* you do not wish to do so, delete this exception statement from your
-* version.
-*
-*/
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//===========================================================================//
#pragma once
@@ -34,16 +14,7 @@
#include
#include
-// dll export stuff
-#ifdef TIER0_DLL_EXPORT
-#define DBG_INTERFACE DLL_EXPORT
-#define DBG_OVERLOAD DLL_GLOBAL_EXPORT
-#define DBG_CLASS DLL_CLASS_EXPORT
-#else
-#define DBG_INTERFACE DLL_IMPORT
-#define DBG_OVERLOAD DLL_GLOBAL_IMPORT
-#define DBG_CLASS DLL_CLASS_IMPORT
-#endif
+#define DBG_DEFAULT_LEVEL 0
// Usage model for the Dbg library
//
@@ -87,22 +58,6 @@
// Msg("Isn't this exciting %d?", 5);
// Error("I'm just thrilled");
//
-// Dynamic Spew messages
-//
-// It is possible to dynamically turn spew on and off. Dynamic spew is
-// identified by a spew group and priority level. To turn spew on for a
-// particular spew group, use SpewActivate("group", level). This will
-// cause all spew in that particular group with priority levels <= the
-// level specified in the SpewActivate function to be printed. Use DSpew
-// to perform the spew:
-//
-// DWarning("group", level, "Oh I feel even yummier!\n");
-//
-// Priority level 0 means that the spew will *always* be printed, and group
-// '*' is the default spew group. If a DWarning is encountered using a group
-// whose priority has not been set, it will use the priority of the default
-// group. The priority of the default group is initially set to 0.
-//
// Spew output
//
// The output of the spew system can be redirected to an externally-supplied
@@ -131,12 +86,6 @@
// }
// );
//
-// Code can be activated based on the dynamic spew groups also. Use
-//
-// DBG_DCODE("group", level,
-// { int x = 5; ++x; }
-// );
-//
// 3. Breaking into the debugger.
//
// To cause an unconditional break into the debugger in debug builds only, use DBG_BREAK
@@ -170,7 +119,7 @@ enum SpewRetval_t
};
// Type of externally defined function used to display debug spew
-typedef SpewRetval_t (*SpewOutputFunc_t)(SpewType_t spewType, const char *pMsg);
+typedef SpewRetval_t (*SpewOutputFunc_t)(SpewType_t spewType, int level, const char *pMsg);
// Used to redirect spew output
void SpewOutputFunc(SpewOutputFunc_t func);
@@ -178,134 +127,220 @@ void SpewOutputFunc(SpewOutputFunc_t func);
// Used ot get the current spew output function
SpewOutputFunc_t GetSpewOutputFunc();
-// Used to manage spew groups and subgroups
-void SpewActivate(const char *pGroupName, int level);
-bool IsSpewActive(const char *pGroupName, int level);
-
// Used to display messages, should never be called directly.
-void _SpewInfo(SpewType_t type, const char *pFile, int line);
-SpewRetval_t _SpewMessage(const char *pMsg, ...);
-SpewRetval_t _DSpewMessage(const char *pGroupName, int level, const char *pMsg, ...);
-
-// Used to define macros, never use these directly.
-#define _Assert(_exp) \
- do { \
- if (!(_exp)) \
- { \
- _SpewInfo(SPEW_ASSERT, __FILE__, __LINE__); \
- if (_SpewMessage("Assertion Failed: " #_exp) == SPEW_DEBUGGER) \
- { \
- DebuggerBreak(); \
- } \
- } \
- } while (0)
-
-#define _AssertMsg(_exp, _msg) \
- do { \
- if (!(_exp)) \
- { \
- _SpewInfo(SPEW_ASSERT, __FILE__, __LINE__); \
- if (_SpewMessage(_msg) == SPEW_DEBUGGER) \
- { \
- DebuggerBreak(); \
- } \
- } \
- } while (0)
-
-#define _AssertFunc(_exp, _f) \
- do { \
- if (!(_exp)) \
- { \
- _SpewInfo(SPEW_ASSERT, __FILE__, __LINE__); \
- SpewRetval_t ret = _SpewMessage("Assertion Failed!" #_exp); \
- _f; \
- if (ret == SPEW_DEBUGGER) \
- { \
- DebuggerBreak(); \
- } \
- } \
- } while (0)
+SpewRetval_t _SpewAssert(const char *pFile, int line, int level, const char *pMsg, ...);
+void _ExitOnFatalAssert();
+bool _SpewAssertDialog();
-#define _AssertEquals(_exp, _expectedValue) \
- do { \
- if ((_exp) != (_expectedValue)) \
- { \
- _SpewInfo(SPEW_ASSERT, __FILE__, __LINE__); \
- SpewRetval_t ret = _SpewMessage("Expected %d but got %d!", (_expectedValue), (_exp)); \
- if (ret == SPEW_DEBUGGER) \
- { \
- DebuggerBreak(); \
- } \
- } \
+inline bool ShouldUseNewAssertDialog()
+{
+#if defined(DBGFLAG_ASSERTDLG)
+ return true; // always show an assert dialog
+#else
+ return Plat_IsInDebugSession(); // only show an assert dialog if the process is being debugged
+#endif // DBGFLAG_ASSERTDLG
+}
+
+#define _AssertMsg(_exp, _msg, _executeExp, _bFatal) \
+ do { \
+ if (!(_exp)) \
+ { \
+ SpewRetval_t ret = _SpewAssert(__FILE__, __LINE__, DBG_DEFAULT_LEVEL, _msg); \
+ if (ret == SPEW_DEBUGGER) \
+ { \
+ if (!ShouldUseNewAssertDialog() || _SpewAssertDialog()) \
+ DebuggerBreakIfDebugging(); \
+ } \
+ _executeExp; \
+ if (_bFatal) \
+ _ExitOnFatalAssert(); \
+ } \
} while (0)
-#define _AssertFloatEquals(_exp, _expectedValue, _tol) \
- do { \
- if (fabs((_exp) - (_expectedValue)) > (_tol)) \
- { \
- _SpewInfo(SPEW_ASSERT, __FILE__, __LINE__); \
- SpewRetval_t ret = _SpewMessage("Expected %f but got %f!", (_expectedValue), (_exp)); \
- if (ret == SPEW_DEBUGGER) \
- { \
- DebuggerBreak(); \
- } \
- } \
+#define _AssertMsgWarn(_exp, _msg) \
+ if (!(_exp)) \
+ { \
+ Warning("%s (%d) : " _msg, __FILE__, __LINE__); \
+ } \
+
+#define _AssertMsgOnce(_exp, _msg, _bFatal) \
+ do { \
+ static bool fAsserted = false; \
+ if (!fAsserted && !(_exp)) \
+ { \
+ fAsserted = true; \
+ _AssertMsg(_exp, _msg, (fAsserted = true), _bFatal); \
+ } \
} while (0)
// Spew macros...
-#ifdef _DEBUG
-
-#define Assert(_exp) _Assert(_exp)
-#define AssertMsg(_exp, _msg) _AssertMsg(_exp, _msg)
-#define AssertFunc(_exp, _f) _AssertFunc(_exp, _f)
-#define AssertEquals(_exp, _expectedValue) _AssertEquals(_exp, _expectedValue)
-#define AssertFloatEquals(_exp, _expectedValue, _tol) _AssertFloatEquals(_exp, _expectedValue, _tol)
-#define Verify(_exp) _Assert(_exp)
-
-#define AssertMsg1(_exp, _msg, a1) _AssertMsg(_exp, CDbgFmtMsg(_msg, a1))
-#define AssertMsg2(_exp, _msg, a1, a2) _AssertMsg(_exp, CDbgFmtMsg(_msg, a1, a2))
-#define AssertMsg3(_exp, _msg, a1, a2, a3) _AssertMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3))
-#define AssertMsg4(_exp, _msg, a1, a2, a3, a4) _AssertMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4))
-#define AssertMsg5(_exp, _msg, a1, a2, a3, a4, a5) _AssertMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5))
-#define AssertMsg6(_exp, _msg, a1, a2, a3, a4, a5, a6) _AssertMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6))
-#define AssertMsg6(_exp, _msg, a1, a2, a3, a4, a5, a6) _AssertMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6))
-#define AssertMsg7(_exp, _msg, a1, a2, a3, a4, a5, a6, a7) _AssertMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6, a7))
-#define AssertMsg8(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8) _AssertMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6, a7, a8))
-#define AssertMsg9(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9) _AssertMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6, a7, a8, a9))
-
-#else // _DEBUG
+// AssertFatal macros
+// AssertFatal is used to detect an unrecoverable error condition.
+// If enabled, it may display an assert dialog (if DBGFLAG_ASSERTDLG is turned on or running under the debugger),
+// and always terminates the application
+
+#if defined(DBGFLAG_ASSERTFATAL)
+
+#define AssertWarn(_exp) _AssertMsgWarn(_exp, "Assertion Failed: " #_exp)
+#define AssertFatal(_exp) _AssertMsg(_exp, "Assertion Failed: " #_exp, ((void)0), true)
+#define AssertFatalOnce(_exp) _AssertMsgOnce(_exp, "Assertion Failed: " #_exp, true)
+#define AssertFatalMsg(_exp, _msg) _AssertMsg(_exp, _msg, ((void)0), true)
+#define AssertFatalMsgOnce(_exp, _msg) _AssertMsgOnce(_exp, _msg, true)
+#define AssertFatalFunc(_exp, _f) _AssertMsg(_exp, "Assertion Failed: " #_exp, _f, true)
+#define AssertFatalEquals(_exp, _expectedValue) AssertFatalMsg2((_exp) == (_expectedValue), "Expected %d but got %d!", (_expectedValue), (_exp))
+#define AssertFatalFloatEquals(_exp, _expectedValue, _tol) AssertFatalMsg2(fabs((_exp) - (_expectedValue)) <= (_tol), "Expected %f but got %f!", (_expectedValue), (_exp))
+#define VerifyFatal(_exp) AssertFatal(_exp)
+#define VerifyEqualsFatal(_exp, _expectedValue) AssertFatalEquals(_exp, _expectedValue)
+
+#if defined(_DEBUG)
+ #define DbgVerifyFatal(_exp) AssertFatal(_exp)
+#else
+ #define DbgVerifyFatal(_exp) ((void)0)
+#endif
-#define Assert(_exp) ((void)0)
-#define AssertMsg(_exp, _msg) ((void)0)
-#define AssertFunc(_exp, _f) ((void)0)
-#define AssertEquals(_exp, _expectedValue) ((void)0)
-#define AssertFloatEquals(_exp, _expectedValue, _tol) ((void)0)
-#define Verify(_exp) (_exp)
-
-#define AssertMsg1(_exp, _msg, a1) ((void)0)
-#define AssertMsg2(_exp, _msg, a1, a2) ((void)0)
-#define AssertMsg3(_exp, _msg, a1, a2, a3) ((void)0)
-#define AssertMsg4(_exp, _msg, a1, a2, a3, a4) ((void)0)
-#define AssertMsg5(_exp, _msg, a1, a2, a3, a4, a5) ((void)0)
-#define AssertMsg6(_exp, _msg, a1, a2, a3, a4, a5, a6) ((void)0)
-#define AssertMsg6(_exp, _msg, a1, a2, a3, a4, a5, a6) ((void)0)
-#define AssertMsg7(_exp, _msg, a1, a2, a3, a4, a5, a6, a7) ((void)0)
-#define AssertMsg8(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8) ((void)0)
-#define AssertMsg9(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9) ((void)0)
+#define AssertFatalMsg1(_exp, _msg, a1) AssertFatalMsg(_exp, CDbgFmtMsg(_msg, a1).ToString())
+#define AssertFatalMsg2(_exp, _msg, a1, a2) AssertFatalMsg(_exp, CDbgFmtMsg(_msg, a1, a2).ToString())
+#define AssertFatalMsg3(_exp, _msg, a1, a2, a3) AssertFatalMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3).ToString())
+#define AssertFatalMsg4(_exp, _msg, a1, a2, a3, a4) AssertFatalMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4).ToString())
+#define AssertFatalMsg5(_exp, _msg, a1, a2, a3, a4, a5) AssertFatalMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5).ToString())
+#define AssertFatalMsg6(_exp, _msg, a1, a2, a3, a4, a5, a6) AssertFatalMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6).ToString())
+#define AssertFatalMsg7(_exp, _msg, a1, a2, a3, a4, a5, a6, a7) AssertFatalMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6, a7).ToString())
+#define AssertFatalMsg8(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8) AssertFatalMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6, a7, a8).ToString())
+#define AssertFatalMsg9(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9) AssertFatalMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6, a7, a8, a9).ToString())
+
+#else // DBGFLAG_ASSERTFATAL
+
+#define AssertWarn(_exp) ((void)0)
+#define AssertFatal(_exp) ((void)0)
+#define AssertFatalOnce(_exp) ((void)0)
+#define AssertFatalMsg(_exp, _msg) ((void)0)
+#define AssertFatalMsgOnce(_exp, _msg) ((void)0)
+#define AssertFatalFunc(_exp, _f) ((void)0)
+#define AssertFatalEquals(_exp, _expectedValue) ((void)0)
+#define AssertFatalFloatEquals(_exp, _expectedValue, _tol) ((void)0)
+#define VerifyFatal(_exp) (_exp)
+#define VerifyEqualsFatal(_exp, _expectedValue) (_exp)
+
+#define DbgVerifyFatal(_exp) (_exp)
+
+#define AssertFatalMsg1(_exp, _msg, a1) ((void)0)
+#define AssertFatalMsg2(_exp, _msg, a1, a2) ((void)0)
+#define AssertFatalMsg3(_exp, _msg, a1, a2, a3) ((void)0)
+#define AssertFatalMsg4(_exp, _msg, a1, a2, a3, a4) ((void)0)
+#define AssertFatalMsg5(_exp, _msg, a1, a2, a3, a4, a5) ((void)0)
+#define AssertFatalMsg6(_exp, _msg, a1, a2, a3, a4, a5, a6) ((void)0)
+#define AssertFatalMsg7(_exp, _msg, a1, a2, a3, a4, a5, a6, a7) ((void)0)
+#define AssertFatalMsg8(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8) ((void)0)
+#define AssertFatalMsg9(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9) ((void)0)
+
+#endif // DBGFLAG_ASSERTFATAL
+
+#if defined(DBGFLAG_ASSERT)
+
+#define Assert(_exp) _AssertMsg(_exp, "Assertion Failed: " #_exp, ((void)0), false)
+#define AssertMsg_(_exp, _msg) _AssertMsg(_exp, _msg, ((void)0), false)
+#define AssertOnce(_exp) _AssertMsgOnce(_exp, "Assertion Failed: " #_exp, false)
+#define AssertMsgOnce(_exp, _msg) _AssertMsgOnce(_exp, _msg, false)
+#define AssertFunc(_exp, _f) _AssertMsg(_exp, "Assertion Failed: " #_exp, _f, false)
+#define AssertEquals(_exp, _expectedValue) AssertMsg2((_exp) == (_expectedValue), "Expected %d but got %d!", (_expectedValue), (_exp))
+#define AssertFloatEquals(_exp, _expectedValue, _tol) AssertMsg2(fabs((_exp) - (_expectedValue)) <= (_tol), "Expected %f but got %f!", (_expectedValue), (_exp))
+#define Verify(_exp) (_exp)
+#define VerifyEquals(_exp, _expectedValue) AssertEquals(_exp, _expectedValue)
+
+#if defined(_DEBUG)
+ #define DbgVerify(_exp) (_exp)
+ #define DbgAssert(_exp) Assert(_exp)
+ #define DbgAssertMsg(_exp, _msg) AssertMsg(_exp, _msg)
+ #define DbgAssertMsg1(_exp, _msg, a1) AssertMsg1(_exp, _msg, a1)
+ #define DbgAssertMsg2(_exp, _msg, a1, a2) AssertMsg2(_exp, _msg, a1, a2)
+ #define DbgAssertMsg3(_exp, _msg, a1, a2, a3) AssertMsg3(_exp, _msg, a1, a2, a3)
+ #define DbgAssertMsg4(_exp, _msg, a1, a2, a3) AssertMsg4(_exp, _msg, a1, a2, a3, a4)
+ #define DbgAssertMsg5(_exp, _msg, a1, a2, a3) AssertMsg5(_exp, _msg, a1, a2, a3, a4, a5)
+ #define DbgAssertMsg6(_exp, _msg, a1, a2, a3) AssertMsg6(_exp, _msg, a1, a2, a3, a4, a5, a6)
+ #define DbgAssertMsg7(_exp, _msg, a1, a2, a3) AssertMsg7(_exp, _msg, a1, a2, a3, a4, a5, a6, a7)
+ #define DbgAssertMsg8(_exp, _msg, a1, a2, a3) AssertMsg8(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8)
+ #define DbgAssertMsg9(_exp, _msg, a1, a2, a3) AssertMsg9(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9)
+#else
+ #define DbgVerify(_exp) ((void)0)
+ #define DbgAssert(_exp) ((void)0)
+ #define DbgAssertMsg(_exp, _msg) ((void)0)
+ #define DbgAssertMsg1(_exp, _msg, a1) ((void)0)
+ #define DbgAssertMsg2(_exp, _msg, a1, a2) ((void)0)
+ #define DbgAssertMsg3(_exp, _msg, a1, a2, a3) ((void)0)
+ #define DbgAssertMsg4(_exp, _msg, a1, a2, a3) ((void)0)
+ #define DbgAssertMsg5(_exp, _msg, a1, a2, a3) ((void)0)
+ #define DbgAssertMsg6(_exp, _msg, a1, a2, a3) ((void)0)
+ #define DbgAssertMsg7(_exp, _msg, a1, a2, a3) ((void)0)
+ #define DbgAssertMsg8(_exp, _msg, a1, a2, a3) ((void)0)
+ #define DbgAssertMsg9(_exp, _msg, a1, a2, a3) ((void)0)
+#endif
-#endif // _DEBUG
+#define AssertMsg(_exp, _msg) AssertMsg_(_exp, _msg)
+#define AssertMsg1(_exp, _msg, a1) AssertMsg_(_exp, CDbgFmtMsg(_msg, a1).ToString())
+#define AssertMsg2(_exp, _msg, a1, a2) AssertMsg_(_exp, CDbgFmtMsg(_msg, a1, a2).ToString())
+#define AssertMsg3(_exp, _msg, a1, a2, a3) AssertMsg_(_exp, CDbgFmtMsg(_msg, a1, a2, a3).ToString())
+#define AssertMsg4(_exp, _msg, a1, a2, a3, a4) AssertMsg_(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4).ToString())
+#define AssertMsg5(_exp, _msg, a1, a2, a3, a4, a5) AssertMsg_(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5).ToString())
+#define AssertMsg6(_exp, _msg, a1, a2, a3, a4, a5, a6) AssertMsg_(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6).ToString())
+#define AssertMsg6(_exp, _msg, a1, a2, a3, a4, a5, a6) AssertMsg_(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6).ToString())
+#define AssertMsg7(_exp, _msg, a1, a2, a3, a4, a5, a6, a7) AssertMsg_(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6, a7).ToString())
+#define AssertMsg8(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8) AssertMsg_(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6, a7, a8).ToString())
+#define AssertMsg9(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9) AssertMsg_(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6, a7, a8, a9).ToString())
+
+#else // DBGFLAG_ASSERT
+
+#define Assert(_exp) ((void)0)
+#define AssertMsg(_exp, _msg) ((void)0)
+#define AssertOnce(_exp) ((void)0)
+#define AssertMsgOnce(_exp, _msg) ((void)0)
+#define AssertFunc(_exp, _f) ((void)0)
+#define AssertEquals(_exp, _expectedValue) ((void)0)
+#define AssertFloatEquals(_exp, _expectedValue, _tol) ((void)0)
+
+#define Verify(_exp) ((void)0)
+#define VerifyEquals(_exp, _expectedValue) ((void)0)
+
+#define DbgVerify(_exp) ((void)0)
+#define DbgAssert(_exp) ((void)0)
+#define DbgAssertMsg(_exp, _msg) ((void)0)
+#define DbgAssertMsg1(_exp, _msg, a1) ((void)0)
+#define DbgAssertMsg2(_exp, _msg, a1, a2) ((void)0)
+#define DbgAssertMsg3(_exp, _msg, a1, a2, a3) ((void)0)
+#define DbgAssertMsg4(_exp, _msg, a1, a2, a3) ((void)0)
+#define DbgAssertMsg5(_exp, _msg, a1, a2, a3) ((void)0)
+#define DbgAssertMsg6(_exp, _msg, a1, a2, a3) ((void)0)
+#define DbgAssertMsg7(_exp, _msg, a1, a2, a3) ((void)0)
+#define DbgAssertMsg8(_exp, _msg, a1, a2, a3) ((void)0)
+#define DbgAssertMsg9(_exp, _msg, a1, a2, a3) ((void)0)
+
+#define AssertMsg1(_exp, _msg, a1) ((void)0)
+#define AssertMsg2(_exp, _msg, a1, a2) ((void)0)
+#define AssertMsg3(_exp, _msg, a1, a2, a3) ((void)0)
+#define AssertMsg4(_exp, _msg, a1, a2, a3, a4) ((void)0)
+#define AssertMsg5(_exp, _msg, a1, a2, a3, a4, a5) ((void)0)
+#define AssertMsg6(_exp, _msg, a1, a2, a3, a4, a5, a6) ((void)0)
+#define AssertMsg6(_exp, _msg, a1, a2, a3, a4, a5, a6) ((void)0)
+#define AssertMsg7(_exp, _msg, a1, a2, a3, a4, a5, a6, a7) ((void)0)
+#define AssertMsg8(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8) ((void)0)
+#define AssertMsg9(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9) ((void)0)
+
+#endif // DBGFLAG_ASSERT
+
+// default level versions (level 0)
+#define Msg(...) _Msg (0, __VA_ARGS__)
+#define Warning(...) _Warning(0, __VA_ARGS__)
+#define Log(...) _Log (0, __VA_ARGS__)
+
+// These looked at the "developer" functions
+#define DevMsg(...) _Msg (1, __VA_ARGS__)
+#define DevWarning(...) _Warning(1, __VA_ARGS__)
+#define DevLog(...) _Log (1, __VA_ARGS__)
// These are always compiled in
-void Msg(const char *pMsg, ...);
-void DMsg(const char *pGroupName, int level, const char *pMsg, ...);
-
-void Warning(const char *pMsg, ...);
-void DWarning(const char *pGroupName, int level, const char *pMsg, ...);
-
-void Log(const char *pMsg, ...);
-void DLog(const char *pGroupName, int level, const char *pMsg, ...);
-
-void Error(const char *pMsg, ...);
+void _Msg (int level, const char *pMsg, ...);
+void _Warning(int level, const char *pMsg, ...);
+void _Log (int level, const char *pMsg, ...);
+void Error (const char *pMsg, ...);
// You can use this macro like a runtime assert macro.
// If the condition fails, then Error is called with the message. This macro is called
@@ -320,57 +355,39 @@ void Error(const char *pMsg, ...);
Error msg; \
}
-// A couple of super-common dynamic spew messages, here for convenience
-// These looked at the "developer" group
-void DevMsg(int level, char const* pMsg, ...);
-void DevWarning(int level, const char *pMsg, ...);
-void DevLog(int level, const char *pMsg, ...);
-
-// default level versions (level 1)
-void DevMsg(char const* pMsg, ...);
-void DevWarning(const char *pMsg, ...);
-void DevLog(const char *pMsg, ...);
-
// Code macros, debugger interface
-#ifdef _DEBUG
-#define DBG_CODE(_code) if (0) ; else { _code }
-#define DBG_DCODE(_g, _l, _code) if (IsSpewActive(_g, _l)) { _code } else {}
-#define DBG_BREAK() DebuggerBreak()
+#if defined(_DEBUG)
+ #define DBG_CODE(_code) if (0) ; else { _code }
+ #define DBG_DCODE(_g, _l, _code) if (IsSpewActive(_g, _l)) { _code } else {}
+ #define DBG_BREAK() DebuggerBreakIfDebugging()
#else // _DEBUG
-#define DBG_CODE(_code) ((void)0)
-#define DBG_DCODE(_g, _l, _code) ((void)0)
-#define DBG_BREAK() ((void)0)
+ #define DBG_CODE(_code) ((void)0)
+ #define DBG_DCODE(_g, _l, _code) ((void)0)
+ #define DBG_BREAK() ((void)0)
#endif // _DEBUG
-// Macro to assist in asserting constant invariants during compilation
-#define UID_PREFIX generated_id_
-#define UID_CAT1(a, c) a ## c
-#define UID_CAT2(a, c) UID_CAT1(a,c)
-#define UNIQUE_ID UID_CAT2(UID_PREFIX, __LINE__)
-
-#ifdef _DEBUG
-#define COMPILE_TIME_ASSERT(pred) switch(0){case 0:case pred:;}
-#define ASSERT_INVARIANT(pred) static void UNIQUE_ID() { COMPILE_TIME_ASSERT(pred) }
-#else
-#define COMPILE_TIME_ASSERT(pred)
-#define ASSERT_INVARIANT(pred)
-#endif
-
// Templates to assist in validating pointers:
// Have to use these stubs so we don't have to include windows.h here.
void _AssertValidReadPtr(void *ptr, int count = 1);
void _AssertValidWritePtr(void *ptr, int count = 1);
void _AssertValidReadWritePtr(void *ptr, int count = 1);
- void AssertValidStringPtr(const char *ptr, int maxchar = 0xFFFFFF);
-template inline void AssertValidReadPtr(T *ptr, int count = 1) { _AssertValidReadPtr((void *)ptr, count); }
-template inline void AssertValidWritePtr(T *ptr, int count = 1) { _AssertValidWritePtr((void *)ptr, count); }
-template inline void AssertValidReadWritePtr(T *ptr, int count = 1) { _AssertValidReadWritePtr((void *)ptr, count); }
-
-#define AssertValidThis() AssertValidReadWritePtr(this, sizeof(*this))
+#if defined(DBGFLAG_ASSERT)
+ void AssertValidStringPtr(const char *ptr, int maxchar = 0xFFFFFF);
+ template inline void AssertValidReadPtr(T *ptr, int count = 1) { _AssertValidReadPtr((void *)ptr, count); }
+ template inline void AssertValidWritePtr(T *ptr, int count = 1) { _AssertValidWritePtr((void *)ptr, count); }
+ template inline void AssertValidReadWritePtr(T *ptr, int count = 1) { _AssertValidReadWritePtr((void *)ptr, count); }
+ #define AssertValidThis() AssertValidReadWritePtr(this, sizeof(*this))
+#else
+ #define AssertValidStringPtr(...) ((void)0)
+ #define AssertValidReadPtr(...) ((void)0)
+ #define AssertValidWritePtr(...) ((void)0)
+ #define AssertValidReadWritePtr(...) ((void)0)
+ #define AssertValidThis() ((void)0)
+#endif // #if defined(DBGFLAG_ASSERT)
// Macro to protect functions that are not reentrant
-#ifdef _DEBUG
+#if defined(_DEBUG)
class CReentryGuard
{
public:
@@ -406,6 +423,7 @@ class CDbgFmtMsg
va_start(arg_ptr, pszFormat);
_vsnprintf(m_szBuf, sizeof(m_szBuf) - 1, pszFormat, arg_ptr);
va_end(arg_ptr);
+
m_szBuf[sizeof(m_szBuf) - 1] = '\0';
}
@@ -414,14 +432,11 @@ class CDbgFmtMsg
return m_szBuf;
}
+ const char *ToString() const
+ {
+ return m_szBuf;
+ }
+
private:
char m_szBuf[256];
};
-
-// Embed debug info in each file.
-//#ifdef _WIN32
-//#ifdef _DEBUG
-//#pragma comment(compiler)
-//#pragma comment(exestr,"*** DEBUG file detected, Last Compile: " __DATE__ ", " __TIME__ " ***")
-//#endif
-//#endif
diff --git a/regamedll/public/tier0/platform.h b/regamedll/public/tier0/platform.h
index c10ae8b9b..5703cf53b 100644
--- a/regamedll/public/tier0/platform.h
+++ b/regamedll/public/tier0/platform.h
@@ -41,7 +41,14 @@
#endif
// Used to step into the debugger
-#define DebuggerBreak() __asm { int 3 }
+#if defined(__GNUC__) && !defined(__clang__)
+ #define DebuggerBreak() __asm__ __volatile__("int3;")
+#else
+ #define DebuggerBreak() __asm { int 3 }
+#endif
+
+#define DebuggerBreakIfDebugging() if (Plat_IsInDebugSession()) { DebuggerBreak(); }
+#define DebuggerSegFault() { volatile int *null = 0; *null = 0; }
// C functions for external declarations that call the appropriate C++ methods
#ifndef EXPORT
@@ -105,6 +112,37 @@
#endif
#endif
+//
+// Macro to assist in asserting constant invariants during compilation
+
+#define STRINGIFY_INTERNAL(x) #x
+#define STRINGIFY(x) STRINGIFY_INTERNAL(x)
+
+// This implementation of compile time assert has zero cost (so it can safely be
+// included in release builds) and can be used at file scope or function scope.
+#define COMPILE_TIME_ASSERT(pred) static_assert(pred, "Compile time assert constraint is not true: " #pred)
+
+// ASSERT_INVARIANT used to be needed in order to allow COMPILE_TIME_ASSERTs at global
+// scope. However the new COMPILE_TIME_ASSERT macro supports that by default.
+#define ASSERT_INVARIANT(pred) COMPILE_TIME_ASSERT(pred)
+
+// Macro to assist in asserting constant invariants during compilation
+//
+// If available use static_assert instead of weird language tricks. This
+// leads to much more readable messages when compile time assert constraints
+// are violated.
+#if !defined(OSX) && (_MSC_VER > 1500 || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
+ #define PLAT_COMPILE_TIME_ASSERT(pred) static_assert(pred, "Compile time assert constraint is not true: " #pred)
+#else
+ #define PLAT_COMPILE_TIME_ASSERT(pred) typedef int UNIQUE_ID[ (pred) ? 1 : -1]
+#endif
+
+bool Plat_IsInDebugSession();
+void Plat_DebugString(const char *psz);
+void Plat_OutputDebugString(const char *psz);
+void Plat_OutputDebugStringRaw(const char *psz);
+const char *Plat_GetCommandLine();
+
// Methods to invoke the constructor, copy constructor, and destructor
template
inline void Construct(T *pMemory)
diff --git a/regamedll/public/tier0/platform_posix.cpp b/regamedll/public/tier0/platform_posix.cpp
new file mode 100644
index 000000000..202040b90
--- /dev/null
+++ b/regamedll/public/tier0/platform_posix.cpp
@@ -0,0 +1,113 @@
+/*
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 of the License, or (at
+* your option) any later version.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+* In addition, as a special exception, the author gives permission to
+* link the code of this program with the Half-Life Game Engine ("HL
+* Engine") and Modified Game Libraries ("MODs") developed by Valve,
+* L.L.C ("Valve"). You must obey the GNU General Public License in all
+* respects for all of the code used other than the HL Engine and MODs
+* from Valve. If you modify this file, you may extend this exception
+* to your version of the file, but you are not obligated to do so. If
+* you do not wish to do so, delete this exception statement from your
+* version.
+*
+*/
+
+#include "precompiled.h"
+
+bool Plat_IsInDebugSession()
+{
+#if defined(OSX)
+ int mib[4];
+ struct kinfo_proc info;
+ size_t size;
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = getpid();
+ size = sizeof(info);
+ info.kp_proc.p_flag = 0;
+ sysctl(mib, 4, &info, &size, NULL, 0);
+ bool result = ((info.kp_proc.p_flag & P_TRACED) == P_TRACED);
+ return result;
+#elif defined(_LINUX)
+ char s[256];
+ snprintf(s, 256, "/proc/%d/cmdline", getppid());
+ FILE *fp = fopen(s, "r");
+ if (fp)
+ {
+ fread(s, 256, 1, fp);
+ fclose(fp);
+ return (0 == strncmp(s, "gdb", 3));
+ }
+ return false;
+#endif
+}
+
+void Plat_OutputDebugStringRaw(const char *psz)
+{
+ fprintf(stderr, "%s", psz);
+}
+
+void Plat_OutputDebugString(const char *psz)
+{
+ fprintf(stderr, "%s", psz);
+}
+
+void Plat_DebugString(const char *psz)
+{
+ fprintf(stderr, "%s", psz);
+}
+
+static char g_CmdLine[2048]{};
+
+const char *Plat_GetCommandLine()
+{
+#if defined(_LINUX)
+ static bool commandline_initialized = false;
+ if (!commandline_initialized)
+ {
+ commandline_initialized = true;
+
+ FILE *fp = fopen("/proc/self/cmdline", "rb");
+ if (fp)
+ {
+ size_t nCharRead = 0;
+
+ // -1 to leave room for the '\0'
+ nCharRead = fread(g_CmdLine, sizeof(g_CmdLine[0]), ARRAYSIZE(g_CmdLine) - 1, fp);
+ if (feof(fp) && !ferror(fp)) // Should have read the whole command line without error
+ {
+ Assert(nCharRead < ARRAYSIZE(g_CmdLine));
+
+ for (int i = 0; i < nCharRead; i++)
+ {
+ if (!g_CmdLine[i])
+ g_CmdLine[i] = ' ';
+ }
+
+ g_CmdLine[nCharRead] = '\0';
+ }
+
+ fclose(fp);
+ }
+
+ Assert(g_CmdLine[0]);
+ }
+#endif // LINUX
+
+ return g_CmdLine;
+}
diff --git a/regamedll/public/tier0/platform_win32.cpp b/regamedll/public/tier0/platform_win32.cpp
new file mode 100644
index 000000000..0ffbf7cf3
--- /dev/null
+++ b/regamedll/public/tier0/platform_win32.cpp
@@ -0,0 +1,57 @@
+/*
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 of the License, or (at
+* your option) any later version.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+* In addition, as a special exception, the author gives permission to
+* link the code of this program with the Half-Life Game Engine ("HL
+* Engine") and Modified Game Libraries ("MODs") developed by Valve,
+* L.L.C ("Valve"). You must obey the GNU General Public License in all
+* respects for all of the code used other than the HL Engine and MODs
+* from Valve. If you modify this file, you may extend this exception
+* to your version of the file, but you are not obligated to do so. If
+* you do not wish to do so, delete this exception statement from your
+* version.
+*
+*/
+
+#include "precompiled.h"
+
+bool Plat_IsInDebugSession()
+{
+ return IsDebuggerPresent() != FALSE;
+}
+
+void Plat_OutputDebugStringRaw(const char *psz)
+{
+ OutputDebugString(psz);
+}
+
+void Plat_OutputDebugString(const char *psz)
+{
+ static char buf[4096];
+ int len = Q_snprintf(buf, sizeof(buf), "%s", psz);
+ Assert(len > 0);
+ OutputDebugString(buf);
+}
+
+void Plat_DebugString(const char *psz)
+{
+ Plat_OutputDebugString(psz);
+}
+
+const char *Plat_GetCommandLine()
+{
+ return GetCommandLineA();
+}
diff --git a/regamedll/public/tier0/resource.h b/regamedll/public/tier0/resource.h
new file mode 100644
index 000000000..d261901a6
--- /dev/null
+++ b/regamedll/public/tier0/resource.h
@@ -0,0 +1,44 @@
+/*
+*
+* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+*/
+
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by assert_dialog.rc
+//
+
+#define IDD_ASSERT_DIALOG 101
+#define IDC_FILENAME_CONTROL 1000
+#define IDC_LINE_CONTROL 1001
+#define IDC_IGNORE_FILE 1002
+#define IDC_IGNORE_NEARBY 1003
+#define IDC_IGNORE_NUMLINES 1004
+#define IDC_IGNORE_THIS 1005
+#define IDC_BREAK 1006
+#define IDC_IGNORE_ALL 1008
+#define IDC_IGNORE_ALWAYS 1009
+#define IDC_IGNORE_NUMTIMES 1010
+#define IDC_ASSERT_MSG_CTRL 1011
+#define IDC_NOID -1
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 103
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1005
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/regamedll/public/utlarray.h b/regamedll/public/utlarray.h
new file mode 100644
index 000000000..1da8aafb0
--- /dev/null
+++ b/regamedll/public/utlarray.h
@@ -0,0 +1,303 @@
+/*
+*
+* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+*/
+
+#pragma once
+
+// A growable array class that maintains a free list and keeps elements
+// in the same location
+#include "tier0/platform.h"
+#include "tier0/dbg.h"
+
+#include
+
+#define FOR_EACH_ARRAY(vecName, iteratorName)\
+ for (int iteratorName = 0; (vecName).IsUtlArray && iteratorName < (vecName).Count(); iteratorName++)
+
+#define FOR_EACH_ARRAY_BACK(vecName, iteratorName)\
+ for (int iteratorName = (vecName).Count() - 1; (vecName).IsUtlArray && iteratorName >= 0; iteratorName--)
+
+template
+class CUtlArray
+{
+public:
+ typedef T ElemType_t;
+ enum { IsUtlArray = true }; // Used to match this at compiletime
+
+ CUtlArray();
+ CUtlArray(T *pMemory, size_t count);
+ ~CUtlArray();
+
+ CUtlArray &operator=(const CUtlArray &other);
+ CUtlArray(CUtlArray const &vec);
+
+ // element access
+ T &operator[](int i);
+ const T &operator[](int i) const;
+ T &Element(int i);
+ const T &Element(int i) const;
+ T &Random();
+ const T &Random() const;
+
+ T *Base();
+ const T *Base() const;
+
+ // Returns the number of elements in the array, NumAllocated() is included for consistency with UtlVector
+ int Count() const;
+ int NumAllocated() const;
+
+ // Is element index valid?
+ bool IsValidIndex(int i) const;
+ static int InvalidIndex();
+
+ void CopyArray(const T *pArray, size_t count);
+
+ void Clear();
+ void RemoveAll();
+ void Swap(CUtlArray< T, MAX_SIZE> &vec);
+
+ // Finds an element (element needs operator== defined)
+ int Find(const T &src) const;
+ void FillWithValue(const T &src);
+
+ bool HasElement(const T &src) const;
+
+ // sort using std:: and expecting a "<" function to be defined for the type
+ void Sort();
+ void Sort(bool (*pfnLessFunc)(const T &src1, const T &src2));
+
+#if defined(_WIN32)
+ void Sort(int (__cdecl *pfnCompare)(const T *, const T *));
+#else
+ void Sort(int (*pfnCompare)(const T *, const T *));
+#endif
+
+ // sort using std:: with a predicate. e.g. [] -> bool (const T &a, const T &b) const { return a < b; }
+ template
+ void SortPredicate(F &&predicate);
+
+protected:
+ T m_Memory[MAX_SIZE];
+};
+
+// Constructor
+template
+inline CUtlArray::CUtlArray()
+{
+}
+
+template
+inline CUtlArray::CUtlArray(T *pMemory, size_t count)
+{
+ CopyArray(pMemory, count);
+}
+
+// Destructor
+template
+inline CUtlArray::~CUtlArray()
+{
+}
+
+template
+inline CUtlArray &CUtlArray::operator=(const CUtlArray &other)
+{
+ if (this != &other)
+ {
+ for (size_t n = 0; n < MAX_SIZE; n++)
+ m_Memory[n] = other.m_Memory[n];
+ }
+
+ return *this;
+}
+
+template
+inline CUtlArray::CUtlArray(CUtlArray const &vec)
+{
+ for (size_t n = 0; n < MAX_SIZE; n++)
+ m_Memory[n] = vec.m_Memory[n];
+}
+
+template
+inline T *CUtlArray::Base()
+{
+ return &m_Memory[0];
+}
+
+template
+inline const T *CUtlArray::Base() const
+{
+ return &m_Memory[0];
+}
+
+// Element access
+template
+inline T &CUtlArray::operator[](int i)
+{
+ DbgAssert(IsValidIndex(i));
+ return m_Memory[i];
+}
+
+template
+inline const T &CUtlArray::operator[](int i) const
+{
+ DbgAssert(IsValidIndex(i));
+ return m_Memory[i];
+}
+
+template
+inline T &CUtlArray::Element(int i)
+{
+ DbgAssert(IsValidIndex(i));
+ return m_Memory[i];
+}
+
+template
+inline const T &CUtlArray::Element(int i) const
+{
+ DbgAssert(IsValidIndex(i));
+ return m_Memory[i];
+}
+
+// Count
+template
+inline int CUtlArray::Count() const
+{
+ return (int)MAX_SIZE;
+}
+
+template
+inline int CUtlArray::NumAllocated() const
+{
+ return (int)MAX_SIZE;
+}
+
+// Is element index valid?
+template
+inline bool CUtlArray::IsValidIndex(int i) const
+{
+ return (i >= 0) && (i < MAX_SIZE);
+}
+
+// Returns in invalid index
+template
+inline int CUtlArray::InvalidIndex()
+{
+ return -1;
+}
+
+// Sort methods
+template
+void CUtlArray::Sort()
+{
+ std::sort(Base(), Base() + Count());
+}
+
+template
+void CUtlArray::Sort(bool (*pfnLessFunc)(const T &src1, const T &src2))
+{
+ std::sort(Base(), Base() + Count(),
+ [pfnLessFunc](const T &a, const T &b) -> bool
+ {
+ if (&a == &b)
+ return false;
+
+ return (*pfnLessFunc)(a, b);
+ });
+}
+
+#if defined(_WIN32)
+
+template
+void CUtlArray::Sort(int (__cdecl *pfnCompare)(const T *, const T *))
+{
+ typedef int (__cdecl *QSortCompareFunc_t)(const void *, const void *);
+ if (Count() <= 1)
+ return;
+
+ qsort(Base(), Count(), sizeof(T), (QSortCompareFunc_t)(pfnCompare));
+}
+
+#else // #if defined(_LINUX)
+
+template
+void CUtlArray::Sort(int (*pfnCompare)(const T *, const T *))
+{
+ typedef int (*QSortCompareFunc_t)(const void *, const void *);
+ if (Count() <= 1)
+ return;
+
+ qsort(Base(), Count(), sizeof(T), (QSortCompareFunc_t)(pfnCompare));
+}
+#endif // #if defined(_LINUX)
+
+template
+template
+void CUtlArray::SortPredicate(F &&predicate)
+{
+ std::sort(Base(), Base() + Count(), predicate);
+}
+
+template
+void CUtlArray::CopyArray(const T *pArray, size_t count)
+{
+ DbgAssert(count < MAX_SIZE);
+
+ for (size_t n = 0; n < count; n++)
+ m_Memory[n] = pArray[n];
+}
+
+template
+void CUtlArray::Clear()
+{
+ Q_memset(m_Memory, 0, MAX_SIZE * sizeof(T));
+}
+
+template
+void CUtlArray::RemoveAll()
+{
+ Clear();
+}
+
+template
+void CUtlArray::Swap(CUtlArray< T, MAX_SIZE> &vec)
+{
+ for (size_t n = 0; n < MAX_SIZE; n++)
+ SWAP(m_Memory[n], vec.m_Memory[n]);
+}
+
+// Finds an element (element needs operator== defined)
+template
+int CUtlArray::Find(const T &src) const
+{
+ for (int i = 0; i < Count(); i++)
+ {
+ if (Element(i) == src)
+ return i;
+ }
+
+ return -1;
+}
+
+template
+void CUtlArray::FillWithValue(const T &src)
+{
+ for (int i = 0; i < Count(); i++)
+ Element(i) = src;
+}
+
+template
+bool CUtlArray::HasElement(const T &src) const
+{
+ return (Find(src) >= 0);
+}
diff --git a/regamedll/public/utllinkedlist.h b/regamedll/public/utllinkedlist.h
index c93369897..6d05231c9 100644
--- a/regamedll/public/utllinkedlist.h
+++ b/regamedll/public/utllinkedlist.h
@@ -248,14 +248,14 @@ inline I CUtlLinkedList::Tail() const
template
inline I CUtlLinkedList::Previous(I i) const
{
- Assert(IsValidIndex(i));
+ DbgAssert(IsValidIndex(i));
return InternalElement(i).m_Previous;
}
template
inline I CUtlLinkedList::Next(I i) const
{
- Assert(IsValidIndex(i));
+ DbgAssert(IsValidIndex(i));
return InternalElement(i).m_Next;
}
@@ -319,7 +319,7 @@ I CUtlLinkedList::AllocInternal(bool multilist)
if (m_TotalElements == m_Memory.NumAllocated())
m_Memory.Grow();
- Assert(m_TotalElements != InvalidIndex());
+ DbgAssert(m_TotalElements != InvalidIndex());
elem = (I)m_TotalElements;
m_TotalElements++;
@@ -356,7 +356,7 @@ I CUtlLinkedList::Alloc(bool multilist)
template
void CUtlLinkedList::Free(I elem)
{
- Assert(IsValidIndex(elem));
+ DbgAssert(IsValidIndex(elem));
Unlink(elem);
ListElem_t &internalElem = InternalElement(elem);
@@ -520,7 +520,7 @@ void CUtlLinkedList::RemoveAll()
template
void CUtlLinkedList::LinkBefore(I before, I elem)
{
- Assert(IsValidIndex(elem));
+ DbgAssert(IsValidIndex(elem));
// Unlink it if it's in the list at the moment
Unlink(elem);
@@ -540,7 +540,7 @@ void CUtlLinkedList::LinkBefore(I before, I elem)
{
// Here, we're not linking to the end. Set the prev pointer to point to
// the element we're linking.
- Assert(IsInList(before));
+ DbgAssert(IsInList(before));
ListElem_t& beforeElem = InternalElement(before);
newElem.m_Previous = beforeElem.m_Previous;
beforeElem.m_Previous = elem;
@@ -559,7 +559,7 @@ void CUtlLinkedList::LinkBefore(I before, I elem)
template