diff --git a/README.md b/README.md
index 6713f49a4..ee928a928 100644
--- a/README.md
+++ b/README.md
@@ -100,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 |
@@ -109,6 +110,11 @@ This means that plugins that do binary code analysis (Orpheu for example) probab
| mp_give_c4_frags | 3 | - | - | How many bonuses (frags) will get the player who defused or exploded the bomb. |
| mp_hostages_rescued_ratio | 1.0 | 0.0 | 1.0 | Ratio of hostages rescued to win the round. |
| mp_legacy_vehicle_block | 1 | 0 | 1 | Legacy func_vehicle behavior when blocked by another entity.
`0` New behavior
`1` Legacy behavior |
+| 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/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 25ba9877f..a1d77c205 100644
--- a/dist/game.cfg
+++ b/dist/game.cfg
@@ -474,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
@@ -521,3 +529,41 @@ mp_hostages_rescued_ratio "1.0"
//
// Default value: "1"
mp_legacy_vehicle_block "1"
+
+// 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"
\ No newline at end of file
diff --git a/regamedll/CMakeLists.txt b/regamedll/CMakeLists.txt
index 8e78fa6bb..6bb79e849 100644
--- a/regamedll/CMakeLists.txt
+++ b/regamedll/CMakeLists.txt
@@ -226,6 +226,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_bomb_reset.cpp"
diff --git a/regamedll/common/const.h b/regamedll/common/const.h
index d667a6b85..024a2a3d5 100644
--- a/regamedll/common/const.h
+++ b/regamedll/common/const.h
@@ -100,6 +100,7 @@
// 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
diff --git a/regamedll/dlls/API/CAPI_Impl.cpp b/regamedll/dlls/API/CAPI_Impl.cpp
index 4208c0b9c..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,
@@ -76,6 +169,13 @@ ReGameFuncs_t g_ReGameApiFuncs = {
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);
@@ -209,6 +309,32 @@ 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;
@@ -271,48 +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);
-}
-
-EXT_FUNC void UTIL_RestartOther_api(const char *szClassname) {
- UTIL_RestartOther(szClassname);
-}
-
-EXT_FUNC void UTIL_ResetEntities_api() {
- UTIL_ResetEntities();
-}
-
-EXT_FUNC void UTIL_RemoveOther_api(const char *szClassname, int nCount)
-{
- UTIL_RemoveOther(szClassname, nCount);
-}
-
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 b430f50c5..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;
@@ -645,6 +645,106 @@ typedef IHookChainRegistryClassImpl CReGameHookRegistry_CBase
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
@@ -779,6 +879,32 @@ class CReGameHookchains: public IReGameHookchains {
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();
@@ -912,6 +1038,32 @@ class CReGameHookchains: public IReGameHookchains {
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;
@@ -938,14 +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);
-
-void UTIL_RestartOther_api(const char *szClassname);
-void UTIL_ResetEntities_api();
-void UTIL_RemoveOther_api(const char *szClassname, int nCount = 0);
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 2a8348cba..09941134e 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);
}
@@ -153,15 +155,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"))
@@ -225,38 +219,20 @@ EXT_FUNC bool CCSPlayer::RemovePlayerItemEx(const char* pszItemName, bool bRemov
return true; // ammo was reduced, this will be considered a successful result
}
- if (pItem == pPlayer->m_pActiveItem) {
- ((CBasePlayerWeapon *)pItem)->RetireWeapon();
- }
-
if (bRemoveAmmo) {
- pPlayer->m_rgAmmo[ pItem->PrimaryAmmoIndex() ] = 0;
- }
- }
-
- if (pPlayer->RemovePlayerItem(pItem))
- {
- if (FClassnameIs(pItem->pev, "weapon_c4")) {
- pPlayer->m_bHasC4 = false;
- pPlayer->pev->body = 0;
- pPlayer->SetBombIcon(FALSE);
- pPlayer->SetProgressBarTime(0);
- }
-
- 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 (!pPlayer->m_rgpPlayerItems[PRIMARY_WEAPON_SLOT]) {
- pPlayer->m_bHasPrimary = false;
+ if (pItem == pPlayer->m_pActiveItem) {
+ ((CBasePlayerWeapon *)pItem)->RetireWeapon();
+
+ if (pItem->CanHolster() && pItem != pPlayer->m_pActiveItem && !(pPlayer->pev->weapons &(1 << pItem->m_iId))) {
+ return true;
+ }
}
-
- return true;
}
+
+ return pItem->DestroyItem();
}
return false;
@@ -273,11 +249,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");
@@ -290,7 +268,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)
@@ -318,14 +296,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()
@@ -574,10 +552,22 @@ void CCSPlayer::ResetVars()
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()
{
m_bGameForcingRespawn = false;
m_flRespawnPending = 0.0f;
+ m_DamageList.Clear();
}
void CCSPlayer::OnKilled()
@@ -595,3 +585,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/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_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/buttons.cpp b/regamedll/dlls/buttons.cpp
index c559f8c03..36e2ff1b6 100644
--- a/regamedll/dlls/buttons.cpp
+++ b/regamedll/dlls/buttons.cpp
@@ -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))))
diff --git a/regamedll/dlls/cbase.cpp b/regamedll/dlls/cbase.cpp
index b1cbe149e..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;
}
@@ -1242,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)
@@ -1340,6 +1360,7 @@ VectorRef CBaseEntity::__API_HOOK(FireBullets3)(VectorRef vecSrc, VectorRef vecD
float flDamageModifier = 0.5;
+ int iStartPenetration = iPenetration;
while (iPenetration != 0)
{
ClearMultiDamage();
@@ -1400,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;
@@ -1459,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 cd52b7bc3..dca3c5690 100644
--- a/regamedll/dlls/client.cpp
+++ b/regamedll/dlls/client.cpp
@@ -621,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;
@@ -670,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)
{
@@ -691,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
@@ -727,7 +737,7 @@ void EXT_FUNC ClientPutInServer(edict_t *pEntity)
}
#ifdef REGAMEDLL_API
- pPlayer->CSPlayer()->ResetVars();
+ pPlayer->CSPlayer()->OnConnect();
#endif
UTIL_ClientPrintAll(HUD_PRINTNOTIFY, "#Game_connected", (sName[0] != '\0') ? sName : "");
@@ -1194,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;
@@ -1435,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;
@@ -1474,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);
@@ -1911,7 +1907,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);
}
@@ -2262,7 +2258,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);
@@ -4817,6 +4813,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
}
}
@@ -4849,7 +4855,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 28f06e41b..d873bd202 100644
--- a/regamedll/dlls/client.h
+++ b/regamedll/dlls/client.h
@@ -112,6 +112,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 620c84cfd..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,12 +16,23 @@ 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)
@@ -90,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;
@@ -97,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;
@@ -290,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/game.cpp b/regamedll/dlls/game.cpp
index 2e0ef12b4..55c2600c1 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 };
@@ -160,16 +161,23 @@ 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 };
+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)
@@ -231,6 +239,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);
@@ -408,6 +417,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);
@@ -418,6 +428,13 @@ void EXT_FUNC GameDLLInit()
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);
+
// print version
CONSOLE_ECHO("ReGameDLL version: " APP_VERSION "\n");
diff --git a/regamedll/dlls/game.h b/regamedll/dlls/game.h
index ed2ae509c..cff031fbb 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;
@@ -186,14 +187,20 @@ 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;
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;
+
#endif
extern cvar_t scoreboard_showmoney;
diff --git a/regamedll/dlls/gamerules.h b/regamedll/dlls/gamerules.h
index d6975df02..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
@@ -206,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
@@ -219,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
@@ -336,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
@@ -541,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();
@@ -564,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:
@@ -692,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);
@@ -733,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
@@ -921,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..41e92f27d 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);
@@ -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
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/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 baf916589..4f4899712 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;
@@ -681,9 +681,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;
@@ -744,7 +744,7 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(GiveC4)()
{
#ifdef REGAMEDLL_FIXES
// we already have bomber
- return;
+ return pPlayer;
#endif
}
}
@@ -772,10 +772,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)
@@ -2035,7 +2037,7 @@ void EXT_FUNC CHalfLifeMultiplay::__API_HOOK(RestartRound)()
#endif
pPlayer->RoundRespawn();
-
+
#ifdef REGAMEDLL_ADD
FireTargets("game_entity_restart", pPlayer, nullptr, USE_TOGGLE, 0.0);
#endif
@@ -2122,7 +2124,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)
{
@@ -2136,8 +2140,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)
@@ -2370,7 +2376,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);
@@ -2393,7 +2401,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;
@@ -3078,17 +3086,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;
}
}
@@ -3456,7 +3458,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)
@@ -3580,14 +3582,15 @@ 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)
{
@@ -3874,7 +3877,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));
}
@@ -3916,7 +3919,7 @@ 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
+#ifdef REGAMEDLL_FIXES
pVictim->pev->flags &= ~FL_FROZEN;
#endif
pVictim->m_afPhysicsFlags &= ~PFLAG_ONTRAIN;
@@ -4073,102 +4076,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
@@ -4191,7 +4152,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);
@@ -4201,8 +4162,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)
{
;
}
@@ -4337,11 +4300,11 @@ int EXT_FUNC CHalfLifeMultiplay::__API_HOOK(DeadPlayerWeapons)(CBasePlayer *pPla
{
case 3:
return GR_PLR_DROP_GUN_ALL;
- case 2:
+ case 2:
break;
case 1:
return GR_PLR_DROP_GUN_BEST;
- default:
+ default:
return GR_PLR_DROP_GUN_NO;
}
#endif
@@ -4888,7 +4851,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)()
@@ -5196,3 +5159,211 @@ 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 kills the victim through the walls
+ if (pVictim->GetDmgPenetrationLevel() > 0)
+ iRarity |= KILLRARITY_PENETRATED;
+
+ // The killer player was blind
+ if (pKiller && pKiller->IsPlayer())
+ {
+ CBasePlayer *pKillerPlayer = static_cast(pKiller);
+ if (pKillerPlayer->IsBlind())
+ iRarity |= KILLRARITY_KILLER_BLIND;
+
+ // The killer player kills the victim with a sniper rifle with no scope
+ WeaponClassType weaponClass = AliasToWeaponClass(killerWeaponName);
+ 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/player.cpp b/regamedll/dlls/player.cpp
index a26dfd623..e896e0b6a 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
@@ -745,24 +743,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
@@ -781,10 +785,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;
@@ -955,7 +960,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)
@@ -970,9 +975,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
}
{
@@ -1033,7 +1042,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);
@@ -1075,16 +1084,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)
@@ -1153,9 +1164,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))
@@ -1195,7 +1203,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)
@@ -1213,9 +1224,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
}
{
@@ -1276,7 +1291,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)
{
@@ -1290,7 +1305,7 @@ 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()]);
@@ -1415,12 +1430,12 @@ void CBasePlayer::PackDeadPlayerItems()
int nBestWeight = 0;
CBasePlayerItem *pBestItem = nullptr;
-#ifdef REGAMEDLL_ADD
+#ifdef REGAMEDLL_ADD
int iGunsPacked = 0;
- if (iPackGun == GR_PLR_DROP_GUN_ACTIVE)
+ if (iPackGun == GR_PLR_DROP_GUN_ACTIVE)
{
- // check if we've just already dropped our active gun
+ // 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;
@@ -1429,7 +1444,7 @@ void CBasePlayer::PackDeadPlayerItems()
}
// are we allowing nade drop?
- if ((int)nadedrops.value >= 1)
+ if ((int)nadedrops.value >= 1)
{
// goto item loop but skip guns
iPackGun = GR_PLR_DROP_GUN_ALL;
@@ -1460,7 +1475,7 @@ void CBasePlayer::PackDeadPlayerItems()
#endif
)
{
-#ifdef REGAMEDLL_ADD
+#ifdef REGAMEDLL_ADD
if (iPackGun == GR_PLR_DROP_GUN_ALL)
{
CBasePlayerItem *pNext = pPlayerItem->m_pNext;
@@ -1469,10 +1484,10 @@ void CBasePlayer::PackDeadPlayerItems()
if (pWeaponBox)
{
// just push a few units in forward to separate them
- pWeaponBox->pev->velocity = pWeaponBox->pev->velocity * (1.0 + (iGunsPacked * 0.2));
+ pWeaponBox->pev->velocity = pWeaponBox->pev->velocity * (1.0 + (iGunsPacked * 0.2));
iGunsPacked++;
}
-
+
pPlayerItem = pNext;
continue;
}
@@ -1676,7 +1691,6 @@ void EXT_FUNC CBasePlayer::__API_HOOK(GiveDefaultItems)()
void CBasePlayer::RemoveAllItems(BOOL removeSuit)
{
- bool bKillProgBar = false;
int i;
#ifdef REGAMEDLL_FIXES
@@ -1690,34 +1704,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();
@@ -2121,7 +2119,7 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Killed)(entvars_t *pevAttacker, int iGib)
if (IsBot() && IsBlind()) // dystopm: shouldn't be !IsBot() ?
wasBlind = true;
- TheCareerTasks->HandleEnemyKill(wasBlind, GetWeaponName(g_pevLastInflictor, pevAttacker), m_bHeadshotKilled, killerHasShield, pAttacker, this); // last 2 param swapped to match function definition
+ TheCareerTasks->HandleEnemyKill(wasBlind, GetKillerWeaponName(GetLastInflictor(), pevAttacker), m_bHeadshotKilled, killerHasShield, pAttacker, this); // last 2 param swapped to match function definition
}
}
#endif
@@ -2152,7 +2150,7 @@ 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);
}
}
}
@@ -2162,7 +2160,7 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Killed)(entvars_t *pevAttacker, int iGib)
if (!m_bKilledByBomb)
{
- g_pGameRules->PlayerKilled(this, pevAttacker, g_pevLastInflictor);
+ g_pGameRules->PlayerKilled(this, pevAttacker, GetLastInflictor());
}
MESSAGE_BEGIN(MSG_ONE, gmsgNVGToggle, nullptr, pev);
@@ -2292,6 +2290,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:
@@ -2307,12 +2307,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());
@@ -2323,15 +2323,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;
}
@@ -2402,8 +2394,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();
@@ -2431,31 +2423,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
@@ -3646,16 +3625,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:
@@ -3679,7 +3662,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");
@@ -3774,18 +3761,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);
@@ -3797,7 +3777,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;
@@ -3857,7 +3839,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();
@@ -4113,11 +4095,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;
}
@@ -4659,12 +4640,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;
}
}
@@ -4673,12 +4659,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;
}
@@ -4784,6 +4775,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.
@@ -4792,7 +4785,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;
@@ -5173,7 +5166,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)
{
@@ -5359,7 +5362,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;
@@ -5688,10 +5693,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)
{
@@ -6003,6 +6005,8 @@ void CBasePlayer::Reset()
if (CSPlayer()->GetProtectionState() == CCSPlayer::ProtectionSt_Active) {
RemoveSpawnProtection();
}
+
+ CSPlayer()->ResetAllStats();
#endif
}
@@ -6378,6 +6382,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;
@@ -6390,6 +6399,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)
@@ -7363,7 +7450,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();
}
}
@@ -8044,8 +8134,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"))
{
@@ -8115,6 +8207,12 @@ CBaseEntity *EXT_FUNC CBasePlayer::__API_HOOK(DropPlayerItem)(const char *pszIte
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;
@@ -8287,14 +8385,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++)
@@ -8523,7 +8613,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");
@@ -8812,6 +8901,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
@@ -8819,9 +8925,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
@@ -8831,6 +8935,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);
@@ -8840,14 +8965,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)
{
@@ -9896,7 +10024,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);
@@ -10096,10 +10224,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()
@@ -10174,8 +10353,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);
@@ -10409,10 +10588,10 @@ bool CBasePlayer::Kill()
{
if (GetObserverMode() != OBS_NONE)
return false;
-
+
if (m_iJoiningState != JOINED)
return false;
-
+
m_LastHitGroup = HITGROUP_GENERIC;
// have the player kill himself
@@ -10421,6 +10600,6 @@ bool CBasePlayer::Kill()
if (CSGameRules()->m_pVIP == this)
CSGameRules()->m_iConsecutiveVIP = 10;
-
+
return true;
}
diff --git a/regamedll/dlls/player.h b/regamedll/dlls/player.h
index e2f76c680..8221bd48f 100644
--- a/regamedll/dlls/player.h
+++ b/regamedll/dlls/player.h
@@ -444,7 +444,11 @@ 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);
@@ -628,12 +633,14 @@ 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;
CBasePlayerItem *GetItemByName(const char *itemName);
CBasePlayerItem *GetItemById(WeaponIdType weaponID);
@@ -907,6 +914,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
{
@@ -968,7 +976,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;
@@ -996,7 +1003,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/triggers.cpp b/regamedll/dlls/triggers.cpp
index f454806ce..49819a0ec 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)
{
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 6b2fda0c7..714fe79d1 100644
--- a/regamedll/dlls/util.cpp
+++ b/regamedll/dlls/util.cpp
@@ -1758,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)
diff --git a/regamedll/dlls/util.h b/regamedll/dlls/util.h
index 9ed3f40ee..f96be669b 100644
--- a/regamedll/dlls/util.h
+++ b/regamedll/dlls/util.h
@@ -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/weapons.cpp b/regamedll/dlls/weapons.cpp
index 7c21920a6..3604c26de 100644
--- a/regamedll/dlls/weapons.cpp
+++ b/regamedll/dlls/weapons.cpp
@@ -74,25 +74,31 @@ float GetBaseAccuracy(WeaponIdType id)
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;
@@ -208,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;
@@ -219,7 +231,7 @@ void AddAmmoNameToAmmoRegistry(const char *szAmmoname)
if (!Q_stricmp(CBasePlayerItem::m_AmmoInfoArray[i].pszName, szAmmoname))
{
// ammo already in registry, just quite
- return;
+ return i;
}
}
@@ -227,7 +239,7 @@ void AddAmmoNameToAmmoRegistry(const char *szAmmoname)
assert(giAmmoIndex < MAX_AMMO_SLOTS);
if (giAmmoIndex >= MAX_AMMO_SLOTS)
- giAmmoIndex = 0;
+ giAmmoIndex = 1;
#ifdef REGAMEDLL_ADD
for (auto& ammo : ammoIndex)
@@ -246,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
@@ -269,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);
}
}
@@ -691,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;
@@ -814,17 +823,25 @@ BOOL CanAttack(float attack_time, float curtime, BOOL isPredicted)
bool CBasePlayerWeapon::HasSecondaryAttack()
{
- if (m_pPlayer && m_pPlayer->HasShield())
+#ifdef REGAMEDLL_API
+ if (CSPlayerWeapon()->m_iStateSecondaryAttack != WEAPON_SECONDARY_ATTACK_NONE)
{
- return true;
+ switch (CSPlayerWeapon()->m_iStateSecondaryAttack)
+ {
+ case WEAPON_SECONDARY_ATTACK_SET:
+ return true;
+ case WEAPON_SECONDARY_ATTACK_BLOCK:
+ return false;
+ default:
+ break;
+ }
}
+#endif
-#ifdef REGAMEDLL_API
- if (CSPlayerWeapon()->m_bHasSecondaryAttack)
+ if (m_pPlayer && m_pPlayer->HasShield())
{
return true;
}
-#endif
switch (m_iId)
{
@@ -888,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;
@@ -1109,8 +1128,10 @@ void CBasePlayerWeapon::ItemPostFrame()
}
}
-void CBasePlayerItem::DestroyItem()
+bool CBasePlayerItem::DestroyItem()
{
+ bool success = false;
+
if (m_pPlayer)
{
// if attached to a player, remove.
@@ -1118,18 +1139,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)
@@ -1195,8 +1229,6 @@ void CBasePlayerWeapon::Spawn()
if (GetItemInfo(&info)) {
CSPlayerItem()->SetItemInfo(&info);
}
-
- CSPlayerWeapon()->m_bHasSecondaryAttack = HasSecondaryAttack();
#endif
}
@@ -1279,7 +1311,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;
@@ -1821,7 +1855,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
@@ -1881,8 +1920,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")))
@@ -1955,7 +1994,7 @@ void CWeaponBox::Touch(CBaseEntity *pOther)
if (pPlayer->AddPlayerItem(pItem))
{
pItem->AttachToPlayer(pPlayer);
- bEmitSound = true;
+ givenItem = pItem;
}
// unlink this weapon from the box
@@ -1992,7 +2031,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
@@ -2014,7 +2053,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
@@ -2048,9 +2091,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)
@@ -2656,3 +2711,4 @@ int CBasePlayerItem::iFlags() const
{
return m_ItemInfoEx.iFlags;
}
+
diff --git a/regamedll/dlls/weapons.h b/regamedll/dlls/weapons.h
index b2928f017..8e4e2651e 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
@@ -540,7 +543,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,
};
@@ -912,6 +915,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:
@@ -1077,7 +1093,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,
};
@@ -1192,7 +1208,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,
};
@@ -1870,6 +1886,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:
@@ -2148,7 +2177,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/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 aa7e177cf..fcbf2d949 100644
--- a/regamedll/dlls/wpn_shared/wpn_knife.cpp
+++ b/regamedll/dlls/wpn_shared/wpn_knife.cpp
@@ -129,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)
@@ -147,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)
@@ -274,11 +280,21 @@ BOOL CKnife::Swing(BOOL fFirst)
vecSrc = m_pPlayer->GetGunPosition();
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)
{
@@ -457,11 +473,21 @@ BOOL CKnife::Stab(BOOL fFirst)
vecSrc = m_pPlayer->GetGunPosition();
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)
{
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_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/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/msvc/ReGameDLL.vcxproj b/regamedll/msvc/ReGameDLL.vcxproj
index cf826fae8..a9c9d6743 100644
--- a/regamedll/msvc/ReGameDLL.vcxproj
+++ b/regamedll/msvc/ReGameDLL.vcxproj
@@ -48,6 +48,10 @@
+
+
+
+
@@ -785,6 +789,7 @@
+
@@ -1122,4 +1127,4 @@
-
+
\ No newline at end of file
diff --git a/regamedll/msvc/ReGameDLL.vcxproj.filters b/regamedll/msvc/ReGameDLL.vcxproj.filters
index 7f1692dd5..34d6ead93 100644
--- a/regamedll/msvc/ReGameDLL.vcxproj.filters
+++ b/regamedll/msvc/ReGameDLL.vcxproj.filters
@@ -540,6 +540,9 @@
dlls\API
+
+ dlls\API
+
regamedll
@@ -1046,6 +1049,9 @@
public\regamedll\API
+
+ public
+
dlls\addons
diff --git a/regamedll/pm_shared/pm_shared.cpp b/regamedll/pm_shared/pm_shared.cpp
index 75d4a4909..c452e406d 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];
@@ -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
@@ -3218,6 +3275,10 @@ void EXT_FUNC __API_HOOK(PM_Move)(struct playermove_s *ppmove, int server)
assert(pm_shared_initialized);
pmove = ppmove;
+
+#ifdef REGAMEDLL_API
+ pmoveplayer = UTIL_PlayerByIndex(pmove->player_index + 1)->CSPlayer();
+#endif
PM_PlayerMove((server != 0) ? TRUE : FALSE);
@@ -3252,7 +3313,7 @@ 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)
{
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/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 16150a56c..476b20013 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,21 @@ class CCSPlayer: public CCSMonster {
m_bAutoBunnyHopping(false),
m_bMegaBunnyJumping(false),
m_bPlantC4Anywhere(false),
- m_bSpawnProtectionEffects(false)
+ m_bSpawnProtectionEffects(false),
+ m_flJumpHeight(0),
+ m_flLongJumpHeight(0),
+ m_flLongJumpForce(0),
+ m_flDuckSpeedMultiplier(0),
+ m_iUserID(-1)
{
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 +75,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);
@@ -104,10 +117,15 @@ class CCSPlayer: public CCSMonster {
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 ResetVars();
+ void ResetAllStats();
void OnSpawn();
void OnKilled();
+ void OnConnect();
CBasePlayer *BasePlayer() const;
@@ -136,6 +154,24 @@ class CCSPlayer: public CCSMonster {
bool m_bMegaBunnyJumping;
bool m_bPlantC4Anywhere;
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
};
// Inlines
@@ -157,3 +193,20 @@ 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;
+}
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 493736ca2..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 22
+#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;
@@ -524,6 +524,106 @@ typedef IHookChainRegistryClass IReGameHookRegistry_CBa
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() {}
@@ -659,6 +759,32 @@ class IReGameHookchains {
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 {
@@ -679,6 +805,12 @@ struct ReGameFuncs_t {
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/utlarray.h b/regamedll/public/utlarray.h
new file mode 100644
index 000000000..6bdb4136c
--- /dev/null
+++ b/regamedll/public/utlarray.h
@@ -0,0 +1,235 @@
+/*
+*
+* 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"
+
+#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;
+
+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)
+{
+ Assert(IsValidIndex(i));
+ return m_Memory[i];
+}
+
+template
+inline const T &CUtlArray::operator[](int i) const
+{
+ Assert(IsValidIndex(i));
+ return m_Memory[i];
+}
+
+template
+inline T &CUtlArray::Element(int i)
+{
+ Assert(IsValidIndex(i));
+ return m_Memory[i];
+}
+
+template
+inline const T &CUtlArray::Element(int i) const
+{
+ Assert(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;
+}
+
+template
+void CUtlArray::CopyArray(const T *pArray, size_t count)
+{
+ Assert(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/version/version.h b/regamedll/version/version.h
index b65ba1ab2..0f32ed96e 100644
--- a/regamedll/version/version.h
+++ b/regamedll/version/version.h
@@ -6,5 +6,5 @@
#pragma once
#define VERSION_MAJOR 5
-#define VERSION_MINOR 22
+#define VERSION_MINOR 26
#define VERSION_MAINTENANCE 0