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