diff --git a/DEVELOP.md b/DEVELOP.md index 7737da9..f80f87d 100644 --- a/DEVELOP.md +++ b/DEVELOP.md @@ -15,7 +15,7 @@ Requirements * Source SDK 2013 - https://github.com/ValveSoftware/source-sdk-2013 * Metamod:Source - https://github.com/alliedmodders/metamod-source * MinHook - https://github.com/TsudaKageyu/minhook -* JsonCpp - https://github.com/open-source-parsers/jsoncpp +* RapidJSON - https://github.com/miloyip/rapidjson Setup ----- @@ -25,7 +25,7 @@ Setup 4. Adjust the `MMSOURCE_DEV` macro in `statusspec.vpc` to the path of the Metamod:Source repository on disk. 5. Adjust the `MINHOOK` macro in `statusspec.vpc` to the path of MinHook repository on disk. 6. Adjust the `MINHOOK_BUILD` macro in `statusspec.vpc` to the path of the Visual Studio project directory you used to build MinHook in step #2. -7. Adjust the `JSONCPP` macro in `statusspec.vpc` to the path of the directory containing the generated JsonCpp files from step #3 (usually the `dist` directory in the JsonCpp repository). +7. Adjust the `RAPIDJSON` macro in `statusspec.vpc` to the path of the RapidJSON include directory (usually the `include` directory in the JsonCpp repository). 8. Add the contents of this repository's `build_tools/project.vgc` to `mp/src/vpc_scripts/projects.vgc` within the Source SDK 2013 repository. 9. Copy this repository's `build_tools/createstatusspec.bat` or `build_tools/createstatusspec` (depending on platform) to `mp/src` within the Source SDK 2013 repository. -10. Run the script file you copied in the previous step to generate platform-appropriate project files. \ No newline at end of file +10. Run the script file you copied in the previous step to generate platform-appropriate project files. diff --git a/README.md b/README.md index 2da7db7..f6ae506 100644 --- a/README.md +++ b/README.md @@ -3,25 +3,94 @@ StatusSpec a Team Fortress 2 client plugin that augments game spectating -![screenshot](http://i.imgur.com/HliUKLk.png) - Changelog --------- -**0.24.0** +### 0.25.0 +* general + * increased reliability + * optimized performance and size +* antifreeze + * optimized module + * removed timer functionality + * moved freeze info to separate module +* camera auto switch + * created new module + * added ability to automatically switch to killer on death (with configurable delay) +* camera smooths + * created new module + * added ability to automatically smooth transitions between camera views +* camera state + * created new module + * optimized camera state updates + * fixed issues with switching camera state * camera tools - * add command to spectate a player by index - * add exposure of SourceTV camera information + * added ability to force camera mode and target + * moved camera state into separate module +* console tools + * created new module + * added ability to change CVar flags + * added ability to filter console by regular expressions +* custom materials + * added reload settings command +* custom models + * added reload settings command +* custom textures + * added reload settings command +* FOV override + * optimized and generalized module +* freeze info + * created new module +* killstreaks + * optimized module +* loadout icons + * removed module +* local player + * optimized module +* medigun info + * optimized performance + * add support for multiple mediguns per team + * add direct support for dynamically switching HUD appearance + * revamped required HUD files + * removed redundant CVars + * removed advantage calculations + * removed custom animations +* player aliases + * removed API-based (ESEA/ETF2L/Twitch) aliases +* player models + * documented previously added reload settings command +* player outlines + * removed module +* projectile outlines + * optimized module + * fix color commands + * fix grenades and stickybombs not being highlighted +* spec GUI order + * removed module +* status icons + * removed module +* Steam tools + * created new module + * added ability to set rich presence +* team health comparison + * optimized performance +* team overrides + * removed module + +### 0.24.0 * general * fix issues with invalid models * fix compatibility with Source SDK * increase performance with exceptions +* camera tools + * add command to spectate a player by index + * add exposure of SourceTV camera information -**0.23.1** +### 0.23.1 * player aliases * fix infinite recursion -**0.23.0** +### 0.23.0 * general * major modularization - modules check dependencies and fail separately * revamp support structures @@ -31,25 +100,25 @@ Changelog * loadout icons * fixed recent issues -**0.22.3** +### 0.22.3 * general * fix issues with multiple detours causing crashes -**0.22.2** +### 0.22.2 * player models * add functionality to replace ragdolls -**0.22.1** +### 0.22.1 * antifreeze * added feature to fix timer freezes -**0.22.0** +### 0.22.0 * general * fixed issues with outlines (hopefully) * custom models * new module -**0.21.0** +### 0.21.0 * general * optimized plugin * camera tools @@ -65,7 +134,7 @@ Changelog * team health comparison * new module -**0.20.1** +### 0.20.1 * general * fix crashing due to invalid entities * camera tools @@ -73,7 +142,7 @@ Changelog * spec GUI order * fix gaps in between players -**0.20.0** +### 0.20.0 * camera tools * new module * FOV override @@ -86,11 +155,11 @@ Changelog * spec GUI order * added reverse ordering of players -**0.19.2** +### 0.19.2 * general * fixed crashes -**0.19.1** +### 0.19.1 * custom materials * removed module * custom textures @@ -98,7 +167,7 @@ Changelog * spec GUI order * new module -**0.19.0** +### 0.19.0 * custom materials * new module * player aliases @@ -114,7 +183,7 @@ Changelog * team overrides * new module -**0.18.0** +### 0.18.0 * general * added plugin glow system * fix issues caused by the 2014-09-10 update @@ -124,29 +193,29 @@ Changelog * projectile outlines * new module -**0.17.4** +### 0.17.4 * general * adjust paint method hooking so that we can draw at the correct location -**0.17.3** +### 0.17.3 * general * update offsets for 2014-07-30 update -**0.17.2** +### 0.17.2 * general * updated version of MinHook and changed build procedures -**0.17.1** +### 0.17.1 * medigun info * fix issues with charge advantage info (thanks Bluee/MattMcNam) * player aliases * add Twitch API support -**0.17.0** +### 0.17.0 * player aliases * add ETF2L API support -**0.16.0** +### 0.16.0 * loadout icons * add ability to only show the active weapon * local player @@ -156,7 +225,7 @@ Changelog * change how progress bars are set (requires changes to MedigunInfo.res) * add ability to have custom meter settings based on medigun type -**0.15.0** +### 0.15.0 * antifreeze * now supports displaying a message when a freeze is occurring * killstreaks @@ -170,119 +239,110 @@ Changelog * make player outline calculations more efficient * add option to disable health-based calculations -**0.14.1** +### 0.14.1 * fix glitches with killstreaks on death * add command to help stop flickering issues with player outlines -**0.14.0** +### 0.14.0 * add killstreaks module -**0.13.1** +### 0.13.1 * fix bleed icons not showing up -**0.13.0** +### 0.13.0 * add support for health-based team colored outlines -**0.12.1** +### 0.12.1 * fix medigun info not disappearing properly * make unloading/pausing/unpausing cleaner and hopefully less error-prone -**0.12.0** +### 0.12.0 * add support for HUD features required for casting HUDs * add ability to set progress direction via resource file and removed command * add setting to allow Vaccinator to have only one charge meter * add ability to view medigun charge advantage * fix issues with medigun finding -**0.11.3** +### 0.11.3 * fix issues with player outlines not changing color after reloads -**0.11.2** +### 0.11.2 * fix player outline issues with players not being hooked/unhooked properly -**0.11.1** +### 0.11.1 * update offsets for TF2 update on 2014-06-11 -**0.11.0** +### 0.11.0 * reorganize entire plugin into modules (changing many console variables and commands) * add player outlines module -**0.10.0** +### 0.10.0 * fix player alias incompatibility with Spec Tools * add utility command for setting the direction of a progress bar -**0.9.0** +### 0.9.0 * implement medigun info box -**0.8.0** +### 0.8.0 * implement player aliasing -**0.7.0** +### 0.7.0 * implement loadout icons -**0.6.0** +### 0.6.0 * implement status icons as part of spectator GUI -**0.5.0** +### 0.5.0 * added option to force refreshing of spectator GUI (partially to fully fixes post-pause issues, YMMV) -**0.4.0** +### 0.4.0 * added option (enabled by default) to have icon backgrounds adjust with icons rather than be static -**0.3.0** +### 0.3.0 * scale HUD positioning values automatically -**0.2.0** +### 0.2.0 * added Vaccinator resistances/Ubers, Soldier banners, Jarate, Mad Milk, bleeding, and on fire icons to display -**0.1.0** +### 0.1.0 * initial version * Uber, Kritz, marked for death status icons * many CVars for customizing appearance Usage ----- -To install, place the `StatusSpec` folder within the `custom` folder in the `tf` directory. Because this plugin is not signed by Valve, you must launch TF2 with the `-insecure` option in order for this plugin to be active and will not be able to use this plugin on VAC-secured servers. +To install, place the `StatusSpec` folder within the `custom` folder in the `tf` directory. Because this plugin is not signed by Valve, you will not be able to use this plugin on VAC-secured servers and must launch TF2 with the `-insecure` option in order for this plugin to be active. ### AntiFreeze *forces spectator GUI to refresh constantly, eliminating many HUD issues after game unpauses* #### Console Variables -* `statusspec_antifreeze_display` - enables display of an info panel when a freeze is detected -* `statusspec_antifreeze_display_threshold` - the time of a freeze (in seconds) before the info panel is displayed * `statusspec_antifreeze_enabled` - enable antifreeze (forces the spectator GUI to refresh) -* `statusspec_antifreeze_timers` - enable forcing of timers to right values -#### Console Commands -* `statusspec_antifreeze_display_reload_settings` - reload settings for the freeze info panel from the resource file +### Camera Auto Switch +*automatically switches the camera based on game events* -#### UI Resource Files -The configuration file for the freeze info HUD is `Resource/UI/FreezeInfo.res`. This HUD cannot be refreshed using the normal `hud_reloadscheme` because it isn't natively implemented into TF2, and thus the command `statusspec_antifreeze_display_reload_settings` is provided as a replacement. +#### Console Variables +* `statusspec_cameraautoswitch_enabled` - enable automatic switching of camera +* `statusspec_cameraautoswitch_killer` - switch to killer upon spectated player death +* `statusspec_cameraautoswitch_killer_delay` - delay before switching to killer -To properly support forced correct timer values, you will also have to adjust `Resource/UI/HudObjectiveTimePanel.res` so that it includes something similar to the `RealTime` section, as demonstrated below. -``` -"Resource/UI/HudObjectiveTimePanel.res" -{ - ... - - "RealTime" - { - "ControlName" "CExLabel" - "fieldName" "RealTime" - "font" "NotoBold22" - "fgcolor" "220 220 220 255" - "xpos" "0" - "ypos" "0" - "zpos" "3" - "wide" "110" - "tall" "19" - "visible" "0" - "enabled" "0" - "textAlignment" "center" - "labelText" "" - } -} -``` +### Camera Smooths +*smooth transitions between camera positions* + +#### Console Variables +* `statusspec_camerasmooths_enabled` - enable smooth transition between camera positions +* `statusspec_camerasmooths_max_angle_difference` - max angle difference at which smoothing will be performed +* `statusspec_camerasmooths_max_distance` - max distance at which smoothing will be performed +* `statusspec_camerasmooths_move_speed` - speed to move view per second + +### Camera State +*exposes the current SourceTV camera state* + +#### Console Variables +* `statusspec_camerastate_change` - JSON to change camera state to +* `statusspec_camerastate_current` - JSON of current camera state +* `statusspec_camerastate_enabled` - enable exposure of camera state ### Camera Tools *allows more options for managing the camera* @@ -290,21 +350,37 @@ To properly support forced correct timer values, you will also have to adjust `R #### Console Commands * `statusspec_cameratools_spec_player ` - spec a certain player by player index * `statusspec_cameratools_spec_player ` - spec a certain player by position on spectator HUD -* `statusspec_cameratools_spec_player_alive` - prevent speccing dead players * `statusspec_cameratools_spec_pos ` - spec a certain camera position -* `statusspec_cameratools_state` - JSON of camera tools state -* `statusspec_cameratools_state_enabled` - enable exposure of camera tools state -### Custom Materials -*allows materials to be swapped out* +#### Console Variables +* `statusspec_cameratools_force_mode` - if a valid mode, force the camera mode to this +* `statusspec_cameratools_force_target` - if a valid target, force the camera target to this +* `statusspec_cameratools_force_valid_target` - forces the camera to only have valid targets +* `statusspec_cameratools_spec_player_alive` - prevent speccing dead players + +### Console Tools +*allows more options for managing the console* + +#### Console Commands +* `statusspec_consoletools_filter_add ` - add a console filter +* `statusspec_consoletools_filter_remove ` - remove a console filter +* `statusspec_consoletools_flags_add [flag2 ...]` - add a flag to a console command or variable +* `statusspec_consoletools_flags_remove [flag2 ...]` - remove a flag from a console command or variable #### Console Variables -* `statusspec_custommaterials_enabled` - enable custom materials +* `statusspec_consoletools_filter_enabled` - enable console filtering + +### Custom Materials +*allows materials to be swapped out* #### Console Commands * `statusspec_custommaterials_load_replacement_group ` - load a material replacement group +* `statusspec_custommaterials_reload_settings` - reload settings for the custom materials from the resource file * `statusspec_custommaterials_unload_replacement_group ` - unload a material replacement group +#### Console Variables +* `statusspec_custommaterials_enabled` - enable custom materials + #### Resource Files Custom material configuration is loaded from the `Resource/CustomMaterials.res` file. Replacement groups should be configured as sections (whose names are used in the commands for this module). Material replacements should be specified by entries with the path of the old material from the `materials` folder as the key and the path of the new material from the `materials` folder as the value. An example of a configured file is given below: ``` @@ -321,13 +397,14 @@ Custom material configuration is loaded from the `Resource/CustomMaterials.res` ### Custom Models *allows models to be swapped out* -#### Console Variables -* `statusspec_custommodels_enabled` - enable custom models - #### Console Commands * `statusspec_custommodels_load_replacement_group ` - load a model replacement group +* `statusspec_custommodels_reload_settings` - reload settings for the custom models from the resource file * `statusspec_custommodels_unload_replacement_group ` - unload a model replacement group +#### Console Variables +* `statusspec_custommodels_enabled` - enable custom models + #### Resource Files Custom model configuration is loaded from the `Resource/CustomModels.res` file. Replacement groups should be configured as sections (whose names are used in the commands for this module). Material replacements should be specified by entries with the path of the old model as the key and the path of the new model as the value. An example of a configured file is given below: @@ -352,13 +429,14 @@ Custom model configuration is loaded from the `Resource/CustomModels.res` file. ### Custom Textures *allows textures to be swapped out* -#### Console Variables -* `statusspec_customtextures_enabled` - enable custom textures - #### Console Commands * `statusspec_customtextures_load_replacement_group ` - load a texture replacement group +* `statusspec_customtextures_reload_settings` - reload settings for the custom textures from the resource file * `statusspec_customtextures_unload_replacement_group ` - unload a texture replacement group +#### Console Variables +* `statusspec_customtextures_enabled` - enable custom textures + #### Resource Files Custom texture configuration is loaded from the `Resource/CustomTextures.res` file. Replacement groups should be configured as sections (whose names are used in the commands for this module). Texture replacements should be specified by entries with the path of the old texture from the `materials` folder as the key and the path of the new texture from the `materials` folder as the value. An example of a configured file is given below: ``` @@ -380,88 +458,75 @@ Custom texture configuration is loaded from the `Resource/CustomTextures.res` fi * `statusspec_fovoverride_fov` - the FOV value used * `statusspec_fovoverride_zoomed` - enable FOV override even when sniper rifle is zoomed -### Killstreaks -*enables killstreak tracking for all weapons, all players* +### Freeze Info +*displays info when the game is frozen* -#### Console Variables -* `statusspec_killstreaks_enabled` - enable killstreaks display -* `statusspec_killstreaks_total_killfeed` - display total kills for player in killfeed instead of only kills with single weapon - -### Loadout Icons -*displays icons to represent weapons in a player's loadout* +#### Console Commands +* `statusspec_freezeinfo_reload_settings` - reload settings for the freeze info panel from the resource file #### Console Variables -* `statusspec_loadouticons_enabled` - enable loadout icons -* `statusspec_loadouticons_nonloadout` - enable loadout icons for nonloadout items -* `statusspec_loadouticons_only_active` - only display loadout icons for the active weapon - -#### Console Commands -* `statusspec_loadouticons_filter_active ` - the RGBA filter applied to the icon for an active item -* `statusspec_loadouticons_filter_inactive ` - the RGBA filter applied to the icon for an inactive item +* `statusspec_freezeinfo_enabled` - enables display of an info panel when a freeze is detected +* `statusspec_freezeinfo_threshold` - the time of a freeze (in seconds) before the info panel is displayed #### UI Resource Files -The configuration file for the loadout icons is `Resource/UI/LoadoutIcons.res`. To properly support loadout icons, you will also have to adjust `Resource/UI/SpectatorTournament.res` so that it includes something similar to the `LoadoutIcons` section below contained within the `playerpanels_kv` section of the `specgui` section, as demonstrated below. -``` -"Resource/UI/SpectatorTournament.res" -{ - "specgui" - { - ... - - "playerpanels_kv" - { - ... - - "LoadoutIcons" - { - "ControlName" "EditablePanel" - "fieldName" "LoadoutIcons" - "xpos" "160" - "ypos" "0" - "zpos" "2" - "wide" "45" - "tall" "15" - "visible" "1" - "enabled" "1" - } - } - } - - ... -} -``` +The configuration file for the freeze info HUD is `Resource/UI/FreezeInfo.res`. This HUD cannot be refreshed using the normal `hud_reloadscheme` because it isn't natively implemented into TF2, and thus the command `statusspec_freezeinfo_reload_settings` is provided as a replacement. + +### Killstreaks +*enables killstreak tracking for all players* + +#### Console Variables +* `statusspec_killstreaks_enabled` - enable killstreaks display ### Local Player *changes the local player locally to affect certain HUD elements like the killfeed* +#### Console Commands +* `statusspec_localplayer_set_current_target` - set the local player to the current spectator target + #### Console Variables * `statusspec_localplayer_enabled` - enable local player override * `statusspec_localplayer_player` - player index to set as the local player - -#### Console Commands -* `statusspec_localplayer_set_current_target` - set the local player to the current spectator target +* `statusspec_localplayer_trac_spec_target` - have the local player value track the spectator target ### Medigun Info *displays info about mediguns for both teams* -#### Console Variables -* `statusspec_mediguninfo_dynamic_meters` - enable charge meters to change based on medigun -* `statusspec_mediguninfo_enabled` - enable medigun info -* `statusspec_mediguninfo_individual_charge_meters` - enable individual charge meters (for Vaccinator) - #### Console Commands * `statusspec_mediguninfo_reload_settings` - reload settings for the medigun info HUD from the resource file -#### UI Resource Files -The configuration file for the medigun info HUD is `Resource/UI/MedigunInfo.res`. In addition, the `Resource/UI/MedigunInfoDynamicMeters.res` file is used for the dynamic meters feature, and contains empty sections for each medigun within which you can add progress bar options that will be applied when the specified medigun is being used. This HUD cannot be refreshed using the normal `hud_reloadscheme` because it isn't natively implemented into TF2, and thus the command `statusspec_mediguninfo_reload_settings` is provided as a replacement. +#### Console Variables +* `statusspec_mediguninfo_enabled` - enable medigun info -In addition, the following HUD animations are triggered by this plugin and may be used to show events on the HUD: -* `MedigunInfoBluChargeReady` - triggered when a BLU medigun charge is ready for use -* `MedigunInfoBluChargeReleased` - triggered when a BLU medigun charge has been released/popped -* `MedigunInfoBluChargeStop` - triggered when the BLU medigun charge is no longer ready/released -* `MedigunInfoRedChargeReady` - triggered when a RED medigun charge is ready for use -* `MedigunInfoRedChargeReleased` - triggered when a RED medigun charge has been released/popped -* `MedigunInfoRedChargeStop` - triggered when the RED medigun charge is no longer ready/released (after a charge is completed/dropped) +#### UI Resource Files +The configuration files for the medigun info HUD are `Resource/UI/MedigunInfo.res`, which controls the overall layout of the panel, and `Resource/UI/MedigunPanel.res`, which controls the display of each medigun. This HUD cannot be refreshed using the normal `hud_reloadscheme` because it isn't natively implemented into TF2, and thus the command `statusspec_mediguninfo_reload_settings` is provided as a replacement. + +The medigun panel located in `Resource/UI/MedigunPanel.res` supports conditional sections. This allows the HUD to change based on certain conditions, such as the medigun type or player team, by putting relevant keys within a section named with the condition. Conditions can be stacked by placing one conditional section within another, which will only trigger the contained keys if both conditions are triggered. The following conditions are supported: +* `charges-0` - no charges are ready +* `charges-1` - one charge is ready +* `charges-2` - two charges are ready +* `charges-3` - three charges are ready +* `charges-4` - four charges are ready +* `resist-bullet` - current medigun resistance is bullet +* `resist-explosive` - current medigun resistance is explosive +* `resist-fire` - current medigun resistance is fire +* `medigun-kritzkrieg` - medigun is the Kritzkrieg +* `medigun-medigun` - medigun is the stock Medi Gun +* `medigun-quickfix` - medigun is the Quick-Fix +* `medigun-vaccinator` - medigun is the Vaccinator +* `player-alive` - player using medigun is currently alive +* `player-dead` - player using medigun is currently dead +* `status-building` - charge is being built +* `status-released` - charge is being used +* `team-blu` - player using medigun is on the BLU team +* `team-red` - player using medigun is on the RED team + +In addition, certain dialog variables will be set for each medigun panel. They are: +* `charge` - total percentage of uber filled (out of 100) +* `charges` - number of Vaccinator charges available +* `charge1` - percentage of first Vaccinator charge filled (out of 100) +* `charge2` - percentage of second Vaccinator charge filled (out of 100) +* `charge3` - percentage of third Vaccinator charge filled (out of 100) +* `charge4` - percentage of fourth Vaccinator charge filled (out of 100) ### Multipanel *displays panels on top of the main game* @@ -473,23 +538,23 @@ In addition, the following HUD animations are triggered by this plugin and may b ### Player Aliases *substitutes in user-defined aliases for player names* -#### Console Variables -* `statusspec_playeraliases_enabled` - enable player aliases -* `statusspec_playeraliases_esea` - enable player aliases from the ESEA API -* `statusspec_playeraliases_etf2l` - enable player aliases from the ETF2L API -* `statusspec_playeraliases_format_blu` - the name format for BLU players -* `statusspec_playeraliases_format_red` - the name format for RED players -* `statusspec_playeraliases_twitch` - enable player aliases from the Twitch API - #### Console Commands * `statusspec_playeraliases_get ` - get an alias for a player * `statusspec_playeraliases_remove ` - remove an alias for a player * `statusspec_playeraliases_set ` - set an alias for a player * `statusspec_playeraliases_switch_teams` - switch name formats for both teams +#### Console Variables +* `statusspec_playeraliases_enabled` - enable player aliases +* `statusspec_playeraliases_format_blu` - the name format for BLU players +* `statusspec_playeraliases_format_red` - the name format for RED players + ### Player Models *changes the model used based on the player* +#### Console Commands +* `statusspec_playermodels_reload_settings` - reload settings for the player models from the resource file + #### Console Variables * `statusspec_playermodels_enabled` - enable custom player models @@ -520,29 +585,13 @@ Player model configuration is loaded from the `Resource/PlayerModels.res` file. } ``` -### Player Outlines -*displays bright outlines around players that can be seen through walls* - -#### Console Variables -* `statusspec_playeroutlines_enabled` - enable player outlines -* `statusspec_playeroutlines_fade` - make outlines fade with distance -* `statusspec_playeroutlines_fade_distance` - the distance (in Hammer units) at which outlines will fade -* `statusspec_playeroutlines_health_adjusted_team_colors` - adjusts team colors depending on health of players -* `statusspec_playeroutlines_team_colors` - override default health-based outline colors with team colors - -#### Console Commands -* `statusspec_playeroutlines_color_blu_buff [alpha]` - the color used for outlines for BLU team players at max buffed health -* `statusspec_playeroutlines_color_blu_full [alpha]` - the color used for outlines for BLU team players at full health -* `statusspec_playeroutlines_color_blu_low [alpha]` - the color used for outlines for BLU team players at low health -* `statusspec_playeroutlines_color_blu_medium [alpha]` - the color used for outlines for BLU team players at medium health -* `statusspec_playeroutlines_color_red_buff [alpha]` - the color used for outlines for RED team players at max buffed health -* `statusspec_playeroutlines_color_red_full [alpha]` - the color used for outlines for RED team players at full health -* `statusspec_playeroutlines_color_red_low [alpha]` - the color used for outlines for RED team players at low health -* `statusspec_playeroutlines_color_red_medium [alpha]` - the color used for outlines for RED team players at medium health - ### Projectile Outlines *displays bright outlines around projectiles that can be seen through walls* +#### Console Commands +* `statusspec_projectileoutlines_color_blu [alpha]` - the color used for outlines for BLU projectiles +* `statusspec_projectileoutlines_color_red [alpha]` - the color used for outlines for RED projectiles + #### Console Variables * `statusspec_projectileoutlines_enabled` - enable projectile outlines * `statusspec_projectileoutlines_fade` - make outlines fade with distance @@ -551,89 +600,30 @@ Player model configuration is loaded from the `Resource/PlayerModels.res` file. * `statusspec_projectileoutlines_rockets` - enable outlines for rockets * `statusspec_projectileoutlines_stickybombs` - enable outlines for stickybombs -#### Console Commands -* `statusspec_projectileoutlines_color_blu [alpha]` - the color used for outlines for BLU projectiles -* `statusspec_projectileoutlines_color_red [alpha]` - the color used for outlines for RED projectiles - -### Spec GUI Order -*orders the spec GUI more logically than player indices* +### Steam Tools +*allows more options for interacting with Steam* #### Console Variables -* `statusspec_specguiorder_enabled` - enable ordering of spec GUI -* `statusspec_specguiorder_reverse_blu` - reverse order for BLU players -* `statusspec_specguiorder_reverse_red` - reverse order for RED players - -### Status Icons -*displays icons representing special statuses of a player* - -#### Console Variables -* `statusspec_statusicons_delta_x` - change in the x direction for each icon -* `statusspec_statusicons_delta_y` - change in the y direction for each icon -* `statusspec_statusicons_enabled` - enable status icons - -#### UI Resource Files -The configuration file for the status icons is `Resource/UI/StatusIcon.res`. A copy of the elements in that file will be created and configured for each icon. To properly support status icons, you will also have to adjust `Resource/UI/SpectatorTournament.res` so that it includes something similar to the `StatusIcons` section below contained within the `playerpanels_kv` section of the `specgui` section, as demonstrated below. -``` -"Resource/UI/SpectatorTournament.res" -{ - "specgui" - { - ... - - "playerpanels_kv" - { - ... - - "StatusIcons" - { - "ControlName" "EditablePanel" - "fieldName" "StatusIcons" - "xpos" "160" - "ypos" "0" - "zpos" "8" - "wide" "45" - "tall" "15" - "visible" "1" - "enabled" "1" - } - } - } - - ... -} -``` +* `statusspec_steamtools_rich_presence_status` - the rich presence status displayed to Steam ### Team Health Comparison *displays a comparison of total health between the two teams* -#### Console Variables -* `statusspec_teamhealthcomparison_enabled` - enable team health comparison - #### Console Commands * `statusspec_teamhealthcomparison_reload_settings` - reload settings for the team health comparison HUD from the resource file -#### UI Resource Files -The configuration file for the team health comparison HUD is `Resource/UI/TeamHealthComparison.res`. This HUD cannot be refreshed using the normal `hud_reloadscheme` because it isn't natively implemented into TF2, and thus the command `statusspec_teamhealthcomparison_reload_settings` is provided as a replacement. - -### Team Overrides -*override team info in HUD* - #### Console Variables -* `statusspec_teamoverrides_enabled` - enable team overrides -* `statusspec_teamoverrides_name_blu` - BLU team name -* `statusspec_teamoverrides_name_red` - RED team name -* `statusspec_teamoverrides_names` - enable overrides for team names -* `statusspec_teamoverrides_score_blu` - BLU team score -* `statusspec_teamoverrides_score_red` - RED team score -* `statusspec_teamoverrides_scores` - enable overrides for team scores +* `statusspec_teamhealthcomparison_enabled` - enable team health comparison -#### Console Commands -* `statusspec_teamoverrides_switch_teams` - switch names and scores for both teams +#### UI Resource Files +The configuration file for the team health comparison HUD is `Resource/UI/TeamHealthComparison.res`. This HUD cannot be refreshed using the normal `hud_reloadscheme` because it isn't natively implemented into TF2, and thus the command `statusspec_teamhealthcomparison_reload_settings` is provided as a replacement. Thanks ------ -**bluee (MattMcNam)** - for the inspiration to do this project and for a lot of code reused from his [AdvSpec project](https://github.com/MattMcNam/advspec) +**Matt McNamara** - for the inspiration to do this project and for a lot of code reused from his [AdvSpec project](https://github.com/MattMcNam/advspec) **AlliedModders** - for in-depth information about the internals of the Source Engine and for [SourceHook](https://github.com/alliedmodders/metamod-source/tree/master/core/sourcehook) -**Tsuda Kageyu and other contributors** - for [MinHook](https://github.com/TsudaKageyu/minhook) \ No newline at end of file +**Tsuda Kageyu and other contributors** - for [MinHook](https://github.com/TsudaKageyu/minhook) + +**Milo Yip and other contributors** - for [RapidJSON](https://github.com/miloyip/rapidjson) diff --git a/materials/vgui/replay/thumbnails/critboost.vmt b/materials/vgui/replay/thumbnails/critboost.vmt deleted file mode 100644 index 050acf5..0000000 --- a/materials/vgui/replay/thumbnails/critboost.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"UnlitGeneric" -{ - "$basetexture" "vgui/replay/thumbnails/critboost" - "$translucent" 1 - "$ignorez" 1 - "$vertexcolor" 1 -} diff --git a/materials/vgui/replay/thumbnails/critboost.vtf b/materials/vgui/replay/thumbnails/critboost.vtf deleted file mode 100644 index 6bc9db2..0000000 Binary files a/materials/vgui/replay/thumbnails/critboost.vtf and /dev/null differ diff --git a/materials/vgui/replay/thumbnails/defense_buff_bullet_blue.vmt b/materials/vgui/replay/thumbnails/defense_buff_bullet_blue.vmt deleted file mode 100644 index cf58af5..0000000 --- a/materials/vgui/replay/thumbnails/defense_buff_bullet_blue.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"UnlitGeneric" -{ - "$basetexture" "vgui/replay/thumbnails/defense_buff_bullet_blue" - "$translucent" 1 - "$ignorez" 1 - "$vertexcolor" 1 -} \ No newline at end of file diff --git a/materials/vgui/replay/thumbnails/defense_buff_bullet_blue.vtf b/materials/vgui/replay/thumbnails/defense_buff_bullet_blue.vtf deleted file mode 100644 index 46e6810..0000000 Binary files a/materials/vgui/replay/thumbnails/defense_buff_bullet_blue.vtf and /dev/null differ diff --git a/materials/vgui/replay/thumbnails/defense_buff_bullet_red.vmt b/materials/vgui/replay/thumbnails/defense_buff_bullet_red.vmt deleted file mode 100644 index bd86e6e..0000000 --- a/materials/vgui/replay/thumbnails/defense_buff_bullet_red.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"UnlitGeneric" -{ - "$basetexture" "vgui/replay/thumbnails/defense_buff_bullet_red" - "$translucent" 1 - "$ignorez" 1 - "$vertexcolor" 1 -} \ No newline at end of file diff --git a/materials/vgui/replay/thumbnails/defense_buff_bullet_red.vtf b/materials/vgui/replay/thumbnails/defense_buff_bullet_red.vtf deleted file mode 100644 index b9991c0..0000000 Binary files a/materials/vgui/replay/thumbnails/defense_buff_bullet_red.vtf and /dev/null differ diff --git a/materials/vgui/replay/thumbnails/defense_buff_explosion_blue.vmt b/materials/vgui/replay/thumbnails/defense_buff_explosion_blue.vmt deleted file mode 100644 index e27a5ce..0000000 --- a/materials/vgui/replay/thumbnails/defense_buff_explosion_blue.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"UnlitGeneric" -{ - "$basetexture" "vgui/replay/thumbnails/defense_buff_explosion_blue" - "$translucent" 1 - "$ignorez" 1 - "$vertexcolor" 1 -} \ No newline at end of file diff --git a/materials/vgui/replay/thumbnails/defense_buff_explosion_blue.vtf b/materials/vgui/replay/thumbnails/defense_buff_explosion_blue.vtf deleted file mode 100644 index 39e8232..0000000 Binary files a/materials/vgui/replay/thumbnails/defense_buff_explosion_blue.vtf and /dev/null differ diff --git a/materials/vgui/replay/thumbnails/defense_buff_explosion_red.vmt b/materials/vgui/replay/thumbnails/defense_buff_explosion_red.vmt deleted file mode 100644 index 5d790f5..0000000 --- a/materials/vgui/replay/thumbnails/defense_buff_explosion_red.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"UnlitGeneric" -{ - "$basetexture" "vgui/replay/thumbnails/defense_buff_explosion_red" - "$translucent" 1 - "$ignorez" 1 - "$vertexcolor" 1 -} \ No newline at end of file diff --git a/materials/vgui/replay/thumbnails/defense_buff_explosion_red.vtf b/materials/vgui/replay/thumbnails/defense_buff_explosion_red.vtf deleted file mode 100644 index 16cb6d7..0000000 Binary files a/materials/vgui/replay/thumbnails/defense_buff_explosion_red.vtf and /dev/null differ diff --git a/materials/vgui/replay/thumbnails/defense_buff_fire_blue.vmt b/materials/vgui/replay/thumbnails/defense_buff_fire_blue.vmt deleted file mode 100644 index 636f230..0000000 --- a/materials/vgui/replay/thumbnails/defense_buff_fire_blue.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"UnlitGeneric" -{ - "$basetexture" "vgui/replay/thumbnails/defense_buff_fire_blue" - "$translucent" 1 - "$ignorez" 1 - "$vertexcolor" 1 -} \ No newline at end of file diff --git a/materials/vgui/replay/thumbnails/defense_buff_fire_blue.vtf b/materials/vgui/replay/thumbnails/defense_buff_fire_blue.vtf deleted file mode 100644 index 5f1103f..0000000 Binary files a/materials/vgui/replay/thumbnails/defense_buff_fire_blue.vtf and /dev/null differ diff --git a/materials/vgui/replay/thumbnails/defense_buff_fire_red.vmt b/materials/vgui/replay/thumbnails/defense_buff_fire_red.vmt deleted file mode 100644 index 83b2a39..0000000 --- a/materials/vgui/replay/thumbnails/defense_buff_fire_red.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"UnlitGeneric" -{ - "$basetexture" "vgui/replay/thumbnails/defense_buff_fire_red" - "$translucent" 1 - "$ignorez" 1 - "$vertexcolor" 1 -} \ No newline at end of file diff --git a/materials/vgui/replay/thumbnails/defense_buff_fire_red.vtf b/materials/vgui/replay/thumbnails/defense_buff_fire_red.vtf deleted file mode 100644 index fd5f0fd..0000000 Binary files a/materials/vgui/replay/thumbnails/defense_buff_fire_red.vtf and /dev/null differ diff --git a/materials/vgui/replay/thumbnails/jarated.vmt b/materials/vgui/replay/thumbnails/jarated.vmt deleted file mode 100644 index 2d4ce9c..0000000 --- a/materials/vgui/replay/thumbnails/jarated.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"UnlitGeneric" -{ - "$basetexture" "vgui/replay/thumbnails/jarated" - "$translucent" 1 - "$ignorez" 1 - "$vertexcolor" 1 -} \ No newline at end of file diff --git a/materials/vgui/replay/thumbnails/jarated.vtf b/materials/vgui/replay/thumbnails/jarated.vtf deleted file mode 100644 index 8d1b77d..0000000 Binary files a/materials/vgui/replay/thumbnails/jarated.vtf and /dev/null differ diff --git a/materials/vgui/replay/thumbnails/megaheal_blue.vmt b/materials/vgui/replay/thumbnails/megaheal_blue.vmt deleted file mode 100644 index 9f9f5c6..0000000 --- a/materials/vgui/replay/thumbnails/megaheal_blue.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"UnlitGeneric" -{ - "$basetexture" "vgui/replay/thumbnails/megaheal_blue" - "$translucent" 1 - "$ignorez" 1 - "$vertexcolor" 1 -} diff --git a/materials/vgui/replay/thumbnails/megaheal_blue.vtf b/materials/vgui/replay/thumbnails/megaheal_blue.vtf deleted file mode 100644 index 74fd9b0..0000000 Binary files a/materials/vgui/replay/thumbnails/megaheal_blue.vtf and /dev/null differ diff --git a/materials/vgui/replay/thumbnails/megaheal_red.vmt b/materials/vgui/replay/thumbnails/megaheal_red.vmt deleted file mode 100644 index b9895ab..0000000 --- a/materials/vgui/replay/thumbnails/megaheal_red.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"UnlitGeneric" -{ - "$basetexture" "vgui/replay/thumbnails/megaheal_red" - "$translucent" 1 - "$ignorez" 1 - "$vertexcolor" 1 -} diff --git a/materials/vgui/replay/thumbnails/megaheal_red.vtf b/materials/vgui/replay/thumbnails/megaheal_red.vtf deleted file mode 100644 index 6f64b1a..0000000 Binary files a/materials/vgui/replay/thumbnails/megaheal_red.vtf and /dev/null differ diff --git a/materials/vgui/replay/thumbnails/null.vmt b/materials/vgui/replay/thumbnails/null.vmt deleted file mode 100644 index 0283f65..0000000 --- a/materials/vgui/replay/thumbnails/null.vmt +++ /dev/null @@ -1,6 +0,0 @@ -"UnlitGeneric" -{ - "$baseTexture" "dev/null" - $translucent 1 - $vertexcolor 1 -} \ No newline at end of file diff --git a/materials/vgui/replay/thumbnails/resist_shield.vmt b/materials/vgui/replay/thumbnails/resist_shield.vmt deleted file mode 100644 index 5db6c32..0000000 --- a/materials/vgui/replay/thumbnails/resist_shield.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"UnlitGeneric" -{ - "$basetexture" "vgui/replay/thumbnails/resist_shield" - "$translucent" 1 - "$ignorez" 1 - "$vertexcolor" 1 -} \ No newline at end of file diff --git a/materials/vgui/replay/thumbnails/resist_shield.vtf b/materials/vgui/replay/thumbnails/resist_shield.vtf deleted file mode 100644 index c210c84..0000000 Binary files a/materials/vgui/replay/thumbnails/resist_shield.vtf and /dev/null differ diff --git a/materials/vgui/replay/thumbnails/resist_shield_blue.vmt b/materials/vgui/replay/thumbnails/resist_shield_blue.vmt deleted file mode 100644 index 3392ce5..0000000 --- a/materials/vgui/replay/thumbnails/resist_shield_blue.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"UnlitGeneric" -{ - "$basetexture" "vgui/replay/thumbnails/resist_shield_blue" - "$translucent" 1 - "$ignorez" 1 - "$vertexcolor" 1 -} \ No newline at end of file diff --git a/materials/vgui/replay/thumbnails/resist_shield_blue.vtf b/materials/vgui/replay/thumbnails/resist_shield_blue.vtf deleted file mode 100644 index 81aaa8d..0000000 Binary files a/materials/vgui/replay/thumbnails/resist_shield_blue.vtf and /dev/null differ diff --git a/materials/vgui/replay/thumbnails/ubercharge.vmt b/materials/vgui/replay/thumbnails/ubercharge.vmt deleted file mode 100644 index 6ce26af..0000000 --- a/materials/vgui/replay/thumbnails/ubercharge.vmt +++ /dev/null @@ -1,7 +0,0 @@ -"UnlitGeneric" -{ - "$basetexture" "vgui/replay/thumbnails/ubercharge" - "$translucent" 1 - "$ignorez" 1 - "$vertexcolor" 1 -} diff --git a/materials/vgui/replay/thumbnails/ubercharge.vtf b/materials/vgui/replay/thumbnails/ubercharge.vtf deleted file mode 100644 index 41defba..0000000 Binary files a/materials/vgui/replay/thumbnails/ubercharge.vtf and /dev/null differ diff --git a/resource/ui/freezeinfo.res b/resource/ui/freezeinfo.res index fce3172..601fa4e 100644 --- a/resource/ui/freezeinfo.res +++ b/resource/ui/freezeinfo.res @@ -28,7 +28,7 @@ "pinCorner" "0" "visible" "1" "enabled" "1" - "fillcolor" "NotoDark" + "fillcolor" "HudBlack" } "FreezeInfoIcon" @@ -48,7 +48,7 @@ "FreezeInfoLabel" { "ControlName" "VariableLabel" - "fieldName" "MedigunInfoRedNameLabel" + "fieldName" "FreezeInfoLabel" "xpos" "32" "ypos" "0" "wide" "128" @@ -61,7 +61,7 @@ "textAlignment" "center" "dulltext" "0" "brighttext" "0" - "font" "Noto16" - "fgcolor" "NotoWhite" + "font" "HudFontMediumSmallSecondary" + "fgcolor" "HudWhite" } } \ No newline at end of file diff --git a/resource/ui/loadouticons.res b/resource/ui/loadouticons.res deleted file mode 100644 index f1d9707..0000000 --- a/resource/ui/loadouticons.res +++ /dev/null @@ -1,105 +0,0 @@ -"Resource/UI/LoadoutIcons.res" -{ - "LoadoutIcons" - { - "ControlName" "EditablePanel" - "fieldName" "LoadoutIcons" - "xpos" "160" - "ypos" "0" - "zpos" "2" - "wide" "45" - "tall" "15" - "visible" "1" - "enabled" "1" - } - "LoadoutIconsBackground" - { - "ControlName" "ImagePanel" - "fieldName" "LoadoutIconsBackground" - "xpos" "0" - "ypos" "0" - "zpos" "0" - "wide" "0" - "tall" "0" - "visible" "0" - "enabled" "0" - } - "LoadoutIconsItem1" - { - "ControlName" "ImagePanel" - "fieldName" "LoadoutIconsItem1" - "xpos" "0" - "ypos" "0" - "zpos" "2" - "wide" "15" - "tall" "15" - "visible" "1" - "enabled" "1" - "scaleImage" "1" - } - "LoadoutIconsItem2" - { - "ControlName" "ImagePanel" - "fieldName" "LoadoutIconsItem2" - "xpos" "15" - "ypos" "0" - "zpos" "2" - "wide" "15" - "tall" "15" - "visible" "1" - "enabled" "1" - "scaleImage" "1" - } - "LoadoutIconsItem3" - { - "ControlName" "ImagePanel" - "fieldName" "LoadoutIconsItem3" - "xpos" "30" - "ypos" "0" - "zpos" "2" - "wide" "15" - "tall" "15" - "visible" "1" - "enabled" "1" - "scaleImage" "1" - } - "LoadoutIconsItem4" - { - "ControlName" "ImagePanel" - "fieldName" "LoadoutIconsItem4" - "xpos" "45" - "ypos" "0" - "zpos" "2" - "wide" "15" - "tall" "15" - "visible" "1" - "enabled" "1" - "scaleImage" "1" - } - "LoadoutIconsItem5" - { - "ControlName" "ImagePanel" - "fieldName" "LoadoutIconsItem5" - "xpos" "60" - "ypos" "0" - "zpos" "2" - "wide" "15" - "tall" "15" - "visible" "1" - "enabled" "1" - "scaleImage" "1" - } - "LoadoutIconsItem6" - { - "ControlName" "ImagePanel" - "fieldName" "LoadoutIconsItem6" - "xpos" "75" - "ypos" "0" - "zpos" "2" - "wide" "15" - "tall" "15" - "visible" "1" - "enabled" "1" - "scaleImage" "1" - } -} \ No newline at end of file diff --git a/resource/ui/mediguninfo.res b/resource/ui/mediguninfo.res index 73354da..a8a0800 100644 --- a/resource/ui/mediguninfo.res +++ b/resource/ui/mediguninfo.res @@ -7,485 +7,20 @@ "xpos" "0" "ypos" "0" "wide" "164" - "tall" "38" + "tall" "480" "autoResize" "0" "pinCorner" "0" "visible" "1" "enabled" "1" "tabPosition" "0" - } - - "MedigunInfoBackground" - { - "ControlName" "ImagePanel" - "fieldName" "MedigunInfoBackground" - "xpos" "0" - "ypos" "0" - "zpos" "0" - "wide" "164" - "tall" "38" - "autoResize" "0" - "pinCorner" "0" - "visible" "1" - "enabled" "1" - "fillcolor" "TransparentBlack" - } - - "MedigunInfoRedBackground" - { - "ControlName" "ScalableImagePanel" - "fieldName" "MedigunInfoRedBackground" - "xpos" "2" - "ypos" "20" - "zpos" "1" - "wide" "160" - "tall" "16" - "autoResize" "0" - "pinCorner" "0" - "visible" "1" - "enabled" "1" - "drawcolor" "HUDRedTeam" - } - - "MedigunInfoRedNameLabel" - { - "ControlName" "VariableLabel" - "fieldName" "MedigunInfoRedNameLabel" - "xpos" "165" - "ypos" "21" - "zpos" "2" - "wide" "200" - "tall" "14" - "autoResize" "1" - "visible" "0" - "enabled" "0" - "labelText" "%redname%" - "tabPosition" "0" - "textAlignment" "left" - "dulltext" "0" - "brighttext" "0" - "font" "DefaultVerySmall" - "fgcolor" "HudWhite" - } - - "MedigunInfoRedChargeLabel" - { - "ControlName" "VariableLabel" - "fieldName" "MedigunInfoRedChargeLabel" - "xpos" "147" - "ypos" "21" - "zpos" "2" - "wide" "14" - "tall" "14" - "autoResize" "1" - "visible" "1" - "enabled" "1" - "labelText" "%redcharge%%" - "tabPosition" "0" - "textAlignment" "center" - "dulltext" "0" - "brighttext" "0" - "font" "DefaultVerySmall" - "fgcolor" "HudWhite" - } - "MedigunInfoRedIndividualChargesLabel" - { - "ControlName" "VariableLabel" - "fieldName" "MedigunInfoRedIndividualChargesLabel" - "xpos" "147" - "ypos" "21" - "zpos" "2" - "wide" "14" - "tall" "14" - "autoResize" "1" - "visible" "1" - "enabled" "1" - "labelText" "%redcharges%" - "tabPosition" "0" - "textAlignment" "center" - "dulltext" "0" - "brighttext" "0" - "font" "DefaultVerySmall" - "fgcolor" "HudWhite" - } - - "MedigunInfoRedChargeAdvantageLabel" - { - "ControlName" "VariableLabel" - "fieldName" "MedigunInfoRedChargeAdvantageLabel" - "xpos" "165" - "ypos" "21" - "zpos" "2" - "wide" "50" - "tall" "14" - "autoResize" "1" - "visible" "1" - "enabled" "1" - "labelText" "+%redadvantage%%" - "tabPosition" "0" - "textAlignment" "center" - "dulltext" "0" - "brighttext" "0" - "font" "DefaultVerySmall" - "fgcolor" "HudWhite" - } - - "MedigunInfoRedChargeMeter" - { - "ControlName" "ImageProgressBar" - "fieldName" "MedigunInfoRedChargeMeter" - "font" "Default" - "xpos" "19" - "ypos" "21" - "zpos" "2" - "wide" "126" - "tall" "14" - "autoResize" "0" - "pinCorner" "0" - "visible" "1" - "enabled" "1" - "textAlignment" "Left" - "dulltext" "0" - "brighttext" "0" - "bgcolor_override" "ProgressBackground" - "fgcolor_override" "ProgressOffWhite" - "direction" "east" - "variable" "redcharge" - } - - "MedigunInfoRedChargeMeter1" - { - "ControlName" "ImageProgressBar" - "fieldName" "MedigunInfoRedChargeMeter1" - "font" "Default" - "xpos" "19" - "ypos" "21" - "zpos" "2" - "wide" "30" - "tall" "14" - "autoResize" "0" - "pinCorner" "0" - "visible" "1" - "enabled" "1" - "textAlignment" "Left" - "dulltext" "0" - "brighttext" "0" - "bgcolor_override" "ProgressBackground" - "fgcolor_override" "ProgressOffWhite" - "direction" "east" - "variable" "redcharge1" - } - - "MedigunInfoRedChargeMeter2" - { - "ControlName" "ImageProgressBar" - "fieldName" "MedigunInfoRedChargeMeter2" - "font" "Default" - "xpos" "51" - "ypos" "21" - "zpos" "2" - "wide" "30" - "tall" "14" - "autoResize" "0" - "pinCorner" "0" - "visible" "1" - "enabled" "1" - "textAlignment" "Left" - "dulltext" "0" - "brighttext" "0" - "bgcolor_override" "ProgressBackground" - "fgcolor_override" "ProgressOffWhite" - "direction" "east" - "variable" "redcharge2" - } - - "MedigunInfoRedChargeMeter3" - { - "ControlName" "ImageProgressBar" - "fieldName" "MedigunInfoRedChargeMeter3" - "font" "Default" - "xpos" "83" - "ypos" "21" - "zpos" "2" - "wide" "30" - "tall" "14" - "autoResize" "0" - "pinCorner" "0" - "visible" "1" - "enabled" "1" - "textAlignment" "Left" - "dulltext" "0" - "brighttext" "0" - "bgcolor_override" "ProgressBackground" - "fgcolor_override" "ProgressOffWhite" - "direction" "east" - "variable" "redcharge3" - } - - "MedigunInfoRedChargeMeter4" - { - "ControlName" "ImageProgressBar" - "fieldName" "MedigunInfoRedChargeMeter4" - "font" "Default" - "xpos" "115" - "ypos" "21" - "zpos" "2" - "wide" "30" - "tall" "14" - "autoResize" "0" - "pinCorner" "0" - "visible" "1" - "enabled" "1" - "textAlignment" "Left" - "dulltext" "0" - "brighttext" "0" - "bgcolor_override" "ProgressBackground" - "fgcolor_override" "ProgressOffWhite" - "direction" "east" - "variable" "redcharge4" - } - - "MedigunInfoRedChargeTypeIcon" - { - "ControlName" "ImagePanel" - "fieldName" "MedigunInfoRedChargeTypeIcon" - "xpos" "3" - "ypos" "21" - "zpos" "2" - "wide" "14" - "tall" "14" - "visible" "1" - "enabled" "1" - "scaleImage" "1" - } - - "MedigunInfoBluBackground" - { - "ControlName" "ScalableImagePanel" - "fieldName" "MedigunInfoBluBackground" - "xpos" "2" - "ypos" "2" - "zpos" "1" - "wide" "160" - "tall" "16" - "autoResize" "0" - "pinCorner" "0" - "visible" "1" - "enabled" "1" - "drawcolor" "HUDBlueTeam" - } - - "MedigunInfoBluNameLabel" - { - "ControlName" "VariableLabel" - "fieldName" "MedigunInfoBluNameLabel" - "xpos" "165" - "ypos" "3" - "zpos" "2" - "wide" "200" - "tall" "14" - "autoResize" "1" - "visible" "0" - "enabled" "0" - "labelText" "%bluname%" - "tabPosition" "0" - "textAlignment" "left" - "dulltext" "0" - "brighttext" "0" - "font" "DefaultVerySmall" - "fgcolor" "HudWhite" - } - - "MedigunInfoBluChargeLabel" - { - "ControlName" "VariableLabel" - "fieldName" "MedigunInfoBluChargeLabel" - "xpos" "147" - "ypos" "3" - "zpos" "2" - "wide" "14" - "tall" "14" - "autoResize" "1" - "visible" "1" - "enabled" "1" - "labelText" "%blucharge%%" - "tabPosition" "0" - "textAlignment" "center" - "dulltext" "0" - "brighttext" "0" - "font" "DefaultVerySmall" - "fgcolor" "HudWhite" - } - - "MedigunInfoBluIndividualChargesLabel" - { - "ControlName" "VariableLabel" - "fieldName" "MedigunInfoBluIndividualChargesLabel" - "xpos" "147" - "ypos" "3" - "zpos" "2" - "wide" "14" - "tall" "14" - "autoResize" "1" - "visible" "1" - "enabled" "1" - "labelText" "%blucharges%" - "tabPosition" "0" - "textAlignment" "center" - "dulltext" "0" - "brighttext" "0" - "font" "DefaultVerySmall" - "fgcolor" "HudWhite" - } - - "MedigunInfoBluChargeAdvantageLabel" - { - "ControlName" "VariableLabel" - "fieldName" "MedigunInfoBluChargeAdvantageLabel" - "xpos" "165" - "ypos" "3" - "zpos" "2" - "wide" "50" - "tall" "14" - "autoResize" "1" - "visible" "1" - "enabled" "1" - "labelText" "+%bluadvantage%%" - "tabPosition" "0" - "textAlignment" "center" - "dulltext" "0" - "brighttext" "0" - "font" "DefaultVerySmall" - "fgcolor" "HudWhite" - } - - "MedigunInfoBluChargeMeter" - { - "ControlName" "ImageProgressBar" - "fieldName" "MedigunInfoBluChargeMeter" - "font" "Default" - "xpos" "19" - "ypos" "3" - "zpos" "2" - "wide" "126" - "tall" "14" - "autoResize" "0" - "pinCorner" "0" - "visible" "1" - "enabled" "1" - "textAlignment" "Left" - "dulltext" "0" - "brighttext" "0" - "bgcolor_override" "ProgressBackground" - "fgcolor_override" "ProgressOffWhite" - "direction" "east" - "variable" "blucharge" - } - - "MedigunInfoBluChargeMeter1" - { - "ControlName" "ImageProgressBar" - "fieldName" "MedigunInfoBluChargeMeter1" - "font" "Default" - "xpos" "19" - "ypos" "3" - "zpos" "2" - "wide" "30" - "tall" "14" - "autoResize" "0" - "pinCorner" "0" - "visible" "1" - "enabled" "1" - "textAlignment" "Left" - "dulltext" "0" - "brighttext" "0" - "bgcolor_override" "ProgressBackground" - "fgcolor_override" "ProgressOffWhite" - "direction" "east" - "variable" "blucharge1" - } - - "MedigunInfoBluChargeMeter2" - { - "ControlName" "ImageProgressBar" - "fieldName" "MedigunInfoBluChargeMeter2" - "font" "Default" - "xpos" "51" - "ypos" "3" - "zpos" "2" - "wide" "30" - "tall" "14" - "autoResize" "0" - "pinCorner" "0" - "visible" "1" - "enabled" "1" - "textAlignment" "Left" - "dulltext" "0" - "brighttext" "0" - "bgcolor_override" "ProgressBackground" - "fgcolor_override" "ProgressOffWhite" - "direction" "east" - "variable" "blucharge2" - } - - "MedigunInfoBluChargeMeter3" - { - "ControlName" "ImageProgressBar" - "fieldName" "MedigunInfoBluChargeMeter3" - "font" "Default" - "xpos" "83" - "ypos" "3" - "zpos" "2" - "wide" "30" - "tall" "14" - "autoResize" "0" - "pinCorner" "0" - "visible" "1" - "enabled" "1" - "textAlignment" "Left" - "dulltext" "0" - "brighttext" "0" - "bgcolor_override" "ProgressBackground" - "fgcolor_override" "ProgressOffWhite" - "direction" "east" - "variable" "blucharge3" - } - - "MedigunInfoBluChargeMeter4" - { - "ControlName" "ImageProgressBar" - "fieldName" "MedigunInfoBluChargeMeter4" - "font" "Default" - "xpos" "115" - "ypos" "3" - "zpos" "2" - "wide" "30" - "tall" "14" - "autoResize" "0" - "pinCorner" "0" - "visible" "1" - "enabled" "1" - "textAlignment" "Left" - "dulltext" "0" - "brighttext" "0" - "bgcolor_override" "ProgressBackground" - "fgcolor_override" "ProgressOffWhite" - "direction" "east" - "variable" "blucharge4" - } - - "MedigunInfoBluChargeTypeIcon" - { - "ControlName" "ImagePanel" - "fieldName" "MedigunInfoBluChargeTypeIcon" - "xpos" "3" - "ypos" "3" - "zpos" "2" - "wide" "14" - "tall" "14" - "visible" "1" - "enabled" "1" - "scaleImage" "1" - } -} \ No newline at end of file + "red_base_x" "0" + "red_base_y" "c0" + "red_offset_x" "0" + "red_offset_y" "18" + "blu_base_x" "0" + "blu_base_y" "c-18" + "blu_offset_x" "0" + "blu_offset_y" "-18" + } +} diff --git a/resource/ui/mediguninfodynamicmeters.res b/resource/ui/mediguninfodynamicmeters.res deleted file mode 100644 index 3832535..0000000 --- a/resource/ui/mediguninfodynamicmeters.res +++ /dev/null @@ -1,18 +0,0 @@ -"Resource/UI/MedigunInfoDynamicMeters.res" -{ - "Medi Gun" - { - } - - "Kritzkrieg" - { - } - - "Quick-Fix" - { - } - - "Vaccinator" - { - } -} \ No newline at end of file diff --git a/resource/ui/medigunpanel.res b/resource/ui/medigunpanel.res new file mode 100644 index 0000000..7b4b4c8 --- /dev/null +++ b/resource/ui/medigunpanel.res @@ -0,0 +1,311 @@ +"Resource/UI/MedigunPanel.res" +{ + "MedigunPanel" + { + "ControlName" "Frame" + "fieldName" "MedigunPanel" + "wide" "164" + "tall" "18" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "0" + } + + "MedigunPanelBackground" + { + "ControlName" "ScalableImagePanel" + "fieldName" "MedigunPanelBackground" + "xpos" "2" + "ypos" "1" + "zpos" "1" + "wide" "160" + "tall" "16" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + + "team-red" + { + "drawcolor" "HUDRedTeam" + } + + "team-blu" + { + "drawcolor" "HUDBlueTeam" + } + } + + + + "MedigunPanelChargeTypeIcon" + { + "ControlName" "ImagePanel" + "fieldName" "MedigunPanelChargeTypeIcon" + "xpos" "3" + "ypos" "2" + "zpos" "2" + "wide" "14" + "tall" "14" + "visible" "1" + "enabled" "1" + "scaleImage" "1" + + "medigun-medigun" + { + "image" "replay/thumbnails/ubercharge" + } + + "medigun-kritzkrieg" + { + "image" "replay/thumbnails/critboost" + } + + "medigun-quickfix" + { + "team-red" + { + "image" "replay/thumbnails/megaheal_red" + } + + "team-blu" + { + "image" "replay/thumbnails/megaheal_blue" + } + } + + "medigun-vaccinator" + { + "team-red" + { + "resist-bullet" + { + "image" "replay/thumbnails/defense_buff_bullet_red" + } + + "resist-explosive" + { + "image" "replay/thumbnails/defense_buff_explosion_red" + } + + "resist-fire" + { + "image" "replay/thumbnails/defense_buff_fire_red" + } + } + + "team-blu" + { + "resist-bullet" + { + "image" "replay/thumbnails/defense_buff_bullet_blue" + } + + "resist-explosive" + { + "image" "replay/thumbnails/defense_buff_explosion_blue" + } + + "resist-fire" + { + "image" "replay/thumbnails/defense_buff_fire_blue" + } + } + } + + "player-dead" + { + "visible" "0" + } + } + + "MedigunPanelChargeLabel" + { + "ControlName" "VariableLabel" + "fieldName" "MedigunPanelChargeLabel" + "xpos" "147" + "ypos" "2" + "zpos" "2" + "wide" "14" + "tall" "14" + "autoResize" "1" + "visible" "1" + "enabled" "1" + "labelText" "%charge%%" + "tabPosition" "0" + "textAlignment" "center" + "dulltext" "0" + "brighttext" "0" + "font" "DefaultVerySmall" + "fgcolor" "HudWhite" + + "medigun-vaccinator" + { + "labelText" "%charges%" + } + + "player-dead" + { + "visible" "0" + } + } + + "MedigunPanelChargeMeter" + { + "ControlName" "ImageProgressBar" + "fieldName" "MedigunPanelChargeMeter" + "font" "Default" + "xpos" "19" + "ypos" "2" + "zpos" "2" + "wide" "126" + "tall" "14" + "autoResize" "0" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "textAlignment" "Left" + "dulltext" "0" + "brighttext" "0" + "bgcolor_override" "ProgressBackground" + "fgcolor_override" "ProgressOffWhite" + "direction" "east" + "variable" "charge" + + "medigun-vaccinator" + { + "visible" "0" + } + + "player-dead" + { + "visible" "0" + } + } + + "MedigunPanelChargeMeter1" + { + "ControlName" "ImageProgressBar" + "fieldName" "MedigunPanelChargeMeter1" + "font" "Default" + "xpos" "19" + "ypos" "2" + "zpos" "2" + "wide" "30" + "tall" "14" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "1" + "textAlignment" "Left" + "dulltext" "0" + "brighttext" "0" + "bgcolor_override" "ProgressBackground" + "fgcolor_override" "ProgressOffWhite" + "direction" "east" + "variable" "charge1" + + "player-alive" + { + "medigun-vaccinator" + { + "visible" "1" + } + } + } + + "MedigunPanelChargeMeter2" + { + "ControlName" "ImageProgressBar" + "fieldName" "MedigunPanelChargeMeter2" + "font" "Default" + "xpos" "51" + "ypos" "2" + "zpos" "2" + "wide" "30" + "tall" "14" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "1" + "textAlignment" "Left" + "dulltext" "0" + "brighttext" "0" + "bgcolor_override" "ProgressBackground" + "fgcolor_override" "ProgressOffWhite" + "direction" "east" + "variable" "charge2" + + "player-alive" + { + "medigun-vaccinator" + { + "visible" "1" + } + } + } + + "MedigunPanelChargeMeter3" + { + "ControlName" "ImageProgressBar" + "fieldName" "MedigunPanelChargeMeter3" + "font" "Default" + "xpos" "83" + "ypos" "2" + "zpos" "2" + "wide" "30" + "tall" "14" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "1" + "textAlignment" "Left" + "dulltext" "0" + "brighttext" "0" + "bgcolor_override" "ProgressBackground" + "fgcolor_override" "ProgressOffWhite" + "direction" "east" + "variable" "charge3" + + "player-alive" + { + "medigun-vaccinator" + { + "visible" "1" + } + } + } + + "MedigunPanelChargeMeter4" + { + "ControlName" "ImageProgressBar" + "fieldName" "MedigunPanelChargeMeter4" + "font" "Default" + "xpos" "115" + "ypos" "2" + "zpos" "2" + "wide" "30" + "tall" "14" + "autoResize" "0" + "pinCorner" "0" + "visible" "0" + "enabled" "1" + "textAlignment" "Left" + "dulltext" "0" + "brighttext" "0" + "bgcolor_override" "ProgressBackground" + "fgcolor_override" "ProgressOffWhite" + "direction" "east" + "variable" "charge4" + + "player-alive" + { + "medigun-vaccinator" + { + "visible" "1" + } + } + } +} diff --git a/resource/ui/statusicon.res b/resource/ui/statusicon.res deleted file mode 100644 index d48b502..0000000 --- a/resource/ui/statusicon.res +++ /dev/null @@ -1,28 +0,0 @@ -"Resource/UI/StatusIcon.res" -{ - "StatusIcon" - { - "ControlName" "EditablePanel" - "fieldName" "StatusIcon" - "xpos" "160" - "ypos" "0" - "zpos" "2" - "wide" "15" - "tall" "15" - "visible" "1" - "enabled" "1" - } - "StatusIconImage" - { - "ControlName" "ImagePanel" - "fieldName" "StatusIconImage" - "xpos" "0" - "ypos" "0" - "zpos" "2" - "wide" "15" - "tall" "15" - "visible" "1" - "enabled" "1" - "scaleImage" "1" - } -} \ No newline at end of file diff --git a/src/common.h b/src/common.h index 9e9b480..c862bde 100644 --- a/src/common.h +++ b/src/common.h @@ -2,7 +2,7 @@ * common.h * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -18,43 +18,11 @@ #include "Color.h" #include "dbg.h" #include "steam/steamclientpublic.h" +#include "strtools.h" class ConCommand; -#define TEXTURE_NULL "vgui/replay/thumbnails/null" -#define TEXTURE_UBERCHARGE "vgui/replay/thumbnails/ubercharge" -#define TEXTURE_CRITBOOST "vgui/replay/thumbnails/critboost" -#define TEXTURE_MEGAHEALRED "vgui/replay/thumbnails/megaheal_red" -#define TEXTURE_MEGAHEALBLU "vgui/replay/thumbnails/megaheal_blue" -#define TEXTURE_RESISTSHIELDRED "vgui/replay/thumbnails/resist_shield" -#define TEXTURE_RESISTSHIELDBLU "vgui/replay/thumbnails/resist_shield_blue" -#define TEXTURE_BULLETRESISTRED "vgui/replay/thumbnails/defense_buff_bullet_red" -#define TEXTURE_BLASTRESISTRED "vgui/replay/thumbnails/defense_buff_explosion_red" -#define TEXTURE_FIRERESISTRED "vgui/replay/thumbnails/defense_buff_fire_red" -#define TEXTURE_BULLETRESISTBLU "vgui/replay/thumbnails/defense_buff_bullet_blue" -#define TEXTURE_BLASTRESISTBLU "vgui/replay/thumbnails/defense_buff_explosion_blue" -#define TEXTURE_FIRERESISTBLU "vgui/replay/thumbnails/defense_buff_fire_blue" -#define TEXTURE_BUFFBANNERRED "effects/soldier_buff_offense_red" -#define TEXTURE_BUFFBANNERBLU "effects/soldier_buff_offense_blue" -#define TEXTURE_BATTALIONSBACKUPRED "effects/soldier_buff_defense_red" -#define TEXTURE_BATTALIONSBACKUPBLU "effects/soldier_buff_defense_blue" -#define TEXTURE_CONCHERORRED "effects/soldier_buff_healonhit_red" -#define TEXTURE_CONCHERORBLU "effects/soldier_buff_healonhit_blue" -#define TEXTURE_JARATE "vgui/replay/thumbnails/jarated" -#define TEXTURE_MADMILK "vgui/bleed_drop" -#define TEXTURE_MARKFORDEATH "vgui/marked_for_death" -#define TEXTURE_BLEEDING "vgui/bleed_drop" -#define TEXTURE_FIRE "hud/leaderboard_class_pyro" - -typedef struct Replacement { - std::string group; - std::string replacement; -} Replacement; - -typedef struct ColorConCommand { - Color color; - ConCommand *command; -} ColorConCommand; +#define GAME_PANEL_MODULE "ClientDLL" inline void FindAndReplaceInString(std::string &str, const std::string &find, const std::string &replace) { if (find.empty()) @@ -68,14 +36,6 @@ inline void FindAndReplaceInString(std::string &str, const std::string &find, co } } -inline float ChangeScale(float currentValue, float currentMin, float currentMax, float newMin, float newMax) { - float deltaScaler = ((newMax - newMin) / (currentMax - currentMin)); - float newDelta = ((currentValue - currentMin) * deltaScaler); - float newValue = newMin + newDelta; - - return newValue; -} - inline int ColorRangeRestrict(int color) { if (color < 0) return 0; else if (color > 255) return 255; @@ -105,9 +65,9 @@ inline std::string ConvertTreeToString(std::vector tree) { std::stringstream ss; std::string string; - for (auto iterator = tree.begin(); iterator != tree.end(); ++iterator) { + for (std::string branch : tree) { ss << ">"; - ss << *iterator; + ss << branch; } ss >> string; @@ -115,6 +75,10 @@ inline std::string ConvertTreeToString(std::vector tree) { return string; } +inline void GetPropIndexString(int index, char string[]) { + V_snprintf(string, sizeof(string), "%03i", index); +} + inline std::string GetVGUITexturePath(std::string normalTexturePath) { std::string path = "../"; path += normalTexturePath; @@ -122,5 +86,5 @@ inline std::string GetVGUITexturePath(std::string normalTexturePath) { return path; } -#define PLUGIN_VERSION "0.24.0" +#define PLUGIN_VERSION "0.25.0" #define PRINT_TAG() ConColorMsg(Color(0, 153, 153, 255), "[StatusSpec] ") \ No newline at end of file diff --git a/src/entities.cpp b/src/entities.cpp index 0e36cfa..a1babc6 100644 --- a/src/entities.cpp +++ b/src/entities.cpp @@ -2,7 +2,7 @@ * entities.cpp * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -37,7 +37,7 @@ bool Entities::RetrieveClassPropOffset(std::string className, std::vectorGetType() == DPT_DataTable) { @@ -48,7 +48,7 @@ bool Entities::RetrieveClassPropOffset(std::string className, std::vectorc_str(), prop, subOffset)) { + if (GetSubProp(table, propertyName.c_str(), prop, subOffset)) { offset += subOffset; } else { diff --git a/src/entities.h b/src/entities.h index bbb8357..c11bfe9 100644 --- a/src/entities.h +++ b/src/entities.h @@ -2,7 +2,7 @@ * entities.h * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * diff --git a/src/exceptions.h b/src/exceptions.h index 70a3ab8..2fa8727 100644 --- a/src/exceptions.h +++ b/src/exceptions.h @@ -2,7 +2,7 @@ * exceptions.h * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * diff --git a/src/funcs.cpp b/src/funcs.cpp index 6f17785..5b8f31f 100644 --- a/src/funcs.cpp +++ b/src/funcs.cpp @@ -2,7 +2,7 @@ * funcs.cpp * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -16,7 +16,10 @@ #include "engine/ivmodelinfo.h" #include "iclientmode.h" +#include "icvar.h" #include "igameevents.h" +#include "iprediction.h" +#include "toolframework/iclientenginetools.h" #include "vgui/IPanel.h" #include "exceptions.h" @@ -36,27 +39,33 @@ SourceHook::Impl::CSourceHookImpl g_SourceHook; SourceHook::ISourceHook *g_SHPtr = &g_SourceHook; int g_PLID = 0; -SH_DECL_MANUALHOOK5_void(C_TFPlayer_CalcView, OFFSET_CALCVIEW, 0, 0, Vector &, QAngle &, float &, float &, float &); SH_DECL_MANUALHOOK0(C_TFPlayer_GetFOV, OFFSET_GETFOV, 0, 0, float); SH_DECL_MANUALHOOK3_void(C_TFPlayer_GetGlowEffectColor, OFFSET_GETGLOWEFFECTCOLOR, 0, 0, float *, float *, float *); -SH_DECL_MANUALHOOK0(C_TFPlayer_GetHealth, OFFSET_GETHEALTH, 0, 0, int); -SH_DECL_MANUALHOOK0(C_TFPlayer_GetMaxHealth, OFFSET_GETMAXHEALTH, 0, 0, int); -SH_DECL_MANUALHOOK0(C_TFPlayer_GetObserverMode, OFFSET_GETOBSERVERMODE, 0, 0, int); -SH_DECL_MANUALHOOK0(C_TFPlayer_GetObserverTarget, OFFSET_GETOBSERVERTARGET, 0, 0, C_BaseEntity *); SH_DECL_HOOK1_void(IBaseClientDLL, FrameStageNotify, SH_NOATTRIB, 0, ClientFrameStage_t); +SH_DECL_HOOK0(IClientEngineTools, InToolMode, SH_NOATTRIB, 0, bool); +SH_DECL_HOOK0(IClientEngineTools, IsThirdPersonCamera, SH_NOATTRIB, 0, bool); +SH_DECL_HOOK3(IClientEngineTools, SetupEngineView, SH_NOATTRIB, 0, bool, Vector &, QAngle &, float &); SH_DECL_HOOK1(IClientMode, DoPostScreenSpaceEffects, SH_NOATTRIB, 0, bool, const CViewSetup *); +SH_DECL_HOOK1_void_vafmt(ICvar, ConsoleColorPrintf, const FMTFUNCTION(3, 4), 0, const Color &); +SH_DECL_HOOK0_void_vafmt(ICvar, ConsolePrintf, const FMTFUNCTION(2, 3), 0); +SH_DECL_HOOK0_void_vafmt(ICvar, ConsoleDPrintf, const FMTFUNCTION(2, 3), 0); SH_DECL_HOOK1(IGameEventManager2, FireEventClientSide, SH_NOATTRIB, 0, bool, IGameEvent *); SH_DECL_HOOK4(IMaterialSystem, FindMaterial, SH_NOATTRIB, 0, IMaterial *, char const *, const char *, bool, const char *); -SH_DECL_HOOK3_void(IPanel, SendMessage, SH_NOATTRIB, 0, VPANEL, KeyValues *, VPANEL); -SH_DECL_HOOK3_void(IPanel, SetPos, SH_NOATTRIB, 0, VPANEL, int, int); +SH_DECL_HOOK0_void(IPrediction, PostEntityPacketReceived, SH_NOATTRIB, 0); SH_DECL_HOOK2(IVEngineClient, GetPlayerInfo, SH_NOATTRIB, 0, bool, int, player_info_t *); +int Funcs::setModeLastHookRegistered = 0; +std::map> Funcs::setModeHooks; int Funcs::setModelLastHookRegistered = 0; std::map> Funcs::setModelHooks; +int Funcs::setPrimaryTargetLastHookRegistered = 0; +std::map> Funcs::setPrimaryTargetHooks; GLPI_t Funcs::getLocalPlayerIndexOriginal = nullptr; +SM_t Funcs::setModeOriginal = nullptr; SMI_t Funcs::setModelIndexOriginal = nullptr; SMP_t Funcs::setModelPointerOriginal = nullptr; +SPT_t Funcs::setPrimaryTargetOriginal = nullptr; bool Funcs::AddDetour(void *target, void *detour, void *&original) { MH_STATUS addHookResult = MH_CreateHook(target, detour, &original); @@ -103,6 +112,28 @@ bool Funcs::AddDetour_C_BaseEntity_SetModelPointer(SMPH_t detour) { return false; } +bool Funcs::AddDetour_C_HLTVCamera_SetMode(SMH_t detour) { + void *original; + + if (AddDetour(GetFunc_C_HLTVCamera_SetMode(), detour, original)) { + setModeOriginal = reinterpret_cast(original); + return true; + } + + return false; +} + +bool Funcs::AddDetour_C_HLTVCamera_SetPrimaryTarget(SPTH_t detour) { + void *original; + + if (AddDetour(GetFunc_C_HLTVCamera_SetPrimaryTarget(), detour, original)) { + setPrimaryTargetOriginal = reinterpret_cast(original); + return true; + } + + return false; +} + int Funcs::AddGlobalHook_C_TFPlayer_GetFOV(C_TFPlayer *instance, fastdelegate::FastDelegate0 hook, bool post) { return SH_ADD_MANUALHOOK(C_TFPlayer_GetFOV, instance, hook, post); } @@ -118,14 +149,54 @@ int Funcs::AddHook_C_BaseEntity_SetModel(std::function hook, bool post) { - return SH_ADD_HOOK(IBaseClientDLL, FrameStageNotify, instance, hook, post); +int Funcs::AddHook_C_HLTVCamera_SetMode(std::function hook) { + if (setModeHooks.size() == 0) { + AddDetour_C_HLTVCamera_SetMode(Detour_C_HLTVCamera_SetMode); + } + + setModeHooks[++setModeLastHookRegistered] = hook; + + return setModeLastHookRegistered; +} + +int Funcs::AddHook_C_HLTVCamera_SetPrimaryTarget(std::function hook) { + if (setPrimaryTargetHooks.size() == 0) { + AddDetour_C_HLTVCamera_SetPrimaryTarget(Detour_C_HLTVCamera_SetPrimaryTarget); + } + + setPrimaryTargetHooks[++setPrimaryTargetLastHookRegistered] = hook; + + return setPrimaryTargetLastHookRegistered; +} + +int Funcs::AddHook_IClientEngineTools_InToolMode(IClientEngineTools *instance, fastdelegate::FastDelegate0 hook, bool post) { + return SH_ADD_HOOK(IClientEngineTools, InToolMode, instance, hook, post); +} + +int Funcs::AddHook_IClientEngineTools_IsThirdPersonCamera(IClientEngineTools *instance, fastdelegate::FastDelegate0 hook, bool post) { + return SH_ADD_HOOK(IClientEngineTools, IsThirdPersonCamera, instance, hook, post); +} + +int Funcs::AddHook_IClientEngineTools_SetupEngineView(IClientEngineTools *instance, fastdelegate::FastDelegate3 hook, bool post) { + return SH_ADD_HOOK(IClientEngineTools, SetupEngineView, instance, hook, post); } int Funcs::AddHook_IClientMode_DoPostScreenSpaceEffects(IClientMode *instance, fastdelegate::FastDelegate1 hook, bool post) { return SH_ADD_HOOK(IClientMode, DoPostScreenSpaceEffects, instance, hook, post); } +int Funcs::AddHook_ICvar_ConsoleColorPrintf(ICvar *instance, fastdelegate::FastDelegate2 hook, bool post) { + return SH_ADD_HOOK(ICvar, ConsoleColorPrintf, instance, hook, post); +} + +int Funcs::AddHook_ICvar_ConsoleDPrintf(ICvar *instance, fastdelegate::FastDelegate1 hook, bool post) { + return SH_ADD_HOOK(ICvar, ConsoleDPrintf, instance, hook, post); +} + +int Funcs::AddHook_ICvar_ConsolePrintf(ICvar *instance, fastdelegate::FastDelegate1 hook, bool post) { + return SH_ADD_HOOK(ICvar, ConsolePrintf, instance, hook, post); +} + int Funcs::AddHook_IGameEventManager2_FireEventClientSide(IGameEventManager2 *instance, fastdelegate::FastDelegate1 hook, bool post) { return SH_ADD_HOOK(IGameEventManager2, FireEventClientSide, instance, hook, post); } @@ -134,12 +205,8 @@ int Funcs::AddHook_IMaterialSystem_FindMaterial(IMaterialSystem *instance, fastd return SH_ADD_HOOK(IMaterialSystem, FindMaterial, instance, hook, post); } -int Funcs::AddHook_IPanel_SendMessage(vgui::IPanel *instance, fastdelegate::FastDelegate3 hook, bool post) { - return SH_ADD_HOOK(IPanel, SendMessage, instance, hook, post); -} - -int Funcs::AddHook_IPanel_SetPos(vgui::IPanel *instance, fastdelegate::FastDelegate3 hook, bool post) { - return SH_ADD_HOOK(IPanel, SetPos, instance, hook, post); +int Funcs::AddHook_IPrediction_PostEntityPacketReceived(IPrediction *instance, fastdelegate::FastDelegate0<> hook, bool post) { + return SH_ADD_HOOK(IPrediction, PostEntityPacketReceived, instance, hook, post); } int Funcs::AddHook_IVEngineClient_GetPlayerInfo(IVEngineClient *instance, fastdelegate::FastDelegate2 hook, bool post) { @@ -173,8 +240,26 @@ void Funcs::CallFunc_C_BaseEntity_SetModelPointer(C_BaseEntity *instance, const } } +void Funcs::CallFunc_C_HLTVCamera_SetCameraAngle(C_HLTVCamera *instance, QAngle &targetAngle) { + GetFunc_C_HLTVCamera_SetCameraAngle()(instance, targetAngle); +} + +void Funcs::CallFunc_C_HLTVCamera_SetMode(C_HLTVCamera *instance, int iMode) { + if (setModeOriginal) { + setModeOriginal(instance, iMode); + } + else { + GetFunc_C_HLTVCamera_SetMode()(instance, iMode); + } +} + void Funcs::CallFunc_C_HLTVCamera_SetPrimaryTarget(C_HLTVCamera *instance, int nEntity) { - GetFunc_C_HLTVCamera_SetPrimaryTarget()(instance, nEntity); + if (setPrimaryTargetOriginal) { + setPrimaryTargetOriginal(instance, nEntity); + } + else { + GetFunc_C_HLTVCamera_SetPrimaryTarget()(instance, nEntity); + } } float Funcs::CallFunc_C_TFPlayer_GetFOV(C_TFPlayer *instance) { @@ -185,22 +270,6 @@ void Funcs::CallFunc_C_TFPlayer_GetGlowEffectColor(C_TFPlayer *instance, float * SH_MCALL(instance, C_TFPlayer_GetGlowEffectColor)(r, g, b); } -int Funcs::CallFunc_C_TFPlayer_GetHealth(C_TFPlayer *instance) { - return SH_MCALL(instance, C_TFPlayer_GetHealth)(); -} - -int Funcs::CallFunc_C_TFPlayer_GetMaxHealth(C_TFPlayer *instance) { - return SH_MCALL(instance, C_TFPlayer_GetMaxHealth)(); -} - -int Funcs::CallFunc_C_TFPlayer_GetObserverMode(C_TFPlayer *instance) { - return SH_MCALL(instance, C_TFPlayer_GetObserverMode)(); -} - -C_BaseEntity *Funcs::CallFunc_C_TFPlayer_GetObserverTarget(C_TFPlayer *instance) { - return SH_MCALL(instance, C_TFPlayer_GetObserverTarget)(); -} - bool Funcs::CallFunc_IVEngineClient_GetPlayerInfo(IVEngineClient *instance, int ent_num, player_info_t *pinfo) { return SH_CALL(instance, &IVEngineClient::GetPlayerInfo)(ent_num, pinfo); } @@ -209,8 +278,8 @@ void Funcs::Detour_C_BaseEntity_SetModelIndex(C_BaseEntity *instance, void *, in const model_t *model = Interfaces::pModelInfoClient->GetModel(index); const char *oldModelName = Interfaces::pModelInfoClient->GetModelName(model); - for (auto iterator = setModelHooks.begin(); iterator != setModelHooks.end(); ++iterator) { - iterator->second(instance, model); + for (auto iterator : setModelHooks) { + iterator.second(instance, model); } if (strcmp(oldModelName, Interfaces::pModelInfoClient->GetModelName(model)) == 0) { @@ -223,13 +292,29 @@ void Funcs::Detour_C_BaseEntity_SetModelIndex(C_BaseEntity *instance, void *, in } void Funcs::Detour_C_BaseEntity_SetModelPointer(C_BaseEntity *instance, void *, const model_t *pModel) { - for (auto iterator = setModelHooks.begin(); iterator != setModelHooks.end(); ++iterator) { - iterator->second(instance, pModel); + for (auto iterator : setModelHooks) { + iterator.second(instance, pModel); } Funcs::CallFunc_C_BaseEntity_SetModelPointer(instance, pModel); } +void Funcs::Detour_C_HLTVCamera_SetMode(C_HLTVCamera *instance, void *, int iMode) { + for (auto iterator : setModeHooks) { + iterator.second(instance, iMode); + } + + Funcs::CallFunc_C_HLTVCamera_SetMode(instance, iMode); +} + +void Funcs::Detour_C_HLTVCamera_SetPrimaryTarget(C_HLTVCamera *instance, void *, int nEntity) { + for (auto iterator : setPrimaryTargetHooks) { + iterator.second(instance, nEntity); + } + + Funcs::CallFunc_C_HLTVCamera_SetPrimaryTarget(instance, nEntity); +} + GLPI_t Funcs::GetFunc_GetLocalPlayerIndex() { #if defined _WIN32 static DWORD pointer = NULL; @@ -290,6 +375,46 @@ SMP_t Funcs::GetFunc_C_BaseEntity_SetModelPointer() { #endif } +SCA_t Funcs::GetFunc_C_HLTVCamera_SetCameraAngle() { +#if defined _WIN32 + static DWORD pointer = NULL; + + if (!pointer) { + pointer = SignatureScan("client", SETCAMERAANGLE_SIG, SETCAMERAANGLE_MASK); + + if (!pointer) { + throw bad_pointer("C_HLTVCamera::SetCameraAngle"); + } + } + + return (SCA_t)(pointer); +#else + throw bad_pointer("C_HLTVCamera::SetCameraAngle"); + + return nullptr; +#endif +} + +SM_t Funcs::GetFunc_C_HLTVCamera_SetMode() { +#if defined _WIN32 + static DWORD pointer = NULL; + + if (!pointer) { + pointer = SignatureScan("client", SETMODE_SIG, SETMODE_MASK); + + if (!pointer) { + throw bad_pointer("C_HLTVCamera::SetMode"); + } + } + + return (SM_t)(pointer); +#else + throw bad_pointer("C_HLTVCamera::SetMode"); + + return nullptr; +#endif +} + SPT_t Funcs::GetFunc_C_HLTVCamera_SetPrimaryTarget() { #if defined _WIN32 static DWORD pointer = NULL; @@ -337,6 +462,24 @@ bool Funcs::RemoveDetour_C_BaseEntity_SetModelPointer() { return false; } +bool Funcs::RemoveDetour_C_HLTVCamera_SetMode() { + if (RemoveDetour(GetFunc_C_HLTVCamera_SetMode())) { + setModeOriginal = nullptr; + return true; + } + + return false; +} + +bool Funcs::RemoveDetour_C_HLTVCamera_SetPrimaryTarget() { + if (RemoveDetour(GetFunc_C_HLTVCamera_SetPrimaryTarget())) { + setPrimaryTargetOriginal = nullptr; + return true; + } + + return false; +} + bool Funcs::RemoveDetour(void *target) { MH_STATUS disableHookResult = MH_DisableHook(target); @@ -362,6 +505,22 @@ void Funcs::RemoveHook_C_BaseEntity_SetModel(int hookID) { } } +void Funcs::RemoveHook_C_HLTVCamera_SetMode(int hookID) { + setModeHooks.erase(hookID); + + if (setModeHooks.size() == 0) { + RemoveDetour_C_HLTVCamera_SetMode(); + } +} + +void Funcs::RemoveHook_C_HLTVCamera_SetPrimaryTarget(int hookID) { + setPrimaryTargetHooks.erase(hookID); + + if (setPrimaryTargetHooks.size() == 0) { + RemoveDetour_C_HLTVCamera_SetPrimaryTarget(); + } +} + bool Funcs::Load() { MH_STATUS minHookResult = MH_Initialize(); diff --git a/src/funcs.h b/src/funcs.h index e88e280..a035646 100644 --- a/src/funcs.h +++ b/src/funcs.h @@ -2,7 +2,7 @@ * funcs.h * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -20,10 +20,14 @@ #include "gamedata.h" +class C_TFPlayer; +class IClientEngineTools; class IClientMode; +class ICvar; class IGameEvent; class IGameEventManager2; class IMaterialSystem; +class IPrediction; namespace vgui { class IPanel; @@ -33,38 +37,48 @@ class Funcs { public: static bool AddDetour_GetLocalPlayerIndex(GLPI_t detour); - static int AddGlobalHook_C_TFPlayer_GetFOV(C_TFPlayer *instance, fastdelegate::FastDelegate0 hook, bool post); static int AddHook_C_BaseEntity_SetModel(std::function hook); - static int AddHook_IBaseClientDLL_FrameStageNotify(IBaseClientDLL *instance, fastdelegate::FastDelegate1 hook, bool post); + static int AddHook_C_HLTVCamera_SetMode(std::function hook); + static int AddHook_C_HLTVCamera_SetPrimaryTarget(std::function hook); + + static int AddGlobalHook_C_TFPlayer_GetFOV(C_TFPlayer *instance, fastdelegate::FastDelegate0 hook, bool post); + static int AddHook_IClientEngineTools_InToolMode(IClientEngineTools *instance, fastdelegate::FastDelegate0 hook, bool post); + static int AddHook_IClientEngineTools_IsThirdPersonCamera(IClientEngineTools *instance, fastdelegate::FastDelegate0 hook, bool post); + static int AddHook_IClientEngineTools_SetupEngineView(IClientEngineTools *instance, fastdelegate::FastDelegate3 hook, bool post); static int AddHook_IClientMode_DoPostScreenSpaceEffects(IClientMode *instance, fastdelegate::FastDelegate1 hook, bool post); + static int AddHook_ICvar_ConsoleColorPrintf(ICvar *instance, fastdelegate::FastDelegate2 hook, bool post); + static int AddHook_ICvar_ConsoleDPrintf(ICvar *instance, fastdelegate::FastDelegate1 hook, bool post); + static int AddHook_ICvar_ConsolePrintf(ICvar *instance, fastdelegate::FastDelegate1 hook, bool post); static int AddHook_IGameEventManager2_FireEventClientSide(IGameEventManager2 *instance, fastdelegate::FastDelegate1 hook, bool post); static int AddHook_IMaterialSystem_FindMaterial(IMaterialSystem *instance, fastdelegate::FastDelegate4 hook, bool post); - static int AddHook_IPanel_SendMessage(vgui::IPanel *instance, fastdelegate::FastDelegate3 hook, bool post); - static int AddHook_IPanel_SetPos(vgui::IPanel *instance, fastdelegate::FastDelegate3 hook, bool post); + static int AddHook_IPrediction_PostEntityPacketReceived(IPrediction *instance, fastdelegate::FastDelegate0<> hook, bool post); static int AddHook_IVEngineClient_GetPlayerInfo(IVEngineClient *instance, fastdelegate::FastDelegate2 hook, bool post); static int CallFunc_GetLocalPlayerIndex(); static void CallFunc_C_BaseEntity_SetModelIndex(C_BaseEntity *instance, int index); static void CallFunc_C_BaseEntity_SetModelPointer(C_BaseEntity *instance, const model_t *pModel); + static void CallFunc_C_HLTVCamera_SetCameraAngle(C_HLTVCamera *instance, QAngle &targetAngle); + static void CallFunc_C_HLTVCamera_SetMode(C_HLTVCamera *instance, int iMode); static void CallFunc_C_HLTVCamera_SetPrimaryTarget(C_HLTVCamera *instance, int nEntity); static float CallFunc_C_TFPlayer_GetFOV(C_TFPlayer *instance); static void CallFunc_C_TFPlayer_GetGlowEffectColor(C_TFPlayer *instance, float *r, float *g, float *b); - static int CallFunc_C_TFPlayer_GetHealth(C_TFPlayer *instance); - static int CallFunc_C_TFPlayer_GetMaxHealth(C_TFPlayer *instance); - static int CallFunc_C_TFPlayer_GetObserverMode(C_TFPlayer *instance); - static C_BaseEntity *CallFunc_C_TFPlayer_GetObserverTarget(C_TFPlayer *instance); static bool CallFunc_IVEngineClient_GetPlayerInfo(IVEngineClient *instance, int ent_num, player_info_t *pinfo); static GLPI_t GetFunc_GetLocalPlayerIndex(); static SMI_t GetFunc_C_BaseEntity_SetModelIndex(); static SMP_t GetFunc_C_BaseEntity_SetModelPointer(); + static SCA_t GetFunc_C_HLTVCamera_SetCameraAngle(); + static SM_t GetFunc_C_HLTVCamera_SetMode(); static SPT_t GetFunc_C_HLTVCamera_SetPrimaryTarget(); static bool RemoveDetour_GetLocalPlayerIndex(); - static bool RemoveHook(int hookID); static void RemoveHook_C_BaseEntity_SetModel(int hookID); + static void RemoveHook_C_HLTVCamera_SetMode(int hookID); + static void RemoveHook_C_HLTVCamera_SetPrimaryTarget(int hookID); + + static bool RemoveHook(int hookID); static bool Load(); @@ -74,10 +88,16 @@ class Funcs { static bool Unpause(); private: + static int setModeLastHookRegistered; + static std::map> setModeHooks; static int setModelLastHookRegistered; static std::map> setModelHooks; + static int setPrimaryTargetLastHookRegistered; + static std::map> setPrimaryTargetHooks; static GLPI_t getLocalPlayerIndexOriginal; + static SM_t setModeOriginal; + static SPT_t setPrimaryTargetOriginal; static SMI_t setModelIndexOriginal; static SMP_t setModelPointerOriginal; @@ -85,12 +105,18 @@ class Funcs { static bool AddDetour_C_BaseEntity_SetModelIndex(SMIH_t detour); static bool AddDetour_C_BaseEntity_SetModelPointer(SMPH_t detour); + static bool AddDetour_C_HLTVCamera_SetMode(SMH_t detour); + static bool AddDetour_C_HLTVCamera_SetPrimaryTarget(SPTH_t detour); static void __fastcall Detour_C_BaseEntity_SetModelIndex(C_BaseEntity *, void *, int); static void __fastcall Detour_C_BaseEntity_SetModelPointer(C_BaseEntity *, void *, const model_t *); + static void __fastcall Detour_C_HLTVCamera_SetMode(C_HLTVCamera *, void *, int); + static void __fastcall Detour_C_HLTVCamera_SetPrimaryTarget(C_HLTVCamera *, void *, int); static bool RemoveDetour_C_BaseEntity_SetModelIndex(); static bool RemoveDetour_C_BaseEntity_SetModelPointer(); + static bool RemoveDetour_C_HLTVCamera_SetMode(); + static bool RemoveDetour_C_HLTVCamera_SetPrimaryTarget(); static bool RemoveDetour(void *target); }; diff --git a/src/gamedata.h b/src/gamedata.h index 07ae28c..4486590 100644 --- a/src/gamedata.h +++ b/src/gamedata.h @@ -2,7 +2,7 @@ * gamedata.h * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -16,47 +16,31 @@ #include #include #undef GetClassName +#undef PostMessage #undef SendMessage #endif // DLL loading info #if defined _WIN32 -#define GetFuncAddress(pAddress, szFunction) ::GetProcAddress((HMODULE)pAddress, szFunction) #define GetHandleOfModule(szModuleName) GetModuleHandle((std::string(szModuleName) + ".dll").c_str()) #elif defined __linux__ -#define GetFuncAddress(pAddress, szFunction) dlsym(pAddress, szFunction) #define GetHandleOfModule(szModuleName) dlopen((std::string(szModuleName) + ".so").c_str(), RTLD_NOLOAD) #endif -// client DLL info -#if defined _WIN32 -#define CLIENT_MODULE_FILE "tf/bin/client.dll" -#elif defined __APPLE__ -#define CLIENT_MODULE_FILE "tf/bin/client.dylib" -#elif defined __linux__ -#define CLIENT_MODULE_FILE "tf/bin/client.so" -#endif - // signatures #if defined _WIN32 -#define GAMERESOURCES_SIG "\xA1\x00\x00\x00\x00\x85\xC0\x74\x06\x05" -#define GAMERESOURCES_MASK "x????xxxxx" #define CLIENTMODE_SIG "\xC7\x05\x00\x00\x00\x00\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x68\x00\x00\x00\x00\x8B\xC8" #define CLIENTMODE_MASK "xx????????x????x????xx" #define CLIENTMODE_OFFSET 2 #define HLTVCAMERA_SIG "\xB9\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x68\x00\x00\x00\x00\xC7\x05\x00\x00\x00\x00\x00\x00\x00\x00\xC6\x05\x00\x00\x00\x00\x00" #define HLTVCAMERA_MASK "x????x????x????xx????xxxxxx????x" #define HLTVCAMERA_OFFSET 1 -#define TEAMPLAYROUNDBASEDRULES_SIG "\xA1\x00\x00\x00\x00\x85\xC0\x74\x14" -#define TEAMPLAYROUNDBASEDRULES_MASK "x????xxxx" -#define TEAMPLAYROUNDBASEDRULES_OFFSET 1 -#define GPGLOBALS_SIG "\xA3\x00\x00\x00\x00\x8D\x45\x08\x6A\x01" -#define GPGLOBALS_MASK "x????xxxxx" -#define GPGLOBALS_OFFSET 1 #define GETLOCALPLAYERINDEX_SIG "\xE8\x00\x00\x00\x00\x85\xC0\x74\x08\x8D\x48\x08\x8B\x01\xFF\x60\x24\x33\xC0\xC3" #define GETLOCALPLAYERINDEX_MASK "x????xxxxxxxxxxxxxxx" -#define SETMODEL_SIG "\x55\x8B\xEC\x8B\x55\x08\x56\x57\x8B\xF9\x85\xD2" -#define SETMODEL_MASK "xxxxxxxxxxxx" +#define SETCAMERAANGLE_SIG "\x55\x8B\xEC\x8B\x45\x08\x56\x8B\xF1\x8D\x56\x00\xD9\x00\xD9\x1A\xD9\x40\x00\xD9\x5A\x00\xD9\x40\x00\x52" +#define SETCAMERAANGLE_MASK "xxxxxxxxxxx?xxxxxx?xx?xx?x" +#define SETMODE_SIG "\x55\x8B\xEC\x8B\x45\x08\x53\x56\x8B\xF1\x8B\x5E\x00" +#define SETMODE_MASK "xxxxxxxxxxxx?" #define SETMODELINDEX_SIG "\x55\x8B\xEC\x8B\x45\x08\x56\x8B\xF1\x57\x66\x89\x86\x00\x00\x00\x00" #define SETMODELINDEX_MASK "xxxxxxxxxxxxx????" #define SETMODELPOINTER_SIG "\x55\x8B\xEC\x56\x8B\xF1\x57\x8B\x7D\x08\x3B\x7E\x00\x74\x00" @@ -67,35 +51,28 @@ class C_BaseEntity; class C_HLTVCamera; -class C_TFPlayer; -class IGameResources; struct model_t; // C_TFPlayer offsets #if defined _WIN32 -#define OFFSET_GETHEALTH 106 -#define OFFSET_GETMAXHEALTH 107 -#define OFFSET_ISALIVE 137 #define OFFSET_GETGLOWEFFECTCOLOR 224 -#define OFFSET_UPDATEGLOWEFFECT 225 -#define OFFSET_DESTROYGLOWEFFECT 226 -#define OFFSET_CALCVIEW 230 -#define OFFSET_GETOBSERVERMODE 241 -#define OFFSET_GETOBSERVERTARGET 242 #define OFFSET_GETFOV 269 #endif // non-member function types typedef int(*GLPI_t)(void); -typedef IGameResources *(*GGR_t)(void); // member function types #if defined _WIN32 +typedef void(__thiscall *SCA_t)(C_HLTVCamera *, QAngle &); +typedef void(__thiscall *SM_t)(C_HLTVCamera *, int); typedef void(__thiscall *SMI_t)(C_BaseEntity *, int); typedef void(__thiscall *SMP_t)(C_BaseEntity *, const model_t *); typedef void(__thiscall *SPT_t)(C_HLTVCamera *, int); +typedef void(__fastcall *SMH_t)(C_HLTVCamera *, void *, int); typedef void(__fastcall *SMIH_t)(C_BaseEntity *, void *, int); typedef void(__fastcall *SMPH_t)(C_BaseEntity *, void *, const model_t *); +typedef void(__fastcall *SPTH_t)(C_HLTVCamera *, void *, int); #endif inline bool DataCompare(const BYTE* pData, const BYTE* bSig, const char* szMask) { diff --git a/src/glows.cpp b/src/glows.cpp index e86489c..35cf6ac 100644 --- a/src/glows.cpp +++ b/src/glows.cpp @@ -132,16 +132,16 @@ void GlowManager::RenderGlowModels(const CViewSetup *pSetup, CMatRenderContextPt stencilState.SetStencilState(pRenderContext); - for (auto iterator = m_GlowObjectDefinitions.begin(); iterator != m_GlowObjectDefinitions.end(); ++iterator) { - if (!iterator->second.ShouldDraw()) { + for (auto iterator : m_GlowObjectDefinitions) { + if (!iterator.second.ShouldDraw()) { continue; } - Interfaces::pRenderView->SetBlend(iterator->second.m_flGlowAlpha); - Vector vGlowColor = iterator->second.m_vGlowColor * iterator->second.m_flGlowAlpha; + Interfaces::pRenderView->SetBlend(iterator.second.m_flGlowAlpha); + Vector vGlowColor = iterator.second.m_vGlowColor * iterator.second.m_flGlowAlpha; Interfaces::pRenderView->SetColorModulation(&vGlowColor[0]); - iterator->second.DrawModel(); + iterator.second.DrawModel(); } g_pStudioRender->ForcedMaterialOverride(NULL); @@ -169,13 +169,13 @@ void GlowManager::ApplyEntityGlowEffects(const CViewSetup *pSetup, CMatRenderCon int iNumGlowObjects = 0; - for (auto iterator = m_GlowObjectDefinitions.begin(); iterator != m_GlowObjectDefinitions.end(); ++iterator) { - if (!iterator->second.ShouldDraw()) { + for (auto iterator : m_GlowObjectDefinitions) { + if (!iterator.second.ShouldDraw()) { continue; } - if (iterator->second.m_bRenderWhenOccluded || iterator->second.m_bRenderWhenUnoccluded) { - if (iterator->second.m_bRenderWhenOccluded && iterator->second.m_bRenderWhenUnoccluded) { + if (iterator.second.m_bRenderWhenOccluded || iterator.second.m_bRenderWhenUnoccluded) { + if (iterator.second.m_bRenderWhenOccluded && iterator.second.m_bRenderWhenUnoccluded) { ShaderStencilState_t stencilState; stencilState.m_bEnable = true; stencilState.m_nReferenceValue = 1; @@ -186,9 +186,9 @@ void GlowManager::ApplyEntityGlowEffects(const CViewSetup *pSetup, CMatRenderCon stencilState.SetStencilState(pRenderContext); - iterator->second.DrawModel(); + iterator.second.DrawModel(); } - else if (iterator->second.m_bRenderWhenOccluded) { + else if (iterator.second.m_bRenderWhenOccluded) { ShaderStencilState_t stencilState; stencilState.m_bEnable = true; stencilState.m_nReferenceValue = 1; @@ -199,9 +199,9 @@ void GlowManager::ApplyEntityGlowEffects(const CViewSetup *pSetup, CMatRenderCon stencilState.SetStencilState(pRenderContext); - iterator->second.DrawModel(); + iterator.second.DrawModel(); } - else if (iterator->second.m_bRenderWhenUnoccluded) { + else if (iterator.second.m_bRenderWhenUnoccluded) { ShaderStencilState_t stencilState; stencilState.m_bEnable = true; stencilState.m_nReferenceValue = 2; @@ -214,19 +214,19 @@ void GlowManager::ApplyEntityGlowEffects(const CViewSetup *pSetup, CMatRenderCon stencilState.SetStencilState(pRenderContext); - iterator->second.DrawModel(); + iterator.second.DrawModel(); } } iNumGlowObjects++; } - for (auto iterator = m_GlowObjectDefinitions.begin(); iterator != m_GlowObjectDefinitions.end(); ++iterator) { - if (!iterator->second.ShouldDraw()) { + for (auto iterator : m_GlowObjectDefinitions) { + if (!iterator.second.ShouldDraw()) { continue; } - if (iterator->second.m_bRenderWhenOccluded && !iterator->second.m_bRenderWhenUnoccluded) { + if (iterator.second.m_bRenderWhenOccluded && !iterator.second.m_bRenderWhenUnoccluded) { ShaderStencilState_t stencilState; stencilState.m_bEnable = true; stencilState.m_nReferenceValue = 2; @@ -236,7 +236,7 @@ void GlowManager::ApplyEntityGlowEffects(const CViewSetup *pSetup, CMatRenderCon stencilState.m_ZFailOp = STENCILOPERATION_KEEP; stencilState.SetStencilState(pRenderContext); - iterator->second.DrawModel(); + iterator.second.DrawModel(); } } diff --git a/src/glows.h b/src/glows.h index f19199e..6078bbf 100644 --- a/src/glows.h +++ b/src/glows.h @@ -132,8 +132,8 @@ class GlowManager { } bool HasGlowEffect(C_BaseEntity *pEntity) { - for (auto iterator = m_GlowObjectDefinitions.begin(); iterator != m_GlowObjectDefinitions.end(); ++iterator) { - if (iterator->second.m_hEntity.Get() == pEntity) { + for (auto iterator : m_GlowObjectDefinitions) { + if (iterator.second.m_hEntity.Get() == pEntity) { return true; } } diff --git a/src/ifaces.cpp b/src/ifaces.cpp index 5b8dcf7..8550bda 100644 --- a/src/ifaces.cpp +++ b/src/ifaces.cpp @@ -2,7 +2,7 @@ * ifaces.cpp * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -17,9 +17,12 @@ #include "filesystem_init.h" #include "icliententitylist.h" #include "igameevents.h" +#include "iprediction.h" #include "ivrenderview.h" #include "steam/steam_api.h" #include "teamplayroundbased_gamerules.h" +#include "toolframework/iclientenginetools.h" +#include "toolframework/ienginetool.h" #include "tier3/tier3.h" #include "vgui_controls/Controls.h" @@ -27,11 +30,13 @@ #include "gamedata.h" IBaseClientDLL *Interfaces::pClientDLL = nullptr; +IClientEngineTools *Interfaces::pClientEngineTools = nullptr; IClientEntityList *Interfaces::pClientEntityList = nullptr; -CDllDemandLoader *Interfaces::pClientModule = nullptr; IVEngineClient *Interfaces::pEngineClient = nullptr; +IEngineTool *Interfaces::pEngineTool = nullptr; IFileSystem *Interfaces::pFileSystem = nullptr; IGameEventManager2 *Interfaces::pGameEventManager = nullptr; +IPrediction *Interfaces::pPrediction = nullptr; IVModelInfoClient *Interfaces::pModelInfoClient = nullptr; IVRenderView *Interfaces::pRenderView = nullptr; CSteamAPIContext *Interfaces::pSteamAPIContext = nullptr; @@ -65,57 +70,6 @@ IClientMode *Interfaces::GetClientMode() { #endif } -IGameResources *Interfaces::GetGameResources() { -#if defined _WIN32 - static DWORD pointer = NULL; - - if (!pointer) { - pointer = SignatureScan("client", GAMERESOURCES_SIG, GAMERESOURCES_MASK); - - if (!pointer) { - throw bad_pointer("IGameResources"); - } - } - - GGR_t GGR = (GGR_t) pointer; - IGameResources *gr = GGR(); - - if (!gr) { - throw bad_pointer("IGameResources"); - } - - return gr; -#else - throw bad_pointer("IGameResources"); - - return nullptr; -#endif -} - -CGlobalVarsBase *Interfaces::GetGlobalVars() { -#if defined _WIN32 - static DWORD pointer = NULL; - - if (!pointer) { - pointer = SignatureScan("client", GPGLOBALS_SIG, GPGLOBALS_MASK) + GPGLOBALS_OFFSET; - - if (!pointer) { - throw bad_pointer("CGlobalVarsBase"); - } - } - - if (!**(CGlobalVarsBase***)pointer) { - throw bad_pointer("CGlobalVarsBase"); - } - - return **(CGlobalVarsBase***)(pointer); -#else - throw bad_pointer("CGlobalVarsBase"); - - return nullptr; -#endif -} - C_HLTVCamera *Interfaces::GetHLTVCamera() { #if defined _WIN32 static DWORD pointer = NULL; @@ -140,30 +94,6 @@ C_HLTVCamera *Interfaces::GetHLTVCamera() { #endif } -C_TeamplayRoundBasedRules *Interfaces::GetTeamplayRoundBasedRules() { -#if defined _WIN32 - static DWORD pointer = NULL; - - if (!pointer) { - pointer = SignatureScan("client", TEAMPLAYROUNDBASEDRULES_SIG, TEAMPLAYROUNDBASEDRULES_MASK) + TEAMPLAYROUNDBASEDRULES_OFFSET; - - if (!pointer) { - throw bad_pointer("C_TeamplayRoundBasedRules"); - } - } - - if (!**(C_TeamplayRoundBasedRules***)pointer) { - throw bad_pointer("C_TeamplayRoundBasedRules"); - } - - return **(C_TeamplayRoundBasedRules***)(pointer); -#else - throw bad_pointer("C_TeamplayRoundBasedRules"); - - return nullptr; -#endif -} - void Interfaces::Load(CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory) { ConnectTier1Libraries(&interfaceFactory, 1); ConnectTier2Libraries(&interfaceFactory, 1); @@ -171,17 +101,19 @@ void Interfaces::Load(CreateInterfaceFn interfaceFactory, CreateInterfaceFn game vguiLibrariesAvailable = vgui::VGui_InitInterfacesList("statusspec", &interfaceFactory, 1); + pClientEngineTools = (IClientEngineTools *)interfaceFactory(VCLIENTENGINETOOLS_INTERFACE_VERSION, nullptr); pEngineClient = (IVEngineClient *)interfaceFactory(VENGINE_CLIENT_INTERFACE_VERSION, nullptr); + pEngineTool = (IEngineTool *)interfaceFactory(VENGINETOOL_INTERFACE_VERSION, nullptr); pGameEventManager = (IGameEventManager2 *)interfaceFactory(INTERFACEVERSION_GAMEEVENTSMANAGER2, nullptr); pModelInfoClient = (IVModelInfoClient *)interfaceFactory(VMODELINFO_CLIENT_INTERFACE_VERSION, nullptr); pRenderView = (IVRenderView *)interfaceFactory(VENGINE_RENDERVIEW_INTERFACE_VERSION, nullptr); - pClientModule = new CDllDemandLoader(CLIENT_MODULE_FILE); - - CreateInterfaceFn gameClientFactory = pClientModule->GetFactory(); + CreateInterfaceFn gameClientFactory; + pEngineTool->GetClientFactory(gameClientFactory); pClientDLL = (IBaseClientDLL*)gameClientFactory(CLIENT_DLL_INTERFACE_VERSION, nullptr); pClientEntityList = (IClientEntityList*)gameClientFactory(VCLIENTENTITYLIST_INTERFACE_VERSION, nullptr); + pPrediction = (IPrediction *)gameClientFactory(VCLIENT_PREDICTION_INTERFACE_VERSION, nullptr); pSteamAPIContext = new CSteamAPIContext(); steamLibrariesAvailable = SteamAPI_InitSafe() && pSteamAPIContext->Init(); @@ -221,9 +153,6 @@ void Interfaces::Unload() { DisconnectTier1Libraries(); pSteamAPIContext->Clear(); - - pClientModule->Unload(); - pClientModule = nullptr; pClientDLL = nullptr; pClientEntityList = nullptr; diff --git a/src/ifaces.h b/src/ifaces.h index 6ac12b1..296d635 100644 --- a/src/ifaces.h +++ b/src/ifaces.h @@ -2,7 +2,7 @@ * ifaces.h * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -13,15 +13,15 @@ #include "interface.h" class C_HLTVCamera; -class C_TeamplayRoundBasedRules; -class CGlobalVarsBase; class CSteamAPIContext; class IBaseClientDLL; +class IClientEngineTools; class IClientEntityList; class IClientMode; +class IEngineTool; class IFileSystem; class IGameEventManager2; -class IGameResources; +class IPrediction; class IVEngineClient; class IVModelInfoClient; class IVRenderView; @@ -32,11 +32,14 @@ class Interfaces { static void Unload(); static IBaseClientDLL *pClientDLL; + static IClientEngineTools *pClientEngineTools; static IClientEntityList *pClientEntityList; static IVEngineClient *pEngineClient; + static IEngineTool *pEngineTool; static IFileSystem *pFileSystem; static IGameEventManager2 *pGameEventManager; static IVModelInfoClient *pModelInfoClient; + static IPrediction *pPrediction; static IVRenderView *pRenderView; static CSteamAPIContext *pSteamAPIContext; @@ -44,10 +47,5 @@ class Interfaces { static bool vguiLibrariesAvailable; static IClientMode *GetClientMode(); - static IGameResources *GetGameResources(); - static CGlobalVarsBase *GetGlobalVars(); static C_HLTVCamera *GetHLTVCamera(); - static C_TeamplayRoundBasedRules *GetTeamplayRoundBasedRules(); - private: - static CDllDemandLoader *pClientModule; }; \ No newline at end of file diff --git a/src/itemschema.cpp b/src/itemschema.cpp deleted file mode 100644 index e076775..0000000 --- a/src/itemschema.cpp +++ /dev/null @@ -1,323 +0,0 @@ -/* - * itemschema.cpp - * StatusSpec project - * - * Copyright (c) 2014 thesupremecommander - * BSD 2-Clause License - * http://opensource.org/licenses/BSD-2-Clause - * - */ - -#include "itemschema.h" - -#include -#include - -#include "filesystem.h" -#include "KeyValues.h" - -#include "common.h" -#include "ifaces.h" - -ItemSchema::ItemSchema() { - itemSchema = new KeyValues("items_game"); - itemSchema->LoadFromFile(Interfaces::pFileSystem, "scripts/items/items_game.txt", "mod"); - - itemInfo = itemSchema->FindKey("items"); - prefabInfo = itemSchema->FindKey("prefabs"); -} - -ItemSchema::~ItemSchema() { - itemSchema->deleteThis(); - itemInfo->deleteThis(); - prefabInfo->deleteThis(); -} - -KeyValues *ItemSchema::GetItemKey(int itemDefinitionIndex, const char *keyName) { - KeyValues *item = itemInfo->FindKey(std::to_string((long long) itemDefinitionIndex).c_str()); - - if (!item) { - return NULL; - } - - KeyValues *value = item->FindKey(keyName, false); - - if (value) { - return value; - } - - int level = -1; - int prefabLevel; - KeyValues *prefabValue; - - std::string prefabs = item->GetString("prefab", ""); - std::stringstream ss(prefabs); - std::string prefabName; - while (std::getline(ss, prefabName, ' ')) { - prefabLevel = 1; - prefabValue = GetPrefabKey(prefabName.c_str(), keyName, prefabLevel); - - if (prefabValue && (level == -1 || prefabLevel < level)) { - value = prefabValue; - level = prefabLevel; - } - } - - return value; -} - -KeyValues *ItemSchema::GetItemKey(const char *itemDefinitionIndex, const char *keyName) { - KeyValues *item = itemInfo->FindKey(itemDefinitionIndex); - - if (!item) { - return NULL; - } - - KeyValues *value = item->FindKey(keyName, false); - - if (value) { - return value; - } - - int level = -1; - int prefabLevel; - KeyValues *prefabValue; - - std::string prefabs = item->GetString("prefab", ""); - std::stringstream ss(prefabs); - std::string prefabName; - while (std::getline(ss, prefabName, ' ')) { - prefabLevel = 1; - prefabValue = GetPrefabKey(prefabName.c_str(), keyName, prefabLevel); - - if (prefabValue && (level == -1 || prefabLevel < level)) { - value = prefabValue; - level = prefabLevel; - } - } - - return value; -} - -KeyValues *ItemSchema::GetPrefabKey(const char *prefabName, const char *keyName) { - KeyValues *prefab = prefabInfo->FindKey(prefabName); - - if (prefab == NULL) { - return NULL; - } - - KeyValues *value = prefab->FindKey(keyName, false); - - if (value != NULL) { - return value; - } - - int level = -1; - int prefabLevel; - KeyValues *prefabValue; - - std::string subprefabs = prefab->GetString("prefab", ""); - std::stringstream ss(subprefabs); - std::string subprefabName; - while (std::getline(ss, subprefabName, ' ')) { - prefabLevel = 1; - prefabValue = GetPrefabKey(subprefabName.c_str(), keyName, prefabLevel); - - if (prefabValue != NULL && (level == -1 || prefabLevel < level)) { - value = prefabValue; - level = prefabLevel; - } - } - - return value; -} - -KeyValues *ItemSchema::GetPrefabKey(const char *prefabName, const char *keyName, int &level) { - KeyValues *prefab = prefabInfo->FindKey(prefabName); - - if (prefab == NULL) { - return NULL; - } - - KeyValues *value = prefab->FindKey(keyName, false); - - if (value != NULL) { - return value; - } - - int nextLevel = level + 1; - int prefabLevel; - level = -1; - KeyValues *prefabValue; - - std::string subprefabs = prefab->GetString("prefab", ""); - std::stringstream ss(subprefabs); - std::string subprefabName; - while (std::getline(ss, subprefabName, ' ')) { - prefabLevel = nextLevel; - prefabValue = GetPrefabKey(subprefabName.c_str(), keyName, prefabLevel); - - if (prefabValue != NULL && (level == -1 || prefabLevel < level)) { - value = prefabValue; - level = prefabLevel; - } - } - - return value; -} - -const char *ItemSchema::GetItemKeyData(int itemDefinitionIndex, const char *keyName) { - KeyValues *item = itemInfo->FindKey(std::to_string((long long) itemDefinitionIndex).c_str()); - - if (!item) { - return NULL; - } - - const char *value = item->GetString(keyName, NULL); - - if (value) { - return value; - } - - int level = -1; - int prefabLevel; - const char *prefabValue; - - std::string prefabs = item->GetString("prefab", ""); - std::stringstream ss(prefabs); - std::string prefabName; - while (std::getline(ss, prefabName, ' ')) { - prefabLevel = 1; - prefabValue = GetPrefabKeyData(prefabName.c_str(), keyName, prefabLevel); - - if (prefabValue && (level == -1 || prefabLevel < level)) { - value = prefabValue; - level = prefabLevel; - } - } - - return value; -} - -const char *ItemSchema::GetItemKeyData(const char *itemDefinitionIndex, const char *keyName) { - KeyValues *item = itemInfo->FindKey(itemDefinitionIndex); - - if (!item) { - return NULL; - } - - const char *value = item->GetString(keyName, NULL); - - if (value) { - return value; - } - - int level = -1; - int prefabLevel; - const char *prefabValue; - - std::string prefabs = item->GetString("prefab", ""); - std::stringstream ss(prefabs); - std::string prefabName; - while (std::getline(ss, prefabName, ' ')) { - prefabLevel = 1; - prefabValue = GetPrefabKeyData(prefabName.c_str(), keyName, prefabLevel); - - if (prefabValue && (level == -1 || prefabLevel < level)) { - value = prefabValue; - level = prefabLevel; - } - } - - return value; -} - -const char *ItemSchema::GetPrefabKeyData(const char *prefabName, const char *keyName) { - KeyValues *prefab = prefabInfo->FindKey(prefabName); - - if (prefab == NULL) { - return NULL; - } - - const char *value = prefab->GetString(keyName, NULL); - - if (value != NULL) { - return value; - } - - int level = -1; - int prefabLevel; - const char *prefabValue; - - std::string subprefabs = prefab->GetString("prefab", ""); - std::stringstream ss(subprefabs); - std::string subprefabName; - while (std::getline(ss, subprefabName, ' ')) { - prefabLevel = 1; - prefabValue = GetPrefabKeyData(subprefabName.c_str(), keyName, prefabLevel); - - if (prefabValue != NULL && (level == -1 || prefabLevel < level)) { - value = prefabValue; - level = prefabLevel; - } - } - - return value; -} - -const char *ItemSchema::GetPrefabKeyData(const char *prefabName, const char *keyName, int &level) { - KeyValues *prefab = prefabInfo->FindKey(prefabName); - - if (prefab == NULL) { - return NULL; - } - - const char *value = prefab->GetString(keyName, NULL); - - if (value != NULL) { - return value; - } - - int nextLevel = level + 1; - int prefabLevel; - level = -1; - const char *prefabValue; - - std::string subprefabs = prefab->GetString("prefab", ""); - std::stringstream ss(subprefabs); - std::string subprefabName; - while (std::getline(ss, subprefabName, ' ')) { - prefabLevel = nextLevel; - prefabValue = GetPrefabKeyData(subprefabName.c_str(), keyName, prefabLevel); - - if (prefabValue != NULL && (level == -1 || prefabLevel < level)) { - value = prefabValue; - level = prefabLevel; - } - } - - return value; -} - -void ItemSchema::ForEachItem(void (*f)(const char *)) { - for (KeyValues *item = itemInfo->GetFirstTrueSubKey(); item; item = item->GetNextTrueSubKey()) { - f(item->GetName()); - } -} - -bool ItemSchema::CheckDependencies() { - KeyValues *itemSchema = new KeyValues("items_game"); - - if (Interfaces::pFileSystem && itemSchema->LoadFromFile(Interfaces::pFileSystem, "scripts/items/items_game.txt", "mod")) { - itemSchema->deleteThis(); - return true; - } - else { - PRINT_TAG(); - Warning("Unable to load item schema from filesystem!\n"); - - itemSchema->deleteThis(); - - return false; - } -} \ No newline at end of file diff --git a/src/itemschema.h b/src/itemschema.h deleted file mode 100644 index 61480f9..0000000 --- a/src/itemschema.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * itemschema.h - * StatusSpec project - * - * Copyright (c) 2014 thesupremecommander - * BSD 2-Clause License - * http://opensource.org/licenses/BSD-2-Clause - * - */ - -#pragma once - -class KeyValues; - -class ItemSchema { - public: - ItemSchema(); - ~ItemSchema(); - KeyValues *GetItemKey(int itemDefinitionIndex, const char *keyName); - KeyValues *GetItemKey(const char *itemDefinitionIndex, const char *keyName); - KeyValues *GetPrefabKey(const char *prefabName, const char *keyName); - const char *GetItemKeyData(int itemDefinitionIndex, const char *keyName); - const char *GetItemKeyData(const char *itemDefinitionIndex, const char *keyName); - const char *GetPrefabKeyData(const char *prefabName, const char *keyName); - void ForEachItem(void (*f)(const char *)); - - static bool CheckDependencies(); - private: - KeyValues *itemSchema; - KeyValues *itemInfo; - KeyValues *prefabInfo; - KeyValues *GetPrefabKey(const char *prefabName, const char *keyName, int &level); - const char *GetPrefabKeyData(const char *prefabName, const char *keyName, int &level); -}; \ No newline at end of file diff --git a/src/modules.cpp b/src/modules.cpp deleted file mode 100644 index ca604d9..0000000 --- a/src/modules.cpp +++ /dev/null @@ -1,26 +0,0 @@ -/* - * modules.cpp - * StatusSpec project - * - * Copyright (c) 2014 thesupremecommander - * BSD 2-Clause License - * http://opensource.org/licenses/BSD-2-Clause - * - */ - -#pragma once - -#include "modules.h" - -#include "common.h" - -void ModuleManager::UnloadAllModules() { - for (auto iterator = modules.begin(); iterator != modules.end(); ++iterator) { - PRINT_TAG(); - ConColorMsg(Color(0, 255, 0, 255), "Module %s unloaded!\n", iterator->first.c_str()); - - delete iterator->second; - } - - modules.clear(); -} \ No newline at end of file diff --git a/src/modules.h b/src/modules.h index 61be3d3..d18e5c0 100644 --- a/src/modules.h +++ b/src/modules.h @@ -2,7 +2,7 @@ * module.h * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -12,32 +12,52 @@ #include #include +#include +#include "common.h" #include "exceptions.h" class Module { public: virtual ~Module() = default; - static bool CheckDependencies(std::string name) { return true; }; -protected: - Module(std::string name) : name(name) {}; - - std::string name; + static bool CheckDependencies() { return true; }; }; class ModuleManager { public: - template bool LoadModule(std::string moduleName); - template ModuleType *GetModule(std::string moduleName); + template ModuleType *GetModule(); + template std::string GetModuleName(); + template bool RegisterAndLoadModule(std::string moduleName); void UnloadAllModules(); private: - std::map modules; + std::map modules; + std::map moduleNames; }; -template inline bool ModuleManager::LoadModule(std::string moduleName) { - if (ModuleType::CheckDependencies(moduleName)) { - modules[moduleName] = new ModuleType(moduleName); +template inline ModuleType *ModuleManager::GetModule() { + if (modules.find(typeid(ModuleType)) != modules.end()) { + return dynamic_cast(modules[typeid(ModuleType)]); + } + else { + throw module_not_loaded(GetModuleName().c_str()); + } +} + +template inline std::string ModuleManager::GetModuleName() { + if (moduleNames.find(typeid(ModuleType)) != moduleNames.end()) { + return moduleNames[typeid(ModuleType)]; + } + else { + return "[Unknown]"; + } +} + +template inline bool ModuleManager::RegisterAndLoadModule(std::string moduleName) { + moduleNames[typeid(ModuleType)] = moduleName; + + if (ModuleType::CheckDependencies()) { + modules[typeid(ModuleType)] = new ModuleType(); PRINT_TAG(); ConColorMsg(Color(0, 255, 0, 255), "Module %s loaded successfully!\n", moduleName.c_str()); @@ -52,13 +72,15 @@ template inline bool ModuleManager::LoadModule(std::string } } -template inline ModuleType *ModuleManager::GetModule(std::string moduleName) { - if (modules.find(moduleName) != modules.end()) { - return dynamic_cast(modules.find(moduleName)->second); - } - else { - throw module_not_loaded(moduleName.c_str()); +inline void ModuleManager::UnloadAllModules() { + for (auto iterator : modules) { + PRINT_TAG(); + ConColorMsg(Color(0, 255, 0, 255), "Module %s unloaded!\n", moduleNames[iterator.first].c_str()); + + delete iterator.second; } + + modules.clear(); } extern ModuleManager *g_ModuleManager; \ No newline at end of file diff --git a/src/modules/antifreeze.cpp b/src/modules/antifreeze.cpp index 3d637df..500d264 100644 --- a/src/modules/antifreeze.cpp +++ b/src/modules/antifreeze.cpp @@ -2,7 +2,7 @@ * antifreeze.cpp * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -11,119 +11,57 @@ #include "antifreeze.h" #include "cbase.h" -#include "c_baseentity.h" #include "convar.h" -#include "KeyValues.h" -#include "icliententity.h" -#include "icliententitylist.h" #include "iclientmode.h" -#include "teamplay_round_timer.h" #include "tier3/tier3.h" +#include "toolframework/ienginetool.h" #include "vgui/IPanel.h" #include "vgui/IVGui.h" -#include "vgui_controls/EditablePanel.h" +#include "vgui_controls/Panel.h" #include "../common.h" -#include "../entities.h" -#include "../exceptions.h" -#include "../funcs.h" #include "../ifaces.h" -#define REAL_TIME_NAME "RealTime" -#define REGULAR_TIME_NAME "TimePanelValue" +class AntiFreeze::Panel : public vgui::Panel { +public: + Panel(vgui::Panel *parent, const char *panelName); -AntiFreeze::AntiFreeze(std::string name) : Module(name) { - bluTime = 0; - bluTimerPanel = vgui::INVALID_PANEL; - entitiesUpdated = false; - frameHook = 0; - freezeInfoPanel = nullptr; - lastEntityUpdate = Plat_FloatTime(); - mainTime = 0; - mainTimerPanel = vgui::INVALID_PANEL; - performLayoutCommand = new KeyValues("Command", "Command", "performlayout"); - redTime = 0; - redTimerPanel = vgui::INVALID_PANEL; - specguiPanel = vgui::INVALID_PANEL; - stopwatchTime = 0; - stopwatchTimerPanel = vgui::INVALID_PANEL; + virtual void OnTick(); +}; - display = new ConVar("statusspec_antifreeze_display", "0", FCVAR_NONE, "enables display of an info panel when a freeze is detected", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule("AntiFreeze")->ToggleDisplay(var, pOldValue, flOldValue); }); - display_reload_settings = new ConCommand("statusspec_antifreeze_display_reload_settings", []() { g_ModuleManager->GetModule("AntiFreeze")->ReloadSettings(); }, "reload settings for the freeze info panel from the resource file", FCVAR_NONE); - display_threshold = new ConVar("statusspec_antifreeze_display_threshold", "1", FCVAR_NONE, "the time of a freeze (in seconds) before the info panel is displayed"); - enabled = new ConVar("statusspec_antifreeze_enabled", "0", FCVAR_NONE, "enable antifreeze (forces the spectator GUI to refresh)", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule("AntiFreeze")->ToggleEnabled(var, pOldValue, flOldValue); }); - timers = new ConVar("statusspec_antifreeze_timers", "0", FCVAR_NONE, "enable forcing of timers to right values", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule("AntiFreeze")->ToggleTimers(var, pOldValue, flOldValue); }); +AntiFreeze::AntiFreeze() { + panel = nullptr; + + enabled = new ConVar("statusspec_antifreeze_enabled", "0", FCVAR_NONE, "enable antifreeze (forces the spectator GUI to refresh)", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule()->ToggleEnabled(var, pOldValue, flOldValue); }); } -bool AntiFreeze::CheckDependencies(std::string name) { +bool AntiFreeze::CheckDependencies() { bool ready = true; - if (!Interfaces::pClientEntityList) { - PRINT_TAG(); - Warning("Required interface IClientEntityList for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!Interfaces::pClientDLL) { - PRINT_TAG(); - Warning("Required interface IBaseClientDLL for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!Interfaces::pEngineClient) { + if (!Interfaces::pEngineTool) { PRINT_TAG(); - Warning("Required interface IVEngineClient for module %s not available!\n", name.c_str()); + Warning("Required interface IEngineTool for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Interfaces::vguiLibrariesAvailable) { PRINT_TAG(); - Warning("Required VGUI library for module %s not available!\n", name.c_str()); + Warning("Required VGUI library for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!g_pVGui) { PRINT_TAG(); - Warning("Required interface vgui::IVGui for module %s not available!\n", name.c_str()); + Warning("Required interface vgui::IVGui for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!g_pVGuiPanel) { PRINT_TAG(); - Warning("Required interface vgui::IPanel for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!Entities::RetrieveClassPropOffset("CTFObjectiveResource", { "m_iTimerToShowInHUD" })) { - PRINT_TAG(); - Warning("Required property m_iTimerToShowInHUD for CTFObjectiveResource for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!Entities::RetrieveClassPropOffset("CTFObjectiveResource", { "m_iStopWatchTimer" })) { - PRINT_TAG(); - Warning("Required property m_iStopWatchTimer for CTFObjectiveResource for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!Entities::RetrieveClassPropOffset("CTFGameRulesProxy", { "m_hRedKothTimer" })) { - PRINT_TAG(); - Warning("Required property m_hRedKothTimer for CTFGameRulesProxy for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!Entities::RetrieveClassPropOffset("CTFGameRulesProxy", { "m_hBlueKothTimer" })) { - PRINT_TAG(); - Warning("Required property m_hBlueKothTimer for CTFGameRulesProxy for module %s not available!\n", name.c_str()); + Warning("Required interface vgui::IPanel for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } @@ -133,466 +71,63 @@ bool AntiFreeze::CheckDependencies(std::string name) { } catch (bad_pointer) { PRINT_TAG(); - Warning("Module %s requires IClientMode, which cannot be verified at this time!\n", name.c_str()); + Warning("Module %s requires IClientMode, which cannot be verified at this time!\n", g_ModuleManager->GetModuleName().c_str()); } return ready; } -void AntiFreeze::FrameHook(ClientFrameStage_t curStage) { - if (curStage == FRAME_NET_UPDATE_END) { - if (display->GetBool()) { - lastEntityUpdate = Plat_FloatTime(); - } - - if (enabled->GetBool()) { - GetSpecGUI(); - - if (specguiPanel != vgui::INVALID_PANEL) { - vgui::VPANEL specguiVPanel = g_pVGui->HandleToPanel(specguiPanel); - - g_pVGuiPanel->SendMessage(specguiVPanel, performLayoutCommand, specguiVPanel); - } - } - - if (timers->GetBool()) { - int maxEntity = Interfaces::pClientEntityList->GetHighestEntityIndex(); - - for (int i = 0; i < maxEntity; i++) { - IClientEntity *entity = Interfaces::pClientEntityList->GetClientEntity(i); - - if (entity) { - if (Entities::CheckEntityBaseclass(entity, "TFObjectiveResource")) { - IClientEntity *mainEntity = Interfaces::pClientEntityList->GetClientEntity(*Entities::GetEntityProp(entity, { "m_iTimerToShowInHUD" })); - - if (mainEntity && Entities::CheckEntityBaseclass(mainEntity, "TeamRoundTimer")) { - C_TeamRoundTimer *mainTimer = dynamic_cast(mainEntity); - - if (mainTimer) { - mainTime = mainTimer->GetTimeRemaining(); - } - } - - IClientEntity *stopwatchEntity = Interfaces::pClientEntityList->GetClientEntity(*Entities::GetEntityProp(entity, { "m_iStopWatchTimer" })); - - if (stopwatchEntity && Entities::CheckEntityBaseclass(stopwatchEntity, "TeamRoundTimer")) { - C_TeamRoundTimer *stopwatchTimer = dynamic_cast(stopwatchEntity); - - if (stopwatchTimer) { - stopwatchTime = stopwatchTimer->GetTimeRemaining(); - } - } - } - else if (Entities::CheckEntityBaseclass(entity, "TFGameRulesProxy")) { - IClientEntity *redEntity = Entities::GetEntityProp(entity, { "m_hRedKothTimer" })->Get(); - - if (redEntity && Entities::CheckEntityBaseclass(redEntity, "TeamRoundTimer")) { - C_TeamRoundTimer *redTimer = dynamic_cast(redEntity); - - if (redTimer) { - redTime = redTimer->GetTimeRemaining(); - } - } - - IClientEntity *bluEntity = Entities::GetEntityProp(entity, { "m_hBlueKothTimer" })->Get(); - - if (bluEntity && Entities::CheckEntityBaseclass(bluEntity, "TeamRoundTimer")) { - C_TeamRoundTimer *bluTimer = dynamic_cast(bluEntity); - - if (bluTimer) { - bluTime = bluTimer->GetTimeRemaining(); - } - } - } - } - } - } - } - else if (curStage == FRAME_START) { - if (display->GetBool() && Interfaces::pEngineClient->IsInGame()) { - double freezeTime = Plat_FloatTime() - lastEntityUpdate; - - if (freezeTime >= display_threshold->GetFloat()) { - int seconds = int(floor(freezeTime)) % 60; - int minutes = int(floor(freezeTime)) / 60; - - char *formattedTime = new char[16]; - V_snprintf(formattedTime, 15, "%i:%02i", minutes, seconds); - - if (freezeInfoPanel) { - freezeInfoPanel->SetDialogVariable("time", formattedTime); - freezeInfoPanel->SetVisible(true); - } - } - else { - if (freezeInfoPanel) { - freezeInfoPanel->SetVisible(false); - } - } - } - - if (timers->GetBool() && Interfaces::pEngineClient->IsInGame()) { - GetTimers(); - - InitTimers(true); - - if (mainTimerPanel != vgui::INVALID_PANEL) { - vgui::VPANEL mainTimerVPanel = g_pVGui->HandleToPanel(mainTimerPanel); - - for (int i = 0; i < g_pVGuiPanel->GetChildCount(mainTimerVPanel); i++) { - vgui::VPANEL mainTimerValue = g_pVGuiPanel->GetChild(mainTimerVPanel, i); - - if (strcmp(g_pVGuiPanel->GetName(mainTimerValue), REAL_TIME_NAME) == 0) { - int mainSeconds = int(floor(mainTime)) % 60; - int mainMinutes = int(floor(mainTime)) / 60; - - char *mainFormattedTime = new char[16]; - V_snprintf(mainFormattedTime, 15, "%i:%02i", mainMinutes, mainSeconds); - - g_pVGuiPanel->SendMessage(mainTimerValue, new KeyValues("SetText", "text", mainFormattedTime), mainTimerVPanel); - - break; - } - } - } - - if (stopwatchTimerPanel != vgui::INVALID_PANEL) { - vgui::VPANEL stopwatchTimerVPanel = g_pVGui->HandleToPanel(stopwatchTimerPanel); - - for (int i = 0; i < g_pVGuiPanel->GetChildCount(stopwatchTimerVPanel); i++) { - vgui::VPANEL stopwatchTimerValue = g_pVGuiPanel->GetChild(stopwatchTimerVPanel, i); - - if (strcmp(g_pVGuiPanel->GetName(stopwatchTimerValue), REAL_TIME_NAME) == 0) { - int stopwatchSeconds = int(floor(stopwatchTime)) % 60; - int stopwatchMinutes = int(floor(stopwatchTime)) / 60; - - char *stopwatchFormattedTime = new char[16]; - V_snprintf(stopwatchFormattedTime, 15, "%i:%02i", stopwatchMinutes, stopwatchSeconds); - - g_pVGuiPanel->SendMessage(stopwatchTimerValue, new KeyValues("SetText", "text", stopwatchFormattedTime), stopwatchTimerVPanel); - - break; - } - } - } - - if (redTimerPanel == vgui::INVALID_PANEL) { - vgui::VPANEL redTimerVPanel = g_pVGui->HandleToPanel(redTimerPanel); - - for (int i = 0; i < g_pVGuiPanel->GetChildCount(redTimerVPanel); i++) { - vgui::VPANEL redTimerValue = g_pVGuiPanel->GetChild(redTimerVPanel, i); - - if (strcmp(g_pVGuiPanel->GetName(redTimerValue), REAL_TIME_NAME) == 0) { - int redSeconds = int(floor(redTime)) % 60; - int redMinutes = int(floor(redTime)) / 60; - - char *redFormattedTime = new char[16]; - V_snprintf(redFormattedTime, 15, "%i:%02i", redMinutes, redSeconds); - - g_pVGuiPanel->SendMessage(redTimerValue, new KeyValues("SetText", "text", redFormattedTime), redTimerVPanel); - - break; - } - } - } - - if (bluTimerPanel == vgui::INVALID_PANEL) { - vgui::VPANEL bluTimerVPanel = g_pVGui->HandleToPanel(bluTimerPanel); - - for (int i = 0; i < g_pVGuiPanel->GetChildCount(bluTimerVPanel); i++) { - vgui::VPANEL bluTimerValue = g_pVGuiPanel->GetChild(bluTimerVPanel, i); - - if (strcmp(g_pVGuiPanel->GetName(bluTimerValue), REAL_TIME_NAME) == 0) { - int bluSeconds = int(floor(bluTime)) % 60; - int bluMinutes = int(floor(bluTime)) / 60; - - char *bluFormattedTime = new char[16]; - V_snprintf(bluFormattedTime, 15, "%i:%02i", bluMinutes, bluSeconds); - - g_pVGuiPanel->SendMessage(bluTimerValue, new KeyValues("SetText", "text", bluFormattedTime), bluTimerVPanel); - - break; - } - } - } - } - } - - RETURN_META(MRES_IGNORED); -} - -void AntiFreeze::GetSpecGUI() { - if (specguiPanel == vgui::INVALID_PANEL) { - vgui::Panel *viewport = Interfaces::GetClientMode()->GetViewport(); - - if (viewport) { - for (int i = 0; i < g_pVGuiPanel->GetChildCount(viewport->GetVPanel()); i++) { - vgui::VPANEL panel = g_pVGuiPanel->GetChild(viewport->GetVPanel(), i); - - if (strcmp(g_pVGuiPanel->GetName(panel), "specgui") == 0) { - specguiPanel = g_pVGui->PanelToHandle(panel); - - break; - } - } - } - } -} - -void AntiFreeze::GetTimers() { - if (mainTimerPanel == vgui::INVALID_PANEL) { - vgui::Panel *viewport = Interfaces::GetClientMode()->GetViewport(); - - if (viewport) { - for (int i = 0; i < g_pVGuiPanel->GetChildCount(viewport->GetVPanel()); i++) { - vgui::VPANEL specgui = g_pVGuiPanel->GetChild(viewport->GetVPanel(), i); - - if (strcmp(g_pVGuiPanel->GetName(specgui), "specgui") == 0) { - for (int i = 0; i < g_pVGuiPanel->GetChildCount(specgui); i++) { - vgui::VPANEL objectiveStatus = g_pVGuiPanel->GetChild(specgui, i); - - if (strcmp(g_pVGuiPanel->GetName(objectiveStatus), "HudObjectiveStatus") == 0) { - for (int i = 0; i < g_pVGuiPanel->GetChildCount(objectiveStatus); i++) { - vgui::VPANEL objectiveStatusTimer = g_pVGuiPanel->GetChild(objectiveStatus, i); - - if (strcmp(g_pVGuiPanel->GetName(objectiveStatusTimer), "ObjectiveStatusTimePanel") == 0) { - mainTimerPanel = g_pVGui->PanelToHandle(objectiveStatusTimer); - - break; - } - } - - break; - } - } - } - } - } - } - - if (stopwatchTimerPanel == vgui::INVALID_PANEL) { - vgui::Panel *viewport = Interfaces::GetClientMode()->GetViewport(); - - if (viewport) { - for (int i = 0; i < g_pVGuiPanel->GetChildCount(viewport->GetVPanel()); i++) { - vgui::VPANEL stopwatch = g_pVGuiPanel->GetChild(viewport->GetVPanel(), i); - - if (strcmp(g_pVGuiPanel->GetName(stopwatch), "HudStopWatch") == 0) { - for (int i = 0; i < g_pVGuiPanel->GetChildCount(stopwatch); i++) { - vgui::VPANEL stopwatchTimer = g_pVGuiPanel->GetChild(stopwatch, i); - - if (strcmp(g_pVGuiPanel->GetName(stopwatchTimer), "ObjectiveStatusTimePanel") == 0) { - stopwatchTimerPanel = g_pVGui->PanelToHandle(stopwatchTimer); - - break; - } - } - - break; - } - } - } - } - - if (redTimerPanel == vgui::INVALID_PANEL) { - vgui::Panel *viewport = Interfaces::GetClientMode()->GetViewport(); - - if (viewport) { - for (int i = 0; i < g_pVGuiPanel->GetChildCount(viewport->GetVPanel()); i++) { - vgui::VPANEL kothTime = g_pVGuiPanel->GetChild(viewport->GetVPanel(), i); +void AntiFreeze::ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue) { + if (enabled->GetBool()) { + if (!panel) { + try { + vgui::Panel *viewport = Interfaces::GetClientMode()->GetViewport(); - if (strcmp(g_pVGuiPanel->GetName(kothTime), "HudKothTimeStatus") == 0) { - for (int i = 0; i < g_pVGuiPanel->GetChildCount(kothTime); i++) { - vgui::VPANEL redTimer = g_pVGuiPanel->GetChild(kothTime, i); + if (viewport) { + for (int i = 0; i < g_pVGuiPanel->GetChildCount(viewport->GetVPanel()); i++) { + vgui::VPANEL childPanel = g_pVGuiPanel->GetChild(viewport->GetVPanel(), i); - if (strcmp(g_pVGuiPanel->GetName(redTimer), "RedTimer") == 0) { - redTimerPanel = g_pVGui->PanelToHandle(redTimer); + if (strcmp(g_pVGuiPanel->GetName(childPanel), "specgui") == 0) { + panel = new Panel(viewport, "AntiFreeze"); + panel->SetParent(childPanel); - break; + return; } } - break; + Warning("Could not initialize the panel!\n"); + var->SetValue(0); } - } - } - } - - if (bluTimerPanel == vgui::INVALID_PANEL) { - vgui::Panel *viewport = Interfaces::GetClientMode()->GetViewport(); - - if (viewport) { - for (int i = 0; i < g_pVGuiPanel->GetChildCount(viewport->GetVPanel()); i++) { - vgui::VPANEL kothTime = g_pVGuiPanel->GetChild(viewport->GetVPanel(), i); - - if (strcmp(g_pVGuiPanel->GetName(kothTime), "HudKothTimeStatus") == 0) { - for (int i = 0; i < g_pVGuiPanel->GetChildCount(kothTime); i++) { - vgui::VPANEL bluTimer = g_pVGuiPanel->GetChild(kothTime, i); - - if (strcmp(g_pVGuiPanel->GetName(bluTimer), "BlueTimer") == 0) { - bluTimerPanel = g_pVGui->PanelToHandle(bluTimer); - - break; - } - } - - break; + else { + Warning("Could not initialize the panel!\n"); + var->SetValue(0); } } - } - } -} - -void AntiFreeze::InitHUD() { - if (!freezeInfoPanel) { - vgui::Panel *viewport = Interfaces::GetClientMode()->GetViewport(); - - if (viewport) { - freezeInfoPanel = new vgui::EditablePanel(viewport, "FreezeInfo"); - g_pVGuiPanel->Init(g_pVGui->AllocPanel(), freezeInfoPanel); - - freezeInfoPanel->LoadControlSettings("Resource/UI/FreezeInfo.res"); - - freezeInfoPanel->SetVisible(false); - } - } -} - -void AntiFreeze::InitTimers(bool moduleTime) { - GetTimers(); - - if (mainTimerPanel != vgui::INVALID_PANEL) { - vgui::VPANEL mainTimerVPanel = g_pVGui->HandleToPanel(mainTimerPanel); - - for (int i = 0; i < g_pVGuiPanel->GetChildCount(mainTimerVPanel); i++) { - vgui::VPANEL mainTimerValue = g_pVGuiPanel->GetChild(mainTimerVPanel, i); - - if (strcmp(g_pVGuiPanel->GetName(mainTimerValue), REAL_TIME_NAME) == 0) { - g_pVGuiPanel->SetEnabled(mainTimerValue, moduleTime); - g_pVGuiPanel->SetVisible(mainTimerValue, moduleTime); - } - else if (strcmp(g_pVGuiPanel->GetName(mainTimerValue), REGULAR_TIME_NAME) == 0) { - g_pVGuiPanel->SetEnabled(mainTimerValue, !moduleTime); - g_pVGuiPanel->SetVisible(mainTimerValue, !moduleTime); - } - } - } - - if (stopwatchTimerPanel != vgui::INVALID_PANEL) { - vgui::VPANEL stopwatchTimerVPanel = g_pVGui->HandleToPanel(stopwatchTimerPanel); - - for (int i = 0; i < g_pVGuiPanel->GetChildCount(stopwatchTimerVPanel); i++) { - vgui::VPANEL stopwatchTimerValue = g_pVGuiPanel->GetChild(stopwatchTimerVPanel, i); - - if (strcmp(g_pVGuiPanel->GetName(stopwatchTimerValue), REAL_TIME_NAME) == 0) { - g_pVGuiPanel->SetEnabled(stopwatchTimerValue, moduleTime); - g_pVGuiPanel->SetVisible(stopwatchTimerValue, moduleTime); - } - else if (strcmp(g_pVGuiPanel->GetName(stopwatchTimerValue), REGULAR_TIME_NAME) == 0) { - g_pVGuiPanel->SetEnabled(stopwatchTimerValue, !moduleTime); - g_pVGuiPanel->SetVisible(stopwatchTimerValue, !moduleTime); - } - } - } - - if (redTimerPanel == vgui::INVALID_PANEL) { - vgui::VPANEL redTimerVPanel = g_pVGui->HandleToPanel(redTimerPanel); - - for (int i = 0; i < g_pVGuiPanel->GetChildCount(redTimerVPanel); i++) { - vgui::VPANEL redTimerValue = g_pVGuiPanel->GetChild(redTimerVPanel, i); - - if (strcmp(g_pVGuiPanel->GetName(redTimerValue), REAL_TIME_NAME) == 0) { - g_pVGuiPanel->SetEnabled(redTimerValue, moduleTime); - g_pVGuiPanel->SetVisible(redTimerValue, moduleTime); - } - else if (strcmp(g_pVGuiPanel->GetName(redTimerValue), REGULAR_TIME_NAME) == 0) { - g_pVGuiPanel->SetEnabled(redTimerValue, !moduleTime); - g_pVGuiPanel->SetVisible(redTimerValue, !moduleTime); + catch (bad_pointer) { + Warning("Could not initialize the panel!\n"); + var->SetValue(0); } } - } - - if (bluTimerPanel == vgui::INVALID_PANEL) { - vgui::VPANEL bluTimerVPanel = g_pVGui->HandleToPanel(bluTimerPanel); - - for (int i = 0; i < g_pVGuiPanel->GetChildCount(bluTimerVPanel); i++) { - vgui::VPANEL bluTimerValue = g_pVGuiPanel->GetChild(bluTimerVPanel, i); - if (strcmp(g_pVGuiPanel->GetName(bluTimerValue), REAL_TIME_NAME) == 0) { - g_pVGuiPanel->SetEnabled(bluTimerValue, moduleTime); - g_pVGuiPanel->SetVisible(bluTimerValue, moduleTime); - } - else if (strcmp(g_pVGuiPanel->GetName(bluTimerValue), REGULAR_TIME_NAME) == 0) { - g_pVGuiPanel->SetEnabled(bluTimerValue, !moduleTime); - g_pVGuiPanel->SetVisible(bluTimerValue, !moduleTime); - } - } - } -} - -void AntiFreeze::ReloadSettings() { - if (freezeInfoPanel) { - freezeInfoPanel->LoadControlSettings("Resource/UI/FreezeInfo.res"); - } -} - -void AntiFreeze::ToggleDisplay(IConVar *var, const char *pOldValue, float flOldValue) { - if (display->GetBool()) { - InitHUD(); - - if (!frameHook) { - frameHook = Funcs::AddHook_IBaseClientDLL_FrameStageNotify(Interfaces::pClientDLL, SH_MEMBER(this, &AntiFreeze::FrameHook), true); - } - - if (freezeInfoPanel) { - freezeInfoPanel->SetEnabled(true); - freezeInfoPanel->SetVisible(false); + if (panel) { + panel->SetEnabled(true); } } else { - if (!enabled->GetBool() && !timers->GetBool() && frameHook) { - if (Funcs::RemoveHook(frameHook)) { - frameHook = 0; - } - } - - if (freezeInfoPanel) { - freezeInfoPanel->SetEnabled(false); - freezeInfoPanel->SetVisible(false); + if (panel) { + delete panel; + panel = nullptr; } } } -void AntiFreeze::ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue) { - if (enabled->GetBool()) { - if (!frameHook) { - frameHook = Funcs::AddHook_IBaseClientDLL_FrameStageNotify(Interfaces::pClientDLL, SH_MEMBER(this, &AntiFreeze::FrameHook), true); - } - } - else { - if (!display->GetBool() && !timers->GetBool() && frameHook) { - if (Funcs::RemoveHook(frameHook)) { - frameHook = 0; - } - } - } +AntiFreeze::Panel::Panel(vgui::Panel *parent, const char *panelName) : vgui::Panel(parent, panelName) { + g_pVGui->AddTickSignal(GetVPanel()); } -void AntiFreeze::ToggleTimers(IConVar *var, const char *pOldValue, float flOldValue) { - if (timers->GetBool()) { - InitTimers(true); +void AntiFreeze::Panel::OnTick() { + Interfaces::pEngineTool->ForceSend(); + Interfaces::pEngineTool->ForceUpdateDuringPause(); - if (!frameHook) { - frameHook = Funcs::AddHook_IBaseClientDLL_FrameStageNotify(Interfaces::pClientDLL, SH_MEMBER(this, &AntiFreeze::FrameHook), true); - } - } - else { - InitTimers(false); - - if (!display->GetBool() && !enabled->GetBool() && frameHook) { - if (Funcs::RemoveHook(frameHook)) { - frameHook = 0; - } - } - } + g_pVGuiPanel->GetPanel(GetVParent(), GAME_PANEL_MODULE)->OnCommand("performlayout"); } \ No newline at end of file diff --git a/src/modules/antifreeze.h b/src/modules/antifreeze.h index ab73f19..ea150fe 100644 --- a/src/modules/antifreeze.h +++ b/src/modules/antifreeze.h @@ -2,7 +2,7 @@ * antifreeze.h * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -10,55 +10,21 @@ #pragma once -#include "cdll_int.h" -#include "vgui/VGUI.h" - #include "../modules.h" class ConCommand; class ConVar; class IConVar; -class KeyValues; - -namespace vgui { - class EditablePanel; -}; class AntiFreeze : public Module { public: - AntiFreeze(std::string name); + AntiFreeze(); - static bool CheckDependencies(std::string name); - - void FrameHook(ClientFrameStage_t curStage); + static bool CheckDependencies(); private: - float bluTime; - vgui::HPanel bluTimerPanel; - bool entitiesUpdated; - int frameHook; - vgui::EditablePanel *freezeInfoPanel; - double lastEntityUpdate; - float mainTime; - vgui::HPanel mainTimerPanel; - KeyValues *performLayoutCommand; - float redTime; - vgui::HPanel redTimerPanel; - vgui::HPanel specguiPanel; - float stopwatchTime; - vgui::HPanel stopwatchTimerPanel; - - void GetSpecGUI(); - void GetTimers(); - void InitHUD(); - void InitTimers(bool moduleTime); + class Panel; + Panel *panel; - ConVar *display; - ConCommand *display_reload_settings; - ConVar *display_threshold; ConVar *enabled; - ConVar *timers; - void ReloadSettings(); - void ToggleDisplay(IConVar *var, const char *pOldValue, float flOldValue); void ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue); - void ToggleTimers(IConVar *var, const char *pOldValue, float flOldValue); }; \ No newline at end of file diff --git a/src/modules/cameraautoswitch.cpp b/src/modules/cameraautoswitch.cpp new file mode 100644 index 0000000..3b6fded --- /dev/null +++ b/src/modules/cameraautoswitch.cpp @@ -0,0 +1,195 @@ +/* + * cameraautoswitch.cpp + * StatusSpec project + * + * Copyright (c) 2014-2015 Forward Command Post + * BSD 2-Clause License + * http://opensource.org/licenses/BSD-2-Clause + * + */ + +#include "cameraautoswitch.h" + +#include "cbase.h" +#include "c_baseentity.h" +#include "cdll_int.h" +#include "gameeventdefs.h" +#include "shareddefs.h" +#include "tier3/tier3.h" +#include "toolframework/ienginetool.h" +#include "vgui/IVGui.h" +#include "vgui_controls/Panel.h" + +#include "../funcs.h" +#include "../ifaces.h" +#include "../player.h" + +class CameraAutoSwitch::Panel : public vgui::Panel { +public: + Panel(vgui::Panel *parent, const char *panelName); + + virtual void OnTick(); + + void SwitchToKiller(int player, float delay); +private: + bool killerSwitch; + int killerSwitchPlayer; + float killerSwitchTime; +}; + +CameraAutoSwitch::CameraAutoSwitch() { + panel = nullptr; + + enabled = new ConVar("statusspec_cameraautoswitch_enabled", "0", FCVAR_NONE, "enable automatic switching of camera", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule()->ToggleEnabled(var, pOldValue, flOldValue); }); + killer = new ConVar("statusspec_cameraautoswitch_killer", "0", FCVAR_NONE, "switch to killer upon spectated player death", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule()->ToggleKillerEnabled(var, pOldValue, flOldValue); }); + killer_delay = new ConVar("statusspec_cameraautoswitch_killer_delay", "0", FCVAR_NONE, "delay before switching to killer"); +} + +bool CameraAutoSwitch::CheckDependencies() { + bool ready = true; + + if (!Interfaces::pEngineClient) { + PRINT_TAG(); + Warning("Required interface IVEngineClient for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); + + ready = false; + } + + if (!Interfaces::pEngineTool) { + PRINT_TAG(); + Warning("Required interface IEngineTool for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); + + ready = false; + } + + if (!Interfaces::pGameEventManager) { + PRINT_TAG(); + Warning("Required interface IGameEventManager2 for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); + + ready = false; + } + + if (!Interfaces::vguiLibrariesAvailable) { + PRINT_TAG(); + Warning("Required VGUI library for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); + + ready = false; + } + + try { + Funcs::GetFunc_C_HLTVCamera_SetPrimaryTarget(); + } + catch (bad_pointer) { + PRINT_TAG(); + Warning("Required function C_HLTVCamera::SetPrimaryTarget for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); + + ready = false; + } + + if (!Player::CheckDependencies()) { + PRINT_TAG(); + Warning("Required player helper class for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); + + ready = false; + } + + try { + Interfaces::GetHLTVCamera(); + } + catch (bad_pointer) { + PRINT_TAG(); + Warning("Module %s requires C_HLTVCamera, which cannot be verified at this time!\n", g_ModuleManager->GetModuleName().c_str()); + } + + return ready; +} + +void CameraAutoSwitch::FireGameEvent(IGameEvent *event) { + if (enabled->GetBool() && killer->GetBool()) { + if (strcmp(event->GetName(), GAME_EVENT_PLAYER_DEATH) == 0) { + Player localPlayer = Interfaces::pEngineClient->GetLocalPlayer(); + + if (localPlayer) { + if (localPlayer.GetObserverMode() == OBS_MODE_FIXED || localPlayer.GetObserverMode() == OBS_MODE_IN_EYE || localPlayer.GetObserverMode() == OBS_MODE_CHASE) { + Player targetPlayer = localPlayer.GetObserverTarget(); + + if (targetPlayer) { + if (Interfaces::pEngineClient->GetPlayerForUserID(event->GetInt("userid")) == targetPlayer->entindex()) { + Player killer = Interfaces::pEngineClient->GetPlayerForUserID(event->GetInt("attacker")); + + if (killer) { + if (killer_delay->GetFloat() > 0.0f) { + if (panel) { + panel->SwitchToKiller(killer->entindex(), killer_delay->GetFloat()); + } + } + else { + try { + Funcs::GetFunc_C_HLTVCamera_SetPrimaryTarget()(Interfaces::GetHLTVCamera(), killer->entindex()); + } + catch (bad_pointer &e) { + Warning("%s\n", e.what()); + } + } + } + } + } + } + } + } + } +} + +void CameraAutoSwitch::ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue) { + if (enabled->GetBool()) { + if (!panel) { + panel = new Panel(nullptr, "CameraAutoSwitch"); + } + + if (panel) { + panel->SetEnabled(true); + } + } + else { + if (panel) { + delete panel; + panel = nullptr; + } + } +} + +void CameraAutoSwitch::ToggleKillerEnabled(IConVar *var, const char *pOldValue, float flOldValue) { + if (enabled->GetBool()) { + if (!Interfaces::pGameEventManager->FindListener(this, GAME_EVENT_PLAYER_DEATH)) { + Interfaces::pGameEventManager->AddListener(this, GAME_EVENT_PLAYER_DEATH, false); + } + } + else { + if (Interfaces::pGameEventManager->FindListener(this, GAME_EVENT_PLAYER_DEATH)) { + Interfaces::pGameEventManager->RemoveListener(this); + } + } +} + +CameraAutoSwitch::Panel::Panel(vgui::Panel *parent, const char *panelName) : vgui::Panel(parent, panelName) { + g_pVGui->AddTickSignal(GetVPanel()); +} + +void CameraAutoSwitch::Panel::OnTick() { + if (killerSwitch && Interfaces::pEngineTool->HostTime() > killerSwitchTime) { + killerSwitch = false; + + try { + Funcs::GetFunc_C_HLTVCamera_SetPrimaryTarget()(Interfaces::GetHLTVCamera(), killerSwitchPlayer); + } + catch (bad_pointer &e) { + Warning("%s\n", e.what()); + } + } +} + +void CameraAutoSwitch::Panel::SwitchToKiller(int player, float delay) { + killerSwitch = true; + killerSwitchPlayer = player; + killerSwitchTime = Interfaces::pEngineTool->HostTime() + delay; +} \ No newline at end of file diff --git a/src/modules/cameraautoswitch.h b/src/modules/cameraautoswitch.h new file mode 100644 index 0000000..e4561b9 --- /dev/null +++ b/src/modules/cameraautoswitch.h @@ -0,0 +1,38 @@ +/* + * cameraautoswitch.h + * StatusSpec project + * + * Copyright (c) 2014-2015 Forward Command Post + * BSD 2-Clause License + * http://opensource.org/licenses/BSD-2-Clause + * + */ + +#pragma once + +#include "igameevents.h" + +#include "../modules.h" + +class CCommand; +class ConCommand; +class ConVar; +class IConVar; + + class CameraAutoSwitch : public Module, IGameEventListener2 { + public: + CameraAutoSwitch(); + + static bool CheckDependencies(); + + virtual void FireGameEvent(IGameEvent *event); + private: + class Panel; + Panel *panel; + + ConVar *enabled; + ConVar *killer; + ConVar *killer_delay; + void ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue); + void ToggleKillerEnabled(IConVar *var, const char *pOldValue, float flOldValue); + }; diff --git a/src/modules/camerasmooths.cpp b/src/modules/camerasmooths.cpp new file mode 100644 index 0000000..62b8e23 --- /dev/null +++ b/src/modules/camerasmooths.cpp @@ -0,0 +1,261 @@ +/* + * camerasmooths.cpp + * StatusSpec project + * + * Copyright (c) 2014-2015 Forward Command Post + * BSD 2-Clause License + * http://opensource.org/licenses/BSD-2-Clause + * + */ + +#include "camerasmooths.h" + +#include "cbase.h" +#include "convar.h" +#include "hltvcamera.h" +#include "shareddefs.h" +#include "toolframework/ienginetool.h" + +#include "../common.h" +#include "../exceptions.h" +#include "../funcs.h" +#include "../ifaces.h" + +class CameraSmooths::HLTVCameraOverride : public C_HLTVCamera { +public: + using C_HLTVCamera::m_nCameraMode; + using C_HLTVCamera::m_iCameraMan; + using C_HLTVCamera::m_vCamOrigin; + using C_HLTVCamera::m_aCamAngle; + using C_HLTVCamera::m_iTraget1; + using C_HLTVCamera::m_iTraget2; + using C_HLTVCamera::m_flFOV; + using C_HLTVCamera::m_flOffset; + using C_HLTVCamera::m_flDistance; + using C_HLTVCamera::m_flLastDistance; + using C_HLTVCamera::m_flTheta; + using C_HLTVCamera::m_flPhi; + using C_HLTVCamera::m_flInertia; + using C_HLTVCamera::m_flLastAngleUpdateTime; + using C_HLTVCamera::m_bEntityPacketReceived; + using C_HLTVCamera::m_nNumSpectators; + using C_HLTVCamera::m_szTitleText; + using C_HLTVCamera::m_LastCmd; + using C_HLTVCamera::m_vecVelocity; +}; + +CameraSmooths::CameraSmooths() { + inToolModeHook = 0; + isThirdPersonCameraHook = 0; + setupEngineViewHook = 0; + smoothEnding = false; + smoothEndMode = OBS_MODE_NONE; + smoothEndTarget = 0; + smoothInProgress = false; + smoothLastAngles = QAngle(); + smoothLastOrigin = Vector(); + smoothLastTime = 0; + + enabled = new ConVar("statusspec_camerasmooths_enabled", "0", FCVAR_NONE, "smooth transition between camera positions", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule()->ToggleEnabled(var, pOldValue, flOldValue); }); + max_angle_difference = new ConVar("statusspec_camerasmooths_max_angle_difference", "90", FCVAR_NONE, "max angle difference at which smoothing will be performed"); + max_distance = new ConVar("statusspec_camerasmooths_max_distance", "800", FCVAR_NONE, "max distance at which smoothing will be performed"); + move_speed = new ConVar("statusspec_camerasmooths_move_speed", "800", FCVAR_NONE, "speed to move view per second"); +} + +bool CameraSmooths::CheckDependencies() { + bool ready = true; + + if (!Interfaces::pClientEngineTools) { + PRINT_TAG(); + Warning("Required interface IClientEngineTools for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); + + ready = false; + } + + if (!Interfaces::pEngineClient) { + PRINT_TAG(); + Warning("Required interface IVEngineClient for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); + + ready = false; + } + + if (!Interfaces::pEngineTool) { + PRINT_TAG(); + Warning("Required interface IEngineTool for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); + + ready = false; + } + + try { + Funcs::GetFunc_C_HLTVCamera_SetCameraAngle(); + } + catch (bad_pointer) { + PRINT_TAG(); + Warning("Required function C_HLTVCamera::SetCameraAngle for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); + + ready = false; + } + + try { + Funcs::GetFunc_C_HLTVCamera_SetMode(); + } + catch (bad_pointer) { + PRINT_TAG(); + Warning("Required function C_HLTVCamera::SetMode for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); + + ready = false; + } + + try { + Interfaces::GetHLTVCamera(); + } + catch (bad_pointer) { + PRINT_TAG(); + Warning("Module %s requires C_HLTVCamera, which cannot be verified at this time!\n", g_ModuleManager->GetModuleName().c_str()); + } + + return ready; +} + +bool CameraSmooths::InToolModeOverride() { + if (!Interfaces::pEngineClient->IsHLTV()) { + RETURN_META_VALUE(MRES_IGNORED, false); + } + + if (smoothInProgress) { + RETURN_META_VALUE(MRES_OVERRIDE, true); + } + + RETURN_META_VALUE(MRES_IGNORED, false); +} + +bool CameraSmooths::IsThirdPersonCameraOverride() { + if (!Interfaces::pEngineClient->IsHLTV()) { + RETURN_META_VALUE(MRES_IGNORED, false); + } + + if (smoothInProgress) { + RETURN_META_VALUE(MRES_OVERRIDE, true); + } + + RETURN_META_VALUE(MRES_IGNORED, false); +} + +bool CameraSmooths::SetupEngineViewOverride(Vector &origin, QAngle &angles, float &fov) { + if (!Interfaces::pEngineClient->IsHLTV()) { + RETURN_META_VALUE(MRES_IGNORED, false); + } + + HLTVCameraOverride *hltvcamera = (HLTVCameraOverride *)Interfaces::GetHLTVCamera(); + + if (hltvcamera->m_nCameraMode == OBS_MODE_IN_EYE || hltvcamera->m_nCameraMode == OBS_MODE_CHASE) { + if (hltvcamera->m_iTraget1 != smoothEndTarget || (hltvcamera->m_nCameraMode != smoothEndMode && !smoothInProgress)) { + smoothEndMode = hltvcamera->m_nCameraMode; + smoothEndTarget = hltvcamera->m_iTraget1; + + Vector moveVector = origin - smoothLastOrigin; + Vector currentAngleVector(smoothLastAngles.x, smoothLastAngles.y, smoothLastAngles.z); + Vector targetAngleVector(angles.x, angles.y, angles.z); + + float angle = acos(currentAngleVector.Dot(targetAngleVector) / (currentAngleVector.Length() * targetAngleVector.Length())) * 180.f / 3.14159265358979323846f; + + smoothInProgress = moveVector.Length() < max_distance->GetFloat() && angle < max_angle_difference->GetFloat(); + } + } + else { + smoothInProgress = false; + } + + if (smoothInProgress) { + float moveDistance = move_speed->GetFloat() * (Interfaces::pEngineTool->HostTime() - smoothLastTime); + + Vector moveVector = origin - smoothLastOrigin; + Vector currentAngleVector(smoothLastAngles.x, smoothLastAngles.y, smoothLastAngles.z); + Vector targetAngleVector(angles.x, angles.y, angles.z); + + float angle = acos(currentAngleVector.Dot(targetAngleVector) / (currentAngleVector.Length() * targetAngleVector.Length())) * 180.f / 3.14159265358979323846f; + + if (moveDistance < moveVector.Length() && moveVector.Length() < max_distance->GetFloat() && angle < max_angle_difference->GetFloat()) { + float movePercentage = moveDistance / moveVector.Length(); + + moveVector *= movePercentage; + + origin = smoothLastOrigin + moveVector; + + angles.x = smoothLastAngles.x + ((angles.x - smoothLastAngles.x) * movePercentage); + angles.y = smoothLastAngles.y + ((angles.y - smoothLastAngles.y) * movePercentage); + angles.z = smoothLastAngles.z + ((angles.z - smoothLastAngles.z) * movePercentage); + + Funcs::CallFunc_C_HLTVCamera_SetCameraAngle(hltvcamera, angles); + hltvcamera->m_vCamOrigin = origin; + + smoothEnding = false; + smoothInProgress = true; + } + else { + C_HLTVCamera *hltvcamera = Interfaces::GetHLTVCamera(); + + if (hltvcamera) { + Funcs::CallFunc_C_HLTVCamera_SetMode(hltvcamera, OBS_MODE_ROAMING); + } + + smoothEnding = true; + smoothInProgress = false; + } + + smoothLastAngles = angles; + smoothLastOrigin = origin; + smoothLastTime = Interfaces::pEngineTool->HostTime(); + + RETURN_META_VALUE(MRES_SUPERCEDE, true); + } + else if (smoothEnding) { + C_HLTVCamera *hltvcamera = Interfaces::GetHLTVCamera(); + + if (hltvcamera) { + Funcs::CallFunc_C_HLTVCamera_SetMode(hltvcamera, smoothEndMode); + } + } + + smoothEnding = false; + smoothEndMode = hltvcamera->m_nCameraMode; + smoothEndTarget = hltvcamera->m_iTraget1; + smoothInProgress = false; + smoothLastAngles = angles; + smoothLastOrigin = origin; + smoothLastTime = Interfaces::pEngineTool->HostTime(); + + RETURN_META_VALUE(MRES_IGNORED, false); +} + +void CameraSmooths::ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue) { + if (enabled->GetBool()) { + if (!inToolModeHook) { + inToolModeHook = Funcs::AddHook_IClientEngineTools_InToolMode(Interfaces::pClientEngineTools, SH_MEMBER(this, &CameraSmooths::InToolModeOverride), false); + } + + if (!isThirdPersonCameraHook) { + isThirdPersonCameraHook = Funcs::AddHook_IClientEngineTools_IsThirdPersonCamera(Interfaces::pClientEngineTools, SH_MEMBER(this, &CameraSmooths::IsThirdPersonCameraOverride), false); + } + + if (!setupEngineViewHook) { + setupEngineViewHook = Funcs::AddHook_IClientEngineTools_SetupEngineView(Interfaces::pClientEngineTools, SH_MEMBER(this, &CameraSmooths::SetupEngineViewOverride), false); + } + } + else { + if (inToolModeHook) { + Funcs::RemoveHook(inToolModeHook); + inToolModeHook = 0; + } + + if (isThirdPersonCameraHook) { + Funcs::RemoveHook(isThirdPersonCameraHook); + isThirdPersonCameraHook = 0; + } + + if (setupEngineViewHook) { + Funcs::RemoveHook(setupEngineViewHook); + setupEngineViewHook = 0; + } + } +} \ No newline at end of file diff --git a/src/modules/camerasmooths.h b/src/modules/camerasmooths.h new file mode 100644 index 0000000..5e1962d --- /dev/null +++ b/src/modules/camerasmooths.h @@ -0,0 +1,48 @@ +/* + * camerasmooths.h + * StatusSpec project + * + * Copyright (c) 2014-2015 Forward Command Post + * BSD 2-Clause License + * http://opensource.org/licenses/BSD-2-Clause + * + */ + +#pragma once + +#include "mathlib/vector.h" + +#include "../modules.h" + +class ConVar; +class IConVar; + +class CameraSmooths : public Module { +public: + CameraSmooths(); + + static bool CheckDependencies(); +private: + int inToolModeHook; + int isThirdPersonCameraHook; + int setupEngineViewHook; + bool smoothEnding; + int smoothEndMode; + int smoothEndTarget; + bool smoothInProgress; + QAngle smoothLastAngles; + Vector smoothLastOrigin; + float smoothLastTime; + + bool InToolModeOverride(); + bool IsThirdPersonCameraOverride(); + bool SetupEngineViewOverride(Vector &origin, QAngle &angles, float &fov); + + class HLTVCameraOverride; + + ConVar *enabled; + ConVar *max_angle_difference; + ConVar *max_distance; + ConVar *move_speed; + void ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue); +}; \ No newline at end of file diff --git a/src/modules/camerastate.cpp b/src/modules/camerastate.cpp new file mode 100644 index 0000000..866ed97 --- /dev/null +++ b/src/modules/camerastate.cpp @@ -0,0 +1,499 @@ +/* + * camerastate.cpp + * StatusSpec project + * + * Copyright (c) 2014-2015 Forward Command Post + * BSD 2-Clause License + * http://opensource.org/licenses/BSD-2-Clause + * + */ + +#include "camerastate.h" + +#include + +#include "rapidjson/document.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/writer.h" + +#include "cbase.h" +#include "hltvcamera.h" +#include "in_buttons.h" +#include "shareddefs.h" +#include "tier3/tier3.h" +#include "vgui/IVGui.h" +#include "vgui_controls/Panel.h" + +#include "../common.h" +#include "../exceptions.h" +#include "../funcs.h" +#include "../ifaces.h" + +class CameraState::HLTVCameraOverride : public C_HLTVCamera { +public: + using C_HLTVCamera::m_nCameraMode; + using C_HLTVCamera::m_iCameraMan; + using C_HLTVCamera::m_vCamOrigin; + using C_HLTVCamera::m_aCamAngle; + using C_HLTVCamera::m_iTraget1; + using C_HLTVCamera::m_iTraget2; + using C_HLTVCamera::m_flFOV; + using C_HLTVCamera::m_flOffset; + using C_HLTVCamera::m_flDistance; + using C_HLTVCamera::m_flLastDistance; + using C_HLTVCamera::m_flTheta; + using C_HLTVCamera::m_flPhi; + using C_HLTVCamera::m_flInertia; + using C_HLTVCamera::m_flLastAngleUpdateTime; + using C_HLTVCamera::m_bEntityPacketReceived; + using C_HLTVCamera::m_nNumSpectators; + using C_HLTVCamera::m_szTitleText; + using C_HLTVCamera::m_LastCmd; + using C_HLTVCamera::m_vecVelocity; +}; + +class CameraState::Panel : public vgui::Panel { +public: + Panel(vgui::Panel *parent, const char *panelName, std::function updateFunction); + + virtual void OnTick(); +private: + std::function updateState; +}; + +CameraState::CameraState() { + panel = nullptr; + + change = new ConVar("statusspec_camerastate_change", "{}", FCVAR_NONE, "JSON to change camera state to", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule()->ChangeState(var, pOldValue, flOldValue); }); + current = new ConVar("statusspec_camerastate_current", "{}", FCVAR_NONE, "JSON of current camera state"); + enabled = new ConVar("statusspec_camerastate_enabled", "0", FCVAR_NONE, "enable exposure of camera state", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule()->ToggleEnabled(var, pOldValue, flOldValue); }); +} + +bool CameraState::CheckDependencies() { + bool ready = true; + + if (!Interfaces::pEngineClient) { + PRINT_TAG(); + Warning("Required interface IVEngineClient for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); + + ready = false; + } + + try { + Funcs::GetFunc_C_HLTVCamera_SetCameraAngle(); + } + catch (bad_pointer) { + PRINT_TAG(); + Warning("Required function C_HLTVCamera::SetCameraAngle for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); + + ready = false; + } + + try { + Funcs::GetFunc_C_HLTVCamera_SetMode(); + } + catch (bad_pointer) { + PRINT_TAG(); + Warning("Required function C_HLTVCamera::SetMode for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); + + ready = false; + } + + try { + Funcs::GetFunc_C_HLTVCamera_SetPrimaryTarget(); + } + catch (bad_pointer) { + PRINT_TAG(); + Warning("Required function C_HLTVCamera::SetPrimaryTarget for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); + + ready = false; + } + + try { + Interfaces::GetHLTVCamera(); + } + catch (bad_pointer) { + PRINT_TAG(); + Warning("Module %s requires C_HLTVCamera, which cannot be verified at this time!\n", g_ModuleManager->GetModuleName().c_str()); + } + + return ready; +} + +void CameraState::UpdateState() { + std::string currentState; + + if (Interfaces::pEngineClient->IsInGame()) { + try { + HLTVCameraOverride *hltvcamera = (HLTVCameraOverride *)Interfaces::GetHLTVCamera(); + + rapidjson::Document cameraState; + cameraState.SetObject(); + cameraState.AddMember("mode", hltvcamera->m_nCameraMode, cameraState.GetAllocator()); + cameraState.AddMember("camera", hltvcamera->m_iCameraMan, cameraState.GetAllocator()); + cameraState.AddMember("origin", rapidjson::Value(rapidjson::kObjectType), cameraState.GetAllocator()); + cameraState["origin"].AddMember("x", hltvcamera->m_vCamOrigin.x, cameraState.GetAllocator()); + cameraState["origin"].AddMember("y", hltvcamera->m_vCamOrigin.y, cameraState.GetAllocator()); + cameraState["origin"].AddMember("z", hltvcamera->m_vCamOrigin.z, cameraState.GetAllocator()); + cameraState.AddMember("angle", rapidjson::Value(rapidjson::kObjectType), cameraState.GetAllocator()); + cameraState["angle"].AddMember("x", hltvcamera->m_aCamAngle.x, cameraState.GetAllocator()); + cameraState["angle"].AddMember("y", hltvcamera->m_aCamAngle.y, cameraState.GetAllocator()); + cameraState["angle"].AddMember("z", hltvcamera->m_aCamAngle.z, cameraState.GetAllocator()); + cameraState.AddMember("target", rapidjson::Value(rapidjson::kArrayType), cameraState.GetAllocator()); + cameraState["target"].PushBack(hltvcamera->m_iTraget1, cameraState.GetAllocator()); + cameraState["target"].PushBack(hltvcamera->m_iTraget2, cameraState.GetAllocator()); + cameraState.AddMember("fov", hltvcamera->m_flFOV, cameraState.GetAllocator()); + cameraState.AddMember("offset", hltvcamera->m_flOffset, cameraState.GetAllocator()); + cameraState.AddMember("distance", hltvcamera->m_flDistance, cameraState.GetAllocator()); + cameraState.AddMember("lastdistance", hltvcamera->m_flLastDistance, cameraState.GetAllocator()); + cameraState.AddMember("theta", hltvcamera->m_flTheta, cameraState.GetAllocator()); + cameraState.AddMember("phi", hltvcamera->m_flPhi, cameraState.GetAllocator()); + cameraState.AddMember("inertia", hltvcamera->m_flInertia, cameraState.GetAllocator()); + cameraState.AddMember("cmd", rapidjson::Value(rapidjson::kObjectType), cameraState.GetAllocator()); + cameraState["cmd"].AddMember("angle", rapidjson::Value(rapidjson::kObjectType), cameraState.GetAllocator()); + cameraState["cmd"]["angle"].AddMember("x", hltvcamera->m_LastCmd.viewangles.x, cameraState.GetAllocator()); + cameraState["cmd"]["angle"].AddMember("y", hltvcamera->m_LastCmd.viewangles.y, cameraState.GetAllocator()); + cameraState["cmd"]["angle"].AddMember("z", hltvcamera->m_LastCmd.viewangles.z, cameraState.GetAllocator()); + cameraState["cmd"].AddMember("buttons", rapidjson::Value(rapidjson::kObjectType), cameraState.GetAllocator()); + cameraState["cmd"]["buttons"].AddMember("speed", (hltvcamera->m_LastCmd.buttons & IN_SPEED) != 0, cameraState.GetAllocator()); + cameraState["cmd"].AddMember("forwardmove", hltvcamera->m_LastCmd.forwardmove, cameraState.GetAllocator()); + cameraState["cmd"].AddMember("sidemove", hltvcamera->m_LastCmd.sidemove, cameraState.GetAllocator()); + cameraState["cmd"].AddMember("upmove", hltvcamera->m_LastCmd.upmove, cameraState.GetAllocator()); + cameraState.AddMember("velocity", rapidjson::Value(rapidjson::kObjectType), cameraState.GetAllocator()); + cameraState["velocity"].AddMember("x", hltvcamera->m_vecVelocity.x, cameraState.GetAllocator()); + cameraState["velocity"].AddMember("y", hltvcamera->m_vecVelocity.y, cameraState.GetAllocator()); + cameraState["velocity"].AddMember("z", hltvcamera->m_vecVelocity.z, cameraState.GetAllocator()); + + rapidjson::StringBuffer buffer; + rapidjson::Writer writer(buffer); + cameraState.Accept(writer); + + currentState = buffer.GetString(); + } + catch (bad_pointer &e) { + Warning("%s\n", e.what()); + } + } + else { + currentState = "{}"; + } + + current->SetValue(currentState.c_str()); +} + +void CameraState::ChangeState(IConVar *var, const char *pOldValue, float flOldValue) { + if (!enabled->GetBool()) { + return; + } + + try { + HLTVCameraOverride *hltvcamera = (HLTVCameraOverride *)Interfaces::GetHLTVCamera(); + + rapidjson::Document newState; + newState.Parse(change->GetString()); + + if (!newState.IsObject()) { + return; + } + + int cameraman = hltvcamera->m_iCameraMan; + if (newState.HasMember("camera") && newState["camera"].IsInt()) { + cameraman = newState["camera"].GetInt(); + } + + hltvcamera->m_iCameraMan = cameraman; + + if (cameraman <= 0) { + int mode = hltvcamera->m_nCameraMode; + if (newState.HasMember("mode") && newState["mode"].IsInt()) { + mode = newState["mode"].GetInt(); + } + + if (hltvcamera->m_nCameraMode != mode) { + Funcs::GetFunc_C_HLTVCamera_SetMode()(Interfaces::GetHLTVCamera(), newState["mode"].GetInt()); + } + + if (mode == OBS_MODE_ROAMING) { + if (newState.HasMember("cmd") && newState["cmd"].IsObject()) { + if (newState["cmd"].HasMember("angle") && newState["cmd"]["angle"].IsObject()) { + if (newState["cmd"]["angle"].HasMember("x") && newState["cmd"]["angle"]["x"].IsDouble()) { + hltvcamera->m_LastCmd.viewangles.x = newState["cmd"]["angle"]["x"].GetDouble(); + } + + if (newState["cmd"]["angle"].HasMember("y") && newState["cmd"]["angle"]["y"].IsDouble()) { + hltvcamera->m_LastCmd.viewangles.y = newState["cmd"]["angle"]["y"].GetDouble(); + } + + if (newState["cmd"]["angle"].HasMember("z") && newState["cmd"]["angle"]["z"].IsDouble()) { + hltvcamera->m_LastCmd.viewangles.z = newState["cmd"]["angle"]["z"].GetDouble(); + } + } + + if (newState["cmd"].HasMember("buttons") && newState["cmd"]["buttons"].IsObject()) { + if (newState["cmd"]["buttons"].HasMember("speed") && newState["cmd"]["buttons"]["speed"].IsBool()) { + if (newState["cmd"]["buttons"]["speed"].GetBool()) { + hltvcamera->m_LastCmd.buttons |= IN_SPEED; + } + else { + hltvcamera->m_LastCmd.buttons &= ~(IN_SPEED); + } + } + } + + if (newState["cmd"].HasMember("forwardmove") && newState["cmd"]["forwardmove"].IsDouble()) { + hltvcamera->m_LastCmd.forwardmove = newState["cmd"]["forwardmove"].GetDouble(); + } + + if (newState["cmd"].HasMember("sidemove") && newState["cmd"]["sidemove"].IsDouble()) { + hltvcamera->m_LastCmd.sidemove = newState["cmd"]["sidemove"].GetDouble(); + } + + if (newState["cmd"].HasMember("upmove") && newState["cmd"]["upmove"].IsDouble()) { + hltvcamera->m_LastCmd.upmove = newState["cmd"]["upmove"].GetDouble(); + } + } + + if (newState.HasMember("velocity") && newState["velocity"].IsObject()) { + if (newState["velocity"].HasMember("x") && newState["velocity"]["x"].IsDouble()) { + hltvcamera->m_vecVelocity.x = newState["velocity"]["x"].GetDouble(); + } + + if (newState["velocity"].HasMember("y") && newState["velocity"]["y"].IsDouble()) { + hltvcamera->m_vecVelocity.y = newState["velocity"]["y"].GetDouble(); + } + + if (newState["velocity"].HasMember("z") && newState["velocity"]["z"].IsDouble()) { + hltvcamera->m_vecVelocity.z = newState["velocity"]["z"].GetDouble(); + } + } + + if (newState.HasMember("origin") && newState["origin"].IsObject()) { + if (newState["origin"].HasMember("x") && newState["origin"]["x"].IsDouble()) { + hltvcamera->m_vCamOrigin.x = newState["origin"]["x"].GetDouble(); + } + + if (newState["origin"].HasMember("y") && newState["origin"]["y"].IsDouble()) { + hltvcamera->m_vCamOrigin.y = newState["origin"]["y"].GetDouble(); + } + + if (newState["origin"].HasMember("z") && newState["origin"]["z"].IsDouble()) { + hltvcamera->m_vCamOrigin.z = newState["origin"]["z"].GetDouble(); + } + } + + if (newState.HasMember("angle") && newState["angle"].IsObject()) { + QAngle angle; + + if (newState["angle"].HasMember("x") && newState["angle"]["x"].IsDouble()) { + angle.x = newState["angle"]["x"].GetDouble(); + } + else { + angle.x = hltvcamera->m_aCamAngle.x; + } + + if (newState["angle"].HasMember("y") && newState["angle"]["y"].IsDouble()) { + angle.y = newState["angle"]["y"].GetDouble(); + } + else { + angle.y = hltvcamera->m_aCamAngle.y; + } + + if (newState["angle"].HasMember("z") && newState["angle"]["z"].IsDouble()) { + angle.z = newState["angle"]["z"].GetDouble(); + } + else { + angle.z = hltvcamera->m_aCamAngle.z; + } + + if (hltvcamera->m_aCamAngle != angle) { + Funcs::GetFunc_C_HLTVCamera_SetCameraAngle()(Interfaces::GetHLTVCamera(), angle); + } + } + + if (newState.HasMember("fov") && newState["fov"].IsDouble()) { + hltvcamera->m_flFOV = newState["fov"].GetDouble(); + } + } + else if (mode == OBS_MODE_FIXED) { + if (newState.HasMember("origin") && newState["origin"].IsObject()) { + if (newState["origin"].HasMember("x") && newState["origin"]["x"].IsDouble()) { + hltvcamera->m_vCamOrigin.x = newState["origin"]["x"].GetDouble(); + } + + if (newState["origin"].HasMember("y") && newState["origin"]["y"].IsDouble()) { + hltvcamera->m_vCamOrigin.y = newState["origin"]["y"].GetDouble(); + } + + if (newState["origin"].HasMember("z") && newState["origin"]["z"].IsDouble()) { + hltvcamera->m_vCamOrigin.z = newState["origin"]["z"].GetDouble(); + } + } + + if (newState.HasMember("angle") && newState["angle"].IsObject()) { + QAngle angle; + + if (newState["angle"].HasMember("x") && newState["angle"]["x"].IsDouble()) { + angle.x = newState["angle"]["x"].GetDouble(); + } + else { + angle.x = hltvcamera->m_aCamAngle.x; + } + + if (newState["angle"].HasMember("y") && newState["angle"]["y"].IsDouble()) { + angle.y = newState["angle"]["y"].GetDouble(); + } + else { + angle.y = hltvcamera->m_aCamAngle.y; + } + + if (newState["angle"].HasMember("z") && newState["angle"]["z"].IsDouble()) { + angle.z = newState["angle"]["z"].GetDouble(); + } + else { + angle.z = hltvcamera->m_aCamAngle.z; + } + + if (hltvcamera->m_aCamAngle != angle) { + Funcs::GetFunc_C_HLTVCamera_SetCameraAngle()(Interfaces::GetHLTVCamera(), angle); + } + } + + if (newState.HasMember("fov") && newState["fov"].IsDouble()) { + hltvcamera->m_flFOV = newState["fov"].GetDouble(); + } + + if (newState.HasMember("target") && newState["target"].IsArray()) { + if (newState["target"][0].IsInt()) { + if (hltvcamera->m_iTraget1 != newState["target"][0].GetInt()) { + Funcs::GetFunc_C_HLTVCamera_SetPrimaryTarget()(Interfaces::GetHLTVCamera(), newState["target"][0].GetInt()); + } + } + } + + if (newState.HasMember("inertia") && newState["inertia"].IsDouble()) { + hltvcamera->m_flInertia = newState["inertia"].GetDouble(); + } + } + else if (mode == OBS_MODE_IN_EYE) { + if (newState.HasMember("target") && newState["target"].IsArray()) { + if (newState["target"][0].IsInt()) { + if (hltvcamera->m_iTraget1 != newState["target"][0].GetInt()) { + Funcs::GetFunc_C_HLTVCamera_SetPrimaryTarget()(Interfaces::GetHLTVCamera(), newState["target"][0].GetInt()); + } + } + } + } + else if (mode == OBS_MODE_CHASE) { + if (newState.HasMember("target") && newState["target"].IsArray()) { + if (newState["target"][0].IsInt()) { + if (hltvcamera->m_iTraget1 != newState["target"][0].GetInt()) { + Funcs::GetFunc_C_HLTVCamera_SetPrimaryTarget()(Interfaces::GetHLTVCamera(), newState["target"][0].GetInt()); + } + } + + if (newState["target"][1].IsInt()) { + hltvcamera->m_iTraget2 = newState["target"][1].GetInt(); + } + } + + if (newState.HasMember("phi") && newState["phi"].IsDouble()) { + hltvcamera->m_flPhi = newState["phi"].GetDouble(); + } + + if (newState.HasMember("theta") && newState["theta"].IsDouble()) { + hltvcamera->m_flTheta = newState["theta"].GetDouble(); + } + + if (newState.HasMember("angle") && newState["angle"].IsObject()) { + QAngle angle; + + if (newState["angle"].HasMember("x") && newState["angle"]["x"].IsDouble()) { + angle.x = newState["angle"]["x"].GetDouble(); + } + else { + angle.x = hltvcamera->m_aCamAngle.x; + } + + if (newState["angle"].HasMember("y") && newState["angle"]["y"].IsDouble()) { + angle.y = newState["angle"]["y"].GetDouble(); + } + else { + angle.y = hltvcamera->m_aCamAngle.y; + } + + if (newState["angle"].HasMember("z") && newState["angle"]["z"].IsDouble()) { + angle.z = newState["angle"]["z"].GetDouble(); + } + else { + angle.z = hltvcamera->m_aCamAngle.z; + } + + if (hltvcamera->m_aCamAngle != angle) { + Funcs::GetFunc_C_HLTVCamera_SetCameraAngle()(Interfaces::GetHLTVCamera(), angle); + } + } + + if (newState.HasMember("distance") && newState["distance"].IsDouble()) { + hltvcamera->m_flDistance = newState["distance"].GetDouble(); + } + + if (newState.HasMember("offset") && newState["offset"].IsDouble()) { + hltvcamera->m_flOffset = newState["offset"].GetDouble(); + } + + if (newState.HasMember("lastdistance") && newState["lastdistance"].IsDouble()) { + hltvcamera->m_flLastDistance = newState["lastdistance"].GetDouble(); + } + + if (newState.HasMember("inertia") && newState["inertia"].IsDouble()) { + hltvcamera->m_flInertia = newState["inertia"].GetDouble(); + } + + if (newState.HasMember("origin") && newState["origin"].IsObject()) { + if (newState["origin"].HasMember("x") && newState["origin"]["x"].IsDouble()) { + hltvcamera->m_vCamOrigin.x = newState["origin"]["x"].GetDouble(); + } + + if (newState["origin"].HasMember("y") && newState["origin"]["y"].IsDouble()) { + hltvcamera->m_vCamOrigin.y = newState["origin"]["y"].GetDouble(); + } + + if (newState["origin"].HasMember("z") && newState["origin"]["z"].IsDouble()) { + hltvcamera->m_vCamOrigin.z = newState["origin"]["z"].GetDouble(); + } + } + } + } + } + catch (bad_pointer &e) { + Warning("%s\n", e.what()); + } +} + +void CameraState::ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue) { + if (enabled->GetBool()) { + if (!panel) { + panel = new Panel(nullptr, "CameraState", std::bind(&CameraState::UpdateState, this)); + } + + if (panel) { + panel->SetEnabled(true); + } + } + else { + if (panel) { + delete panel; + panel = nullptr; + } + } +} + +CameraState::Panel::Panel(vgui::Panel *parent, const char *panelName, std::function updateFunction) : vgui::Panel(parent, panelName) { + g_pVGui->AddTickSignal(GetVPanel()); + + updateState = updateFunction; +} + +void CameraState::Panel::OnTick() { + updateState(); +} diff --git a/src/modules/camerastate.h b/src/modules/camerastate.h new file mode 100644 index 0000000..f33f2b4 --- /dev/null +++ b/src/modules/camerastate.h @@ -0,0 +1,38 @@ +/* + * camerastate.h + * StatusSpec project + * + * Copyright (c) 2014-2015 Forward Command Post + * BSD 2-Clause License + * http://opensource.org/licenses/BSD-2-Clause + * + */ + +#pragma once + +#include "../modules.h" + +class ConVar; +class IConVar; + +class CameraState : public Module { +public: + CameraState(); + + static bool CheckDependencies(); +private: + void UpdateState(); + + class Panel; + Panel *panel; + + bool currentlyUpdating; + + class HLTVCameraOverride; + + ConVar *change; + ConVar *current; + ConVar *enabled; + void ChangeState(IConVar *var, const char *pOldValue, float flOldValue); + void ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue); +}; diff --git a/src/modules/cameratools.cpp b/src/modules/cameratools.cpp index eb8673b..77b0d7f 100644 --- a/src/modules/cameratools.cpp +++ b/src/modules/cameratools.cpp @@ -2,7 +2,7 @@ * cameratools.cpp * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -10,23 +10,20 @@ #include "cameratools.h" -#include +#include -#include "json/json.h" - -class C_BaseEntity; #include "cbase.h" -#include "convar.h" #include "filesystem.h" -#include "globalvars_base.h" -#include "usercmd.h" #include "hltvcamera.h" #include "icliententity.h" +#include "icliententitylist.h" #include "iclientmode.h" -#include "in_buttons.h" #include "KeyValues.h" #include "shareddefs.h" #include "tier3/tier3.h" +#include "toolframework/ienginetool.h" +#include "vgui/IScheme.h" +#include "vgui/IVGui.h" #include "vgui_controls/EditablePanel.h" #include "../common.h" @@ -58,41 +55,53 @@ class CameraTools::HLTVCameraOverride : public C_HLTVCamera { using C_HLTVCamera::m_vecVelocity; }; -CameraTools::CameraTools(std::string name) : Module(name) { - frameHook = 0; +CameraTools::CameraTools() { + setModeHook = 0; + setPrimaryTargetHook = 0; specguiSettings = new KeyValues("Resource/UI/SpectatorTournament.res"); specguiSettings->LoadFromFile(Interfaces::pFileSystem, "resource/ui/spectatortournament.res", "mod"); - spec_player = new ConCommand("statusspec_cameratools_spec_player", [](const CCommand &command) { g_ModuleManager->GetModule("Camera Tools")->SpecPlayer(command); }, "spec a certain player", FCVAR_NONE); + force_mode = new ConVar("statusspec_cameratools_force_mode", "0", FCVAR_NONE, "if a valid mode, force the camera mode to this", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule()->ChangeForceMode(var, pOldValue, flOldValue); }); + force_target = new ConVar("statusspec_cameratools_force_target", "-1", FCVAR_NONE, "if a valid target, force the camera target to this", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule()->ChangeForceTarget(var, pOldValue, flOldValue); }); + force_valid_target = new ConVar("statusspec_cameratools_force_valid_target", "0", FCVAR_NONE, "forces the camera to only have valid targets", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule()->ToggleForceValidTarget(var, pOldValue, flOldValue); }); + spec_player = new ConCommand("statusspec_cameratools_spec_player", [](const CCommand &command) { g_ModuleManager->GetModule()->SpecPlayer(command); }, "spec a certain player", FCVAR_NONE); spec_player_alive = new ConVar("statusspec_cameratools_spec_player_alive", "1", FCVAR_NONE, "prevent speccing dead players"); - spec_pos = new ConCommand("statusspec_cameratools_spec_pos", [](const CCommand &command) { g_ModuleManager->GetModule("Camera Tools")->SpecPosition(command); }, "spec a certain camera position", FCVAR_NONE); - state = new ConVar("statusspec_cameratools_state", "{}", FCVAR_NONE, "JSON of camera tools state", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule("Camera Tools")->ChangeState(var, pOldValue, flOldValue); }); - state_enabled = new ConVar("statusspec_cameratools_state_enabled", "0", FCVAR_NONE, "enable exposure of camera tools state", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule("Camera Tools")->ToggleStateEnabled(var, pOldValue, flOldValue); }); + spec_pos = new ConCommand("statusspec_cameratools_spec_pos", [](const CCommand &command) { g_ModuleManager->GetModule()->SpecPosition(command); }, "spec a certain camera position", FCVAR_NONE); } -bool CameraTools::CheckDependencies(std::string name) { +bool CameraTools::CheckDependencies() { bool ready = true; + if (!Interfaces::pEngineTool) { + PRINT_TAG(); + Warning("Required interface IEngineTool for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); + + ready = false; + } + if (!Interfaces::pFileSystem) { PRINT_TAG(); - Warning("Required interface IFileSystem for module %s not available!\n", name.c_str()); + Warning("Required interface IFileSystem for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } - if (!Interfaces::pEngineClient) { + try { + Funcs::GetFunc_C_HLTVCamera_SetCameraAngle(); + } + catch (bad_pointer) { PRINT_TAG(); - Warning("Required interface IVEngineClient for module %s not available!\n", name.c_str()); + Warning("Required function C_HLTVCamera::SetCameraAngle for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } try { - Interfaces::GetGlobalVars(); + Funcs::GetFunc_C_HLTVCamera_SetMode(); } catch (bad_pointer) { PRINT_TAG(); - Warning("Required interface CGlobalVarsBase for module %s not available!\n", name.c_str()); + Warning("Required function C_HLTVCamera::SetMode for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } @@ -102,35 +111,35 @@ bool CameraTools::CheckDependencies(std::string name) { } catch (bad_pointer) { PRINT_TAG(); - Warning("Required function C_HLTVCamera::SetPrimaryTarget for module %s not available!\n", name.c_str()); + Warning("Required function C_HLTVCamera::SetPrimaryTarget for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!g_pVGuiPanel) { PRINT_TAG(); - Warning("Required interface vgui::IPanel for module %s not available!\n", name.c_str()); + Warning("Required interface vgui::IPanel for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!g_pVGuiSchemeManager) { PRINT_TAG(); - Warning("Required interface vgui::ISchemeManager for module %s not available!\n", name.c_str()); + Warning("Required interface vgui::ISchemeManager for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Player::CheckDependencies()) { PRINT_TAG(); - Warning("Required player helper class for module %s not available!\n", name.c_str()); + Warning("Required player helper class for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Player::nameRetrievalAvailable) { PRINT_TAG(); - Warning("Required player name retrieval for module %s not available!\n", name.c_str()); + Warning("Required player name retrieval for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } @@ -140,7 +149,7 @@ bool CameraTools::CheckDependencies(std::string name) { } catch (bad_pointer) { PRINT_TAG(); - Warning("Module %s requires IClientMode, which cannot be verified at this time!\n", name.c_str()); + Warning("Module %s requires IClientMode, which cannot be verified at this time!\n", g_ModuleManager->GetModuleName().c_str()); } try { @@ -148,214 +157,79 @@ bool CameraTools::CheckDependencies(std::string name) { } catch (bad_pointer) { PRINT_TAG(); - Warning("Module %s requires C_HLTVCamera, which cannot be verified at this time!\n", name.c_str()); + Warning("Module %s requires C_HLTVCamera, which cannot be verified at this time!\n", g_ModuleManager->GetModuleName().c_str()); } return ready; } -void CameraTools::FrameHook(ClientFrameStage_t curStage) { - if (curStage == FRAME_START) { - std::thread update(std::bind(&CameraTools::UpdateState, this)); - update.detach(); - } - - RETURN_META(MRES_IGNORED); -} - -void CameraTools::UpdateState() { - std::string currentState; - - if (Interfaces::pEngineClient->IsInGame()) { - try { - HLTVCameraOverride *hltvcamera = (HLTVCameraOverride *)Interfaces::GetHLTVCamera(); +void CameraTools::SetModeOverride(C_HLTVCamera *hltvcamera, int &iMode) { + int forceMode = force_mode->GetInt(); - Json::Value cameraState; - cameraState["mode"] = hltvcamera->m_nCameraMode; - cameraState["camera"] = hltvcamera->m_iCameraMan; - cameraState["origin"]["x"] = hltvcamera->m_vCamOrigin.x; - cameraState["origin"]["y"] = hltvcamera->m_vCamOrigin.y; - cameraState["origin"]["z"] = hltvcamera->m_vCamOrigin.z; - cameraState["angle"]["x"] = hltvcamera->m_aCamAngle.x; - cameraState["angle"]["y"] = hltvcamera->m_aCamAngle.y; - cameraState["angle"]["z"] = hltvcamera->m_aCamAngle.z; - cameraState["target"][0] = hltvcamera->m_iTraget1; - cameraState["target"][1] = hltvcamera->m_iTraget2; - cameraState["fov"] = hltvcamera->m_flFOV; - cameraState["offset"] = hltvcamera->m_flOffset; - cameraState["distance"] = hltvcamera->m_flDistance; - cameraState["lastdistance"] = hltvcamera->m_flLastDistance; - cameraState["theta"] = hltvcamera->m_flTheta; - cameraState["phi"] = hltvcamera->m_flPhi; - cameraState["cmd"]["angle"]["x"] = hltvcamera->m_LastCmd.viewangles.x; - cameraState["cmd"]["angle"]["y"] = hltvcamera->m_LastCmd.viewangles.y; - cameraState["cmd"]["angle"]["z"] = hltvcamera->m_LastCmd.viewangles.z; - cameraState["cmd"]["buttons"]["speed"] = (hltvcamera->m_LastCmd.buttons & IN_SPEED) != 0; - cameraState["cmd"]["forwardmove"] = hltvcamera->m_LastCmd.forwardmove; - cameraState["cmd"]["sidemove"] = hltvcamera->m_LastCmd.sidemove; - cameraState["cmd"]["upmove"] = hltvcamera->m_LastCmd.upmove; - cameraState["velocity"]["x"] = hltvcamera->m_vecVelocity.x; - cameraState["velocity"]["y"] = hltvcamera->m_vecVelocity.y; - cameraState["velocity"]["z"] = hltvcamera->m_vecVelocity.z; - - currentState = Json::FastWriter().write(cameraState); - } - catch (bad_pointer &e) { - Warning("%s\n", e.what()); - } - } - else { - currentState = "{}"; + if (forceMode == OBS_MODE_FIXED || forceMode == OBS_MODE_IN_EYE || forceMode == OBS_MODE_CHASE || forceMode == OBS_MODE_ROAMING) { + iMode = forceMode; } - - currentlyUpdating = true; - state->SetValue(currentState.c_str()); - currentlyUpdating = false; } -void CameraTools::ChangeState(IConVar *var, const char *pOldValue, float flOldValue) { - if (!state_enabled->GetBool()) { - return; - } +void CameraTools::SetPrimaryTargetOverride(C_HLTVCamera *hltvcamera, int &nEntity) { + int forceTarget = force_target->GetInt(); - if (currentlyUpdating) { - return; + if (Interfaces::pClientEntityList->GetClientEntity(forceTarget)) { + nEntity = forceTarget; } - try { - HLTVCameraOverride *hltvcamera = (HLTVCameraOverride *)Interfaces::GetHLTVCamera(); - - Json::Value newState; - Json::Reader().parse(state->GetString(), newState); - - if (newState.isMember("mode") && newState["mode"].isInt()) { - hltvcamera->m_nCameraMode = newState["mode"].asInt(); - } - - if (newState.isMember("camera") && newState["camera"].isInt()) { - hltvcamera->m_iCameraMan = newState["camera"].asInt(); - } - - if (newState.isMember("origin") && newState["origin"].isObject()) { - if (newState["origin"].isMember("x") && newState["origin"]["x"].isDouble()) { - hltvcamera->m_vCamOrigin.x = newState["origin"]["x"].asFloat(); - } - - if (newState["origin"].isMember("y") && newState["origin"]["y"].isDouble()) { - hltvcamera->m_vCamOrigin.y = newState["origin"]["y"].asFloat(); - } - - if (newState["origin"].isMember("z") && newState["origin"]["z"].isDouble()) { - hltvcamera->m_vCamOrigin.z = newState["origin"]["z"].asFloat(); - } - } - - if (newState.isMember("angle") && newState["angle"].isObject()) { - if (newState["angle"].isMember("x") && newState["angle"]["x"].isDouble()) { - hltvcamera->m_aCamAngle.x = newState["angle"]["x"].asFloat(); - } - - if (newState["angle"].isMember("y") && newState["angle"]["y"].isDouble()) { - hltvcamera->m_aCamAngle.y = newState["angle"]["y"].asFloat(); - } - - if (newState["angle"].isMember("z") && newState["angle"]["z"].isDouble()) { - hltvcamera->m_aCamAngle.z = newState["angle"]["z"].asFloat(); - } - } + if (!Interfaces::pClientEntityList->GetClientEntity(nEntity)) { + nEntity = ((HLTVCameraOverride *)hltvcamera)->m_iTraget1; + } +} - if (newState.isMember("target") && newState["target"].isArray()) { - if (newState["target"].isValidIndex(0) && newState["target"][0].isInt()) { - hltvcamera->m_iTraget1 = newState["target"][0].asInt(); - } +void CameraTools::ChangeForceMode(IConVar *var, const char *pOldValue, float flOldValue) { + int forceMode = force_mode->GetInt(); - if (newState["target"].isValidIndex(1) && newState["target"][1].isInt()) { - hltvcamera->m_iTraget2 = newState["target"][1].asInt(); - } + if (forceMode == OBS_MODE_FIXED || forceMode == OBS_MODE_IN_EYE || forceMode == OBS_MODE_CHASE || forceMode == OBS_MODE_ROAMING) { + if (!setModeHook) { + setModeHook = Funcs::AddHook_C_HLTVCamera_SetMode(std::bind(&CameraTools::SetModeOverride, this, std::placeholders::_1, std::placeholders::_2)); } - if (newState.isMember("fov") && newState["fov"].isDouble()) { - hltvcamera->m_flFOV = newState["fov"].asFloat(); + try { + Funcs::GetFunc_C_HLTVCamera_SetMode()(Interfaces::GetHLTVCamera(), forceMode); } - - if (newState.isMember("offset") && newState["offset"].isDouble()) { - hltvcamera->m_flOffset = newState["offset"].asFloat(); + catch (bad_pointer) { + Warning("Error in setting mode.\n"); } + } + else { + var->SetValue(OBS_MODE_NONE); - if (newState.isMember("distance") && newState["distance"].isDouble()) { - hltvcamera->m_flDistance = newState["distance"].asFloat(); + if (setModeHook) { + Funcs::RemoveHook_C_HLTVCamera_SetMode(setModeHook); + setModeHook = 0; } + } +} - if (newState.isMember("lastdistance") && newState["lastdistance"].isDouble()) { - hltvcamera->m_flLastDistance = newState["lastdistance"].asFloat(); - } +void CameraTools::ChangeForceTarget(IConVar *var, const char *pOldValue, float flOldValue) { + int forceTarget = force_target->GetInt(); - if (newState.isMember("theta") && newState["theta"].isDouble()) { - hltvcamera->m_flTheta = newState["theta"].asFloat(); + if (Interfaces::pClientEntityList->GetClientEntity(forceTarget)) { + if (!setPrimaryTargetHook) { + setPrimaryTargetHook = Funcs::AddHook_C_HLTVCamera_SetPrimaryTarget(std::bind(&CameraTools::SetPrimaryTargetOverride, this, std::placeholders::_1, std::placeholders::_2)); } - if (newState.isMember("phi") && newState["phi"].isDouble()) { - hltvcamera->m_flPhi = newState["phi"].asFloat(); + try { + Funcs::GetFunc_C_HLTVCamera_SetPrimaryTarget()(Interfaces::GetHLTVCamera(), forceTarget); } - - if (newState.isMember("cmd") && newState["cmd"].isObject()) { - if (newState["cmd"].isMember("angle") && newState["cmd"]["angle"].isObject()) { - if (newState["cmd"]["angle"].isMember("x") && newState["cmd"]["angle"]["x"].isDouble()) { - hltvcamera->m_LastCmd.viewangles.x = newState["cmd"]["angle"]["x"].asFloat(); - } - - if (newState["cmd"]["angle"].isMember("y") && newState["cmd"]["angle"]["y"].isDouble()) { - hltvcamera->m_LastCmd.viewangles.y = newState["cmd"]["angle"]["y"].asFloat(); - } - - if (newState["cmd"]["angle"].isMember("z") && newState["cmd"]["angle"]["z"].isDouble()) { - hltvcamera->m_LastCmd.viewangles.z = newState["cmd"]["angle"]["z"].asFloat(); - } - } - - if (newState["cmd"].isMember("buttons") && newState["cmd"]["buttons"].isObject()) { - if (newState["cmd"]["buttons"].isMember("speed") && newState["cmd"]["buttons"]["speed"].isBool()) { - if (newState["cmd"]["buttons"]["speed"].asBool()) { - hltvcamera->m_LastCmd.buttons |= IN_SPEED; - } - else { - hltvcamera->m_LastCmd.buttons &= ~(IN_SPEED); - } - } - } - - if (newState["cmd"].isMember("forwardmove") && newState["cmd"]["forwardmove"].isDouble()) { - hltvcamera->m_LastCmd.forwardmove = newState["cmd"]["forwardmove"].asFloat(); - } - - if (newState["cmd"].isMember("sidemove") && newState["cmd"]["sidemove"].isDouble()) { - hltvcamera->m_LastCmd.sidemove = newState["cmd"]["sidemove"].asFloat(); - } - - if (newState["cmd"].isMember("upmove") && newState["cmd"]["upmove"].isDouble()) { - hltvcamera->m_LastCmd.upmove = newState["cmd"]["upmove"].asFloat(); - } + catch (bad_pointer) { + Warning("Error in setting target.\n"); } - - if (newState.isMember("velocity") && newState["velocity"].isObject()) { - if (newState["velocity"].isMember("x") && newState["velocity"]["x"].isDouble()) { - hltvcamera->m_vecVelocity.x = newState["velocity"]["x"].asFloat(); - } - - if (newState["velocity"].isMember("y") && newState["velocity"]["y"].isDouble()) { - hltvcamera->m_vecVelocity.y = newState["velocity"]["y"].asFloat(); - } - - if (newState["velocity"].isMember("z") && newState["velocity"]["z"].isDouble()) { - hltvcamera->m_vecVelocity.z = newState["velocity"]["z"].asFloat(); + } + else { + if (!force_valid_target->GetBool()) { + if (setPrimaryTargetHook) { + Funcs::RemoveHook_C_HLTVCamera_SetPrimaryTarget(setPrimaryTargetHook); + setPrimaryTargetHook = 0; } } - - std::thread update(std::bind(&CameraTools::UpdateState, this)); - update.detach(); - } - catch (bad_pointer &e) { - Warning("%s\n", e.what()); } } @@ -373,7 +247,7 @@ void CameraTools::SpecPlayer(const CCommand &command) { vgui::VPANEL playerPanel = g_pVGuiPanel->GetChild(specgui, i); if (strcmp(g_pVGuiPanel->GetClassName(playerPanel), "CTFPlayerPanel") == 0) { - vgui::EditablePanel *panel = dynamic_cast(g_pVGuiPanel->GetPanel(playerPanel, "ClientDLL")); + vgui::EditablePanel *panel = dynamic_cast(g_pVGuiPanel->GetPanel(playerPanel, GAME_PANEL_MODULE)); if (panel) { KeyValues *dialogVariables = panel->GetDialogVariables(); @@ -381,9 +255,7 @@ void CameraTools::SpecPlayer(const CCommand &command) { if (dialogVariables) { const char *name = dialogVariables->GetString("playername"); - for (auto iterator = Player::begin(); iterator != Player::end(); ++iterator) { - Player player = *iterator; - + for (Player player : Player::Iterable()) { if (player.GetName().compare(name) == 0) { int baseX = 0; int baseY = 0; @@ -434,7 +306,7 @@ void CameraTools::SpecPlayer(const CCommand &command) { } if (!spec_player_alive->GetBool() || player.IsAlive()) { - Funcs::CallFunc_C_HLTVCamera_SetPrimaryTarget(Interfaces::GetHLTVCamera(), player->entindex()); + Funcs::GetFunc_C_HLTVCamera_SetPrimaryTarget()(Interfaces::GetHLTVCamera(), player->entindex()); } return; @@ -461,7 +333,12 @@ void CameraTools::SpecPlayer(const CCommand &command) { if (player) { if (!spec_player_alive->GetBool() || player.IsAlive()) { - Funcs::CallFunc_C_HLTVCamera_SetPrimaryTarget(Interfaces::GetHLTVCamera(), player->entindex()); + try { + Funcs::GetFunc_C_HLTVCamera_SetPrimaryTarget()(Interfaces::GetHLTVCamera(), player->entindex()); + } + catch (bad_pointer &e) { + Warning("%s\n", e.what()); + } } } } @@ -486,9 +363,9 @@ void CameraTools::SpecPosition(const CCommand &command) { hltvcamera->m_aCamAngle.y = atoi(command.Arg(5)); hltvcamera->m_iTraget1 = 0; hltvcamera->m_iTraget2 = 0; - hltvcamera->m_flLastAngleUpdateTime = Interfaces::GetGlobalVars()->realtime; + hltvcamera->m_flLastAngleUpdateTime = Interfaces::pEngineTool->GetRealTime(); - Interfaces::pEngineClient->SetViewAngles(hltvcamera->m_aCamAngle); + Funcs::GetFunc_C_HLTVCamera_SetCameraAngle()(hltvcamera, hltvcamera->m_aCamAngle); } catch (bad_pointer &e) { Warning("%s\n", e.what()); @@ -501,16 +378,17 @@ void CameraTools::SpecPosition(const CCommand &command) { } } -void CameraTools::ToggleStateEnabled(IConVar *var, const char *pOldValue, float flOldValue) { - if (state_enabled->GetBool()) { - if (!frameHook) { - frameHook = Funcs::AddHook_IBaseClientDLL_FrameStageNotify(Interfaces::pClientDLL, SH_MEMBER(this, &CameraTools::FrameHook), true); +void CameraTools::ToggleForceValidTarget(IConVar *var, const char *pOldValue, float flOldValue) { + if (force_valid_target->GetBool()) { + if (!setPrimaryTargetHook) { + setPrimaryTargetHook = Funcs::AddHook_C_HLTVCamera_SetPrimaryTarget(std::bind(&CameraTools::SetPrimaryTargetOverride, this, std::placeholders::_1, std::placeholders::_2)); } } else { - if (frameHook) { - if (Funcs::RemoveHook(frameHook)) { - frameHook = 0; + if (!Interfaces::pClientEntityList->GetClientEntity(force_target->GetInt())) { + if (setPrimaryTargetHook) { + Funcs::RemoveHook_C_HLTVCamera_SetPrimaryTarget(setPrimaryTargetHook); + setPrimaryTargetHook = 0; } } } diff --git a/src/modules/cameratools.h b/src/modules/cameratools.h index 1b2ed8f..111d55c 100644 --- a/src/modules/cameratools.h +++ b/src/modules/cameratools.h @@ -2,7 +2,7 @@ * cameratools.h * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -10,39 +10,39 @@ #pragma once -#include "cdll_int.h" -#include "convar.h" - #include "../modules.h" class CCommand; +class C_HLTVCamera; class ConCommand; class ConVar; class KeyValues; +class IConVar; class CameraTools : public Module { public: - CameraTools(std::string name); - - static bool CheckDependencies(std::string name); + CameraTools(); - void FrameHook(ClientFrameStage_t curStage); + static bool CheckDependencies(); private: - bool currentlyUpdating; - int frameHook; + int setModeHook; + int setPrimaryTargetHook; KeyValues *specguiSettings; - void UpdateState(); + void SetModeOverride(C_HLTVCamera *hltvcamera, int &iMode); + void SetPrimaryTargetOverride(C_HLTVCamera *hltvcamera, int &nEntity); class HLTVCameraOverride; + ConVar *force_mode; + ConVar *force_target; + ConVar *force_valid_target; ConCommand *spec_player; ConVar *spec_player_alive; ConCommand *spec_pos; - ConVar *state; - ConVar *state_enabled; - void ChangeState(IConVar *var, const char *pOldValue, float flOldValue); + void ChangeForceMode(IConVar *var, const char *pOldValue, float flOldValue); + void ChangeForceTarget(IConVar *var, const char *pOldValue, float flOldValue); void SpecPlayer(const CCommand &command); void SpecPosition(const CCommand &command); - void ToggleStateEnabled(IConVar *var, const char *pOldValue, float flOldValue); + void ToggleForceValidTarget(IConVar *var, const char *pOldValue, float flOldValue); }; \ No newline at end of file diff --git a/src/modules/consoletools.cpp b/src/modules/consoletools.cpp new file mode 100644 index 0000000..615e36f --- /dev/null +++ b/src/modules/consoletools.cpp @@ -0,0 +1,277 @@ +/* + * consoletools.cpp + * StatusSpec project + * + * Copyright (c) 2014-2015 Forward Command Post + * BSD 2-Clause License + * http://opensource.org/licenses/BSD-2-Clause + * + */ + +#include "consoletools.h" + +#include + +#include "convar.h" +#include "icvar.h" + +#include "../funcs.h" + +// this is a total hijack of a friend class declared but never defined in the public SDK +class CCvar { +public: + static int GetFlags(ConCommandBase *base); + static void SetFlags(ConCommandBase *base, int flags); +}; + +int CCvar::GetFlags(ConCommandBase *base) { + return base->m_nFlags; +} + +void CCvar::SetFlags(ConCommandBase *base, int flags) { + base->m_nFlags = flags; +} + +ConsoleTools::ConsoleTools() { + consoleColorPrintfHook = 0; + consoleDPrintfHook = 0; + consolePrintfHook = 0; + + filter_add = new ConCommand("statusspec_consoletools_filter_add", [](const CCommand &command) { g_ModuleManager->GetModule()->AddFilter(command); }, "add a console filter", FCVAR_NONE); + filter_enabled = new ConVar("statusspec_consoletools_filter_enabled", "0", FCVAR_NONE, "enable console filtering", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule()->ToggleFilterEnabled(var, pOldValue, flOldValue); }); + filter_remove = new ConCommand("statusspec_consoletools_filter_remove", [](const CCommand &command) { g_ModuleManager->GetModule()->RemoveFilter(command); }, "remove a console filter", FCVAR_NONE); + flags_add = new ConCommand("statusspec_consoletools_flags_add", [](const CCommand &command) { g_ModuleManager->GetModule()->AddFlags(command); }, "add a flag to a console command or variable", FCVAR_NONE); + flags_remove = new ConCommand("statusspec_consoletools_flags_remove", [](const CCommand &command) { g_ModuleManager->GetModule()->RemoveFlags(command); }, "remove a flag from a console command or variable", FCVAR_NONE); +} + +bool ConsoleTools::CheckDependencies() { + bool ready = true; + + if (!g_pCVar) { + PRINT_TAG(); + Warning("Required interface ICVar for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); + + ready = false; + } + + return ready; +} + +void ConsoleTools::ConsoleColorPrintfHook(const Color &clr, const char *message) { + if (CheckFilters(message)) { + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +void ConsoleTools::ConsoleDPrintfHook(const char *message) { + if (CheckFilters(message)) { + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +void ConsoleTools::ConsolePrintfHook(const char *message) { + if (CheckFilters(message)) { + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +bool ConsoleTools::CheckFilters(std::string message) { + for (std::string filter : filters) { + if (std::regex_search(message, std::regex(filter))) { + return true; + } + } + + return false; +} + +void ConsoleTools::AddFilter(const CCommand &command) { + if (command.ArgC() >= 2) { + std::string filter = command.Arg(1); + + if (!filters.count(filter)) { + filters.insert(filter); + } + else { + Warning("Filter %s is already present.\n", command.Arg(1)); + } + } + else { + Warning("Usage: statusspec_consoletools_filter_add \n"); + } +} + +void ConsoleTools::AddFlags(const CCommand &command) { + if (command.ArgC() >= 3) { + const char *name = command.Arg(1); + + ConCommandBase *base = g_pCVar->FindCommandBase(name); + + if (base) { + for (int i = 2; i < command.ArgC(); i++) { + std::string flag = command.Arg(i); + + if (flag.compare("game") == 0) { + base->AddFlags(FCVAR_GAMEDLL); + } + else if (flag.compare("client") == 0) { + base->AddFlags(FCVAR_CLIENTDLL); + } + else if (flag.compare("archive") == 0) { + base->AddFlags(FCVAR_ARCHIVE); + } + else if (flag.compare("notify") == 0) { + base->AddFlags(FCVAR_NOTIFY); + } + else if (flag.compare("singleplayer") == 0) { + base->AddFlags(FCVAR_SPONLY); + } + else if (flag.compare("notconnected") == 0) { + base->AddFlags(FCVAR_NOT_CONNECTED); + } + else if (flag.compare("cheat") == 0) { + base->AddFlags(FCVAR_CHEAT); + } + else if (flag.compare("replicated") == 0) { + base->AddFlags(FCVAR_REPLICATED); + } + else if (flag.compare("server_can_execute") == 0) { + base->AddFlags(FCVAR_SERVER_CAN_EXECUTE); + } + else if (flag.compare("clientcmd_can_execute") == 0) { + base->AddFlags(FCVAR_CLIENTCMD_CAN_EXECUTE); + } + else if (IsInteger(flag)) { + base->AddFlags(1 << atoi(flag.c_str())); + } + else { + Warning("Unrecognized flag %s!\n", command.Arg(i)); + } + } + } + else { + Warning("%s is not a valid command or variable!\n", command.Arg(1)); + } + } + else { + Warning("Usage: statusspec_consoletools_flags_add [flag2 ...]\n"); + } +} + +void ConsoleTools::RemoveFilter(const CCommand &command) { + if (command.ArgC() >= 2) { + std::string filter = command.Arg(1); + + if (filters.count(filter)) { + filters.erase(filter); + } + else { + Warning("Filter %s is not already present.\n", command.Arg(1)); + } + } + else { + Warning("Usage: statusspec_consoletools_filter_remove \n"); + } +} + +void ConsoleTools::RemoveFlags(const CCommand &command) { + if (command.ArgC() >= 3) { + const char *name = command.Arg(1); + + ConCommandBase *base = g_pCVar->FindCommandBase(name); + + if (base) { + int flags = CCvar::GetFlags(base); + + for (int i = 2; i < command.ArgC(); i++) { + std::string flag = command.Arg(i); + + if (flag.compare("game") == 0) { + flags &= ~(FCVAR_GAMEDLL); + } + else if (flag.compare("client") == 0) { + flags &= ~(FCVAR_CLIENTDLL); + } + else if (flag.compare("archive") == 0) { + flags &= ~(FCVAR_ARCHIVE); + } + else if (flag.compare("notify") == 0) { + flags &= ~(FCVAR_NOTIFY); + } + else if (flag.compare("singleplayer") == 0) { + flags &= ~(FCVAR_SPONLY); + } + else if (flag.compare("notconnected") == 0) { + flags &= ~(FCVAR_NOT_CONNECTED); + } + else if (flag.compare("cheat") == 0) { + flags &= ~(FCVAR_CHEAT); + } + else if (flag.compare("replicated") == 0) { + flags &= ~(FCVAR_REPLICATED); + } + else if (flag.compare("server_can_execute") == 0) { + flags &= ~(FCVAR_SERVER_CAN_EXECUTE); + } + else if (flag.compare("clientcmd_can_execute") == 0) { + flags &= ~(FCVAR_CLIENTCMD_CAN_EXECUTE); + } + else if (IsInteger(flag)) { + flags &= ~(1 << atoi(flag.c_str())); + } + else { + Warning("Unrecognized flag %s!\n", command.Arg(i)); + } + } + + CCvar::SetFlags(base, flags); + } + else { + Warning("%s is not a valid command or variable!\n", command.Arg(1)); + } + } + else { + Warning("Usage: statusspec_consoletools_flags_remove [flag2 ...]\n"); + } +} + +void ConsoleTools::ToggleFilterEnabled(IConVar *var, const char *pOldValue, float flOldValue) { + if (filter_enabled->GetBool()) { + if (!consoleColorPrintfHook) { + consoleColorPrintfHook = Funcs::AddHook_ICvar_ConsoleColorPrintf(g_pCVar, SH_MEMBER(this, &ConsoleTools::ConsoleColorPrintfHook), false); + } + + if (!consoleDPrintfHook) { + consoleDPrintfHook = Funcs::AddHook_ICvar_ConsoleDPrintf(g_pCVar, SH_MEMBER(this, &ConsoleTools::ConsoleDPrintfHook), false); + } + + if (!consolePrintfHook) { + consolePrintfHook = Funcs::AddHook_ICvar_ConsolePrintf(g_pCVar, SH_MEMBER(this, &ConsoleTools::ConsolePrintfHook), false); + } + } + else { + if (consoleColorPrintfHook) { + if (Funcs::RemoveHook(consoleColorPrintfHook)) { + consoleColorPrintfHook = 0; + } + } + + if (consoleDPrintfHook) { + if (Funcs::RemoveHook(consoleDPrintfHook)) { + consoleDPrintfHook = 0; + } + } + + if (consolePrintfHook) { + if (Funcs::RemoveHook(consolePrintfHook)) { + consolePrintfHook = 0; + } + } + } +} \ No newline at end of file diff --git a/src/modules/consoletools.h b/src/modules/consoletools.h new file mode 100644 index 0000000..6cef1a6 --- /dev/null +++ b/src/modules/consoletools.h @@ -0,0 +1,48 @@ +/* + * consoletools.h + * StatusSpec project + * + * Copyright (c) 2014-2015 Forward Command Post + * BSD 2-Clause License + * http://opensource.org/licenses/BSD-2-Clause + * + */ + +#include + +#include "../common.h" +#include "../modules.h" + +class CCommand; +class ConCommand; +class ConVar; +class IConVar; + +class ConsoleTools : public Module { +public: + ConsoleTools(); + + static bool CheckDependencies(); +private: + void ConsoleColorPrintfHook(const Color &clr, const char *message); + void ConsoleDPrintfHook(const char *message); + void ConsolePrintfHook(const char *message); + + bool CheckFilters(std::string message); + + int consoleColorPrintfHook; + int consoleDPrintfHook; + int consolePrintfHook; + std::set filters; + + ConCommand *filter_add; + ConVar *filter_enabled; + ConCommand *filter_remove; + ConCommand *flags_add; + ConCommand *flags_remove; + void AddFilter(const CCommand &command); + void AddFlags(const CCommand &command); + void RemoveFilter(const CCommand &command); + void RemoveFlags(const CCommand &command); + void ToggleFilterEnabled(IConVar *var, const char *pOldValue, float flOldValue); +}; \ No newline at end of file diff --git a/src/modules/custommaterials.cpp b/src/modules/custommaterials.cpp index 9c191af..8be4b3b 100644 --- a/src/modules/custommaterials.cpp +++ b/src/modules/custommaterials.cpp @@ -2,7 +2,7 @@ * custommaterials.cpp * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -18,29 +18,30 @@ #include "../funcs.h" #include "../ifaces.h" -CustomMaterials::CustomMaterials(std::string name) : Module(name) { +CustomMaterials::CustomMaterials() { findMaterialHook = 0; materialConfig = new KeyValues("materials"); materialConfig->LoadFromFile(Interfaces::pFileSystem, "resource/custommaterials.res", "mod"); - enabled = new ConVar("statusspec_custommaterials_enabled", "0", FCVAR_NONE, "enable custom materials", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule("Custom Materials")->ToggleEnabled(var, pOldValue, flOldValue); }); - load_replacement_group = new ConCommand("statusspec_custommaterials_load_replacement_group", [](const CCommand &command) { g_ModuleManager->GetModule("Custom Materials")->LoadReplacementGroup(command); }, "load a material replacement group", FCVAR_NONE); - unload_replacement_group = new ConCommand("statusspec_custommaterials_unload_replacement_group", [](const CCommand &command) { g_ModuleManager->GetModule("Custom Materials")->UnloadReplacementGroup(command); }, "unload a material replacement group", FCVAR_NONE); + enabled = new ConVar("statusspec_custommaterials_enabled", "0", FCVAR_NONE, "enable custom materials", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule()->ToggleEnabled(var, pOldValue, flOldValue); }); + load_replacement_group = new ConCommand("statusspec_custommaterials_load_replacement_group", [](const CCommand &command) { g_ModuleManager->GetModule()->LoadReplacementGroup(command); }, "load a material replacement group", FCVAR_NONE); + reload_settings = new ConCommand("statusspec_custommaterials_reload_settings", []() { g_ModuleManager->GetModule()->ReloadSettings(); }, "reload settings for the custom materials from the resource file", FCVAR_NONE); + unload_replacement_group = new ConCommand("statusspec_custommaterials_unload_replacement_group", [](const CCommand &command) { g_ModuleManager->GetModule()->UnloadReplacementGroup(command); }, "unload a material replacement group", FCVAR_NONE); } -bool CustomMaterials::CheckDependencies(std::string name) { +bool CustomMaterials::CheckDependencies() { bool ready = true; if (!Interfaces::pFileSystem) { PRINT_TAG(); - Warning("Required interface IFileSystem for module %s not available!\n", name.c_str()); + Warning("Required interface IFileSystem for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!g_pMaterialSystem) { PRINT_TAG(); - Warning("Required interface IMaterialSystem for module %s not available!\n", name.c_str()); + Warning("Required interface IMaterialSystem for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } @@ -83,6 +84,11 @@ void CustomMaterials::LoadReplacementGroup(const CCommand &command) { } } +void CustomMaterials::ReloadSettings() { + materialConfig = new KeyValues("materials"); + materialConfig->LoadFromFile(Interfaces::pFileSystem, "resource/custommaterials.res", "mod"); +} + void CustomMaterials::ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue) { if (enabled->GetBool()) { if (!findMaterialHook) { diff --git a/src/modules/custommaterials.h b/src/modules/custommaterials.h index 75f9df4..e9e2281 100644 --- a/src/modules/custommaterials.h +++ b/src/modules/custommaterials.h @@ -2,7 +2,7 @@ * custommaterials.h * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -22,20 +22,27 @@ class KeyValues; class CustomMaterials : public Module { public: - CustomMaterials(std::string name); + CustomMaterials(); - static bool CheckDependencies(std::string name); - - IMaterial *FindMaterialOverride(char const *pMaterialName, const char *pTextureGroupName, bool complain = true, const char *pComplainPrefix = NULL); + static bool CheckDependencies(); private: + IMaterial *FindMaterialOverride(char const *pMaterialName, const char *pTextureGroupName, bool complain = true, const char *pComplainPrefix = NULL); + + struct Replacement { + std::string group; + std::string replacement; + }; + int findMaterialHook; KeyValues *materialConfig; std::map materialReplacements; ConVar *enabled; ConCommand *load_replacement_group; + ConCommand *reload_settings; ConCommand *unload_replacement_group; void LoadReplacementGroup(const CCommand &command); + void ReloadSettings(); void ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue); void UnloadReplacementGroup(const CCommand &command); }; \ No newline at end of file diff --git a/src/modules/custommodels.cpp b/src/modules/custommodels.cpp index c778335..4c2cd51 100644 --- a/src/modules/custommodels.cpp +++ b/src/modules/custommodels.cpp @@ -2,7 +2,7 @@ * custommodels.cpp * StatusSpec project * -* Copyright (c) 2014 thesupremecommander +* Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -19,29 +19,30 @@ #include "../funcs.h" #include "../ifaces.h" -CustomModels::CustomModels(std::string name) : Module(name) { +CustomModels::CustomModels() { modelConfig = new KeyValues("models"); modelConfig->LoadFromFile(Interfaces::pFileSystem, "resource/custommodels.res", "mod"); setModelHook = 0; - enabled = new ConVar("statusspec_custommodels_enabled", "0", FCVAR_NONE, "enable custom models", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule("Custom Models")->ToggleEnabled(var, pOldValue, flOldValue); }); - load_replacement_group = new ConCommand("statusspec_custommodels_load_replacement_group", [](const CCommand &command) { g_ModuleManager->GetModule("Custom Models")->LoadReplacementGroup(command); }, "load a model replacement group", FCVAR_NONE); - unload_replacement_group = new ConCommand("statusspec_custommodels_unload_replacement_group", [](const CCommand &command) { g_ModuleManager->GetModule("Custom Models")->UnloadReplacementGroup(command); }, "unload a model replacement group", FCVAR_NONE); + enabled = new ConVar("statusspec_custommodels_enabled", "0", FCVAR_NONE, "enable custom models", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule()->ToggleEnabled(var, pOldValue, flOldValue); }); + load_replacement_group = new ConCommand("statusspec_custommodels_load_replacement_group", [](const CCommand &command) { g_ModuleManager->GetModule()->LoadReplacementGroup(command); }, "load a model replacement group", FCVAR_NONE); + reload_settings = new ConCommand("statusspec_custommodels_reload_settings", []() { g_ModuleManager->GetModule()->ReloadSettings(); }, "reload settings for the custom models from the resource file", FCVAR_NONE); + unload_replacement_group = new ConCommand("statusspec_custommodels_unload_replacement_group", [](const CCommand &command) { g_ModuleManager->GetModule()->UnloadReplacementGroup(command); }, "unload a model replacement group", FCVAR_NONE); } -bool CustomModels::CheckDependencies(std::string name) { +bool CustomModels::CheckDependencies() { bool ready = true; if (!Interfaces::pFileSystem) { PRINT_TAG(); - Warning("Required interface IFileSystem for module %s not available!\n", name.c_str()); + Warning("Required interface IFileSystem for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Interfaces::pModelInfoClient) { PRINT_TAG(); - Warning("Required interface IVModelInfoClient for module %s not available!\n", name.c_str()); + Warning("Required interface IVModelInfoClient for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } @@ -51,7 +52,7 @@ bool CustomModels::CheckDependencies(std::string name) { } catch (bad_pointer) { PRINT_TAG(); - Warning("Required function C_BaseEntity::SetModelIndex for module %s not available!\n", name.c_str()); + Warning("Required function C_BaseEntity::SetModelIndex for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } @@ -61,7 +62,7 @@ bool CustomModels::CheckDependencies(std::string name) { } catch (bad_pointer) { PRINT_TAG(); - Warning("Required function C_BaseEntity::SetModelPointer for module %s not available!\n", name.c_str()); + Warning("Required function C_BaseEntity::SetModelPointer for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } @@ -104,6 +105,11 @@ void CustomModels::LoadReplacementGroup(const CCommand &command) { } } +void CustomModels::ReloadSettings() { + modelConfig = new KeyValues("models"); + modelConfig->LoadFromFile(Interfaces::pFileSystem, "resource/custommodels.res", "mod"); +} + void CustomModels::ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue) { if (enabled->GetBool()) { if (!setModelHook) { diff --git a/src/modules/custommodels.h b/src/modules/custommodels.h index 1cd0f41..db829fa 100644 --- a/src/modules/custommodels.h +++ b/src/modules/custommodels.h @@ -2,7 +2,7 @@ * custommodels.h * StatusSpec project * -* Copyright (c) 2014 thesupremecommander +* Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -23,20 +23,27 @@ struct model_t; class CustomModels : public Module { public: - CustomModels(std::string name); + CustomModels(); - static bool CheckDependencies(std::string name); + static bool CheckDependencies(); private: + void SetModelOverride(C_BaseEntity *entity, const model_t *&model); + + struct Replacement { + std::string group; + std::string replacement; + }; + KeyValues *modelConfig; std::map modelReplacements; int setModelHook; - void SetModelOverride(C_BaseEntity *entity, const model_t *&model); - ConVar *enabled; ConCommand *load_replacement_group; + ConCommand *reload_settings; ConCommand *unload_replacement_group; void LoadReplacementGroup(const CCommand &command); + void ReloadSettings(); void ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue); void UnloadReplacementGroup(const CCommand &command); }; \ No newline at end of file diff --git a/src/modules/customtextures.cpp b/src/modules/customtextures.cpp index fcc427a..235d25b 100644 --- a/src/modules/customtextures.cpp +++ b/src/modules/customtextures.cpp @@ -2,7 +2,7 @@ * customtextures.cpp * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -17,28 +17,29 @@ #include "../ifaces.h" -CustomTextures::CustomTextures(std::string name) : Module(name) { +CustomTextures::CustomTextures() { textureConfig = new KeyValues("textures"); textureConfig->LoadFromFile(Interfaces::pFileSystem, "resource/customtextures.res", "mod"); - enabled = new ConVar("statusspec_customtextures_enabled", "0", FCVAR_NONE, "enable custom materials", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule("Custom Textures")->ToggleEnabled(var, pOldValue, flOldValue); }); - load_replacement_group = new ConCommand("statusspec_customtextures_load_replacement_group", [](const CCommand &command) { g_ModuleManager->GetModule("Custom Textures")->LoadReplacementGroup(command); }, "load a texture replacement group", FCVAR_NONE); - unload_replacement_group = new ConCommand("statusspec_customtextures_unload_replacement_group", [](const CCommand &command) { g_ModuleManager->GetModule("Custom Textures")->UnloadReplacementGroup(command); }, "unload a texture replacement group", FCVAR_NONE); + enabled = new ConVar("statusspec_customtextures_enabled", "0", FCVAR_NONE, "enable custom materials", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule()->ToggleEnabled(var, pOldValue, flOldValue); }); + load_replacement_group = new ConCommand("statusspec_customtextures_load_replacement_group", [](const CCommand &command) { g_ModuleManager->GetModule()->LoadReplacementGroup(command); }, "load a texture replacement group", FCVAR_NONE); + reload_settings = new ConCommand("statusspec_customtextures_reload_settings", []() { g_ModuleManager->GetModule()->ReloadSettings(); }, "reload settings for the custom textures from the resource file", FCVAR_NONE); + unload_replacement_group = new ConCommand("statusspec_customtextures_unload_replacement_group", [](const CCommand &command) { g_ModuleManager->GetModule()->UnloadReplacementGroup(command); }, "unload a texture replacement group", FCVAR_NONE); } -bool CustomTextures::CheckDependencies(std::string name) { +bool CustomTextures::CheckDependencies() { bool ready = true; if (!Interfaces::pFileSystem) { PRINT_TAG(); - Warning("Required interface IFileSystem for module %s not available!\n", name.c_str()); + Warning("Required interface IFileSystem for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!g_pMaterialSystem) { PRINT_TAG(); - Warning("Required interface IMaterialSystem for module %s not available!\n", name.c_str()); + Warning("Required interface IMaterialSystem for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } @@ -81,15 +82,20 @@ void CustomTextures::LoadReplacementGroup(const CCommand &command) { } } +void CustomTextures::ReloadSettings() { + textureConfig = new KeyValues("textures"); + textureConfig->LoadFromFile(Interfaces::pFileSystem, "resource/customtextures.res", "mod"); +} + void CustomTextures::ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue) { if (enabled->GetBool()) { - for (auto iterator = textureReplacements.begin(); iterator != textureReplacements.end(); ++iterator) { - g_pMaterialSystem->AddTextureAlias(iterator->first.c_str(), iterator->second.replacement.c_str()); + for (auto iterator : textureReplacements) { + g_pMaterialSystem->AddTextureAlias(iterator.first.c_str(), iterator.second.replacement.c_str()); } } else { - for (auto iterator = textureReplacements.begin(); iterator != textureReplacements.end(); ++iterator) { - g_pMaterialSystem->RemoveTextureAlias(iterator->first.c_str()); + for (auto iterator : textureReplacements) { + g_pMaterialSystem->RemoveTextureAlias(iterator.first.c_str()); } } } diff --git a/src/modules/customtextures.h b/src/modules/customtextures.h index 7341f9b..af1b697 100644 --- a/src/modules/customtextures.h +++ b/src/modules/customtextures.h @@ -2,7 +2,7 @@ * customtextures.h * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -21,17 +21,24 @@ class KeyValues; class CustomTextures : public Module { public: - CustomTextures(std::string name); + CustomTextures(); - static bool CheckDependencies(std::string name); + static bool CheckDependencies(); private: + struct Replacement { + std::string group; + std::string replacement; + }; + KeyValues *textureConfig; std::map textureReplacements; ConVar *enabled; ConCommand *load_replacement_group; + ConCommand *reload_settings; ConCommand *unload_replacement_group; void LoadReplacementGroup(const CCommand &command); + void ReloadSettings(); void ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue); void UnloadReplacementGroup(const CCommand &command); }; \ No newline at end of file diff --git a/src/modules/fovoverride.cpp b/src/modules/fovoverride.cpp index a632bbe..d14215b 100644 --- a/src/modules/fovoverride.cpp +++ b/src/modules/fovoverride.cpp @@ -2,7 +2,7 @@ * fovoverride.cpp * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -10,42 +10,61 @@ #include "fovoverride.h" +#include "cbase.h" +#include "c_baseplayer.h" #include "convar.h" +#include "icliententity.h" +#include "shareddefs.h" #include "../common.h" #include "../funcs.h" #include "../ifaces.h" #include "../player.h" +#include "../tfdefs.h" -FOVOverride::FOVOverride(std::string name) : Module(name) { - frameHook = 0; - getFOVHook = 0; +FOVOverride::FOVOverride() { + inToolModeHook = 0; + setupEngineViewHook = 0; - enabled = new ConVar("statusspec_fovoverride_enabled", "0", FCVAR_NONE, "enable FOV override", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule("FOV Override")->ToggleEnabled(var, pOldValue, flOldValue); }); + enabled = new ConVar("statusspec_fovoverride_enabled", "0", FCVAR_NONE, "enable FOV override", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule()->ToggleEnabled(var, pOldValue, flOldValue); }); fov = new ConVar("statusspec_fovoverride_fov", "90", FCVAR_NONE, "the FOV value used"); zoomed = new ConVar("statusspec_fovoverride_zoomed", "0", FCVAR_NONE, "enable FOV override even when sniper rifle is zoomed"); } -bool FOVOverride::CheckDependencies(std::string name) { +bool FOVOverride::CheckDependencies() { bool ready = true; + + if (!Interfaces::pClientEngineTools) { + PRINT_TAG(); + Warning("Required interface IClientEngineTools for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); + + ready = false; + } - if (!Interfaces::pClientDLL) { + if (!Interfaces::pEngineClient) { PRINT_TAG(); - Warning("Required interface IBaseClientDLL for module %s not available!\n", name.c_str()); + Warning("Required interface IVEngineClient for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); + + ready = false; + } + + if (!Interfaces::pEngineTool) { + PRINT_TAG(); + Warning("Required interface IEngineTool for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Player::CheckDependencies()) { PRINT_TAG(); - Warning("Required player helper class for module %s not available!\n", name.c_str()); + Warning("Required player helper class for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Player::conditionsRetrievalAvailable) { PRINT_TAG(); - Warning("Required player condition retrieval for module %s not available!\n", name.c_str()); + Warning("Required player condition retrieval for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } @@ -53,64 +72,49 @@ bool FOVOverride::CheckDependencies(std::string name) { return ready; } -void FOVOverride::FrameHook(ClientFrameStage_t curStage) { - if (curStage == FRAME_NET_UPDATE_END) { - if (HookGetFOV()) { - Funcs::RemoveHook(frameHook); - frameHook = 0; - } - } - - RETURN_META(MRES_IGNORED); +bool FOVOverride::InToolModeOverride() { + RETURN_META_VALUE(MRES_OVERRIDE, true); } -float FOVOverride::GetFOVOverride() { - if (!zoomed->GetBool()) { - Player player = (IClientEntity *) META_IFACEPTR(C_TFPlayer); +bool FOVOverride::SetupEngineViewOverride(Vector &origin, QAngle &angles, float &fov) { + Player localPlayer = Interfaces::pEngineClient->GetLocalPlayer(); - if (player && player.CheckCondition(TFCond_Zoomed)) { - RETURN_META_VALUE(MRES_IGNORED, 0.0f); + if (localPlayer) { + if (localPlayer.CheckCondition(TFCond_Zoomed)) { + RETURN_META_VALUE(MRES_IGNORED, false); } - } - - RETURN_META_VALUE(MRES_SUPERCEDE, fov->GetFloat()); -} - -bool FOVOverride::HookGetFOV() { - if (getFOVHook) { - return true; - } - - for (auto iterator = Player::begin(); iterator != Player::end(); ++iterator) { - Player player = *iterator; + else if (localPlayer.GetObserverMode() == OBS_MODE_IN_EYE) { + Player targetPlayer = localPlayer.GetObserverTarget(); - getFOVHook = Funcs::AddGlobalHook_C_TFPlayer_GetFOV((C_TFPlayer *)player.GetEntity(), SH_MEMBER(this, &FOVOverride::GetFOVOverride), false); - - if (getFOVHook) { - return true; + if (targetPlayer && targetPlayer.CheckCondition(TFCond_Zoomed)) { + RETURN_META_VALUE(MRES_IGNORED, false); + } } } - return false; + fov = this->fov->GetFloat(); + RETURN_META_VALUE(MRES_SUPERCEDE, true); } void FOVOverride::ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue) { if (enabled->GetBool()) { - if (!HookGetFOV() && !frameHook) { - frameHook = Funcs::AddHook_IBaseClientDLL_FrameStageNotify(Interfaces::pClientDLL, SH_MEMBER(this, &FOVOverride::FrameHook), true); + if (!inToolModeHook) { + inToolModeHook = Funcs::AddHook_IClientEngineTools_InToolMode(Interfaces::pClientEngineTools, SH_MEMBER(this, &FOVOverride::InToolModeOverride), false); + } + + if (!setupEngineViewHook) { + setupEngineViewHook = Funcs::AddHook_IClientEngineTools_SetupEngineView(Interfaces::pClientEngineTools, SH_MEMBER(this, &FOVOverride::SetupEngineViewOverride), false); } } else { - if (getFOVHook) { - if (Funcs::RemoveHook(getFOVHook)) { - getFOVHook = 0; - } + if (inToolModeHook) { + Funcs::RemoveHook(inToolModeHook); + inToolModeHook = 0; } - if (frameHook) { - if (Funcs::RemoveHook(frameHook)) { - frameHook = 0; - } + if (setupEngineViewHook) { + Funcs::RemoveHook(setupEngineViewHook); + setupEngineViewHook = 0; } } } \ No newline at end of file diff --git a/src/modules/fovoverride.h b/src/modules/fovoverride.h index 28b50a0..768ca06 100644 --- a/src/modules/fovoverride.h +++ b/src/modules/fovoverride.h @@ -2,7 +2,7 @@ * fovoverride.h * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -10,26 +10,25 @@ #pragma once -#include "../modules.h" +#include "mathlib/vector.h" -#include "cdll_int.h" +#include "../modules.h" class ConVar; class IConVar; class FOVOverride : public Module { public: - FOVOverride(std::string name); - - static bool CheckDependencies(std::string name); + FOVOverride(); - void FrameHook(ClientFrameStage_t curStage); - float GetFOVOverride(); + static bool CheckDependencies(); private: - bool HookGetFOV(); + int inToolModeHook; + int setupEngineViewHook; + bool InToolModeOverride(); + bool SetupEngineViewOverride(Vector &origin, QAngle &angles, float &fov); - int frameHook; - int getFOVHook; + class HLTVCameraOverride; ConVar *enabled; ConVar *fov; diff --git a/src/modules/freezeinfo.cpp b/src/modules/freezeinfo.cpp new file mode 100644 index 0000000..05a6f09 --- /dev/null +++ b/src/modules/freezeinfo.cpp @@ -0,0 +1,183 @@ +/* + * freezeinfo.cpp + * StatusSpec project + * + * Copyright (c) 2014-2015 Forward Command Post + * BSD 2-Clause License + * http://opensource.org/licenses/BSD-2-Clause + * + */ + +#include "freezeinfo.h" + +#include "cbase.h" +#include "convar.h" +#include "iclientmode.h" +#include "tier3/tier3.h" +#include "toolframework/ienginetool.h" +#include "vgui/IVGui.h" +#include "vgui_controls/EditablePanel.h" + +#include "../common.h" +#include "../funcs.h" +#include "../ifaces.h" + +class FreezeInfo::Panel : public vgui::EditablePanel { +public: + Panel(vgui::Panel *parent, const char *panelName); + virtual ~Panel(); + + virtual void OnTick(); + + void SetDisplayThreshold(float threshold); +private: + void PostEntityPacketReceivedHook(); + + float lastUpdate; + int postEntityPacketReceivedHook; + float threshold; +}; + +FreezeInfo::FreezeInfo() { + panel = nullptr; + + enabled = new ConVar("statusspec_freezeinfo_enabled", "0", FCVAR_NONE, "enables display of an info panel when a freeze is detected", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule()->ToggleEnabled(var, pOldValue, flOldValue); }); + reload_settings = new ConCommand("statusspec_freezeinfo_reload_settings", []() { g_ModuleManager->GetModule()->ReloadSettings(); }, "reload settings for the freeze info panel from the resource file", FCVAR_NONE); + threshold = new ConVar("statusspec_freezeinfo_threshold", "1", FCVAR_NONE, "the time of a freeze (in seconds) before the info panel is displayed", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule()->ChangeThreshold(var, pOldValue, flOldValue); }); +} + +bool FreezeInfo::CheckDependencies() { + bool ready = true; + + if (!Interfaces::pEngineTool) { + PRINT_TAG(); + Warning("Required interface IEngineTool for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); + + ready = false; + } + + if (!Interfaces::pPrediction) { + PRINT_TAG(); + Warning("Required interface IPrediction for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); + + ready = false; + } + + if (!Interfaces::vguiLibrariesAvailable) { + PRINT_TAG(); + Warning("Required VGUI library for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); + + ready = false; + } + + if (!g_pVGui) { + PRINT_TAG(); + Warning("Required interface vgui::IVGui for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); + + ready = false; + } + + if (!g_pVGuiPanel) { + PRINT_TAG(); + Warning("Required interface vgui::IPanel for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); + + ready = false; + } + + try { + Interfaces::GetClientMode(); + } + catch (bad_pointer) { + PRINT_TAG(); + Warning("Module %s requires IClientMode, which cannot be verified at this time!\n", g_ModuleManager->GetModuleName().c_str()); + } + + return ready; +} + +void FreezeInfo::ChangeThreshold(IConVar *var, const char *pOldValue, float flOldValue) { + if (panel) { + panel->SetDisplayThreshold(threshold->GetFloat()); + } +} + +void FreezeInfo::ReloadSettings() { + if (panel) { + panel->LoadControlSettings("Resource/UI/FreezeInfo.res"); + } +} + +void FreezeInfo::ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue) { + if (enabled->GetBool()) { + if (!panel) { + try { + vgui::Panel *viewport = Interfaces::GetClientMode()->GetViewport(); + + if (viewport) { + panel = new Panel(viewport, "FreezeInfo"); + panel->SetDisplayThreshold(threshold->GetFloat()); + } + else { + Warning("Could not initialize the panel!\n"); + var->SetValue(0); + } + } + catch (bad_pointer) { + Warning("Could not initialize the panel!\n"); + var->SetValue(0); + } + } + + if (panel) { + panel->SetEnabled(true); + } + } + else { + if (panel) { + delete panel; + panel = nullptr; + } + } +} + +FreezeInfo::Panel::Panel(vgui::Panel *parent, const char *panelName) : vgui::EditablePanel(parent, panelName) { + g_pVGui->AddTickSignal(GetVPanel()); + postEntityPacketReceivedHook = Funcs::AddHook_IPrediction_PostEntityPacketReceived(Interfaces::pPrediction, SH_MEMBER(this, &FreezeInfo::Panel::PostEntityPacketReceivedHook), true); + + LoadControlSettings("Resource/UI/FreezeInfo.res"); +} + +FreezeInfo::Panel::~Panel() { + Funcs::RemoveHook(postEntityPacketReceivedHook); +} + +void FreezeInfo::Panel::OnTick() { + float interval = Interfaces::pEngineTool->HostTime() - lastUpdate; + + if (interval > threshold) { + if (!IsVisible()) { + SetVisible(true); + } + + int seconds = int(floor(interval)) % 60; + int minutes = int(floor(interval)) / 60; + + char *formattedTime = new char[16]; + V_snprintf(formattedTime, 15, "%i:%02i", minutes, seconds); + + SetDialogVariable("time", formattedTime); + } + else { + if (IsVisible()) { + SetVisible(false); + } + } +} + +void FreezeInfo::Panel::SetDisplayThreshold(float displayThreshold) { + threshold = displayThreshold; +} + +void FreezeInfo::Panel::PostEntityPacketReceivedHook() { + lastUpdate = Interfaces::pEngineTool->HostTime(); +} \ No newline at end of file diff --git a/src/modules/freezeinfo.h b/src/modules/freezeinfo.h new file mode 100644 index 0000000..81f005b --- /dev/null +++ b/src/modules/freezeinfo.h @@ -0,0 +1,34 @@ +/* + * freezeinfo.h + * StatusSpec project + * + * Copyright (c) 2014-2015 Forward Command Post + * BSD 2-Clause License + * http://opensource.org/licenses/BSD-2-Clause + * + */ + +#pragma once + +#include "../modules.h" + +class ConCommand; +class ConVar; +class IConVar; + +class FreezeInfo : public Module { +public: + FreezeInfo(); + + static bool CheckDependencies(); +private: + class Panel; + Panel *panel; + + ConVar *enabled; + ConCommand *reload_settings; + ConVar *threshold; + void ChangeThreshold(IConVar *var, const char *pOldValue, float flOldValue); + void ReloadSettings(); + void ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue); +}; \ No newline at end of file diff --git a/src/modules/killstreaks.cpp b/src/modules/killstreaks.cpp index 04fc98d..10a264e 100644 --- a/src/modules/killstreaks.cpp +++ b/src/modules/killstreaks.cpp @@ -2,7 +2,7 @@ * killstreaks.cpp * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -10,13 +10,13 @@ #include "killstreaks.h" -#include - #include "cbase.h" #include "c_baseentity.h" #include "convar.h" #include "igameevents.h" #include "shareddefs.h" +#include "vgui/IVGui.h" +#include "vgui_controls/Panel.h" #include "../common.h" #include "../entities.h" @@ -24,65 +24,75 @@ #include "../ifaces.h" #include "../player.h" -Killstreaks::Killstreaks(std::string name) : Module(name) { - bluTopKillstreak = 0; - bluTopKillstreakPlayer = 0; - fireEventClientSideHook = 0; - frameHook = 0; - redTopKillstreak = 0; - redTopKillstreakPlayer = 0; +class Killstreaks::Panel : public vgui::Panel { +public: + Panel(vgui::Panel *parent, const char *panelName); + virtual ~Panel(); + + virtual void OnTick(); +private: + bool FireEventClientSideOverride(IGameEvent *event); + + int bluTopKillstreak; + int bluTopKillstreakPlayer; + std::map currentKillstreaks; + int fireEventClientSideHook; + CHandle gameResourcesEntity; + int redTopKillstreak; + int redTopKillstreakPlayer; +}; - enabled = new ConVar("statusspec_killstreaks_enabled", "0", FCVAR_NONE, "enable killstreaks display", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule("Killstreaks")->ToggleEnabled(var, pOldValue, flOldValue); }); - total_killfeed = new ConVar("statusspec_killstreaks_total_killfeed", "0", FCVAR_NONE, "display total kills for player in killfeed instead of only kills with single weapon"); +Killstreaks::Killstreaks() { + panel = nullptr; + + enabled = new ConVar("statusspec_killstreaks_enabled", "0", FCVAR_NONE, "enable killstreaks display", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule()->ToggleEnabled(var, pOldValue, flOldValue); }); } -bool Killstreaks::CheckDependencies(std::string name) { +bool Killstreaks::CheckDependencies() { bool ready = true; if (!Interfaces::pClientEntityList) { PRINT_TAG(); - Warning("Required interface IClientEntityList for module %s not available!\n", name.c_str()); + Warning("Required interface IClientEntityList for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Interfaces::pClientDLL) { PRINT_TAG(); - Warning("Required interface IBaseClientDLL for module %s not available!\n", name.c_str()); + Warning("Required interface IBaseClientDLL for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Interfaces::pEngineClient) { PRINT_TAG(); - Warning("Required interface IVEngineClient for module %s not available!\n", name.c_str()); + Warning("Required interface IVEngineClient for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Interfaces::pGameEventManager) { PRINT_TAG(); - Warning("Required interface IGameEventManager2 for module %s not available!\n", name.c_str()); + Warning("Required interface IGameEventManager2 for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Player::CheckDependencies()) { PRINT_TAG(); - Warning("Required player helper class for module %s not available!\n", name.c_str()); + Warning("Required player helper class for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } for (int i = 0; i < MAX_WEAPONS; i++) { - std::stringstream ss; - std::string arrayIndex; - ss << std::setfill('0') << std::setw(3) << i; - ss >> arrayIndex; + char index[4]; + GetPropIndexString(i, index); - if (!Entities::RetrieveClassPropOffset("CTFPlayer", { "m_hMyWeapons", arrayIndex })) { + if (!Entities::RetrieveClassPropOffset("CTFPlayer", { "m_hMyWeapons", index })) { PRINT_TAG(); - Warning("Required property table m_hMyWeapons for CTFPlayer for module %s not available!\n", name.c_str()); + Warning("Required property table m_hMyWeapons for CTFPlayer for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; @@ -91,14 +101,12 @@ bool Killstreaks::CheckDependencies(std::string name) { } for (int i = 0; i < 3; i++) { - std::stringstream ss; - std::string arrayIndex; - ss << std::setfill('0') << std::setw(3) << i; - ss >> arrayIndex; + char index[4]; + GetPropIndexString(i, index); - if (!Entities::RetrieveClassPropOffset("CTFPlayer", { "m_nStreaks", arrayIndex })) { + if (!Entities::RetrieveClassPropOffset("CTFPlayer", { "m_nStreaks", index })) { PRINT_TAG(); - Warning("Required property table m_nStreaks for CTFPlayer for module %s not available!\n", name.c_str()); + Warning("Required property table m_nStreaks for CTFPlayer for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; @@ -107,14 +115,12 @@ bool Killstreaks::CheckDependencies(std::string name) { } for (int i = 0; i <= MAX_PLAYERS; i++) { - std::stringstream ss; - std::string arrayIndex; - ss << std::setfill('0') << std::setw(3) << i; - ss >> arrayIndex; + char index[4]; + GetPropIndexString(i, index); - if (!Entities::RetrieveClassPropOffset("CTFPlayerResource", { "m_iStreaks", arrayIndex })) { + if (!Entities::RetrieveClassPropOffset("CTFPlayerResource", { "m_iStreaks", index })) { PRINT_TAG(); - Warning("Required property table m_iStreaks for CTFPlayerResource for module %s not available!\n", name.c_str()); + Warning("Required property table m_iStreaks for CTFPlayerResource for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; @@ -124,14 +130,14 @@ bool Killstreaks::CheckDependencies(std::string name) { if (!Entities::RetrieveClassPropOffset("CWeaponMedigun", { "m_bHealing" })) { PRINT_TAG(); - Warning("Required property m_bHealing for CWeaponMedigun for module %s not available!\n", name.c_str()); + Warning("Required property m_bHealing for CWeaponMedigun for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Entities::RetrieveClassPropOffset("CWeaponMedigun", { "m_hHealingTarget" })) { PRINT_TAG(); - Warning("Required property m_hHealingTarget for CWeaponMedigun for module %s not available!\n", name.c_str()); + Warning("Required property m_hHealingTarget for CWeaponMedigun for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } @@ -139,7 +145,136 @@ bool Killstreaks::CheckDependencies(std::string name) { return ready; } -bool Killstreaks::FireEventClientSideOverride(IGameEvent *event) { +void Killstreaks::ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue) { + if (enabled->GetBool()) { + if (!panel) { + panel = new Panel(nullptr, "Killstreaks"); + } + + if (panel) { + panel->SetEnabled(true); + } + } + else { + if (panel) { + delete panel; + panel = nullptr; + } + } +} + +Killstreaks::Panel::Panel(vgui::Panel *parent, const char *panelName) : vgui::Panel(parent, panelName) { + g_pVGui->AddTickSignal(GetVPanel()); + + bluTopKillstreak = 0; + bluTopKillstreakPlayer = 0; + fireEventClientSideHook = Funcs::AddHook_IGameEventManager2_FireEventClientSide(Interfaces::pGameEventManager, SH_MEMBER(this, &Killstreaks::Panel::FireEventClientSideOverride), false); + redTopKillstreak = 0; + redTopKillstreakPlayer = 0; +} + +Killstreaks::Panel::~Panel() { + Funcs::RemoveHook(fireEventClientSideHook); + + int maxEntity = Interfaces::pClientEntityList->GetHighestEntityIndex(); + + for (int i = 1; i <= maxEntity; i++) { + IClientEntity *entity = Interfaces::pClientEntityList->GetClientEntity(i); + + if (!entity) { + continue; + } + + if (Entities::CheckEntityBaseclass(entity, "TFPlayerResource")) { + for (int i = 1; i <= MAX_PLAYERS; i++) { + char index[4]; + GetPropIndexString(i, index); + + int *killstreakGlobal = Entities::GetEntityProp(entity, { "m_iStreaks", index }); + *killstreakGlobal = 0; + } + + break; + } + } + + for (Player player : Player::Iterable()) { + int *killstreakPrimary = Entities::GetEntityProp(player.GetEntity(), { "m_nStreaks", "000" }); + int *killstreakSecondary = Entities::GetEntityProp(player.GetEntity(), { "m_nStreaks", "001" }); + int *killstreakMelee = Entities::GetEntityProp(player.GetEntity(), { "m_nStreaks", "002" }); + int *killstreakPDA = Entities::GetEntityProp(player.GetEntity(), { "m_nStreaks", "003" }); + + *killstreakPrimary = 0; + *killstreakSecondary = 0; + *killstreakMelee = 0; + *killstreakPDA = 0; + } +} + +void Killstreaks::Panel::OnTick() { + if (Interfaces::pEngineClient->IsConnected()) { + if (!gameResourcesEntity.IsValid() || !gameResourcesEntity.Get()) { + int maxEntity = Interfaces::pClientEntityList->GetHighestEntityIndex(); + + for (int i = 1; i <= maxEntity; i++) { + IClientEntity *entity = Interfaces::pClientEntityList->GetClientEntity(i); + + if (!entity) { + continue; + } + + if (Entities::CheckEntityBaseclass(entity, "TFPlayerResource")) { + gameResourcesEntity = dynamic_cast(entity); + + break; + } + } + } + + for (Player player : Player::Iterable()) { + int *killstreakPrimary = Entities::GetEntityProp(player.GetEntity(), { "m_nStreaks", "000" }); + int *killstreakSecondary = Entities::GetEntityProp(player.GetEntity(), { "m_nStreaks", "001" }); + int *killstreakMelee = Entities::GetEntityProp(player.GetEntity(), { "m_nStreaks", "002" }); + int *killstreakPDA = Entities::GetEntityProp(player.GetEntity(), { "m_nStreaks", "003" }); + + int userid = player.GetUserID(); + + if (currentKillstreaks.find(userid) != currentKillstreaks.end()) { + *killstreakPrimary = currentKillstreaks[userid]; + *killstreakSecondary = currentKillstreaks[userid]; + *killstreakMelee = currentKillstreaks[userid]; + *killstreakPDA = currentKillstreaks[userid]; + + if (gameResourcesEntity.IsValid() && gameResourcesEntity.Get()) { + char index[4]; + GetPropIndexString(player->entindex(), index); + + int *killstreakGlobal = Entities::GetEntityProp(gameResourcesEntity.Get(), { "m_iStreaks", index }); + *killstreakGlobal = currentKillstreaks[userid]; + } + } + else { + *killstreakPrimary = 0; + *killstreakSecondary = 0; + *killstreakMelee = 0; + *killstreakPDA = 0; + + if (gameResourcesEntity.IsValid() && gameResourcesEntity.Get()) { + char index[4]; + GetPropIndexString(player->entindex(), index); + + int *killstreakGlobal = Entities::GetEntityProp(gameResourcesEntity.Get(), { "m_iStreaks", index }); + *killstreakGlobal = 0; + } + } + } + } + else { + currentKillstreaks.clear(); + } +} + +bool Killstreaks::Panel::FireEventClientSideOverride(IGameEvent *event) { if (strcmp(event->GetName(), "player_spawn") == 0) { int userID = event->GetInt("userid", -1); @@ -157,34 +292,23 @@ bool Killstreaks::FireEventClientSideOverride(IGameEvent *event) { if (attackerUserID != -1) { if (attackerUserID != victimUserID) { - currentKillstreaks[attackerUserID][weapon]++; + currentKillstreaks[attackerUserID]++; - event->SetInt("kill_streak_total", GetCurrentPlayerKillstreak(attackerUserID)); - - if (total_killfeed->GetBool()) { - event->SetInt("kill_streak_wep", GetCurrentPlayerKillstreak(attackerUserID)); - } - else { - if (IsAttributableKill(weapon)) { - event->SetInt("kill_streak_wep", GetCurrentSlotKillstreak(attackerUserID, GetKillTypeSlot(weapon))); - } - else { - event->SetInt("kill_streak_wep", 0); - } - } + event->SetInt("kill_streak_total", currentKillstreaks[attackerUserID]); + event->SetInt("kill_streak_wep", currentKillstreaks[attackerUserID]); Player attacker = Interfaces::pEngineClient->GetPlayerForUserID(attackerUserID); if (attacker) { if (attacker.GetTeam() == TFTeam_Red) { - if (GetCurrentPlayerKillstreak(attackerUserID) > redTopKillstreak) { - redTopKillstreak = GetCurrentPlayerKillstreak(attackerUserID); + if (currentKillstreaks[attackerUserID] > redTopKillstreak) { + redTopKillstreak = currentKillstreaks[attackerUserID]; redTopKillstreakPlayer = attackerUserID; } } else if (attacker.GetTeam() == TFTeam_Blue) { - if (GetCurrentPlayerKillstreak(attackerUserID) > bluTopKillstreak) { - bluTopKillstreak = GetCurrentPlayerKillstreak(attackerUserID); + if (currentKillstreaks[attackerUserID] > bluTopKillstreak) { + bluTopKillstreak = currentKillstreaks[attackerUserID]; bluTopKillstreakPlayer = attackerUserID; } } @@ -201,12 +325,10 @@ bool Killstreaks::FireEventClientSideOverride(IGameEvent *event) { if (assister) { for (int i = 0; i < MAX_WEAPONS; i++) { - std::stringstream ss; - std::string arrayIndex; - ss << std::setfill('0') << std::setw(3) << i; - ss >> arrayIndex; + char index[4]; + GetPropIndexString(i, index); - IClientEntity *weapon = Entities::GetEntityProp(assister.GetEntity(), { "m_hMyWeapons", arrayIndex })->Get(); + IClientEntity *weapon = Entities::GetEntityProp(assister.GetEntity(), { "m_hMyWeapons", index })->Get(); if (!weapon || !Entities::CheckEntityBaseclass(weapon, "WeaponMedigun")) { continue; @@ -218,18 +340,17 @@ bool Killstreaks::FireEventClientSideOverride(IGameEvent *event) { int healingTarget = Entities::GetEntityProp(weapon, { "m_hHealingTarget" })->GetEntryIndex(); if (healingTarget == Interfaces::pEngineClient->GetPlayerForUserID(attackerUserID)) { - // add medigun killstreak onto a special "kill type" - currentKillstreaks[assisterUserID]["medigun"]++; + currentKillstreaks[assisterUserID]++; if (assister.GetTeam() == TFTeam_Red) { - if (GetCurrentPlayerKillstreak(assisterUserID) > redTopKillstreak) { - redTopKillstreak = GetCurrentPlayerKillstreak(assisterUserID); + if (currentKillstreaks[assisterUserID] > redTopKillstreak) { + redTopKillstreak = currentKillstreaks[assisterUserID]; redTopKillstreakPlayer = assisterUserID; } } else if (assister.GetTeam() == TFTeam_Blue) { - if (GetCurrentPlayerKillstreak(assisterUserID) > bluTopKillstreak) { - bluTopKillstreak = GetCurrentPlayerKillstreak(assisterUserID); + if (currentKillstreaks[assisterUserID] > bluTopKillstreak) { + bluTopKillstreak = currentKillstreaks[assisterUserID]; bluTopKillstreakPlayer = assisterUserID; } } @@ -238,11 +359,11 @@ bool Killstreaks::FireEventClientSideOverride(IGameEvent *event) { } } - event->SetInt("kill_streak_assist", GetCurrentPlayerKillstreak(assisterUserID)); + event->SetInt("kill_streak_assist", currentKillstreaks[assisterUserID]); } if (victimUserID != -1) { - event->SetInt("kill_streak_victim", GetCurrentPlayerKillstreak(victimUserID)); + event->SetInt("kill_streak_victim", currentKillstreaks[victimUserID]); } RETURN_META_VALUE(MRES_HANDLED, false); @@ -269,188 +390,4 @@ bool Killstreaks::FireEventClientSideOverride(IGameEvent *event) { } RETURN_META_VALUE(MRES_IGNORED, false); -} - -void Killstreaks::FrameHook(ClientFrameStage_t curStage) { - if (curStage == FRAME_NET_UPDATE_END) { - if (!gameResourcesEntity.IsValid() || !gameResourcesEntity.Get()) { - int maxEntity = Interfaces::pClientEntityList->GetMaxEntities(); - - for (int i = 1; i <= maxEntity; i++) { - IClientEntity *entity = Interfaces::pClientEntityList->GetClientEntity(i); - - if (!entity) { - continue; - } - - if (Entities::CheckEntityBaseclass(entity, "TFPlayerResource")) { - gameResourcesEntity = dynamic_cast(entity); - - break; - } - } - } - - for (auto iterator = Player::begin(); iterator != Player::end(); ++iterator) { - Player player = *iterator; - - int *killstreakPrimary = Entities::GetEntityProp(player.GetEntity(), { "m_nStreaks", "000" }); - int *killstreakSecondary = Entities::GetEntityProp(player.GetEntity(), { "m_nStreaks", "001" }); - int *killstreakMelee = Entities::GetEntityProp(player.GetEntity(), { "m_nStreaks", "002" }); - - int userid = player.GetUserID(); - - if (currentKillstreaks.find(userid) != currentKillstreaks.end()) { - *killstreakPrimary = GetCurrentSlotKillstreak(userid, 0); - *killstreakSecondary = GetCurrentSlotKillstreak(userid, 1); - *killstreakMelee = GetCurrentSlotKillstreak(userid, 2); - - if (gameResourcesEntity.IsValid() && gameResourcesEntity.Get()) { - std::stringstream ss; - std::string arrayIndex; - ss << std::setfill('0') << std::setw(3) << player->entindex(); - ss >> arrayIndex; - - int *killstreakGlobal = Entities::GetEntityProp(gameResourcesEntity.Get(), { "m_iStreaks", arrayIndex }); - *killstreakGlobal = GetCurrentPlayerKillstreak(userid); - } - } - else { - *killstreakPrimary = 0; - *killstreakSecondary = 0; - *killstreakMelee = 0; - - if (gameResourcesEntity.IsValid() && gameResourcesEntity.Get()) { - std::stringstream ss; - std::string arrayIndex; - ss << std::setfill('0') << std::setw(3) << player->entindex(); - ss >> arrayIndex; - - int *killstreakGlobal = Entities::GetEntityProp(gameResourcesEntity.Get(), { "m_iStreaks", arrayIndex }); - *killstreakGlobal = 0; - } - } - } - - RETURN_META(MRES_HANDLED); - } - else if (curStage == FRAME_START) { - if (!Interfaces::pEngineClient->IsInGame()) { - currentKillstreaks.clear(); - } - } - - RETURN_META(MRES_IGNORED); -} - -int Killstreaks::GetCurrentPlayerKillstreak(int userid) { - int killstreak = 0; - - for (auto iterator = currentKillstreaks[userid].begin(); iterator != currentKillstreaks[userid].end(); ++iterator) { - killstreak += iterator->second; - } - - return killstreak; -} - -int Killstreaks::GetCurrentSlotKillstreak(int userid, int slot) { - int killstreak = 0; - - for (auto iterator = TFDefinitions::slotKillIcons.find(slot)->second.begin(); iterator != TFDefinitions::slotKillIcons.find(slot)->second.end(); ++iterator) { - killstreak += currentKillstreaks[userid][*iterator]; - } - - if (slot == 1) { - // mediguns aren't kill icons, so let's add them in manually to the secondary slot - killstreak += currentKillstreaks[userid]["medigun"]; - } - - return killstreak; -} - -int Killstreaks::GetKillTypeSlot(std::string killType) { - for (auto slotIterator = TFDefinitions::slotKillIcons.begin(); slotIterator != TFDefinitions::slotKillIcons.end(); ++slotIterator) { - for (auto iterator = slotIterator->second.begin(); iterator != slotIterator->second.end(); ++iterator) { - if (killType.compare(*iterator) == 0) { - return slotIterator->first; - } - } - } - - return -1; -} - -bool Killstreaks::IsAttributableKill(std::string killType) { - for (auto slotIterator = TFDefinitions::slotKillIcons.begin(); slotIterator != TFDefinitions::slotKillIcons.end(); ++slotIterator) { - for (auto iterator = slotIterator->second.begin(); iterator != slotIterator->second.end(); ++iterator) { - if (killType.compare(*iterator) == 0) { - return true; - } - } - } - - return false; -} - -void Killstreaks::ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue) { - if (enabled->GetBool()) { - if (!fireEventClientSideHook) { - fireEventClientSideHook = Funcs::AddHook_IGameEventManager2_FireEventClientSide(Interfaces::pGameEventManager, SH_MEMBER(this, &Killstreaks::FireEventClientSideOverride), false); - } - - if (!frameHook) { - frameHook = Funcs::AddHook_IBaseClientDLL_FrameStageNotify(Interfaces::pClientDLL, SH_MEMBER(this, &Killstreaks::FrameHook), true); - } - } - else { - if (fireEventClientSideHook) { - if (Funcs::RemoveHook(fireEventClientSideHook)) { - fireEventClientSideHook = 0; - } - } - - if (frameHook) { - if (Funcs::RemoveHook(frameHook)) { - frameHook = 0; - } - } - - int maxEntity = Interfaces::pClientEntityList->GetMaxEntities(); - - for (int i = 1; i <= maxEntity; i++) { - IClientEntity *entity = Interfaces::pClientEntityList->GetClientEntity(i); - - if (!entity) { - continue; - } - - if (Entities::CheckEntityBaseclass(entity, "TFPlayerResource")) { - gameResourcesEntity = dynamic_cast(entity); - - for (int i = 1; i <= MAX_PLAYERS; i++) { - std::stringstream ss; - std::string arrayIndex; - ss << std::setfill('0') << std::setw(3) << i; - ss >> arrayIndex; - - int *killstreakGlobal = Entities::GetEntityProp(gameResourcesEntity.Get(), { "m_iStreaks", arrayIndex }); - *killstreakGlobal = 0; - } - - break; - } - } - - for (auto iterator = Player::begin(); iterator != Player::end(); ++iterator) { - Player player = *iterator; - - int *killstreakPrimary = Entities::GetEntityProp(player.GetEntity(), { "m_nStreaks", "000" }); - int *killstreakSecondary = Entities::GetEntityProp(player.GetEntity(), { "m_nStreaks", "001" }); - int *killstreakMelee = Entities::GetEntityProp(player.GetEntity(), { "m_nStreaks", "002" }); - - *killstreakPrimary = 0; - *killstreakSecondary = 0; - *killstreakMelee = 0; - } - } } \ No newline at end of file diff --git a/src/modules/killstreaks.h b/src/modules/killstreaks.h index d0fd3dc..ff2dc34 100644 --- a/src/modules/killstreaks.h +++ b/src/modules/killstreaks.h @@ -2,7 +2,7 @@ * killstreaks.h * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -15,37 +15,21 @@ class C_BaseEntity; class ConVar; -class IGameEvent; +class IConVar; -#include "cdll_int.h" #include "ehandle.h" #include "../modules.h" class Killstreaks : public Module { public: - Killstreaks(std::string name); + Killstreaks(); - static bool CheckDependencies(std::string name); - - bool FireEventClientSideOverride(IGameEvent *event); - void FrameHook(ClientFrameStage_t curStage); + static bool CheckDependencies(); private: - int bluTopKillstreak; - int bluTopKillstreakPlayer; - std::map> currentKillstreaks; - int fireEventClientSideHook; - int frameHook; - CHandle gameResourcesEntity; - int redTopKillstreak; - int redTopKillstreakPlayer; - - int GetCurrentSlotKillstreak(int userid, int slot); - int GetCurrentPlayerKillstreak(int userid); - int GetKillTypeSlot(std::string killType); - bool IsAttributableKill(std::string killType); + class Panel; + Panel *panel; ConVar *enabled; - ConVar *total_killfeed; void ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue); }; \ No newline at end of file diff --git a/src/modules/loadouticons.cpp b/src/modules/loadouticons.cpp deleted file mode 100644 index 7212871..0000000 --- a/src/modules/loadouticons.cpp +++ /dev/null @@ -1,598 +0,0 @@ -/* - * loadouticons.cpp - * StatusSpec project - * - * Copyright (c) 2014 thesupremecommander - * BSD 2-Clause License - * http://opensource.org/licenses/BSD-2-Clause - * - */ - -#include "loadouticons.h" - -#include -#include - -#include "cbase.h" -#include "c_baseentity.h" -#include "convar.h" -#include "icliententitylist.h" -#include "iclientmode.h" -#include "KeyValues.h" -#include "shareddefs.h" -#include "tier3/tier3.h" -#include "vgui/IVGui.h" -#include "vgui_controls/EditablePanel.h" -#include "vgui_controls/ImagePanel.h" -#include "vgui_controls/Panel.h" - -#include "../common.h" -#include "../entities.h" -#include "../funcs.h" -#include "../ifaces.h" -#include "../itemschema.h" -#include "../modules.h" - -LoadoutIcons::LoadoutIcons(std::string name) : Module(name) { - filter_active_color = Color(255, 255, 255, 255); - filter_inactive_color = Color(127, 127, 127, 255); - frameHook = 0; - itemSchema = new ItemSchema(); - - enabled = new ConVar("statusspec_loadouticons_enabled", "0", FCVAR_NONE, "enable loadout icons", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule("Loadout Icons")->ToggleEnabled(var, pOldValue, flOldValue); }); - filter_active = new ConCommand("statusspec_loadouticons_filter_active", [](const CCommand &command) { g_ModuleManager->GetModule("Loadout Icons")->SetFilter(command); }, "the RGBA filter applied to the icon for an active item", FCVAR_NONE, [](const char *partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])->int { return g_ModuleManager->GetModule("Loadout Icons")->GetCurrentFilter(partial, commands); }); - filter_inactive = new ConCommand("statusspec_loadouticons_filter_inactive", [](const CCommand &command) { g_ModuleManager->GetModule("Loadout Icons")->SetFilter(command); }, "the RGBA filter applied to the icon for an inactive item", FCVAR_NONE, [](const char *partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])->int { return g_ModuleManager->GetModule("Loadout Icons")->GetCurrentFilter(partial, commands); }); - nonloadout = new ConVar("statusspec_loadouticons_nonloadout", "0", FCVAR_NONE, "enable loadout icons for nonloadout items"); - only_active = new ConVar("statusspec_loadouticons_only_active", "0", FCVAR_NONE, "only display loadout icons for the active weapon"); -} - -bool LoadoutIcons::CheckDependencies(std::string name) { - bool ready = true; - - if (!Interfaces::pClientDLL) { - PRINT_TAG(); - Warning("Required interface IBaseClientDLL for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!Interfaces::pClientEntityList) { - PRINT_TAG(); - Warning("Required interface IClientEntityList for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!Interfaces::vguiLibrariesAvailable) { - PRINT_TAG(); - Warning("Required VGUI library for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!g_pVGui) { - PRINT_TAG(); - Warning("Required interface vgui::IVGui for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!g_pVGuiPanel) { - PRINT_TAG(); - Warning("Required interface vgui::IPanel for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!Entities::RetrieveClassPropOffset("CEconEntity", { "m_hOwnerEntity" })) { - PRINT_TAG(); - Warning("Required property m_hOwnerEntity for CEconEntity for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!Entities::RetrieveClassPropOffset("CEconEntity", { "m_iItemDefinitionIndex" })) { - PRINT_TAG(); - Warning("Required property m_hOwnerEntity for CEconEntity for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!Entities::RetrieveClassPropOffset("CTFPlayer", { "m_hActiveWeapon" })) { - PRINT_TAG(); - Warning("Required property m_hActiveWeapon for CTFPlayer for module %s not available!\n", name.c_str()); - - ready = false; - } - - for (int i = 0; i < MAX_WEAPONS; i++) { - std::stringstream ss; - std::string arrayIndex; - ss << std::setfill('0') << std::setw(3) << i; - ss >> arrayIndex; - - if (!Entities::RetrieveClassPropOffset("CTFPlayer", { "m_hMyWeapons", arrayIndex })) { - PRINT_TAG(); - Warning("Required property table m_hMyWeapons for CTFPlayer for module %s not available!\n", name.c_str()); - - ready = false; - - break; - } - } - - if (!ItemSchema::CheckDependencies()) { - PRINT_TAG(); - Warning("Required item schema helper class for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!Player::CheckDependencies()) { - PRINT_TAG(); - Warning("Required player helper class for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!Player::classRetrievalAvailable) { - PRINT_TAG(); - Warning("Required player class retrieval for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!Player::nameRetrievalAvailable) { - PRINT_TAG(); - Warning("Required player name retrieval for module %s not available!\n", name.c_str()); - - ready = false; - } - - try { - Interfaces::GetClientMode(); - } - catch (bad_pointer) { - PRINT_TAG(); - Warning("Module %s requires IClientMode, which cannot be verified at this time!\n", name.c_str()); - } - - return ready; -} - -void LoadoutIcons::FrameHook(ClientFrameStage_t curStage) { - if (curStage == FRAME_NET_UPDATE_END) { - loadoutInfo.clear(); - - int maxEntity = Interfaces::pClientEntityList->GetHighestEntityIndex(); - - for (int i = 0; i < maxEntity; i++) { - IClientEntity *entity = Interfaces::pClientEntityList->GetClientEntity(i); - - if (!entity || !Entities::CheckEntityBaseclass(entity, "EconEntity")) { - continue; - } - - Player player = Entities::GetEntityProp(entity, { "m_hOwnerEntity" })->GetEntryIndex(); - - if (!player) { - continue; - } - - int itemDefinitionIndex = *Entities::GetEntityProp(entity, { "m_iItemDefinitionIndex" }); - - if (itemIconTextures.find(itemDefinitionIndex) == itemIconTextures.end()) { - itemIconTextures[itemDefinitionIndex] = std::string("../") + itemSchema->GetItemKeyData(itemDefinitionIndex, "image_inventory"); - } - - const char *itemSlot = itemSchema->GetItemKeyData(itemDefinitionIndex, "item_slot"); - - TFClassType tfclass = player.GetClass(); - KeyValues *classUses = itemSchema->GetItemKey(itemDefinitionIndex, "used_by_classes"); - if (classUses) { - const char *classUse = classUses->GetString(TFDefinitions::classNames.find(tfclass)->second.c_str(), ""); - - if (std::find(std::begin(TFDefinitions::itemSlots), std::end(TFDefinitions::itemSlots), classUse) != std::end(TFDefinitions::itemSlots)) { - itemSlot = classUse; - } - } - - if (strcmp(itemSlot, "primary") == 0) { - loadoutInfo[player].primary = itemDefinitionIndex; - } - else if (strcmp(itemSlot, "secondary") == 0) { - loadoutInfo[player].secondary = itemDefinitionIndex; - } - else if (strcmp(itemSlot, "melee") == 0) { - loadoutInfo[player].melee = itemDefinitionIndex; - } - else if (strcmp(itemSlot, "pda") == 0) { - loadoutInfo[player].pda = itemDefinitionIndex; - } - else if (strcmp(itemSlot, "pda2") == 0) { - loadoutInfo[player].pda2 = itemDefinitionIndex; - } - else if (strcmp(itemSlot, "building") == 0) { - loadoutInfo[player].building = itemDefinitionIndex; - } - else if (strcmp(itemSlot, "head") == 0 || strcmp(itemSlot, "misc") == 0) { - for (int slot = 0; slot < MAX_COSMETIC_SLOTS; slot++) { - if (loadoutInfo[player].cosmetic[slot] == -1) { - loadoutInfo[player].cosmetic[slot] = itemDefinitionIndex; - break; - } - } - } - else if (strcmp(itemSlot, "taunt") == 0) { - for (int slot = 0; slot < MAX_TAUNT_SLOTS; slot++) { - if (loadoutInfo[player].taunt[slot] == -1) { - loadoutInfo[player].taunt[slot] = itemDefinitionIndex; - break; - } - } - } - else if (strcmp(itemSlot, "action") == 0) { - loadoutInfo[player].action = itemDefinitionIndex; - } - - int activeWeapon = Entities::GetEntityProp(player.GetEntity(), { "m_hActiveWeapon" })->GetEntryIndex(); - if (activeWeapon == entity->entindex()) { - loadoutInfo[player].activeWeaponSlot = itemDefinitionIndex; - } - } - - for (auto iterator = Player::begin(); iterator != Player::end(); ++iterator) { - Player player = *iterator; - - TFClassType tfclass = player.GetClass(); - int activeWeapon = Entities::GetEntityProp(player.GetEntity(), { "m_hActiveWeapon" })->GetEntryIndex(); - - loadoutInfo[player].tfclass = tfclass; - - for (int i = 0; i < MAX_WEAPONS; i++) { - std::stringstream ss; - std::string arrayIndex; - ss << std::setfill('0') << std::setw(3) << i; - ss >> arrayIndex; - - IClientEntity *weapon = Entities::GetEntityProp(player.GetEntity(), { "m_hMyWeapons", arrayIndex })->Get(); - - if (!weapon || !Entities::CheckEntityBaseclass(weapon, "EconEntity")) { - continue; - } - - int itemDefinitionIndex = *Entities::GetEntityProp(weapon, { "m_iItemDefinitionIndex" }); - - const char *itemSlot = itemSchema->GetItemKeyData(itemDefinitionIndex, "item_slot"); - - KeyValues *classUses = itemSchema->GetItemKey(itemDefinitionIndex, "used_by_classes"); - if (classUses) { - const char *classUse = classUses->GetString(TFDefinitions::classNames.find(tfclass)->second.c_str(), ""); - - if (std::find(std::begin(TFDefinitions::itemSlots), std::end(TFDefinitions::itemSlots), classUse) != std::end(TFDefinitions::itemSlots)) { - itemSlot = classUse; - } - } - - if (activeWeapon == weapon->entindex()) { - loadoutInfo[player].activeWeaponSlot = itemDefinitionIndex; - } - - if (strcmp(itemSlot, "primary") == 0) { - loadoutInfo[player].primary = itemDefinitionIndex; - } - else if (strcmp(itemSlot, "secondary") == 0) { - loadoutInfo[player].secondary = itemDefinitionIndex; - } - else if (strcmp(itemSlot, "melee") == 0) { - loadoutInfo[player].melee = itemDefinitionIndex; - } - else if (strcmp(itemSlot, "pda") == 0) { - loadoutInfo[player].pda = itemDefinitionIndex; - } - else if (strcmp(itemSlot, "pda2") == 0) { - loadoutInfo[player].pda2 = itemDefinitionIndex; - } - else if (strcmp(itemSlot, "building") == 0) { - loadoutInfo[player].building = itemDefinitionIndex; - } - else if (strcmp(itemSlot, "head") == 0 || strcmp(itemSlot, "misc") == 0) { - for (int slot = 0; slot < MAX_COSMETIC_SLOTS; slot++) { - if (loadoutInfo[player].cosmetic[slot] == -1) { - loadoutInfo[player].cosmetic[slot] = itemDefinitionIndex; - break; - } - } - } - else if (strcmp(itemSlot, "taunt") == 0) { - for (int slot = 0; slot < MAX_TAUNT_SLOTS; slot++) { - if (loadoutInfo[player].taunt[slot] == -1) { - loadoutInfo[player].taunt[slot] = itemDefinitionIndex; - break; - } - } - } - else if (strcmp(itemSlot, "action") == 0) { - loadoutInfo[player].action = itemDefinitionIndex; - } - } - } - - if (Interfaces::GetClientMode() && Interfaces::GetClientMode()->GetViewport()) { - vgui::VPANEL viewport = Interfaces::GetClientMode()->GetViewport()->GetVPanel(); - - for (int i = 0; i < g_pVGuiPanel->GetChildCount(viewport); i++) { - vgui::VPANEL specgui = g_pVGuiPanel->GetChild(viewport, i); - - if (strcmp(g_pVGuiPanel->GetName(specgui), "specgui") == 0) { - for (int i = 0; i < g_pVGuiPanel->GetChildCount(specgui); i++) { - vgui::VPANEL playerPanel = g_pVGuiPanel->GetChild(specgui, i); - - if (strcmp(g_pVGuiPanel->GetClassName(playerPanel), "CTFPlayerPanel") == 0) { - for (int i = 0; i < g_pVGuiPanel->GetChildCount(playerPanel); i++) { - vgui::VPANEL loadoutIconsVPanel = g_pVGuiPanel->GetChild(playerPanel, i); - - if (strcmp(g_pVGuiPanel->GetName(loadoutIconsVPanel), "LoadoutIcons") == 0) { - vgui::EditablePanel *loadoutIcons = dynamic_cast(g_pVGuiPanel->GetPanel(loadoutIconsVPanel, "ClientDLL")); - - if (loadoutIcons) { - loadoutIcons->SetEnabled(true); - loadoutIcons->SetVisible(true); - - if (loadoutIcons->GetChildCount() == 0) { - InitIcons(loadoutIcons); - } - else { - DisplayIcons(playerPanel); - } - } - - break; - } - } - } - } - - break; - } - } - } - } -} - -void LoadoutIcons::DisableHUD() { - if (Interfaces::GetClientMode() && Interfaces::GetClientMode()->GetViewport()) { - vgui::VPANEL viewport = Interfaces::GetClientMode()->GetViewport()->GetVPanel(); - - for (int i = 0; i < g_pVGuiPanel->GetChildCount(viewport); i++) { - vgui::VPANEL specgui = g_pVGuiPanel->GetChild(viewport, i); - - if (strcmp(g_pVGuiPanel->GetName(specgui), "specgui") == 0) { - for (int i = 0; i < g_pVGuiPanel->GetChildCount(specgui); i++) { - vgui::VPANEL playerPanel = g_pVGuiPanel->GetChild(specgui, i); - - if (strcmp(g_pVGuiPanel->GetClassName(playerPanel), "CTFPlayerPanel") == 0) { - for (int i = 0; i < g_pVGuiPanel->GetChildCount(playerPanel); i++) { - vgui::VPANEL loadoutIconsVPanel = g_pVGuiPanel->GetChild(playerPanel, i); - - if (strcmp(g_pVGuiPanel->GetName(loadoutIconsVPanel), "LoadoutIcons") == 0) { - g_pVGuiPanel->SetEnabled(loadoutIconsVPanel, false); - g_pVGuiPanel->SetVisible(loadoutIconsVPanel, false); - - break; - } - } - } - } - - break; - } - } - } -} - -void LoadoutIcons::DisplayIcon(vgui::ImagePanel *panel, int itemDefinitionIndex, bool active) { - if (panel) { - if (active) { - panel->SetDrawColor(filter_active_color); - } - else { - panel->SetDrawColor(filter_inactive_color); - } - - if (itemDefinitionIndex != -1) { - panel->SetVisible(true); - panel->SetImage(itemIconTextures[itemDefinitionIndex].c_str()); - } - else { - panel->SetVisible(false); - panel->SetImage("dev/null"); - } - } -} - -void LoadoutIcons::DisplayIcons(vgui::VPANEL playerPanel) { - if (strcmp(g_pVGuiPanel->GetClassName(playerPanel), "CTFPlayerPanel") == 0) { - vgui::EditablePanel *panel = dynamic_cast(g_pVGuiPanel->GetPanel(playerPanel, "ClientDLL")); - - if (panel) { - vgui::HPanel panelHandle = g_pVGui->PanelToHandle(playerPanel); - - KeyValues *dialogVariables = panel->GetDialogVariables(); - - if (dialogVariables) { - const char *name = dialogVariables->GetString("playername"); - - for (auto iterator = Player::begin(); iterator != Player::end(); ++iterator) { - Player player = *iterator; - - if (player.GetName().compare(name) == 0) { - if (only_active->GetBool()) { - DisplayIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem1"]), loadoutInfo[player].activeWeaponSlot, true); - } - else { - if (loadoutInfo[player].tfclass == TFClass_Engineer) { - if (nonloadout->GetBool()) { - DisplayIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem1"]), loadoutInfo[player].primary, loadoutInfo[player].primary == loadoutInfo[player].activeWeaponSlot); - DisplayIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem2"]), loadoutInfo[player].secondary, loadoutInfo[player].secondary == loadoutInfo[player].activeWeaponSlot); - DisplayIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem3"]), loadoutInfo[player].melee, loadoutInfo[player].melee == loadoutInfo[player].activeWeaponSlot); - DisplayIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem4"]), loadoutInfo[player].pda, loadoutInfo[player].pda == loadoutInfo[player].activeWeaponSlot); - DisplayIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem5"]), loadoutInfo[player].pda2, loadoutInfo[player].pda2 == loadoutInfo[player].activeWeaponSlot); - DisplayIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem6"]), loadoutInfo[player].building, loadoutInfo[player].building == loadoutInfo[player].activeWeaponSlot); - } - else { - DisplayIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem1"]), loadoutInfo[player].primary, loadoutInfo[player].primary == loadoutInfo[player].activeWeaponSlot); - DisplayIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem2"]), loadoutInfo[player].secondary, loadoutInfo[player].secondary == loadoutInfo[player].activeWeaponSlot); - DisplayIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem3"]), loadoutInfo[player].melee, loadoutInfo[player].melee == loadoutInfo[player].activeWeaponSlot); - DisplayIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem4"]), loadoutInfo[player].pda, loadoutInfo[player].pda == loadoutInfo[player].activeWeaponSlot); - HideIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem5"])); - HideIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem6"])); - } - } - else if (loadoutInfo[player].tfclass == TFClass_Spy) { - if (nonloadout->GetBool()) { - DisplayIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem1"]), loadoutInfo[player].secondary, loadoutInfo[player].secondary == loadoutInfo[player].activeWeaponSlot); - DisplayIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem2"]), loadoutInfo[player].building, loadoutInfo[player].building == loadoutInfo[player].activeWeaponSlot); - DisplayIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem3"]), loadoutInfo[player].melee, loadoutInfo[player].melee == loadoutInfo[player].activeWeaponSlot); - DisplayIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem4"]), loadoutInfo[player].pda, loadoutInfo[player].pda == loadoutInfo[player].activeWeaponSlot); - DisplayIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem5"]), loadoutInfo[player].pda2, loadoutInfo[player].pda2 == loadoutInfo[player].activeWeaponSlot); - HideIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem6"])); - } - else { - DisplayIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem1"]), loadoutInfo[player].secondary, loadoutInfo[player].secondary == loadoutInfo[player].activeWeaponSlot); - DisplayIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem2"]), loadoutInfo[player].building, loadoutInfo[player].building == loadoutInfo[player].activeWeaponSlot); - DisplayIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem3"]), loadoutInfo[player].melee, loadoutInfo[player].melee == loadoutInfo[player].activeWeaponSlot); - DisplayIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem4"]), loadoutInfo[player].pda2, loadoutInfo[player].pda2 == loadoutInfo[player].activeWeaponSlot); - HideIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem5"])); - HideIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem6"])); - } - } - else { - DisplayIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem1"]), loadoutInfo[player].primary, loadoutInfo[player].primary == loadoutInfo[player].activeWeaponSlot); - DisplayIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem2"]), loadoutInfo[player].secondary, loadoutInfo[player].secondary == loadoutInfo[player].activeWeaponSlot); - DisplayIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem3"]), loadoutInfo[player].melee, loadoutInfo[player].melee == loadoutInfo[player].activeWeaponSlot); - HideIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem4"])); - HideIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem5"])); - HideIcon(dynamic_cast(loadoutIconPanels[panelHandle]["LoadoutIconsItem6"])); - } - } - - break; - } - } - } - } - } -} - -void LoadoutIcons::HideIcon(vgui::ImagePanel *panel) { - if (panel) { - panel->SetVisible(false); - panel->SetImage("../dev/null"); - } -} - -void LoadoutIcons::InitIcons(vgui::EditablePanel *panel) { - panel->LoadControlSettings("Resource/UI/LoadoutIcons.res"); - - if (panel->GetChildCount() == 0) { - vgui::EditablePanel *editablePanel = new vgui::EditablePanel(panel, "LoadoutIcons"); - editablePanel->LoadControlSettings("Resource/UI/LoadoutIcons.res"); - - vgui::HPanel panelHandle = g_pVGui->PanelToHandle(panel->GetVParent()); - - while (editablePanel->GetChildCount() > 0) { - vgui::Panel *childPanel = editablePanel->GetChild(0); - loadoutIconPanels[panelHandle][childPanel->GetName()] = childPanel; - - childPanel->SetParent(panel); - } - - delete editablePanel; - - panel->LoadControlSettings("Resource/UI/LoadoutIcons.res"); - } - else { - vgui::HPanel panelHandle = g_pVGui->PanelToHandle(panel->GetVParent()); - - for (int i = 0; i < g_pVGuiPanel->GetChildCount(panel->GetVPanel()); i++) { - vgui::VPANEL vpanel = g_pVGuiPanel->GetChild(panel->GetVPanel(), i); - const char *name = g_pVGuiPanel->GetName(vpanel); - vgui::Panel *panel = g_pVGuiPanel->GetPanel(vpanel, "ClientDLL"); - - loadoutIconPanels[panelHandle][name] = panel; - } - } -} - -int LoadoutIcons::GetCurrentFilter(const char *partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH]) { - std::stringstream ss(partial); - std::string command; - std::getline(ss, command, ' '); - - if (stricmp(command.c_str(), "statusspec_loadouticons_filter_active") == 0) { - V_snprintf(commands[0], COMMAND_COMPLETION_ITEM_LENGTH, "%s %i %i %i %i", command.c_str(), filter_active_color.r(), filter_active_color.g(), filter_active_color.b(), filter_active_color.a()); - - return 1; - } - else if (stricmp(command.c_str(), "statusspec_loadouticons_filter_inactive") == 0) { - V_snprintf(commands[0], COMMAND_COMPLETION_ITEM_LENGTH, "%s %i %i %i %i", command.c_str(), filter_inactive_color.r(), filter_inactive_color.g(), filter_inactive_color.b(), filter_inactive_color.a()); - - return 1; - } - else { - return 0; - } -} - -void LoadoutIcons::SetFilter(const CCommand &command) { - if (command.ArgC() == 0) { - if (stricmp(command.Arg(0), "statusspec_loadouticons_filter_active")) { - Msg("The current active loadout item icon filter is rgba(%i, %i, %i, %i).\n", filter_active_color.r(), filter_active_color.g(), filter_active_color.b(), filter_active_color.a()); - return; - } - else if (stricmp(command.Arg(0), "statusspec_loadouticons_filter_inactive")) { - Msg("The current inactive loadout item icon filter is rgba(%i, %i, %i, %i).\n", filter_inactive_color.r(), filter_inactive_color.g(), filter_inactive_color.b(), filter_inactive_color.a()); - return; - } - } - else if (command.ArgC() < 4 || !IsInteger(command.Arg(1)) || !IsInteger(command.Arg(2)) || !IsInteger(command.Arg(3)) || !IsInteger(command.Arg(4))) - { - Warning("Usage: %s \n", command.Arg(0)); - return; - } - - int red = ColorRangeRestrict(std::stoi(command.Arg(1))); - int green = ColorRangeRestrict(std::stoi(command.Arg(2))); - int blue = ColorRangeRestrict(std::stoi(command.Arg(3))); - int alpha = ColorRangeRestrict(std::stoi(command.Arg(4))); - - if (stricmp(command.Arg(0), "statusspec_loadouticons_filter_active")) { - filter_active_color.SetColor(red, green, blue, alpha); - Msg("Set active loadout item icon filter to rgba(%i, %i, %i, %i).\n", red, green, blue, alpha); - } - else if (stricmp(command.Arg(0), "statusspec_loadouticons_filter_inactive")) { - filter_inactive_color.SetColor(red, green, blue, alpha); - Msg("Set inactive loadout item icon filter to rgba(%i, %i, %i, %i).\n", red, green, blue, alpha); - } - else { - Warning("Unrecognized command!\n"); - } -} - -void LoadoutIcons::ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue) { - if (enabled->GetBool()) { - if (!frameHook) { - frameHook = Funcs::AddHook_IBaseClientDLL_FrameStageNotify(Interfaces::pClientDLL, SH_MEMBER(this, &LoadoutIcons::FrameHook), true); - } - } - else { - DisableHUD(); - - if (frameHook) { - if (Funcs::RemoveHook(frameHook)) { - frameHook = 0; - } - } - } -} \ No newline at end of file diff --git a/src/modules/loadouticons.h b/src/modules/loadouticons.h deleted file mode 100644 index d123b35..0000000 --- a/src/modules/loadouticons.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * loadouticons.h - * StatusSpec project - * - * Copyright (c) 2014 thesupremecommander - * BSD 2-Clause License - * http://opensource.org/licenses/BSD-2-Clause - * - */ - -#pragma once - -#include - -namespace vgui { - class EditablePanel; - class ImagePanel; - class Panel; -}; - -#include "cdll_int.h" -#include "Color.h" -#include "convar.h" -#include "vgui/VGUI.h" - -#include "../itemschema.h" -#include "../modules.h" -#include "../player.h" -#include "../tfdefs.h" - -typedef struct Loadout_s { - Loadout_s() { - tfclass = TFClass_Unknown; - primary = -1; - secondary = -1; - melee = -1; - pda = -1; - pda2 = -1; - building = -1; - std::fill(&cosmetic[0], &cosmetic[MAX_COSMETIC_SLOTS], -1); - std::fill(&taunt[0], &taunt[MAX_TAUNT_SLOTS], -1); - action = -1; - activeWeaponSlot = -1; - }; - - TFClassType tfclass; - int primary; - int secondary; - int melee; - int pda; - int pda2; - int building; - int cosmetic[MAX_COSMETIC_SLOTS]; - int taunt[MAX_TAUNT_SLOTS]; - int action; - int activeWeaponSlot; -} Loadout_t; - -class LoadoutIcons : public Module { -public: - LoadoutIcons(std::string name); - - static bool CheckDependencies(std::string name); - - void FrameHook(ClientFrameStage_t curStage); -private: - Color filter_active_color; - Color filter_inactive_color; - int frameHook; - std::map itemIconTextures; - ItemSchema *itemSchema; - std::map loadoutInfo; - std::map> loadoutIconPanels; - - void DisableHUD(); - void DisplayIcon(vgui::ImagePanel *panel, int itemDefinitionIndex, bool active); - void DisplayIcons(vgui::VPANEL playerPanel); - void HideIcon(vgui::ImagePanel *panel); - void InitIcons(vgui::EditablePanel *panel); - - ConVar *enabled; - ConCommand *filter_active; - ConCommand *filter_inactive; - ConVar *nonloadout; - ConVar *only_active; - int GetCurrentFilter(const char *partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH]); - void SetFilter(const CCommand &command); - void ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue); -}; \ No newline at end of file diff --git a/src/modules/localplayer.cpp b/src/modules/localplayer.cpp index dbdc3a3..fe6b645 100644 --- a/src/modules/localplayer.cpp +++ b/src/modules/localplayer.cpp @@ -2,7 +2,7 @@ * localplayer.cpp * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -10,48 +10,61 @@ #include "localplayer.h" +#include #include #include "cbase.h" #include "c_baseplayer.h" +#include "cdll_int.h" #include "convar.h" #include "shareddefs.h" +#include "vgui/IVGui.h" +#include "vgui_controls/Panel.h" #include "../common.h" #include "../funcs.h" #include "../ifaces.h" #include "../player.h" -LocalPlayer::LocalPlayer(std::string name) : Module(name) { - frameHook = 0; +class LocalPlayer::Panel : public vgui::Panel { +public: + Panel(vgui::Panel *parent, const char *panelName, std::function setFunction); + + virtual void OnTick(); +private: + std::function setToCurrentTarget; +}; + +LocalPlayer::LocalPlayer() { getLocalPlayerIndexDetoured = false; + panel = nullptr; - enabled = new ConVar("statusspec_localplayer_enabled", "0", FCVAR_NONE, "enable local player override", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule("Local Player")->ToggleEnabled(var, pOldValue, flOldValue); }); + enabled = new ConVar("statusspec_localplayer_enabled", "0", FCVAR_NONE, "enable local player override", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule()->ToggleEnabled(var, pOldValue, flOldValue); }); player = new ConVar("statusspec_localplayer_player", "0", FCVAR_NONE, "player index to set as the local player"); - track_spec_target = new ConVar("statusspec_localplayer_track_spec_target", "0", FCVAR_NONE, "have the local player value track the spectator target", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule("Local Player")->ToggleTrackSpecTarget(var, pOldValue, flOldValue); }); - set_current_target = new ConCommand("statusspec_localplayer_set_current_target", []() { g_ModuleManager->GetModule("Local Player")->SetToCurrentTarget(); }, "set the local player to the current spectator target", FCVAR_NONE); + set_current_target = new ConCommand("statusspec_localplayer_set_current_target", []() { g_ModuleManager->GetModule()->SetToCurrentTarget(); }, "set the local player to the current spectator target", FCVAR_NONE); + track_spec_target = new ConVar("statusspec_localplayer_track_spec_target", "0", FCVAR_NONE, "have the local player value track the spectator target", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule()->ToggleTrackSpecTarget(var, pOldValue, flOldValue); }); } -bool LocalPlayer::CheckDependencies(std::string name) { +bool LocalPlayer::CheckDependencies() { bool ready = true; if (!Interfaces::pClientDLL) { PRINT_TAG(); - Warning("Required interface IBaseClientDLL for module %s not available!\n", name.c_str()); + Warning("Required interface IBaseClientDLL for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Interfaces::pEngineClient) { PRINT_TAG(); - Warning("Required interface IVEngineClient for module %s not available!\n", name.c_str()); + Warning("Required interface IVEngineClient for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Player::conditionsRetrievalAvailable) { PRINT_TAG(); - Warning("Required player condition retrieval for module %s not available!\n", name.c_str()); + Warning("Required player condition retrieval for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } @@ -61,7 +74,7 @@ bool LocalPlayer::CheckDependencies(std::string name) { } catch (bad_pointer) { PRINT_TAG(); - Warning("Required function GetLocalPlayerIndex for module %s not available!\n", name.c_str()); + Warning("Required function GetLocalPlayerIndex for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } @@ -69,14 +82,6 @@ bool LocalPlayer::CheckDependencies(std::string name) { return ready; } -void LocalPlayer::FrameHook(ClientFrameStage_t curStage) { - if (curStage == FRAME_START) { - if (track_spec_target->GetBool() && Interfaces::pEngineClient->IsInGame()) { - SetToCurrentTarget(); - } - } -} - int LocalPlayer::GetLocalPlayerIndexOverride() { if (enabled->GetBool()) { Player localPlayer = player->GetInt(); @@ -110,7 +115,7 @@ void LocalPlayer::SetToCurrentTarget() { void LocalPlayer::ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue) { if (enabled->GetBool()) { if (!getLocalPlayerIndexDetoured) { - getLocalPlayerIndexDetoured = Funcs::AddDetour_GetLocalPlayerIndex([]()->int { return g_ModuleManager->GetModule("Local Player")->GetLocalPlayerIndexOverride(); }); + getLocalPlayerIndexDetoured = Funcs::AddDetour_GetLocalPlayerIndex([]()->int { return g_ModuleManager->GetModule()->GetLocalPlayerIndexOverride(); }); } } else { @@ -121,16 +126,31 @@ void LocalPlayer::ToggleEnabled(IConVar *var, const char *pOldValue, float flOld } void LocalPlayer::ToggleTrackSpecTarget(IConVar *var, const char *pOldValue, float flOldValue) { - if (enabled->GetBool()) { - if (!frameHook) { - frameHook = Funcs::AddHook_IBaseClientDLL_FrameStageNotify(Interfaces::pClientDLL, SH_MEMBER(this, &LocalPlayer::FrameHook), true); + if (track_spec_target->GetBool()) { + if (!panel) { + panel = new Panel(nullptr, "LocalPlayer", std::bind(&LocalPlayer::SetToCurrentTarget, this)); + } + + if (panel) { + panel->SetEnabled(true); } } else { - if (frameHook) { - if (Funcs::RemoveHook(frameHook)) { - frameHook = 0; - } + if (panel) { + delete panel; + panel = nullptr; } } +} + +LocalPlayer::Panel::Panel(vgui::Panel *parent, const char *panelName, std::function setFunction) : vgui::Panel(parent, panelName) { + g_pVGui->AddTickSignal(GetVPanel()); + + setToCurrentTarget = setFunction; +} + +void LocalPlayer::Panel::OnTick() { + if (Interfaces::pEngineClient->IsInGame()) { + setToCurrentTarget(); + } } \ No newline at end of file diff --git a/src/modules/localplayer.h b/src/modules/localplayer.h index b47a23d..9d980eb 100644 --- a/src/modules/localplayer.h +++ b/src/modules/localplayer.h @@ -2,7 +2,7 @@ * localplayer.h * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -12,27 +12,27 @@ class ConCommand; class ConVar; - -#include "cdll_int.h" +class IConVar; #include "../modules.h" class LocalPlayer : public Module { public: - LocalPlayer(std::string name); - - static bool CheckDependencies(std::string name); + LocalPlayer(); - void FrameHook(ClientFrameStage_t curStage); - int GetLocalPlayerIndexOverride(); + static bool CheckDependencies(); private: - int frameHook; + int GetLocalPlayerIndexOverride(); + + class Panel; + Panel *panel; + bool getLocalPlayerIndexDetoured; ConVar *enabled; ConVar *player; - ConVar *track_spec_target; ConCommand *set_current_target; + ConVar *track_spec_target; void SetToCurrentTarget(); void ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue); void ToggleTrackSpecTarget(IConVar *var, const char *pOldValue, float flOldValue); diff --git a/src/modules/mediguninfo.cpp b/src/modules/mediguninfo.cpp index 0b01cef..e9d8de7 100644 --- a/src/modules/mediguninfo.cpp +++ b/src/modules/mediguninfo.cpp @@ -2,7 +2,7 @@ * mediguninfo.cpp * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -10,21 +10,15 @@ #include "mediguninfo.h" -#include +#include #include "cbase.h" -#include "c_baseentity.h" #include "convar.h" -#include "filesystem.h" #include "iclientmode.h" -#include "KeyValues.h" -#include "shareddefs.h" -#include "vgui_controls/AnimationController.h" +#include "vgui/IScheme.h" +#include "vgui/ISurface.h" +#include "vgui/IVGui.h" #include "vgui_controls/EditablePanel.h" -#include "vgui_controls/ImagePanel.h" -#include "../vgui_controls/ImageProgressBar.h" -#include "vgui_controls/ScalableImagePanel.h" -#include "../vgui_controls/VariableLabel.h" #include "../common.h" #include "../entities.h" @@ -32,88 +26,111 @@ #include "../ifaces.h" #include "../player.h" -MedigunInfo::MedigunInfo(std::string name) : Module(name) { - dynamicMeterSettings = new KeyValues("MedigunInfoDynamicMeters"); - dynamicMeterSettings->LoadFromFile(Interfaces::pFileSystem, "resource/ui/mediguninfodynamicmeters.res", "mod"); - frameHook = 0; - - dynamic_meters = new ConVar("statusspec_mediguninfo_dynamic_meters", "0", FCVAR_NONE, "enable charge meters to change based on medigun"); - enabled = new ConVar("statusspec_mediguninfo_enabled", "0", FCVAR_NONE, "enable medigun info", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule("Medigun Info")->ToggleEnabled(var, pOldValue, flOldValue); }); - individual_charge_meters = new ConVar("statusspec_mediguninfo_individual_charge_meters", "1", FCVAR_NONE, "enable individual charge meters (for Vaccinator)"); - reload_settings = new ConCommand("statusspec_mediguninfo_reload_settings", []() { g_ModuleManager->GetModule("Medigun Info")->ReloadSettings(); }, "reload settings for the medigun info HUD from the resource file", FCVAR_NONE); +class MedigunInfo::MainPanel : public vgui::EditablePanel { + DECLARE_CLASS_SIMPLE(MainPanel, vgui::EditablePanel); + +public: + MainPanel(vgui::Panel *parent, const char *panelName); + + virtual void ApplySettings(KeyValues *inResourceData); + virtual void LoadControlSettings(const char *dialogResourceName, const char *pathID = NULL, KeyValues *pPreloadedKeyValues = NULL, KeyValues *pConditions = NULL); + virtual void OnTick(); + +private: + int bluBaseX; + int bluBaseY; + int bluOffsetX; + int bluOffsetY; + int redBaseX; + int redBaseY; + int redOffsetX; + int redOffsetY; + + std::vector bluMedigunPanels; + std::vector redMedigunPanels; +}; + +class MedigunInfo::MedigunPanel : public vgui::EditablePanel { + DECLARE_CLASS_SIMPLE(MedigunPanel, vgui::EditablePanel); + +public: + MedigunPanel(vgui::Panel *parent, const char *panelName); + +private: + MESSAGE_FUNC_PARAMS(OnMedigunInfoUpdate, "MedigunInfo", attributes); + MESSAGE_FUNC_PARAMS(OnReloadControlSettings, "ReloadControlSettings", data); + + bool alive; + int charges; + float level; + TFMedigun medigun; + bool released; + TFResistType resistType; + TFTeam team; +}; + +MedigunInfo::MedigunInfo() { + mainPanel = nullptr; + + enabled = new ConVar("statusspec_mediguninfo_enabled", "0", FCVAR_NONE, "enable medigun info", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule()->ToggleEnabled(var, pOldValue, flOldValue); }); + reload_settings = new ConCommand("statusspec_mediguninfo_reload_settings", []() { g_ModuleManager->GetModule()->ReloadSettings(); }, "reload settings for the medigun info HUD from the resource file", FCVAR_NONE); } -bool MedigunInfo::CheckDependencies(std::string name) { +bool MedigunInfo::CheckDependencies() { bool ready = true; - if (!Interfaces::pClientDLL) { + if (!g_pVGuiSchemeManager) { PRINT_TAG(); - Warning("Required interface IBaseClientDLL for module %s not available!\n", name.c_str()); + Warning("Required interface vgui::ISchemeManager for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } - if (!Interfaces::pFileSystem) { + if (!g_pVGuiSurface) { PRINT_TAG(); - Warning("Required interface IFileSystem for module %s not available!\n", name.c_str()); + Warning("Required interface vgui::ISurface for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Interfaces::vguiLibrariesAvailable) { PRINT_TAG(); - Warning("Required VGUI library for module %s not available!\n", name.c_str()); + Warning("Required VGUI library for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Entities::RetrieveClassPropOffset("CWeaponMedigun", { "m_iItemDefinitionIndex" })) { PRINT_TAG(); - Warning("Required property m_iItemDefinitionIndex for CWeaponMedigun for module %s not available!\n", name.c_str()); + Warning("Required property m_iItemDefinitionIndex for CWeaponMedigun for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Entities::RetrieveClassPropOffset("CWeaponMedigun", { "m_bChargeRelease" })) { PRINT_TAG(); - Warning("Required property m_bChargeRelease for CWeaponMedigun for module %s not available!\n", name.c_str()); + Warning("Required property m_bChargeRelease for CWeaponMedigun for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Entities::RetrieveClassPropOffset("CWeaponMedigun", { "m_nChargeResistType" })) { PRINT_TAG(); - Warning("Required property m_nChargeResistType for CWeaponMedigun for module %s not available!\n", name.c_str()); + Warning("Required property m_nChargeResistType for CWeaponMedigun for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Entities::RetrieveClassPropOffset("CWeaponMedigun", { "m_flChargeLevel" })) { PRINT_TAG(); - Warning("Required property m_flChargeLevel for CWeaponMedigun for module %s not available!\n", name.c_str()); + Warning("Required property m_flChargeLevel for CWeaponMedigun for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } - for (int i = 0; i < MAX_WEAPONS; i++) { - std::stringstream ss; - std::string arrayIndex; - ss << std::setfill('0') << std::setw(3) << i; - ss >> arrayIndex; - - if (!Entities::RetrieveClassPropOffset("CTFPlayer", { "m_hMyWeapons", arrayIndex })) { - PRINT_TAG(); - Warning("Required property table m_hMyWeapons for CTFPlayer for module %s not available!\n", name.c_str()); - - ready = false; - - break; - } - } - if (!Player::CheckDependencies()) { PRINT_TAG(); - Warning("Required player helper class for module %s not available!\n", name.c_str()); + Warning("Required player helper class for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } @@ -123,771 +140,327 @@ bool MedigunInfo::CheckDependencies(std::string name) { } catch (bad_pointer) { PRINT_TAG(); - Warning("Module %s requires IClientMode, which cannot be verified at this time!\n", name.c_str()); + Warning("Module %s requires IClientMode, which cannot be verified at this time!\n", g_ModuleManager->GetModuleName().c_str()); } return ready; } -void MedigunInfo::FrameHook(ClientFrameStage_t curStage) { - if (curStage == FRAME_NET_UPDATE_END) { - medigunInfo.clear(); - - for (auto iterator = Player::begin(); iterator != Player::end(); ++iterator) { - Player player = *iterator; - - TFTeam team = player.GetTeam(); - - if (team != TFTeam_Red && team != TFTeam_Blue) { - continue; - } - - if (!player.IsAlive()) { - continue; - } - - for (int i = 0; i < MAX_WEAPONS; i++) { - std::stringstream ss; - std::string arrayIndex; - ss << std::setfill('0') << std::setw(3) << i; - ss >> arrayIndex; - - IClientEntity *weapon = Entities::GetEntityProp(player.GetEntity(), { "m_hMyWeapons", arrayIndex })->Get(); +void MedigunInfo::ReloadSettings() { + mainPanel->LoadControlSettings("Resource/UI/MedigunInfo.res"); +} - if (!weapon || !Entities::CheckEntityBaseclass(weapon, "WeaponMedigun")) { - continue; - } +void MedigunInfo::ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue) { + if (enabled->GetBool()) { + if (!mainPanel) { + try { + vgui::Panel *viewport = Interfaces::GetClientMode()->GetViewport(); - Medigun_t medigun; - - int itemDefinitionIndex = *Entities::GetEntityProp(weapon, { "m_iItemDefinitionIndex" }); - - switch (itemDefinitionIndex) { - case 29: - case 211: - case 663: - case 796: - case 805: - case 885: - case 894: - case 903: - case 912: - case 961: - case 970: - { - medigun.type = TFMedigun_MediGun; - break; - } - case 35: - { - medigun.type = TFMedigun_Kritzkrieg; - break; - } - case 411: - { - medigun.type = TFMedigun_QuickFix; - break; - } - case 998: - { - medigun.type = TFMedigun_Vaccinator; - break; - } - default: - { - medigun.type = TFMedigun_Unknown; - break; + if (viewport) { + mainPanel = new MainPanel(viewport, "MedigunInfo"); } + else { + Warning("Could not initialize the panel!\n"); + mainPanel = nullptr; + var->SetValue(0); } - - medigun.chargeRelease = *Entities::GetEntityProp(weapon, { "m_bChargeRelease" }); - medigun.chargeResistType = (TFResistType)*Entities::GetEntityProp(weapon, { "m_nChargeResistType" }); - medigun.chargeLevel = *Entities::GetEntityProp(weapon, { "m_flChargeLevel" }); - - if (medigunInfo.find(team) == medigunInfo.end() || medigunInfo[team].chargeLevel <= 0.0f && medigun.chargeLevel >= 0.0f) { - medigunInfo[team] = medigun; - } + } + catch (bad_pointer) { + Warning("Could not initialize the panel!\n"); + mainPanel = nullptr; + var->SetValue(0); } } - Paint(); + if (mainPanel) { + mainPanel->SetEnabled(true); + } } - - RETURN_META(MRES_IGNORED); -} - -void MedigunInfo::InitHud() { - if (panels.find("MedigunInfo") == panels.end()) { - vgui::Panel *viewport = Interfaces::GetClientMode()->GetViewport(); - - if (viewport) { - vgui::EditablePanel *medigunInfoPanel = new vgui::EditablePanel(viewport, "MedigunInfo"); - panels["MedigunInfo"] = medigunInfoPanel; - panels["MedigunInfoBackground"] = new vgui::ImagePanel(medigunInfoPanel, "MedigunInfoBackground"); - panels["MedigunInfoRedBackground"] = new vgui::ScalableImagePanel(medigunInfoPanel, "MedigunInfoRedBackground"); - panels["MedigunInfoRedNameLabel"] = new vgui::VariableLabel(medigunInfoPanel, "MedigunInfoRedNameLabel", ""); - panels["MedigunInfoRedChargeMeter"] = new vgui::ImageProgressBar(medigunInfoPanel, "MedigunInfoRedChargeMeter"); - panels["MedigunInfoRedChargeMeter1"] = new vgui::ImageProgressBar(medigunInfoPanel, "MedigunInfoRedChargeMeter1"); - panels["MedigunInfoRedChargeMeter2"] = new vgui::ImageProgressBar(medigunInfoPanel, "MedigunInfoRedChargeMeter2"); - panels["MedigunInfoRedChargeMeter3"] = new vgui::ImageProgressBar(medigunInfoPanel, "MedigunInfoRedChargeMeter3"); - panels["MedigunInfoRedChargeMeter4"] = new vgui::ImageProgressBar(medigunInfoPanel, "MedigunInfoRedChargeMeter4"); - panels["MedigunInfoRedChargeLabel"] = new vgui::VariableLabel(medigunInfoPanel, "MedigunInfoRedChargeLabel", ""); - panels["MedigunInfoRedIndividualChargesLabel"] = new vgui::VariableLabel(medigunInfoPanel, "MedigunInfoRedIndividualChargesLabel", ""); - panels["MedigunInfoRedChargeAdvantageLabel"] = new vgui::VariableLabel(medigunInfoPanel, "MedigunInfoRedChargeAdvantageLabel", ""); - panels["MedigunInfoRedChargeTypeIcon"] = new vgui::ImagePanel(medigunInfoPanel, "MedigunInfoRedChargeTypeIcon"); - panels["MedigunInfoBluBackground"] = new vgui::ScalableImagePanel(medigunInfoPanel, "MedigunInfoBluBackground"); - panels["MedigunInfoBluNameLabel"] = new vgui::VariableLabel(medigunInfoPanel, "MedigunInfoBluNameLabel", ""); - panels["MedigunInfoBluChargeMeter"] = new vgui::ImageProgressBar(medigunInfoPanel, "MedigunInfoBluChargeMeter"); - panels["MedigunInfoBluChargeMeter1"] = new vgui::ImageProgressBar(medigunInfoPanel, "MedigunInfoBluChargeMeter1"); - panels["MedigunInfoBluChargeMeter2"] = new vgui::ImageProgressBar(medigunInfoPanel, "MedigunInfoBluChargeMeter2"); - panels["MedigunInfoBluChargeMeter3"] = new vgui::ImageProgressBar(medigunInfoPanel, "MedigunInfoBluChargeMeter3"); - panels["MedigunInfoBluChargeMeter4"] = new vgui::ImageProgressBar(medigunInfoPanel, "MedigunInfoBluChargeMeter4"); - panels["MedigunInfoBluChargeLabel"] = new vgui::VariableLabel(medigunInfoPanel, "MedigunInfoBluChargeLabel", ""); - panels["MedigunInfoBluIndividualChargesLabel"] = new vgui::VariableLabel(medigunInfoPanel, "MedigunInfoBluIndividualChargesLabel", ""); - panels["MedigunInfoBluChargeAdvantageLabel"] = new vgui::VariableLabel(medigunInfoPanel, "MedigunInfoBluChargeAdvantageLabel", ""); - panels["MedigunInfoBluChargeTypeIcon"] = new vgui::ImagePanel(medigunInfoPanel, "MedigunInfoBluChargeTypeIcon"); - - medigunInfoPanel->LoadControlSettings("Resource/UI/MedigunInfo.res"); + else { + if (mainPanel) { + delete mainPanel; + mainPanel = nullptr; } } } -void MedigunInfo::Paint() { - panels["MedigunInfo"]->SetVisible(true); - - static bool redChargeReady = false; - static bool redChargeReleased = false; - - if (medigunInfo.find(TFTeam_Red) != medigunInfo.end()) { - panels["MedigunInfoRedBackground"]->SetVisible(true); - - const char *redname; - - switch (medigunInfo[TFTeam_Red].type) { - case TFMedigun_MediGun: - { - redname = "Medi Gun"; - break; - } - case TFMedigun_Kritzkrieg: - { - redname = "Kritzkrieg"; - break; - } - case TFMedigun_QuickFix: - { - redname = "Quick-Fix"; - break; - } - case TFMedigun_Vaccinator: - { - redname = "Vaccinator"; - break; - } - case TFMedigun_Unknown: - default: - { - redname = "Unknown"; - break; - } - } - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("redname", redname); - - if (dynamic_meters->GetBool()) { - KeyValues *medigunSettings = dynamicMeterSettings->FindKey(redname); - - if (medigunSettings) { - panels["MedigunInfoRedChargeMeter"]->ApplySettings(medigunSettings); - panels["MedigunInfoRedChargeMeter1"]->ApplySettings(medigunSettings); - panels["MedigunInfoRedChargeMeter2"]->ApplySettings(medigunSettings); - panels["MedigunInfoRedChargeMeter3"]->ApplySettings(medigunSettings); - panels["MedigunInfoRedChargeMeter4"]->ApplySettings(medigunSettings); - } - } +MedigunInfo::MainPanel::MainPanel(vgui::Panel *parent, const char *panelName) : vgui::EditablePanel(parent, panelName) { + LoadControlSettings("Resource/UI/MedigunInfo.res"); - panels["MedigunInfoRedNameLabel"]->SetVisible(true); + g_pVGui->AddTickSignal(GetVPanel()); +} - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("redcharge", int(floor(medigunInfo[TFTeam_Red].chargeLevel * 100.0f))); +void MedigunInfo::MainPanel::ApplySettings(KeyValues *inResourceData) { + vgui::EditablePanel::ApplySettings(inResourceData); - int redChargeAdvantage; + int alignScreenWide, alignScreenTall; + g_pVGuiSurface->GetScreenSize(alignScreenWide, alignScreenTall); - if (medigunInfo.find(TFTeam_Blue) != medigunInfo.end()) { - redChargeAdvantage = int(floor(medigunInfo[TFTeam_Red].chargeLevel * 100.0f)) - int(floor(medigunInfo[TFTeam_Blue].chargeLevel * 100.0f)); - } - else { - redChargeAdvantage = int(floor(medigunInfo[TFTeam_Red].chargeLevel * 100.0f)); - } + int wide, tall; + GetSize(wide, tall); - if (redChargeAdvantage > 0) { - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("redadvantage", redChargeAdvantage); + GetPos(redBaseX, redBaseY); + ComputePos(inResourceData->GetString("red_base_x"), redBaseX, wide, alignScreenWide, true); + ComputePos(inResourceData->GetString("red_base_y"), redBaseY, tall, alignScreenTall, false); - panels["MedigunInfoRedChargeAdvantageLabel"]->SetVisible(true); - } - else { - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("redadvantage", 0); + GetPos(bluBaseX, bluBaseY); + ComputePos(inResourceData->GetString("blu_base_x"), bluBaseX, wide, alignScreenWide, true); + ComputePos(inResourceData->GetString("blu_base_y"), bluBaseY, tall, alignScreenTall, false); - panels["MedigunInfoRedChargeAdvantageLabel"]->SetVisible(false); - } + redOffsetX = g_pVGuiSchemeManager->GetProportionalScaledValue(inResourceData->GetInt("red_offset_x")); + redOffsetY = g_pVGuiSchemeManager->GetProportionalScaledValue(inResourceData->GetInt("red_offset_y")); + bluOffsetX = g_pVGuiSchemeManager->GetProportionalScaledValue(inResourceData->GetInt("blu_offset_x")); + bluOffsetY = g_pVGuiSchemeManager->GetProportionalScaledValue(inResourceData->GetInt("blu_offset_y")); +} - switch (medigunInfo[TFTeam_Red].type) { - case TFMedigun_Vaccinator: - { - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("redcharges", int(floor(medigunInfo[TFTeam_Red].chargeLevel * 4.0f))); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("redcharge1", int(floor(medigunInfo[TFTeam_Red].chargeLevel * 400.0f) - 0.0f) < 0 ? 0 : int(floor(medigunInfo[TFTeam_Red].chargeLevel * 400.0f) - 0.0f)); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("redcharge2", int(floor(medigunInfo[TFTeam_Red].chargeLevel * 400.0f) - 100.0f) < 0 ? 0 : int(floor(medigunInfo[TFTeam_Red].chargeLevel * 400.0f) - 100.0f)); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("redcharge3", int(floor(medigunInfo[TFTeam_Red].chargeLevel * 400.0f) - 200.0f) < 0 ? 0 : int(floor(medigunInfo[TFTeam_Red].chargeLevel * 400.0f) - 200.0f)); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("redcharge4", int(floor(medigunInfo[TFTeam_Red].chargeLevel * 400.0f) - 300.0f) < 0 ? 0 : int(floor(medigunInfo[TFTeam_Red].chargeLevel * 400.0f) - 300.0f)); - - panels["MedigunInfoRedChargeLabel"]->SetVisible(false); - panels["MedigunInfoRedIndividualChargesLabel"]->SetVisible(true); - - if (individual_charge_meters->GetBool()) { - panels["MedigunInfoRedChargeMeter"]->SetVisible(false); - panels["MedigunInfoRedChargeMeter1"]->SetVisible(true); - panels["MedigunInfoRedChargeMeter2"]->SetVisible(true); - panels["MedigunInfoRedChargeMeter3"]->SetVisible(true); - panels["MedigunInfoRedChargeMeter4"]->SetVisible(true); - } - else { - panels["MedigunInfoRedChargeMeter"]->SetVisible(true); - panels["MedigunInfoRedChargeMeter1"]->SetVisible(false); - panels["MedigunInfoRedChargeMeter2"]->SetVisible(false); - panels["MedigunInfoRedChargeMeter3"]->SetVisible(false); - panels["MedigunInfoRedChargeMeter4"]->SetVisible(false); - } +void MedigunInfo::MainPanel::LoadControlSettings(const char *dialogResourceName, const char *pathID, KeyValues *pPreloadedKeyValues, KeyValues *pConditions) { + vgui::EditablePanel::LoadControlSettings(dialogResourceName, pathID, pPreloadedKeyValues, pConditions); - if (medigunInfo[TFTeam_Red].chargeRelease) { - if (!redChargeReleased) { - Interfaces::GetClientMode()->GetViewportAnimationController()->StartAnimationSequence("MedigunInfoRedChargeReleased"); - } + PostActionSignal(new KeyValues("ReloadControlSettings")); +} - redChargeReleased = true; - redChargeReady = false; - } - else if (medigunInfo[TFTeam_Red].chargeLevel >= 0.25f) { - if (!redChargeReady) { - Interfaces::GetClientMode()->GetViewportAnimationController()->StartAnimationSequence("MedigunInfoRedChargeReady"); - } +void MedigunInfo::MainPanel::OnTick() { + vgui::EditablePanel::OnTick(); + + size_t bluMediguns = 0; + size_t redMediguns = 0; + + for (Player player : Player::Iterable()) { + if (player.GetClass() == TFClass_Medic && (player.GetTeam() == TFTeam_Blue || player.GetTeam() == TFTeam_Red)) { + for (int weaponIndex = 0; weaponIndex < MAX_WEAPONS; weaponIndex++) { + C_BaseCombatWeapon *weapon = player.GetWeapon(weaponIndex); + + if (weapon && Entities::CheckEntityBaseclass(weapon, "WeaponMedigun")) { + MedigunPanel *medigunPanel; + int x, y; + + if (player.GetTeam() == TFTeam_Red) { + redMediguns++; + + if (redMediguns > redMedigunPanels.size()) { + medigunPanel = new MedigunPanel(this, "MedigunPanel"); + AddActionSignalTarget(medigunPanel); + redMedigunPanels.push_back(medigunPanel); + } + else { + medigunPanel = redMedigunPanels.at(redMediguns - 1); + } + + x = redBaseX + (redOffsetX * (redMediguns - 1)); + y = redBaseY + (redOffsetY * (redMediguns - 1)); + } + else if (player.GetTeam() == TFTeam_Blue) { + bluMediguns++; + + if (bluMediguns > bluMedigunPanels.size()) { + medigunPanel = new MedigunPanel(this, "MedigunPanel"); + AddActionSignalTarget(medigunPanel); + bluMedigunPanels.push_back(medigunPanel); + } + else { + medigunPanel = bluMedigunPanels.at(bluMediguns - 1); + } + + x = bluBaseX + (bluOffsetX * (bluMediguns - 1)); + y = bluBaseY + (bluOffsetY * (bluMediguns - 1)); + } + + KeyValues *medigunInfo = new KeyValues("MedigunInfo"); + + int itemDefinitionIndex = *Entities::GetEntityProp(weapon, { "m_iItemDefinitionIndex" }); + TFMedigun type = TFMedigun_Unknown; + if (itemDefinitionIndex == 29 || itemDefinitionIndex == 211 || itemDefinitionIndex == 663 || itemDefinitionIndex == 796 || itemDefinitionIndex == 805 || itemDefinitionIndex == 885 || itemDefinitionIndex == 894 || itemDefinitionIndex == 903 || itemDefinitionIndex == 912 || itemDefinitionIndex == 961 || itemDefinitionIndex == 970) { + type = TFMedigun_MediGun; + } + else if (itemDefinitionIndex == 35) { + type = TFMedigun_Kritzkrieg; + } + else if (itemDefinitionIndex == 411) { + type = TFMedigun_QuickFix; + } + else if (itemDefinitionIndex == 998) { + type = TFMedigun_Vaccinator; + } + + float level = *Entities::GetEntityProp(weapon, { "m_flChargeLevel" }); + + medigunInfo->SetBool("alive", player.IsAlive()); + medigunInfo->SetInt("charges", type == TFMedigun_Vaccinator ? int(floor(level * 4.0f)) : int(floor(level))); + medigunInfo->SetFloat("level", level); + medigunInfo->SetInt("medigun", type); + medigunInfo->SetBool("released", *Entities::GetEntityProp(weapon, { "m_bChargeRelease" })); + medigunInfo->SetInt("resistType", *Entities::GetEntityProp(weapon, { "m_nChargeResistType" })); + medigunInfo->SetInt("team", player.GetTeam()); + + PostMessage(medigunPanel, medigunInfo); + medigunPanel->SetPos(x, y); - redChargeReleased = false; - redChargeReady = true; - } - else { - if (redChargeReleased || redChargeReady) { - Interfaces::GetClientMode()->GetViewportAnimationController()->StartAnimationSequence("MedigunInfoRedChargeStop"); + break; } - - redChargeReleased = false; - redChargeReady = false; } - - break; } - case TFMedigun_MediGun: - case TFMedigun_Kritzkrieg: - case TFMedigun_QuickFix: - case TFMedigun_Unknown: - default: - { - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("redcharges", int(floor(medigunInfo[TFTeam_Red].chargeLevel))); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("redcharge1", 0); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("redcharge2", 0); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("redcharge3", 0); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("redcharge4", 0); - - panels["MedigunInfoRedChargeLabel"]->SetVisible(false); - panels["MedigunInfoRedIndividualChargesLabel"]->SetVisible(true); - - if (individual_charge_meters->GetBool()) { - panels["MedigunInfoRedChargeMeter"]->SetVisible(false); - panels["MedigunInfoRedChargeMeter1"]->SetVisible(true); - panels["MedigunInfoRedChargeMeter2"]->SetVisible(true); - panels["MedigunInfoRedChargeMeter3"]->SetVisible(true); - panels["MedigunInfoRedChargeMeter4"]->SetVisible(true); - } - else { - panels["MedigunInfoRedChargeMeter"]->SetVisible(true); - panels["MedigunInfoRedChargeMeter1"]->SetVisible(false); - panels["MedigunInfoRedChargeMeter2"]->SetVisible(false); - panels["MedigunInfoRedChargeMeter3"]->SetVisible(false); - panels["MedigunInfoRedChargeMeter4"]->SetVisible(false); - } - - panels["MedigunInfoRedChargeMeter"]->SetVisible(true); - panels["MedigunInfoRedChargeMeter1"]->SetVisible(false); - panels["MedigunInfoRedChargeMeter2"]->SetVisible(false); - panels["MedigunInfoRedChargeMeter3"]->SetVisible(false); - panels["MedigunInfoRedChargeMeter4"]->SetVisible(false); - panels["MedigunInfoRedChargeLabel"]->SetVisible(true); - panels["MedigunInfoRedIndividualChargesLabel"]->SetVisible(false); - - if (medigunInfo[TFTeam_Red].chargeRelease) { - if (!redChargeReleased) { - Interfaces::GetClientMode()->GetViewportAnimationController()->StartAnimationSequence("MedigunInfoRedChargeReleased"); - } - - redChargeReleased = true; - redChargeReady = false; - } - else if (medigunInfo[TFTeam_Red].chargeLevel >= 1.0f) { - if (!redChargeReady) { - Interfaces::GetClientMode()->GetViewportAnimationController()->StartAnimationSequence("MedigunInfoRedChargeReady"); - } + } - redChargeReleased = false; - redChargeReady = true; - } - else { - if (redChargeReleased || redChargeReady) { - Interfaces::GetClientMode()->GetViewportAnimationController()->StartAnimationSequence("MedigunInfoRedChargeStop"); - } + while (redMediguns < redMedigunPanels.size()) { + delete redMedigunPanels.back(); + redMedigunPanels.pop_back(); + } + + while (bluMediguns < bluMedigunPanels.size()) { + delete bluMedigunPanels.back(); + bluMedigunPanels.pop_back(); + } +} - redChargeReleased = false; - redChargeReady = false; - } +MedigunInfo::MedigunPanel::MedigunPanel(vgui::Panel *parent, const char *panelName) : vgui::EditablePanel(parent, panelName) {} - break; - } - } +void MedigunInfo::MedigunPanel::OnMedigunInfoUpdate(KeyValues *attributes) { + bool reloadSettings = (alive != attributes->GetBool("alive") || charges != attributes->GetInt("charges") || medigun != attributes->GetInt("medigun") || released != attributes->GetBool("released") || resistType != attributes->GetInt("resistType") || team != attributes->GetInt("team")); - switch (medigunInfo[TFTeam_Red].type) { - case TFMedigun_MediGun: - { - ((vgui::ImagePanel *) panels["MedigunInfoRedChargeTypeIcon"])->SetImage(GetVGUITexturePath(TEXTURE_UBERCHARGE).c_str()); + alive = attributes->GetBool("alive"); + charges = attributes->GetInt("charges"); + level = attributes->GetFloat("level"); + medigun = (TFMedigun) attributes->GetInt("medigun"); + released = attributes->GetBool("released"); + resistType = (TFResistType) attributes->GetInt("resistType"); + team = (TFTeam) attributes->GetInt("team"); - panels["MedigunInfoRedChargeTypeIcon"]->SetVisible(true); + if (reloadSettings) { + KeyValues *conditions = new KeyValues("conditions"); - break; + if (alive) { + conditions->SetBool("player-alive", true); } - case TFMedigun_Kritzkrieg: - { - ((vgui::ImagePanel *) panels["MedigunInfoRedChargeTypeIcon"])->SetImage(GetVGUITexturePath(TEXTURE_CRITBOOST).c_str()); - - panels["MedigunInfoRedChargeTypeIcon"]->SetVisible(true); - - break; + else { + conditions->SetBool("player-dead", true); } - case TFMedigun_QuickFix: - { - ((vgui::ImagePanel *) panels["MedigunInfoRedChargeTypeIcon"])->SetImage(GetVGUITexturePath(TEXTURE_MEGAHEALRED).c_str()); - - panels["MedigunInfoRedChargeTypeIcon"]->SetVisible(true); - break; + if (charges == 0) { + conditions->SetBool("charges-0", true); } - case TFMedigun_Vaccinator: - { - switch (medigunInfo[TFTeam_Red].chargeResistType) { - case TFResistType_Bullet: - { - ((vgui::ImagePanel *) panels["MedigunInfoRedChargeTypeIcon"])->SetImage(GetVGUITexturePath(TEXTURE_BULLETRESISTRED).c_str()); - - panels["MedigunInfoRedChargeTypeIcon"]->SetVisible(true); - - break; - } - case TFResistType_Explosive: - { - ((vgui::ImagePanel *) panels["MedigunInfoRedChargeTypeIcon"])->SetImage(GetVGUITexturePath(TEXTURE_BLASTRESISTRED).c_str()); - - panels["MedigunInfoRedChargeTypeIcon"]->SetVisible(true); - - break; - } - case TFResistType_Fire: - { - ((vgui::ImagePanel *) panels["MedigunInfoRedChargeTypeIcon"])->SetImage(GetVGUITexturePath(TEXTURE_FIRERESISTRED).c_str()); - - panels["MedigunInfoRedChargeTypeIcon"]->SetVisible(true); - - break; - } - default: - { - ((vgui::ImagePanel *) panels["MedigunInfoRedChargeTypeIcon"])->SetImage(GetVGUITexturePath(TEXTURE_NULL).c_str()); - - panels["MedigunInfoRedChargeTypeIcon"]->SetVisible(false); - - break; - } - } - - break; + else if (charges == 1) { + conditions->SetBool("charges-1", true); } - case TFMedigun_Unknown: - default: - { - ((vgui::ImagePanel *) panels["MedigunInfoRedChargeTypeIcon"])->SetImage(GetVGUITexturePath(TEXTURE_NULL).c_str()); - - panels["MedigunInfoRedChargeTypeIcon"]->SetVisible(false); - - break; + else if (charges == 2) { + conditions->SetBool("charges-2", true); } + else if (charges == 3) { + conditions->SetBool("charges-3", true); } - } - else { - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("redname", ""); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("redcharge", 0); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("redcharges", 0); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("redcharge1", 0); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("redcharge2", 0); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("redcharge3", 0); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("redcharge4", 0); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("redadvantage", 0); - ((vgui::ImagePanel *) panels["MedigunInfoRedChargeTypeIcon"])->SetImage(GetVGUITexturePath(TEXTURE_NULL).c_str()); - - panels["MedigunInfoRedNameLabel"]->SetVisible(false); - panels["MedigunInfoRedChargeMeter"]->SetVisible(false); - panels["MedigunInfoRedChargeMeter1"]->SetVisible(false); - panels["MedigunInfoRedChargeMeter2"]->SetVisible(false); - panels["MedigunInfoRedChargeMeter3"]->SetVisible(false); - panels["MedigunInfoRedChargeMeter4"]->SetVisible(false); - panels["MedigunInfoRedChargeLabel"]->SetVisible(false); - panels["MedigunInfoRedIndividualChargesLabel"]->SetVisible(false); - panels["MedigunInfoRedChargeAdvantageLabel"]->SetVisible(false); - panels["MedigunInfoRedChargeTypeIcon"]->SetVisible(false); - - if (redChargeReady || redChargeReleased) { - redChargeReady = false; - redChargeReleased = false; - - Interfaces::GetClientMode()->GetViewportAnimationController()->StartAnimationSequence("MedigunInfoRedChargeNormal"); + else if (charges == 4) { + conditions->SetBool("charges-4", true); } - } - - static bool bluChargeReady = false; - static bool bluChargeReleased = false; - if (medigunInfo.find(TFTeam_Blue) != medigunInfo.end()) { - panels["MedigunInfoBluBackground"]->SetVisible(true); - - const char *bluname; - - switch (medigunInfo[TFTeam_Blue].type) { - case TFMedigun_MediGun: - { - bluname = "Medi Gun"; - break; - } - case TFMedigun_Kritzkrieg: - { - bluname = "Kritzkrieg"; - break; - } - case TFMedigun_QuickFix: - { - bluname = "Quick-Fix"; - break; - } - case TFMedigun_Vaccinator: - { - bluname = "Vaccinator"; - break; - } - case TFMedigun_Unknown: - default: - { - bluname = "Unknown"; - break; + if (medigun == TFMedigun_MediGun) { + conditions->SetBool("medigun-medigun", true); } + else if (medigun == TFMedigun_Kritzkrieg) { + conditions->SetBool("medigun-kritzkrieg", true); } - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("bluname", bluname); - - if (dynamic_meters->GetBool()) { - KeyValues *medigunSettings = dynamicMeterSettings->FindKey(bluname); - - if (medigunSettings) { - panels["MedigunInfoBluChargeMeter"]->ApplySettings(medigunSettings); - panels["MedigunInfoBluChargeMeter1"]->ApplySettings(medigunSettings); - panels["MedigunInfoBluChargeMeter2"]->ApplySettings(medigunSettings); - panels["MedigunInfoBluChargeMeter3"]->ApplySettings(medigunSettings); - panels["MedigunInfoBluChargeMeter4"]->ApplySettings(medigunSettings); - } + else if (medigun == TFMedigun_QuickFix) { + conditions->SetBool("medigun-quickfix", true); } - - panels["MedigunInfoBluNameLabel"]->SetVisible(true); - - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("blucharge", int(floor(medigunInfo[TFTeam_Blue].chargeLevel * 100.0f))); - - int bluChargeAdvantage; - - if (medigunInfo.find(TFTeam_Blue) != medigunInfo.end()) { - bluChargeAdvantage = int(floor(medigunInfo[TFTeam_Blue].chargeLevel * 100.0f)) - int(floor(medigunInfo[TFTeam_Red].chargeLevel * 100.0f)); + else if (medigun == TFMedigun_Vaccinator) { + conditions->SetBool("medigun-vaccinator", true); } - else { - bluChargeAdvantage = int(floor(medigunInfo[TFTeam_Blue].chargeLevel * 100.0f)); - } - - if (bluChargeAdvantage > 0) { - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("bluadvantage", bluChargeAdvantage); - panels["MedigunInfoBluChargeAdvantageLabel"]->SetVisible(true); + if (released) { + conditions->SetBool("status-released", true); } else { - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("bluadvantage", 0); - - panels["MedigunInfoBluChargeAdvantageLabel"]->SetVisible(false); + conditions->SetBool("status-building", true); } - switch (medigunInfo[TFTeam_Blue].type) { - case TFMedigun_Vaccinator: - { - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("blucharges", int(floor(medigunInfo[TFTeam_Blue].chargeLevel * 4.0f))); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("blucharge1", int(floor(medigunInfo[TFTeam_Blue].chargeLevel * 400.0f) - 0.0f) < 0 ? 0 : int(floor(medigunInfo[TFTeam_Blue].chargeLevel * 400.0f) - 0.0f)); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("blucharge2", int(floor(medigunInfo[TFTeam_Blue].chargeLevel * 400.0f) - 100.0f) < 0 ? 0 : int(floor(medigunInfo[TFTeam_Blue].chargeLevel * 400.0f) - 100.0f)); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("blucharge3", int(floor(medigunInfo[TFTeam_Blue].chargeLevel * 400.0f) - 200.0f) < 0 ? 0 : int(floor(medigunInfo[TFTeam_Blue].chargeLevel * 400.0f) - 200.0f)); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("blucharge4", int(floor(medigunInfo[TFTeam_Blue].chargeLevel * 400.0f) - 300.0f) < 0 ? 0 : int(floor(medigunInfo[TFTeam_Blue].chargeLevel * 400.0f) - 300.0f)); - - panels["MedigunInfoBluChargeLabel"]->SetVisible(false); - panels["MedigunInfoBluIndividualChargesLabel"]->SetVisible(true); - - if (individual_charge_meters->GetBool()) { - panels["MedigunInfoBluChargeMeter"]->SetVisible(false); - panels["MedigunInfoBluChargeMeter1"]->SetVisible(true); - panels["MedigunInfoBluChargeMeter2"]->SetVisible(true); - panels["MedigunInfoBluChargeMeter3"]->SetVisible(true); - panels["MedigunInfoBluChargeMeter4"]->SetVisible(true); - } - else { - panels["MedigunInfoBluChargeMeter"]->SetVisible(true); - panels["MedigunInfoBluChargeMeter1"]->SetVisible(false); - panels["MedigunInfoBluChargeMeter2"]->SetVisible(false); - panels["MedigunInfoBluChargeMeter3"]->SetVisible(false); - panels["MedigunInfoBluChargeMeter4"]->SetVisible(false); - } - - if (medigunInfo[TFTeam_Blue].chargeRelease) { - if (!bluChargeReleased) { - Interfaces::GetClientMode()->GetViewportAnimationController()->StartAnimationSequence("MedigunInfoBluChargeReleased"); - } - - bluChargeReleased = true; - bluChargeReady = false; - } - else if (medigunInfo[TFTeam_Blue].chargeLevel >= 0.25f) { - if (!bluChargeReady) { - Interfaces::GetClientMode()->GetViewportAnimationController()->StartAnimationSequence("MedigunInfoBluChargeReady"); - } - - bluChargeReleased = false; - bluChargeReady = true; - } - else { - if (bluChargeReleased || bluChargeReady) { - Interfaces::GetClientMode()->GetViewportAnimationController()->StartAnimationSequence("MedigunInfoBluChargeStop"); - } - - bluChargeReleased = false; - bluChargeReady = false; - } - - break; - } - case TFMedigun_MediGun: - case TFMedigun_Kritzkrieg: - case TFMedigun_QuickFix: - case TFMedigun_Unknown: - default: - { - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("blucharges", int(floor(medigunInfo[TFTeam_Blue].chargeLevel))); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("blucharge1", 0); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("blucharge2", 0); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("blucharge3", 0); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("blucharge4", 0); - - panels["MedigunInfoBluChargeLabel"]->SetVisible(false); - panels["MedigunInfoBluIndividualChargesLabel"]->SetVisible(true); - - if (individual_charge_meters->GetBool()) { - panels["MedigunInfoBluChargeMeter"]->SetVisible(false); - panels["MedigunInfoBluChargeMeter1"]->SetVisible(true); - panels["MedigunInfoBluChargeMeter2"]->SetVisible(true); - panels["MedigunInfoBluChargeMeter3"]->SetVisible(true); - panels["MedigunInfoBluChargeMeter4"]->SetVisible(true); - } - else { - panels["MedigunInfoBluChargeMeter"]->SetVisible(true); - panels["MedigunInfoBluChargeMeter1"]->SetVisible(false); - panels["MedigunInfoBluChargeMeter2"]->SetVisible(false); - panels["MedigunInfoBluChargeMeter3"]->SetVisible(false); - panels["MedigunInfoBluChargeMeter4"]->SetVisible(false); - } - - panels["MedigunInfoBluChargeMeter"]->SetVisible(true); - panels["MedigunInfoBluChargeMeter1"]->SetVisible(false); - panels["MedigunInfoBluChargeMeter2"]->SetVisible(false); - panels["MedigunInfoBluChargeMeter3"]->SetVisible(false); - panels["MedigunInfoBluChargeMeter4"]->SetVisible(false); - panels["MedigunInfoBluChargeLabel"]->SetVisible(true); - panels["MedigunInfoBluIndividualChargesLabel"]->SetVisible(false); - - if (medigunInfo[TFTeam_Blue].chargeRelease) { - if (!bluChargeReleased) { - Interfaces::GetClientMode()->GetViewportAnimationController()->StartAnimationSequence("MedigunInfoBluChargeReleased"); - } - - bluChargeReleased = true; - bluChargeReady = false; - } - else if (medigunInfo[TFTeam_Blue].chargeLevel >= 1.0f) { - if (!bluChargeReady) { - Interfaces::GetClientMode()->GetViewportAnimationController()->StartAnimationSequence("MedigunInfoBluChargeReady"); - } - - bluChargeReleased = false; - bluChargeReady = true; - } - else { - if (bluChargeReleased || bluChargeReady) { - Interfaces::GetClientMode()->GetViewportAnimationController()->StartAnimationSequence("MedigunInfoBluChargeStop"); - } - - bluChargeReleased = false; - bluChargeReady = false; - } - - break; + if (resistType == TFResistType_Bullet) { + conditions->SetBool("resist-bullet", true); } + else if (resistType == TFResistType_Explosive) { + conditions->SetBool("resist-explosive", true); } - - switch (medigunInfo[TFTeam_Blue].type) { - case TFMedigun_MediGun: - { - ((vgui::ImagePanel *) panels["MedigunInfoBluChargeTypeIcon"])->SetImage(GetVGUITexturePath(TEXTURE_UBERCHARGE).c_str()); - - panels["MedigunInfoBluChargeTypeIcon"]->SetVisible(true); - - break; + else if (resistType == TFResistType_Fire) { + conditions->SetBool("resist-fire", true); } - case TFMedigun_Kritzkrieg: - { - ((vgui::ImagePanel *) panels["MedigunInfoBluChargeTypeIcon"])->SetImage(GetVGUITexturePath(TEXTURE_CRITBOOST).c_str()); - - panels["MedigunInfoBluChargeTypeIcon"]->SetVisible(true); - break; + if (team == TFTeam_Red) { + conditions->SetBool("team-red", true); } - case TFMedigun_QuickFix: - { - ((vgui::ImagePanel *) panels["MedigunInfoBluChargeTypeIcon"])->SetImage(GetVGUITexturePath(TEXTURE_MEGAHEALBLU).c_str()); - - panels["MedigunInfoBluChargeTypeIcon"]->SetVisible(true); - - break; + else if (team == TFTeam_Blue) { + conditions->SetBool("team-blu", true); } - case TFMedigun_Vaccinator: - { - switch (medigunInfo[TFTeam_Blue].chargeResistType) { - case TFResistType_Bullet: - { - ((vgui::ImagePanel *) panels["MedigunInfoBluChargeTypeIcon"])->SetImage(GetVGUITexturePath(TEXTURE_BULLETRESISTBLU).c_str()); - - panels["MedigunInfoBluChargeTypeIcon"]->SetVisible(true); - - break; - } - case TFResistType_Explosive: - { - ((vgui::ImagePanel *) panels["MedigunInfoBluChargeTypeIcon"])->SetImage(GetVGUITexturePath(TEXTURE_BLASTRESISTBLU).c_str()); - - panels["MedigunInfoBluChargeTypeIcon"]->SetVisible(true); - - break; - } - case TFResistType_Fire: - { - ((vgui::ImagePanel *) panels["MedigunInfoBluChargeTypeIcon"])->SetImage(GetVGUITexturePath(TEXTURE_FIRERESISTBLU).c_str()); - - panels["MedigunInfoBluChargeTypeIcon"]->SetVisible(true); - break; - } - default: - { - ((vgui::ImagePanel *) panels["MedigunInfoBluChargeTypeIcon"])->SetImage(GetVGUITexturePath(TEXTURE_NULL).c_str()); - - panels["MedigunInfoBluChargeTypeIcon"]->SetVisible(false); - - break; - } - } + LoadControlSettings("Resource/UI/MedigunPanel.res", nullptr, nullptr, conditions); + } - break; - } - case TFMedigun_Unknown: - default: - { - ((vgui::ImagePanel *) panels["MedigunInfoBluChargeTypeIcon"])->SetImage(GetVGUITexturePath(TEXTURE_NULL).c_str()); + SetDialogVariable("charge", int(floor(level * 100.0f))); + SetDialogVariable("charges", int(floor(level * 4.0f))); + SetDialogVariable("charge1", int(floor(level * 400.0f) - 0.0f) < 0 ? 0 : int(floor(level * 400.0f) - 0.0f)); + SetDialogVariable("charge2", int(floor(level * 400.0f) - 100.0f) < 0 ? 0 : int(floor(level * 400.0f) - 100.0f)); + SetDialogVariable("charge3", int(floor(level * 400.0f) - 200.0f) < 0 ? 0 : int(floor(level * 400.0f) - 200.0f)); + SetDialogVariable("charge4", int(floor(level * 400.0f) - 300.0f) < 0 ? 0 : int(floor(level * 400.0f) - 300.0f)); +} - panels["MedigunInfoBluChargeTypeIcon"]->SetVisible(false); +void MedigunInfo::MedigunPanel::OnReloadControlSettings(KeyValues *attributes) { + KeyValues *conditions = new KeyValues("conditions"); - break; - } - } + if (alive) { + conditions->SetBool("player-alive", true); } else { - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("bluname", ""); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("blucharge", 0); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("blucharges", 0); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("blucharge1", 0); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("blucharge2", 0); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("blucharge3", 0); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("blucharge4", 0); - ((vgui::EditablePanel *) panels["MedigunInfo"])->SetDialogVariable("bluadvantage", 0); - ((vgui::ImagePanel *) panels["MedigunInfoBluChargeTypeIcon"])->SetImage(GetVGUITexturePath(TEXTURE_NULL).c_str()); - - panels["MedigunInfoBluNameLabel"]->SetVisible(false); - panels["MedigunInfoBluChargeMeter"]->SetVisible(false); - panels["MedigunInfoBluChargeMeter1"]->SetVisible(false); - panels["MedigunInfoBluChargeMeter2"]->SetVisible(false); - panels["MedigunInfoBluChargeMeter3"]->SetVisible(false); - panels["MedigunInfoBluChargeMeter4"]->SetVisible(false); - panels["MedigunInfoBluChargeLabel"]->SetVisible(false); - panels["MedigunInfoBluIndividualChargesLabel"]->SetVisible(false); - panels["MedigunInfoBluChargeAdvantageLabel"]->SetVisible(false); - panels["MedigunInfoBluChargeTypeIcon"]->SetVisible(false); - - if (bluChargeReady || bluChargeReleased) { - bluChargeReady = false; - bluChargeReleased = false; - - Interfaces::GetClientMode()->GetViewportAnimationController()->StartAnimationSequence("MedigunInfoBluChargeNormal"); - } + conditions->SetBool("player-dead", true); } -} -void MedigunInfo::ReloadSettings() { - if (panels.find("MedigunInfo") != panels.end()) { - ((vgui::EditablePanel *) panels["MedigunInfo"])->LoadControlSettings("Resource/UI/MedigunInfo.res"); + if (charges == 0) { + conditions->SetBool("charges-0", true); + } + else if (charges == 1) { + conditions->SetBool("charges-1", true); + } + else if (charges == 2) { + conditions->SetBool("charges-2", true); + } + else if (charges == 3) { + conditions->SetBool("charges-3", true); + } + else if (charges == 4) { + conditions->SetBool("charges-4", true); } - dynamicMeterSettings = new KeyValues("MedigunInfoDynamicMeters"); - dynamicMeterSettings->LoadFromFile(Interfaces::pFileSystem, "resource/ui/mediguninfodynamicmeters.res", "mod"); -} - -void MedigunInfo::ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue) { - if (enabled->GetBool()) { - InitHud(); - - if (!frameHook) { - frameHook = Funcs::AddHook_IBaseClientDLL_FrameStageNotify(Interfaces::pClientDLL, SH_MEMBER(this, &MedigunInfo::FrameHook), true); - } + if (medigun == TFMedigun_MediGun) { + conditions->SetBool("medigun-medigun", true); + } + else if (medigun == TFMedigun_Kritzkrieg) { + conditions->SetBool("medigun-kritzkrieg", true); + } + else if (medigun == TFMedigun_QuickFix) { + conditions->SetBool("medigun-quickfix", true); + } + else if (medigun == TFMedigun_Vaccinator) { + conditions->SetBool("medigun-vaccinator", true); + } - if (panels.find("MedigunInfo") != panels.end()) { - panels["MedigunInfo"]->SetEnabled(true); - panels["MedigunInfo"]->SetVisible(true); - } + if (released) { + conditions->SetBool("status-released", true); } else { - if (frameHook) { - if (Funcs::RemoveHook(frameHook)) { - frameHook = 0; - } - } + conditions->SetBool("status-building", true); + } - if (panels.find("MedigunInfo") != panels.end()) { - panels["MedigunInfo"]->SetEnabled(false); - panels["MedigunInfo"]->SetVisible(false); - } + if (resistType == TFResistType_Bullet) { + conditions->SetBool("resist-bullet", true); } + else if (resistType == TFResistType_Explosive) { + conditions->SetBool("resist-explosive", true); + } + else if (resistType == TFResistType_Fire) { + conditions->SetBool("resist-fire", true); + } + + if (team == TFTeam_Red) { + conditions->SetBool("team-red", true); + } + else if (team == TFTeam_Blue) { + conditions->SetBool("team-blu", true); + } + + LoadControlSettings("Resource/UI/MedigunPanel.res", nullptr, nullptr, conditions); } \ No newline at end of file diff --git a/src/modules/mediguninfo.h b/src/modules/mediguninfo.h index 3624349..5aacd66 100644 --- a/src/modules/mediguninfo.h +++ b/src/modules/mediguninfo.h @@ -2,7 +2,7 @@ * mediguninfo.h * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -10,45 +10,25 @@ #pragma once -class ConCommand; -class ConVar; -class KeyValues; - -namespace vgui { - class Panel; -}; - -#include "cdll_int.h" +#include #include "../modules.h" -#include "../tfdefs.h" -typedef struct Medigun_s { - TFMedigun type; - float chargeLevel; - TFResistType chargeResistType; - bool chargeRelease; -} Medigun_t; +class ConCommand; +class ConVar; +class IConVar; class MedigunInfo : public Module { public: - MedigunInfo(std::string name); + MedigunInfo(); - static bool CheckDependencies(std::string name); - - void FrameHook(ClientFrameStage_t curStage); + static bool CheckDependencies(); private: - KeyValues *dynamicMeterSettings; - int frameHook; - std::map medigunInfo; - std::map panels; - - void InitHud(); - void Paint(); + class MainPanel; + MainPanel *mainPanel; + class MedigunPanel; - ConVar *dynamic_meters; ConVar *enabled; - ConVar *individual_charge_meters; ConCommand *reload_settings; void ReloadSettings(); void ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue); diff --git a/src/modules/multipanel.cpp b/src/modules/multipanel.cpp index e562d70..2b6f196 100644 --- a/src/modules/multipanel.cpp +++ b/src/modules/multipanel.cpp @@ -2,7 +2,7 @@ * multipanel.cpp * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -16,40 +16,39 @@ #include "iclientmode.h" #include "vgui/IVGui.h" #include "../vgui_controls/gameconsoledialog.h" +#include "viewport_panel_names.h" #include "../common.h" #include "../ifaces.h" -#define SCOREBOARD_PANEL_NAME "scores" - -MultiPanel::MultiPanel(std::string name) : Module(name) { +MultiPanel::MultiPanel() { consoleDialog = nullptr; scoreboardPanel = vgui::INVALID_PANEL; - console = new ConVar("statusspec_multipanel_console", "0", FCVAR_NONE, "displays a console in the HUD", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule("MultiPanel")->ToggleConsole(var, pOldValue, flOldValue); }); - scoreboard = new ConVar("statusspec_multipanel_scoreboard", "0", FCVAR_NONE, "displays the scoreboard", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule("MultiPanel")->ToggleScoreboard(var, pOldValue, flOldValue); }); + console = new ConVar("statusspec_multipanel_console", "0", FCVAR_NONE, "displays a console in the HUD", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule()->ToggleConsole(var, pOldValue, flOldValue); }); + scoreboard = new ConVar("statusspec_multipanel_scoreboard", "0", FCVAR_NONE, "displays the scoreboard", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule()->ToggleScoreboard(var, pOldValue, flOldValue); }); } -bool MultiPanel::CheckDependencies(std::string name) { +bool MultiPanel::CheckDependencies() { bool ready = true; if (!Interfaces::vguiLibrariesAvailable) { PRINT_TAG(); - Warning("Required VGUI library for module %s not available!\n", name.c_str()); + Warning("Required VGUI library for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!g_pVGui) { PRINT_TAG(); - Warning("Required interface vgui::IVGui for module %s not available!\n", name.c_str()); + Warning("Required interface vgui::IVGui for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!g_pVGuiPanel) { PRINT_TAG(); - Warning("Required interface vgui::IPanel for module %s not available!\n", name.c_str()); + Warning("Required interface vgui::IPanel for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } @@ -59,7 +58,7 @@ bool MultiPanel::CheckDependencies(std::string name) { } catch (bad_pointer) { PRINT_TAG(); - Warning("Module %s requires IClientMode, which cannot be verified at this time!\n", name.c_str()); + Warning("Module %s requires IClientMode, which cannot be verified at this time!\n", g_ModuleManager->GetModuleName().c_str()); } return ready; @@ -83,7 +82,7 @@ void MultiPanel::InitHud() { for (int i = 0; i < children; i++) { vgui::VPANEL child = g_pVGuiPanel->GetChild(vpanel, i); - if (strcmp(g_pVGuiPanel->GetName(child), SCOREBOARD_PANEL_NAME) == 0) { + if (strcmp(g_pVGuiPanel->GetName(child), PANEL_SCOREBOARD) == 0) { scoreboardPanel = g_pVGui->PanelToHandle(child); break; @@ -123,8 +122,8 @@ void MultiPanel::ToggleScoreboard(IConVar *var, const char *pOldValue, float flO IViewPort *viewport = dynamic_cast(Interfaces::GetClientMode()->GetViewport()); if (viewport) { - viewport->ShowPanel(SCOREBOARD_PANEL_NAME, true); - viewport->ShowPanel(SCOREBOARD_PANEL_NAME, false); + viewport->ShowPanel(PANEL_SCOREBOARD, true); + viewport->ShowPanel(PANEL_SCOREBOARD, false); } } diff --git a/src/modules/multipanel.h b/src/modules/multipanel.h index ab2a476..b586401 100644 --- a/src/modules/multipanel.h +++ b/src/modules/multipanel.h @@ -2,7 +2,7 @@ * multipanel.h * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -20,9 +20,9 @@ class IConVar; class MultiPanel : public Module { public: - MultiPanel(std::string name); + MultiPanel(); - static bool CheckDependencies(std::string name); + static bool CheckDependencies(); private: CGameConsoleDialog *consoleDialog; vgui::HPanel scoreboardPanel; diff --git a/src/modules/playeraliases.cpp b/src/modules/playeraliases.cpp index fa240f4..34daf2d 100644 --- a/src/modules/playeraliases.cpp +++ b/src/modules/playeraliases.cpp @@ -2,7 +2,7 @@ * playeraliases.cpp * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -10,62 +10,52 @@ #include "playeraliases.h" -#include "json/json.h" +#include "rapidjson/document.h" #include "../common.h" #include "../funcs.h" #include "../ifaces.h" #include "../player.h" -#define MAX_URL_LENGTH 2048 - -#define ESEA_PLAYER_API_URL "http://play.esea.net/index.php" -#define ETF2L_PLAYER_API_URL "http://api.etf2l.org/player/%llu.json" -#define TWITCH_USER_API_URL "http://api.twitch.tv/api/steam/%llu" -#define STEAM_USER_ID_FORMAT "[U:%i:%lu]" - -PlayerAliases::PlayerAliases(std::string name) : Module(name) { +PlayerAliases::PlayerAliases() { getPlayerInfoHook = 0; - enabled = new ConVar("statusspec_playeraliases_enabled", "0", FCVAR_NONE, "enable player aliases", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule("Player Aliases")->ToggleEnabled(var, pOldValue, flOldValue); }); - esea = new ConVar("statusspec_playeraliases_esea", "0", FCVAR_NONE, "enable player aliases from the ESEA API"); - etf2l = new ConVar("statusspec_playeraliases_etf2l", "0", FCVAR_NONE, "enable player aliases from the ETF2L API"); + enabled = new ConVar("statusspec_playeraliases_enabled", "0", FCVAR_NONE, "enable player aliases", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule()->ToggleEnabled(var, pOldValue, flOldValue); }); format_blu = new ConVar("statusspec_playeraliases_format_blu", "%alias%", FCVAR_NONE, "the name format for BLU players"); format_red = new ConVar("statusspec_playeraliases_format_red", "%alias%", FCVAR_NONE, "the name format for RED players"); - get = new ConCommand("statusspec_playeraliases_get", [](const CCommand &command) { g_ModuleManager->GetModule("Player Aliases")->GetCustomPlayerAlias(command); }, "get a custom player alias", FCVAR_NONE, [](const char *partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])->int { return g_ModuleManager->GetModule("Player Aliases")->GetCurrentAliasedPlayers(partial, commands); }); - remove = new ConCommand("statusspec_playeraliases_remove", [](const CCommand &command) { g_ModuleManager->GetModule("Player Aliases")->RemoveCustomPlayerAlias(command); }, "remove a custom player alias", FCVAR_NONE, [](const char *partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])->int { return g_ModuleManager->GetModule("Player Aliases")->GetCurrentAliasedPlayers(partial, commands); }); - set = new ConCommand("statusspec_playeraliases_set", [](const CCommand &command) { g_ModuleManager->GetModule("Player Aliases")->SetCustomPlayerAlias(command); }, "set a custom player alias", FCVAR_NONE, [](const char *partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])->int { return g_ModuleManager->GetModule("Player Aliases")->GetCurrentGamePlayers(partial, commands); }); - twitch = new ConVar("statusspec_playeraliases_twitch", "0", FCVAR_NONE, "enable player aliases from the Twitch API"); - switch_teams = new ConCommand("statusspec_playeraliases_switch_teams", []() { g_ModuleManager->GetModule("Player Aliases")->SwitchTeams(); }, "switch name formats for both teams", FCVAR_NONE); + get = new ConCommand("statusspec_playeraliases_get", [](const CCommand &command) { g_ModuleManager->GetModule()->GetCustomPlayerAlias(command); }, "get a custom player alias", FCVAR_NONE, [](const char *partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])->int { return g_ModuleManager->GetModule()->GetCurrentAliasedPlayers(partial, commands); }); + remove = new ConCommand("statusspec_playeraliases_remove", [](const CCommand &command) { g_ModuleManager->GetModule()->RemoveCustomPlayerAlias(command); }, "remove a custom player alias", FCVAR_NONE, [](const char *partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])->int { return g_ModuleManager->GetModule()->GetCurrentAliasedPlayers(partial, commands); }); + set = new ConCommand("statusspec_playeraliases_set", [](const CCommand &command) { g_ModuleManager->GetModule()->SetCustomPlayerAlias(command); }, "set a custom player alias", FCVAR_NONE, [](const char *partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])->int { return g_ModuleManager->GetModule()->GetCurrentGamePlayers(partial, commands); }); + switch_teams = new ConCommand("statusspec_playeraliases_switch_teams", []() { g_ModuleManager->GetModule()->SwitchTeams(); }, "switch name formats for both teams", FCVAR_NONE); } -bool PlayerAliases::CheckDependencies(std::string name) { +bool PlayerAliases::CheckDependencies() { bool ready = true; if (!Interfaces::pEngineClient) { PRINT_TAG(); - Warning("Required interface IVEngineClient for module %s not available!\n", name.c_str()); + Warning("Required interface IVEngineClient for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Interfaces::steamLibrariesAvailable) { PRINT_TAG(); - Warning("Required Steam libraries for module %s not available!\n", name.c_str()); + Warning("Required Steam libraries for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Player::CheckDependencies()) { PRINT_TAG(); - Warning("Required player helper class for module %s not available!\n", name.c_str()); + Warning("Required player helper class for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Player::steamIDRetrievalAvailable) { PRINT_TAG(); - Warning("Required player Steam ID retrieval for module %s not available!\n", name.c_str()); + Warning("Required player Steam ID retrieval for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } @@ -128,212 +118,10 @@ std::string PlayerAliases::GetAlias(CSteamID player, std::string gameAlias) { if (customAliases.find(player) != customAliases.end()) { return customAliases[player]; } - - if (esea->GetBool()) { - if (eseaAliases[player].status == API_UNKNOWN) { - RequestESEAPlayerInfo(player); - } - else if (eseaAliases[player].status == API_SUCCESSFUL) { - return eseaAliases[player].name; - } - } - - if (etf2l->GetBool()) { - if (etf2lAliases[player].status == API_UNKNOWN) { - RequestETF2LPlayerInfo(player); - } - else if (etf2lAliases[player].status == API_SUCCESSFUL) { - return etf2lAliases[player].name; - } - } - - if (twitch->GetBool()) { - if (twitchAliases[player].status == API_UNKNOWN) { - RequestTwitchUserInfo(player); - } - else if (twitchAliases[player].status == API_SUCCESSFUL) { - return twitchAliases[player].name; - } - } return gameAlias; } -void PlayerAliases::GetESEAPlayerInfo(HTTPRequestCompleted_t *requestCompletionInfo, bool bIOFailure) { - CSteamID player = CSteamID(requestCompletionInfo->m_ulContextValue); - - if (bIOFailure || !requestCompletionInfo->m_bRequestSuccessful) { - eseaAliases[player].status = API_UNKNOWN; - } - else if (requestCompletionInfo->m_eStatusCode != k_EHTTPStatusCode200OK) { - eseaAliases[player].status = API_FAILED; - } - else { - ISteamHTTP *httpClient = Interfaces::pSteamAPIContext->SteamHTTP(); - - uint32 bodySize; - httpClient->GetHTTPResponseBodySize(requestCompletionInfo->m_hRequest, &bodySize); - - uint8 *body = new uint8[bodySize]; - httpClient->GetHTTPResponseBodyData(requestCompletionInfo->m_hRequest, body, bodySize); - - std::string json = (char *)body; - - Json::Reader reader; - Json::Value root; - - if (reader.parse(json, root)) { - if (root.isMember("results") && root["results"].size() > 0) { - if (root["results"][0].isMember("alias")) { - eseaAliases[player].name = root["results"][0]["alias"].asString(); - eseaAliases[player].status = API_SUCCESSFUL; - httpClient->ReleaseHTTPRequest(requestCompletionInfo->m_hRequest); - - return; - } - } - } - - eseaAliases[player].status = API_FAILED; - } - - Interfaces::pSteamAPIContext->SteamHTTP()->ReleaseHTTPRequest(requestCompletionInfo->m_hRequest); -} - -void PlayerAliases::GetETF2LPlayerInfo(HTTPRequestCompleted_t *requestCompletionInfo, bool bIOFailure) { - CSteamID player = CSteamID(requestCompletionInfo->m_ulContextValue); - - if (bIOFailure || !requestCompletionInfo->m_bRequestSuccessful) { - etf2lAliases[player].status = API_UNKNOWN; - } - else if (requestCompletionInfo->m_eStatusCode != k_EHTTPStatusCode200OK) { - etf2lAliases[player].status = API_FAILED; - } - else { - ISteamHTTP *httpClient = Interfaces::pSteamAPIContext->SteamHTTP(); - - uint32 bodySize; - httpClient->GetHTTPResponseBodySize(requestCompletionInfo->m_hRequest, &bodySize); - - uint8 *body = new uint8[bodySize]; - httpClient->GetHTTPResponseBodyData(requestCompletionInfo->m_hRequest, body, bodySize); - - std::string json = (char *)body; - - Json::Reader reader; - Json::Value root; - - if (reader.parse(json, root)) { - if (root["status"]["code"].asInt() == 200) { - if (root["player"]["steam"]["id64"].asString() == std::to_string(player.ConvertToUint64())) { - etf2lAliases[player].name = root["player"]["name"].asString(); - etf2lAliases[player].status = API_SUCCESSFUL; - httpClient->ReleaseHTTPRequest(requestCompletionInfo->m_hRequest); - - return; - } - } - } - - etf2lAliases[player].status = API_FAILED; - } - - Interfaces::pSteamAPIContext->SteamHTTP()->ReleaseHTTPRequest(requestCompletionInfo->m_hRequest); -} - -void PlayerAliases::GetTwitchUserInfo(HTTPRequestCompleted_t *requestCompletionInfo, bool bIOFailure) { - CSteamID player = CSteamID(requestCompletionInfo->m_ulContextValue); - - if (bIOFailure || !requestCompletionInfo->m_bRequestSuccessful) { - twitchAliases[player].status = API_UNKNOWN; - } - else if (requestCompletionInfo->m_eStatusCode != k_EHTTPStatusCode200OK) { - twitchAliases[player].status = API_FAILED; - } - else { - ISteamHTTP *httpClient = Interfaces::pSteamAPIContext->SteamHTTP(); - - uint32 bodySize; - httpClient->GetHTTPResponseBodySize(requestCompletionInfo->m_hRequest, &bodySize); - - uint8 *body = new uint8[bodySize]; - httpClient->GetHTTPResponseBodyData(requestCompletionInfo->m_hRequest, body, bodySize); - - std::string json = (char *)body; - - Json::Reader reader; - Json::Value root; - - if (reader.parse(json, root)) { - if (!root.isMember("status") || root["status"] == 200) { - twitchAliases[player].name = root["name"].asString(); - twitchAliases[player].status = API_SUCCESSFUL; - httpClient->ReleaseHTTPRequest(requestCompletionInfo->m_hRequest); - - return; - } - } - - twitchAliases[player].status = API_FAILED; - } - - Interfaces::pSteamAPIContext->SteamHTTP()->ReleaseHTTPRequest(requestCompletionInfo->m_hRequest); -} - -void PlayerAliases::RequestESEAPlayerInfo(CSteamID player) { - ISteamHTTP *httpClient = Interfaces::pSteamAPIContext->SteamHTTP(); - - char id[MAX_URL_LENGTH]; - V_snprintf(id, sizeof(id), STEAM_USER_ID_FORMAT, Interfaces::pSteamAPIContext->SteamUtils()->GetConnectedUniverse(), player.GetAccountID()); - - HTTPRequestHandle request = httpClient->CreateHTTPRequest(k_EHTTPMethodGET, ESEA_PLAYER_API_URL); - httpClient->SetHTTPRequestGetOrPostParameter(request, "s", "search"); - httpClient->SetHTTPRequestGetOrPostParameter(request, "query", id); - httpClient->SetHTTPRequestGetOrPostParameter(request, "source", "users"); - httpClient->SetHTTPRequestGetOrPostParameter(request, "fields%5Bunique_ids%5D", "1"); - httpClient->SetHTTPRequestGetOrPostParameter(request, "format", "json"); - httpClient->SetHTTPRequestHeaderValue(request, "Cookie", "viewed_welcome_page=1"); - httpClient->SetHTTPRequestContextValue(request, player.ConvertToUint64()); - - SteamAPICall_t apiCall; - if (httpClient->SendHTTPRequest(request, &apiCall)) { - eseaAliases[player].status = API_REQUESTED; - eseaAliases[player].call.Set(apiCall, this, &PlayerAliases::GetESEAPlayerInfo); - } -} - -void PlayerAliases::RequestETF2LPlayerInfo(CSteamID player) { - ISteamHTTP *httpClient = Interfaces::pSteamAPIContext->SteamHTTP(); - - char url[MAX_URL_LENGTH]; - V_snprintf(url, sizeof(url), ETF2L_PLAYER_API_URL, player.ConvertToUint64()); - - HTTPRequestHandle request = httpClient->CreateHTTPRequest(k_EHTTPMethodGET, url); - httpClient->SetHTTPRequestContextValue(request, player.ConvertToUint64()); - - SteamAPICall_t apiCall; - if (httpClient->SendHTTPRequest(request, &apiCall)) { - etf2lAliases[player].status = API_REQUESTED; - etf2lAliases[player].call.Set(apiCall, this, &PlayerAliases::GetETF2LPlayerInfo); - } -} - -void PlayerAliases::RequestTwitchUserInfo(CSteamID player) { - ISteamHTTP *httpClient = Interfaces::pSteamAPIContext->SteamHTTP(); - - char url[MAX_URL_LENGTH]; - V_snprintf(url, sizeof(url), TWITCH_USER_API_URL, player.ConvertToUint64()); - - HTTPRequestHandle request = httpClient->CreateHTTPRequest(k_EHTTPMethodGET, url); - httpClient->SetHTTPRequestContextValue(request, player.ConvertToUint64()); - - SteamAPICall_t apiCall; - if (httpClient->SendHTTPRequest(request, &apiCall)) { - twitchAliases[player].status = API_REQUESTED; - twitchAliases[player].call.Set(apiCall, this, &PlayerAliases::GetTwitchUserInfo); - } -} - int PlayerAliases::GetCurrentAliasedPlayers(const char *partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH]) { int playerCount = 0; @@ -341,8 +129,8 @@ int PlayerAliases::GetCurrentAliasedPlayers(const char *partial, char commands[C std::string command; std::getline(ss, command, ' '); - for (auto playerAlias = customAliases.begin(); playerAlias != customAliases.end() && playerCount < COMMAND_COMPLETION_MAXITEMS; ++playerAlias) { - CSteamID playerSteamID = playerAlias->first; + for (auto iterator : customAliases) { + CSteamID playerSteamID = iterator.first; V_snprintf(commands[playerCount], COMMAND_COMPLETION_ITEM_LENGTH, "%s %llu", command.c_str(), playerSteamID.ConvertToUint64()); playerCount++; @@ -358,9 +146,7 @@ int PlayerAliases::GetCurrentGamePlayers(const char *partial, char commands[COMM std::string command; std::getline(ss, command, ' '); - for (auto iterator = Player::begin(); iterator != Player::end(); ++iterator) { - Player player = *iterator; - + for (Player player : Player::Iterable()) { CSteamID playerSteamID = player.GetSteamID(); if (playerSteamID.IsValid()) { diff --git a/src/modules/playeraliases.h b/src/modules/playeraliases.h index 268f920..1e01a78 100644 --- a/src/modules/playeraliases.h +++ b/src/modules/playeraliases.h @@ -2,7 +2,7 @@ * playeraliases.h * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -16,55 +16,26 @@ #include "../modules.h" -typedef enum APIStatus_s { - API_UNKNOWN, - API_REQUESTED, - API_FAILED, - API_NO_RESULT, - API_SUCCESSFUL -} APIStatus_t; - -class PlayerAliases; - -typedef struct APIAlias_s { - std::string name; - APIStatus_t status = API_UNKNOWN; - CCallResult call; -} APIAlias_t; - class PlayerAliases : public Module { public: - PlayerAliases(std::string name); - - static bool CheckDependencies(std::string name); + PlayerAliases(); + static bool CheckDependencies(); +private: bool GetPlayerInfoOverride(int ent_num, player_info_t *pinfo); - void GetESEAPlayerInfo(HTTPRequestCompleted_t *requestCompletionInfo, bool bIOFailure); - void GetETF2LPlayerInfo(HTTPRequestCompleted_t *requestCompletionInfo, bool bIOFailure); - void GetTwitchUserInfo(HTTPRequestCompleted_t *requestCompletionInfo, bool bIOFailure); -private: std::map customAliases; - std::map eseaAliases; - std::map etf2lAliases; int getPlayerInfoHook; - std::map twitchAliases; std::string GetAlias(CSteamID player, std::string gameAlias); - void RequestESEAPlayerInfo(CSteamID player); - void RequestETF2LPlayerInfo(CSteamID player); - void RequestTwitchUserInfo(CSteamID player); ConVar *enabled; - ConVar *esea; - ConVar *etf2l; ConVar *format_blu; ConVar *format_red; ConCommand *get; ConCommand *remove; ConCommand *set; ConCommand *switch_teams; - ConVar *twitch; int GetCurrentAliasedPlayers(const char *partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH]); int GetCurrentGamePlayers(const char *partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH]); void GetCustomPlayerAlias(const CCommand &command); diff --git a/src/modules/playermodels.cpp b/src/modules/playermodels.cpp index 5786e3c..457b795 100644 --- a/src/modules/playermodels.cpp +++ b/src/modules/playermodels.cpp @@ -2,7 +2,7 @@ * playermodels.cpp * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -21,35 +21,35 @@ #include "../ifaces.h" #include "../player.h" -PlayerModels::PlayerModels(std::string name) : Module(name) { +PlayerModels::PlayerModels() { modelConfig = new KeyValues("models"); modelConfig->LoadFromFile(Interfaces::pFileSystem, "resource/playermodels.res", "mod"); setModelHook = 0; - enabled = new ConVar("statusspec_playermodels_enabled", "0", FCVAR_NONE, "enable custom player models", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule("Player Models")->ToggleEnabled(var, pOldValue, flOldValue); }); - reload_settings = new ConCommand("statusspec_playermodels_reload_settings", []() { g_ModuleManager->GetModule("Player Models")->ReloadSettings(); }, "reload settings for the player models from the resource file", FCVAR_NONE); + enabled = new ConVar("statusspec_playermodels_enabled", "0", FCVAR_NONE, "enable custom player models", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule()->ToggleEnabled(var, pOldValue, flOldValue); }); + reload_settings = new ConCommand("statusspec_playermodels_reload_settings", []() { g_ModuleManager->GetModule()->ReloadSettings(); }, "reload settings for the player models from the resource file", FCVAR_NONE); } -bool PlayerModels::CheckDependencies(std::string name) { +bool PlayerModels::CheckDependencies() { bool ready = true; if (!Interfaces::pFileSystem) { PRINT_TAG(); - Warning("Required interface IFileSystem for module %s not available!\n", name.c_str()); + Warning("Required interface IFileSystem for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Interfaces::pModelInfoClient) { PRINT_TAG(); - Warning("Required interface IVModelInfoClient for module %s not available!\n", name.c_str()); + Warning("Required interface IVModelInfoClient for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Entities::RetrieveClassPropOffset("CTFRagdoll", { "m_iPlayerIndex" })) { PRINT_TAG(); - Warning("Required property m_iPlayerIndex for CTFRagdoll for module %s not available!\n", name.c_str()); + Warning("Required property m_iPlayerIndex for CTFRagdoll for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } @@ -59,7 +59,7 @@ bool PlayerModels::CheckDependencies(std::string name) { } catch (bad_pointer) { PRINT_TAG(); - Warning("Required function C_BaseEntity::SetModelIndex for module %s not available!\n", name.c_str()); + Warning("Required function C_BaseEntity::SetModelIndex for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } @@ -69,21 +69,21 @@ bool PlayerModels::CheckDependencies(std::string name) { } catch (bad_pointer) { PRINT_TAG(); - Warning("Required function C_BaseEntity::SetModelPointer for module %s not available!\n", name.c_str()); + Warning("Required function C_BaseEntity::SetModelPointer for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Player::CheckDependencies()) { PRINT_TAG(); - Warning("Required player helper class for module %s not available!\n", name.c_str()); + Warning("Required player helper class for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Player::steamIDRetrievalAvailable) { PRINT_TAG(); - Warning("Required player Steam ID retrieval for module %s not available!\n", name.c_str()); + Warning("Required player Steam ID retrieval for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } @@ -133,6 +133,7 @@ void PlayerModels::SetModelOverride(C_BaseEntity *entity, const model_t *&model) } void PlayerModels::ReloadSettings() { + modelConfig = new KeyValues("models"); modelConfig->LoadFromFile(Interfaces::pFileSystem, "resource/playermodels.res", "mod"); } diff --git a/src/modules/playermodels.h b/src/modules/playermodels.h index 4b9881e..f5375d2 100644 --- a/src/modules/playermodels.h +++ b/src/modules/playermodels.h @@ -2,7 +2,7 @@ * playermodels.h * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -21,15 +21,15 @@ struct model_t; class PlayerModels : public Module { public: - PlayerModels(std::string name); + PlayerModels(); - static bool CheckDependencies(std::string name); + static bool CheckDependencies(); private: + void SetModelOverride(C_BaseEntity *entity, const model_t *&model); + KeyValues *modelConfig; int setModelHook; - void SetModelOverride(C_BaseEntity *entity, const model_t *&model); - ConVar *enabled; ConCommand *reload_settings; void ReloadSettings(); diff --git a/src/modules/playeroutlines.cpp b/src/modules/playeroutlines.cpp deleted file mode 100644 index ecdfc9b..0000000 --- a/src/modules/playeroutlines.cpp +++ /dev/null @@ -1,375 +0,0 @@ -/* - * playeroutlines.cpp - * StatusSpec project - * - * Copyright (c) 2014 thesupremecommander - * BSD 2-Clause License - * http://opensource.org/licenses/BSD-2-Clause - * - */ - -#include "playeroutlines.h" - -#include "../funcs.h" -#include "../ifaces.h" -#include "../player.h" - -#include "view_shared.h" - -PlayerOutlines::PlayerOutlines(std::string name) : Module(name) { - colors["blu_low"].color = Color(88, 133, 162, 255); - colors["blu_low"].command = new ConCommand("statusspec_playeroutlines_color_blu_low", [](const CCommand &command) { g_ModuleManager->GetModule("Player Outlines")->ColorCommand(command); }, "the color used for outlines for BLU team players at low health", FCVAR_NONE, [](const char *partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])->int { return g_ModuleManager->GetModule("Player Outlines")->GetCurrentColor(partial, commands); }); - colors["blu_medium"].color = Color(88, 133, 162, 255); - colors["blu_medium"].command = new ConCommand("statusspec_playeroutlines_color_blu_medium", [](const CCommand &command) { g_ModuleManager->GetModule("Player Outlines")->ColorCommand(command); }, "the color used for outlines for BLU team players at medium health", FCVAR_NONE, [](const char *partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])->int { return g_ModuleManager->GetModule("Player Outlines")->GetCurrentColor(partial, commands); }); - colors["blu_full"].color = Color(88, 133, 162, 255); - colors["blu_full"].command = new ConCommand("statusspec_playeroutlines_color_blu_full", [](const CCommand &command) { g_ModuleManager->GetModule("Player Outlines")->ColorCommand(command); }, "the color used for outlines for BLU team players at full health", FCVAR_NONE, [](const char *partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])->int { return g_ModuleManager->GetModule("Player Outlines")->GetCurrentColor(partial, commands); }); - colors["blu_buff"].color = Color(88, 133, 162, 255); - colors["blu_buff"].command = new ConCommand("statusspec_playeroutlines_color_blu_buff", [](const CCommand &command) { g_ModuleManager->GetModule("Player Outlines")->ColorCommand(command); }, "the color used for outlines for BLU team players at max buffed health", FCVAR_NONE, [](const char *partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])->int { return g_ModuleManager->GetModule("Player Outlines")->GetCurrentColor(partial, commands); }); - colors["red_low"].color = Color(184, 56, 59, 255); - colors["red_low"].command = new ConCommand("statusspec_playeroutlines_color_red_low", [](const CCommand &command) { g_ModuleManager->GetModule("Player Outlines")->ColorCommand(command); }, "the color used for outlines for RED team players at low health", FCVAR_NONE, [](const char *partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])->int { return g_ModuleManager->GetModule("Player Outlines")->GetCurrentColor(partial, commands); }); - colors["red_medium"].color = Color(184, 56, 59, 255); - colors["red_medium"].command = new ConCommand("statusspec_playeroutlines_color_red_medium", [](const CCommand &command) { g_ModuleManager->GetModule("Player Outlines")->ColorCommand(command); }, "the color used for outlines for RED team players at medium health", FCVAR_NONE, [](const char *partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])->int { return g_ModuleManager->GetModule("Player Outlines")->GetCurrentColor(partial, commands); }); - colors["red_full"].color = Color(184, 56, 59, 255); - colors["red_full"].command = new ConCommand("statusspec_playeroutlines_color_red_full", [](const CCommand &command) { g_ModuleManager->GetModule("Player Outlines")->ColorCommand(command); }, "the color used for outlines for RED team players at full health", FCVAR_NONE, [](const char *partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])->int { return g_ModuleManager->GetModule("Player Outlines")->GetCurrentColor(partial, commands); }); - colors["red_buff"].color = Color(184, 56, 59, 255); - colors["red_buff"].command = new ConCommand("statusspec_playeroutlines_color_red_buff", [](const CCommand &command) { g_ModuleManager->GetModule("Player Outlines")->ColorCommand(command); }, "the color used for outlines for RED team players at max buffed health", FCVAR_NONE, [](const char *partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])->int { return g_ModuleManager->GetModule("Player Outlines")->GetCurrentColor(partial, commands); }); - doPostScreenSpaceEffectsHook = 0; - frameHook = 0; - - enabled = new ConVar("statusspec_playeroutlines_enabled", "0", FCVAR_NONE, "enable player outlines", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule("Player Outlines")->ToggleEnabled(var, pOldValue, flOldValue); }); - fade = new ConVar("statusspec_playeroutlines_fade", "0", FCVAR_NONE, "make outlines fade with distance"); - fade_distance = new ConVar("statusspec_playeroutlines_fade_distance", "3200", FCVAR_NONE, "the distance (in Hammer units) at which outlines will fade"); - health_adjusted_team_colors = new ConVar("statusspec_playeroutlines_health_adjusted_team_colors", "0", FCVAR_NONE, "adjusts team colors depending on health of players"); - team_colors = new ConVar("statusspec_playeroutlines_team_colors", "0", FCVAR_NONE, "override default health-based outline colors with team colors"); -} - -bool PlayerOutlines::CheckDependencies(std::string name) { - bool ready = true; - - if (!Interfaces::pClientDLL) { - PRINT_TAG(); - Warning("Required interface IBaseClientDLL for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!Player::CheckDependencies()) { - PRINT_TAG(); - Warning("Required player helper class for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!GlowManager::CheckDependencies()) { - PRINT_TAG(); - Warning("Required glow manager for module %s not available!\n", name.c_str()); - - ready = false; - } - - try { - Interfaces::GetClientMode(); - } - catch (bad_pointer) { - PRINT_TAG(); - Warning("Module %s requires IClientMode, which cannot be verified at this time!\n", name.c_str()); - } - - return ready; -} - -bool PlayerOutlines::DoPostScreenSpaceEffectsHook(const CViewSetup *pSetup) { - if (fade->GetBool()) { - for (auto iterator = glows.begin(); iterator != glows.end(); ++iterator) { - if (iterator->first) { - vec_t distance = pSetup->origin.DistTo(iterator->first->GetRenderOrigin()); - - if (distance > fade_distance->GetFloat()) { - Color glowColor = GetGlowColor(iterator->first.Get()); - float alpha = glowColor.a() / 255.0f; - - float scalar = fade_distance->GetFloat() / distance; - - iterator->second->SetAlpha(alpha * scalar); - } - } - } - } - - glowManager.RenderGlowEffects(pSetup); - - RETURN_META_VALUE(MRES_IGNORED, false); -} - -void PlayerOutlines::FrameHook(ClientFrameStage_t curStage) { - if (curStage == FRAME_NET_UPDATE_END) { - for (auto iterator = Player::begin(); iterator != Player::end(); ++iterator) { - Player player = *iterator; - - if (enabled->GetBool()) { - Color glowColor = GetGlowColor(player); - - float red = glowColor.r() / 255.0f; - float green = glowColor.g() / 255.0f; - float blue = glowColor.b() / 255.0f; - float alpha = glowColor.a() / 255.0f; - - SetGlowEffect(player, true, Vector(red, green, blue), alpha); - } - else { - SetGlowEffect(player, false); - } - } - } - else if (curStage == FRAME_START) { - if (!doPostScreenSpaceEffectsHook) { - try { - doPostScreenSpaceEffectsHook = Funcs::AddHook_IClientMode_DoPostScreenSpaceEffects(Interfaces::GetClientMode(), SH_MEMBER(this, &PlayerOutlines::DoPostScreenSpaceEffectsHook), false); - } - catch (bad_pointer &e) { - Warning("%s\n", e.what()); - } - } - } - - RETURN_META(MRES_IGNORED); -} - -Color PlayerOutlines::GetGlowColor(Player player) { - if (!player) { - return Color(0, 0, 0, 0); - } - - float red = 255.0f; - float green = 255.0f; - float blue = 255.0f; - float alpha = 255.0f; - - if (!team_colors->GetBool()) { - Funcs::CallFunc_C_TFPlayer_GetGlowEffectColor((C_TFPlayer *)player.GetEntity(), &red, &green, &blue); - - red *= 255.0f; - green *= 255.0f; - blue *= 255.0f; - } - else { - TFTeam team = player.GetTeam(); - - if (!health_adjusted_team_colors->GetBool()) { - if (team == TFTeam_Red) { - red = colors["red_full"].color.r(); - green = colors["red_full"].color.g(); - blue = colors["red_full"].color.b(); - alpha = colors["red_full"].color.a(); - } - else if (team == TFTeam_Blue) { - red = colors["blu_full"].color.r(); - green = colors["blu_full"].color.g(); - blue = colors["blu_full"].color.b(); - alpha = colors["blu_full"].color.a(); - } - } - else { - int health = player.GetHealth(); - int maxHealth = player.GetMaxHealth(); - - // CTFPlayerResource isn't giving us proper values so let's calculate it manually - int maxBuffedHealth = ((maxHealth / 5) * 3 / 2) * 5; - - // calculate this once instead of several times - float halfHealth = maxHealth * 0.5f; - - if (team == TFTeam_Red) { - if (health < 0) { - // this should never happen - - red = colors["red_low"].color.r(); - green = colors["red_low"].color.g(); - blue = colors["red_low"].color.b(); - alpha = colors["red_low"].color.a(); - } - else if (health >= 0 && health < halfHealth) { - red = ChangeScale(health, 0, halfHealth, colors["red_low"].color.r(), colors["red_medium"].color.r()); - green = ChangeScale(health, 0, halfHealth, colors["red_low"].color.g(), colors["red_medium"].color.g()); - blue = ChangeScale(health, 0, halfHealth, colors["red_low"].color.b(), colors["red_medium"].color.b()); - alpha = ChangeScale(health, 0, halfHealth, colors["red_low"].color.a(), colors["red_medium"].color.a()); - } - else if (health >= halfHealth && health < maxHealth) { - red = ChangeScale(health, halfHealth, maxHealth, colors["red_medium"].color.r(), colors["red_full"].color.r()); - green = ChangeScale(health, halfHealth, maxHealth, colors["red_medium"].color.g(), colors["red_full"].color.g()); - blue = ChangeScale(health, halfHealth, maxHealth, colors["red_medium"].color.b(), colors["red_full"].color.b()); - alpha = ChangeScale(health, halfHealth, maxHealth, colors["red_medium"].color.a(), colors["red_full"].color.a()); - } - else if (health >= maxHealth && health <= maxBuffedHealth) { - red = ChangeScale(health, maxHealth, maxBuffedHealth, colors["red_full"].color.r(), colors["red_buff"].color.r()); - green = ChangeScale(health, maxHealth, maxBuffedHealth, colors["red_full"].color.g(), colors["red_buff"].color.g()); - blue = ChangeScale(health, maxHealth, maxBuffedHealth, colors["red_full"].color.b(), colors["red_buff"].color.b()); - alpha = ChangeScale(health, maxHealth, maxBuffedHealth, colors["red_full"].color.a(), colors["red_buff"].color.a()); - } - else if (health >= maxBuffedHealth) { - // our max buffed health above does not take into account special cases so we have to compensate - - red = colors["red_buff"].color.r(); - green = colors["red_buff"].color.g(); - blue = colors["red_buff"].color.b(); - alpha = colors["red_buff"].color.a(); - } - else { - // this DEFINITELY shouldn't ever happen - - return Color(0, 0, 0, 0); - } - } - else if (team == TFTeam_Blue) { - if (health < 0) { - // this should never happen - - red = colors["blu_low"].color.r(); - green = colors["blu_low"].color.g(); - blue = colors["blu_low"].color.b(); - alpha = colors["blu_low"].color.a(); - } - else if (health >= 0 && health < (maxHealth * 0.5f)) { - red = ChangeScale(health, 0, maxHealth * 0.5f, colors["blu_low"].color.r(), colors["blu_medium"].color.r()); - green = ChangeScale(health, 0, maxHealth * 0.5f, colors["blu_low"].color.g(), colors["blu_medium"].color.g()); - blue = ChangeScale(health, 0, maxHealth * 0.5f, colors["blu_low"].color.b(), colors["blu_medium"].color.b()); - alpha = ChangeScale(health, 0, maxHealth * 0.5f, colors["blu_low"].color.a(), colors["blu_medium"].color.a()); - } - else if (health >= (maxHealth * 0.5f) && health < maxHealth) { - red = ChangeScale(health, maxHealth * 0.5f, maxHealth, colors["blu_medium"].color.r(), colors["blu_full"].color.r()); - green = ChangeScale(health, maxHealth * 0.5f, maxHealth, colors["blu_medium"].color.g(), colors["blu_full"].color.g()); - blue = ChangeScale(health, maxHealth * 0.5f, maxHealth, colors["blu_medium"].color.b(), colors["blu_full"].color.b()); - alpha = ChangeScale(health, maxHealth * 0.5f, maxHealth, colors["blu_medium"].color.a(), colors["blu_full"].color.a()); - } - else if (health >= maxHealth && health <= maxBuffedHealth) { - red = ChangeScale(health, maxHealth, maxBuffedHealth, colors["blu_full"].color.r(), colors["blu_buff"].color.r()); - green = ChangeScale(health, maxHealth, maxBuffedHealth, colors["blu_full"].color.g(), colors["blu_buff"].color.g()); - blue = ChangeScale(health, maxHealth, maxBuffedHealth, colors["blu_full"].color.b(), colors["blu_buff"].color.b()); - alpha = ChangeScale(health, maxHealth, maxBuffedHealth, colors["blu_full"].color.a(), colors["blu_buff"].color.a()); - } - else if (health >= maxBuffedHealth) { - // our max buffed health above does not take into account special cases so we have to compensate - - red = colors["blu_buff"].color.r(); - green = colors["blu_buff"].color.g(); - blue = colors["blu_buff"].color.b(); - alpha = colors["blu_buff"].color.a(); - } - else { - // this DEFINITELY shouldn't ever happen - - return Color(0, 0, 0, 0); - } - } - } - } - - return Color(red, green, blue, alpha); -} - -void PlayerOutlines::SetGlowEffect(IClientEntity *entity, bool enabled, Vector color, float alpha) { - EHANDLE entityHandle = dynamic_cast(entity); - - if (enabled) { - if (glows.find(entityHandle) == glows.end()) { - glows[entityHandle] = new GlowManager::GlowObject(&glowManager, entityHandle.Get(), color, alpha, true, true); - } - else { - glows[entityHandle]->SetColor(color); - glows[entityHandle]->SetAlpha(alpha); - } - } - else { - if (glows.find(entityHandle) != glows.end()) { - delete glows[entityHandle]; - glows.erase(entityHandle); - } - } -} - -void PlayerOutlines::ColorCommand(const CCommand &command) { - if (strncmp(command.Arg(0), "statusspec_playeroutlines_color_", 32) == 0) { - std::string mainCommand = command.Arg(0); - std::string colorType = mainCommand.substr(32); - - if (colors.find(colorType) != colors.end()) { - if (command.ArgC() == 1) { - Warning("\"%s\" = %i %i %i %i\n", colors[colorType].command->GetName(), colors[colorType].color.r(), colors[colorType].color.g(), colors[colorType].color.b(), colors[colorType].color.a()); - Msg(" - %s\n", colors[colorType].command->GetHelpText()); - - return; - } - else if (command.ArgC() >= 5 && IsInteger(command.Arg(1)) && IsInteger(command.Arg(2)) && IsInteger(command.Arg(3)) && IsInteger(command.Arg(4))) - { - colors[colorType].color.SetColor(ColorRangeRestrict(std::stoi(command.Arg(1))), ColorRangeRestrict(std::stoi(command.Arg(2))), ColorRangeRestrict(std::stoi(command.Arg(3))), ColorRangeRestrict(std::stoi(command.Arg(4)))); - - return; - } - else if (command.ArgC() >= 4 && IsInteger(command.Arg(1)) && IsInteger(command.Arg(2)) && IsInteger(command.Arg(3))) - { - colors[colorType].color.SetColor(ColorRangeRestrict(std::stoi(command.Arg(1))), ColorRangeRestrict(std::stoi(command.Arg(2))), ColorRangeRestrict(std::stoi(command.Arg(3))), 255); - - return; - } - else { - Warning("Usage: %s [alpha]\n", command.Arg(0)); - - return; - } - } - } - - Warning("Unrecognized command!\n"); -} - -int PlayerOutlines::GetCurrentColor(const char *partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH]) { - std::stringstream ss(partial); - std::string command; - std::getline(ss, command, ' '); - - if (command.compare(0, 32, "statusspec_playeroutlines_color_") == 0) { - std::string colorType = command.substr(32); - - if (colors.find(colorType) != colors.end()) { - V_snprintf(commands[0], sizeof(commands[0]), "%s %i %i %i %i", command.c_str(), colors[colorType].color.r(), colors[colorType].color.g(), colors[colorType].color.b(), colors[colorType].color.a()); - - return 1; - } - } - - return 0; -} - -void PlayerOutlines::ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue) { - if (enabled->GetBool()) { - if (!doPostScreenSpaceEffectsHook) { - try { - doPostScreenSpaceEffectsHook = Funcs::AddHook_IClientMode_DoPostScreenSpaceEffects(Interfaces::GetClientMode(), SH_MEMBER(this, &PlayerOutlines::DoPostScreenSpaceEffectsHook), false); - } - catch (bad_pointer &e) { - Warning("%s\n", e.what()); - } - } - if (!frameHook) { - frameHook = Funcs::AddHook_IBaseClientDLL_FrameStageNotify(Interfaces::pClientDLL, SH_MEMBER(this, &PlayerOutlines::FrameHook), true); - } - } - else { - for (auto iterator = glows.begin(); iterator != glows.end(); ++iterator) { - delete iterator->second; - } - - glows.clear(); - - if (doPostScreenSpaceEffectsHook) { - if (Funcs::RemoveHook(doPostScreenSpaceEffectsHook)) { - doPostScreenSpaceEffectsHook = 0; - } - } - if (frameHook) { - if (Funcs::RemoveHook(frameHook)) { - frameHook = 0; - } - } - } -} \ No newline at end of file diff --git a/src/modules/playeroutlines.h b/src/modules/playeroutlines.h deleted file mode 100644 index 3dd6ef0..0000000 --- a/src/modules/playeroutlines.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * playeroutlines.h - * StatusSpec project - * - * Copyright (c) 2014 thesupremecommander - * BSD 2-Clause License - * http://opensource.org/licenses/BSD-2-Clause - * - */ - -#pragma once - -#include "../common.h" -#include "../glows.h" -#include "../modules.h" -#include "../player.h" - -class PlayerOutlines : public Module { -public: - PlayerOutlines(std::string name); - - static bool CheckDependencies(std::string name); - - bool DoPostScreenSpaceEffectsHook(const CViewSetup *pSetup); - void FrameHook(ClientFrameStage_t curStage); -private: - std::map colors; - int doPostScreenSpaceEffectsHook; - int frameHook; - std::map glows; - GlowManager glowManager; - - Color GetGlowColor(Player player); - void SetGlowEffect(IClientEntity *entity, bool enabled, Vector color = Vector(1.0f, 1.0f, 1.0f), float alpha = 1.0f); - - ConVar *enabled; - ConVar *fade; - ConVar *fade_distance; - ConVar *health_adjusted_team_colors; - ConVar *team_colors; - void ColorCommand(const CCommand &command); - int GetCurrentColor(const char *partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH]); - void ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue); - void ToggleFade(IConVar *var, const char *pOldValue, float flOldValue); -}; \ No newline at end of file diff --git a/src/modules/projectileoutlines.cpp b/src/modules/projectileoutlines.cpp index dc67d17..b0284de 100644 --- a/src/modules/projectileoutlines.cpp +++ b/src/modules/projectileoutlines.cpp @@ -2,7 +2,7 @@ * projectileoutlines.cpp * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -10,25 +10,42 @@ #include "projectileoutlines.h" +#include "cbase.h" +#include "c_baseentity.h" +#include "vgui/IVGui.h" +#include "vgui_controls/Panel.h" +#include "view_shared.h" + #include "../common.h" #include "../entities.h" #include "../funcs.h" #include "../ifaces.h" #include "../tfdefs.h" -#include "cbase.h" -#include "c_baseentity.h" -#include "view_shared.h" +class ProjectileOutlines::Panel : public vgui::Panel { +public: + Panel(vgui::Panel *parent, const char *panelName, std::function updateFunction, std::function updateFadesFunction); + + virtual void OnTick(); + + GlowManager *GetGlowManager(); +private: + bool DoPostScreenSpaceEffectsHook(const CViewSetup *pSetup); -ProjectileOutlines::ProjectileOutlines(std::string name) : Module(name) { + int doPostScreenSpaceEffectsHook; + GlowManager glowManager; + std::function updateGlowFades; + std::function updateGlows; +}; + +ProjectileOutlines::ProjectileOutlines() { colors["blu"].color = Color(88, 133, 162, 255); - colors["blu"].command = new ConCommand("statusspec_projectileoutlines_color_blu", [](const CCommand &command) { g_ModuleManager->GetModule("Projectile Outlines")->ColorCommand(command); }, "the color used for outlines for BLU projectiles", FCVAR_NONE, [](const char *partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])->int { return g_ModuleManager->GetModule("Projectile Outlines")->GetCurrentColor(partial, commands); }); + colors["blu"].command = new ConCommand("statusspec_projectileoutlines_color_blu", [](const CCommand &command) { g_ModuleManager->GetModule()->ColorCommand(command); }, "the color used for outlines for BLU projectiles", FCVAR_NONE, [](const char *partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])->int { return g_ModuleManager->GetModule()->GetCurrentColor(partial, commands); }); colors["red"].color = Color(184, 56, 59, 255); - colors["red"].command = new ConCommand("statusspec_projectileoutlines_color_red", [](const CCommand &command) { g_ModuleManager->GetModule("Projectile Outlines")->ColorCommand(command); }, "the color used for outlines for RED projectiles", FCVAR_NONE, [](const char *partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])->int { return g_ModuleManager->GetModule("Projectile Outlines")->GetCurrentColor(partial, commands); }); - doPostScreenSpaceEffectsHook = 0; - frameHook = 0; + colors["red"].command = new ConCommand("statusspec_projectileoutlines_color_red", [](const CCommand &command) { g_ModuleManager->GetModule()->ColorCommand(command); }, "the color used for outlines for RED projectiles", FCVAR_NONE, [](const char *partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])->int { return g_ModuleManager->GetModule()->GetCurrentColor(partial, commands); }); + panel = nullptr; - enabled = new ConVar("statusspec_projectileoutlines_enabled", "0", FCVAR_NONE, "enable projectile outlines", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule("Projectile Outlines")->ToggleEnabled(var, pOldValue, flOldValue); }); + enabled = new ConVar("statusspec_projectileoutlines_enabled", "0", FCVAR_NONE, "enable projectile outlines", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule()->ToggleEnabled(var, pOldValue, flOldValue); }); fade = new ConVar("statusspec_projectileoutlines_fade", "0", FCVAR_NONE, "make outlines fade with distance"); fade_distance = new ConVar("statusspec_projectileoutlines_fade_distance", "1600", FCVAR_NONE, "the distance (in Hammer units) at which outlines will fade"); grenades = new ConVar("statusspec_projectileoutlines_grenades", "0", FCVAR_NONE, "enable outlines for grenades"); @@ -36,33 +53,33 @@ ProjectileOutlines::ProjectileOutlines(std::string name) : Module(name) { stickybombs = new ConVar("statusspec_projectileoutlines_stickybombs", "0", FCVAR_NONE, "enable outlines for stickybombs"); } -bool ProjectileOutlines::CheckDependencies(std::string name) { +bool ProjectileOutlines::CheckDependencies() { bool ready = true; if (!Interfaces::pClientDLL) { PRINT_TAG(); - Warning("Required interface IBaseClientDLL for module %s not available!\n", name.c_str()); + Warning("Required interface IBaseClientDLL for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Interfaces::pClientEntityList) { PRINT_TAG(); - Warning("Required interface IClientEntityList for module %s not available!\n", name.c_str()); + Warning("Required interface IClientEntityList for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Entities::RetrieveClassPropOffset("CTFGrenadePipebombProjectile", { "m_iType" })) { PRINT_TAG(); - Warning("Required property m_iType for CTFGrenadePipebombProjectile for module %s not available!\n", name.c_str()); + Warning("Required property m_iType for CTFGrenadePipebombProjectile for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!GlowManager::CheckDependencies()) { PRINT_TAG(); - Warning("Required glow manager for module %s not available!\n", name.c_str()); + Warning("Required glow manager for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } @@ -72,47 +89,58 @@ bool ProjectileOutlines::CheckDependencies(std::string name) { } catch (bad_pointer) { PRINT_TAG(); - Warning("Module %s requires IClientMode, which cannot be verified at this time!\n", name.c_str()); + Warning("Module %s requires IClientMode, which cannot be verified at this time!\n", g_ModuleManager->GetModuleName().c_str()); } return ready; } -bool ProjectileOutlines::DoPostScreenSpaceEffectsHook(const CViewSetup *pSetup) { +void ProjectileOutlines::UpdateGlowFades(Vector origin) { if (fade->GetBool()) { - for (auto iterator = glows.begin(); iterator != glows.end(); ++iterator) { - if (iterator->first.Get()) { - vec_t distance = pSetup->origin.DistTo(iterator->first->GetRenderOrigin()); + for (auto iterator : glows) { + if (iterator.first.Get()) { + vec_t distance = origin.DistTo(iterator.first->GetRenderOrigin()); if (distance > fade_distance->GetFloat()) { - Color glowColor = GetGlowColor(iterator->first); + Color glowColor = GetGlowColor(iterator.first); float alpha = glowColor.a() / 255.0f; float scalar = fade_distance->GetFloat() / distance; - iterator->second->SetAlpha(alpha * scalar); + iterator.second->SetAlpha(alpha * scalar); } } } } +} - glowManager.RenderGlowEffects(pSetup); +void ProjectileOutlines::UpdateGlows() { + int maxEntity = Interfaces::pClientEntityList->GetHighestEntityIndex(); - RETURN_META_VALUE(MRES_IGNORED, false); -} + for (int i = 0; i < maxEntity; i++) { + IClientEntity *entity = Interfaces::pClientEntityList->GetClientEntity(i); -void ProjectileOutlines::FrameHook(ClientFrameStage_t curStage) { - if (curStage == FRAME_NET_UPDATE_END) { - int maxEntity = Interfaces::pClientEntityList->GetHighestEntityIndex(); + if (!entity) { + continue; + } - for (int i = 0; i < maxEntity; i++) { - IClientEntity *entity = Interfaces::pClientEntityList->GetClientEntity(i); + if (rockets->GetBool() && Entities::CheckEntityBaseclass(entity, "TFProjectile_Rocket")) { + Color glowColor = GetGlowColor(entity); - if (!entity) { - continue; - } + float red = glowColor.r() / 255.0f; + float green = glowColor.g() / 255.0f; + float blue = glowColor.b() / 255.0f; + float alpha = glowColor.a() / 255.0f; + + SetGlowEffect(entity, true, Vector(red, green, blue), alpha); - if (rockets->GetBool() && Entities::CheckEntityBaseclass(entity, "TFProjectile_Rocket")) { + continue; + } + + if (Entities::CheckEntityBaseclass(entity, "TFProjectile_Pipebomb")) { + int type = *Entities::GetEntityProp(entity, { "m_iType" }); + + if (type == TFGrenadePipebombType_Grenade && grenades->GetBool()) { Color glowColor = GetGlowColor(entity); float red = glowColor.r() / 255.0f; @@ -124,51 +152,22 @@ void ProjectileOutlines::FrameHook(ClientFrameStage_t curStage) { continue; } + else if (type == TFGrenadePipebombType_Stickybomb && stickybombs->GetBool()) { + Color glowColor = GetGlowColor(entity); - if (Entities::CheckEntityBaseclass(entity, "TFGrenadePipebombProjectile")) { - int type = *Entities::GetEntityProp(entity, { "m_iType" }); - - if (type == TFGrenadePipebombType_Grenade && grenades->GetBool()) { - Color glowColor = GetGlowColor(entity); - - float red = glowColor.r() / 255.0f; - float green = glowColor.g() / 255.0f; - float blue = glowColor.b() / 255.0f; - float alpha = glowColor.a() / 255.0f; - - SetGlowEffect(entity, true, Vector(red, green, blue), alpha); - - continue; - } - else if (type == TFGrenadePipebombType_Stickybomb && stickybombs->GetBool()) { - Color glowColor = GetGlowColor(entity); - - float red = glowColor.r() / 255.0f; - float green = glowColor.g() / 255.0f; - float blue = glowColor.b() / 255.0f; - float alpha = glowColor.a() / 255.0f; - - SetGlowEffect(entity, true, Vector(red, green, blue), alpha); + float red = glowColor.r() / 255.0f; + float green = glowColor.g() / 255.0f; + float blue = glowColor.b() / 255.0f; + float alpha = glowColor.a() / 255.0f; - continue; - } - } + SetGlowEffect(entity, true, Vector(red, green, blue), alpha); - SetGlowEffect(entity, false); - } - } - else if (curStage == FRAME_START) { - if (!doPostScreenSpaceEffectsHook) { - try { - doPostScreenSpaceEffectsHook = Funcs::AddHook_IClientMode_DoPostScreenSpaceEffects(Interfaces::GetClientMode(), SH_MEMBER(this, &ProjectileOutlines::DoPostScreenSpaceEffectsHook), false); - } - catch (bad_pointer &e) { - Warning("%s\n", e.what()); + continue; } } - } - RETURN_META(MRES_IGNORED); + SetGlowEffect(entity, false); + } } Color ProjectileOutlines::GetGlowColor(IClientEntity *entity) { @@ -200,7 +199,7 @@ void ProjectileOutlines::SetGlowEffect(IClientEntity *entity, bool enabled, Vect if (enabled) { if (glows.find(entityHandle) == glows.end()) { - glows[entityHandle] = new GlowManager::GlowObject(&glowManager, entityHandle.Get(), color, alpha, true, true); + glows[entityHandle] = new GlowManager::GlowObject(panel->GetGlowManager(), entityHandle.Get(), color, alpha, true, true); } else { glows[entityHandle]->SetColor(color); @@ -216,9 +215,9 @@ void ProjectileOutlines::SetGlowEffect(IClientEntity *entity, bool enabled, Vect } void ProjectileOutlines::ColorCommand(const CCommand &command) { - if (strncmp(command.Arg(0), "statusspec_projectileoutlines_color_", 32) == 0) { + if (strncmp(command.Arg(0), "statusspec_projectileoutlines_color_", 36) == 0) { std::string mainCommand = command.Arg(0); - std::string colorType = mainCommand.substr(32); + std::string colorType = mainCommand.substr(36); if (colors.find(colorType) != colors.end()) { if (command.ArgC() == 1) { @@ -255,8 +254,8 @@ int ProjectileOutlines::GetCurrentColor(const char *partial, char commands[COMMA std::string command; std::getline(ss, command, ' '); - if (command.compare(0, 32, "statusspec_projectileoutlines_color_") == 0) { - std::string colorType = command.substr(32); + if (command.compare(0, 36, "statusspec_projectileoutlines_color_") == 0) { + std::string colorType = command.substr(36); if (colors.find(colorType) != colors.end()) { V_snprintf(commands[0], sizeof(commands[0]), "%s %i %i %i %i", command.c_str(), colors[colorType].color.r(), colors[colorType].color.g(), colors[colorType].color.b(), colors[colorType].color.a()); @@ -270,28 +269,58 @@ int ProjectileOutlines::GetCurrentColor(const char *partial, char commands[COMMA void ProjectileOutlines::ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue) { if (enabled->GetBool()) { - if (!doPostScreenSpaceEffectsHook) { - try { - doPostScreenSpaceEffectsHook = Funcs::AddHook_IClientMode_DoPostScreenSpaceEffects(Interfaces::GetClientMode(), SH_MEMBER(this, &ProjectileOutlines::DoPostScreenSpaceEffectsHook), false); - } - catch (bad_pointer &e) { - Warning("%s\n", e.what()); - } + if (!panel) { + panel = new Panel(nullptr, "ProjectileOutlines", std::bind(&ProjectileOutlines::UpdateGlows, this), std::bind(&ProjectileOutlines::UpdateGlowFades, this, std::placeholders::_1)); } - if (!frameHook) { - frameHook = Funcs::AddHook_IBaseClientDLL_FrameStageNotify(Interfaces::pClientDLL, SH_MEMBER(this, &ProjectileOutlines::FrameHook), true); + + if (panel) { + panel->SetEnabled(true); } } else { - if (doPostScreenSpaceEffectsHook) { - if (Funcs::RemoveHook(doPostScreenSpaceEffectsHook)) { - doPostScreenSpaceEffectsHook = 0; - } + if (panel) { + delete panel; + panel = nullptr; } - if (frameHook) { - if (Funcs::RemoveHook(frameHook)) { - frameHook = 0; - } + } +} + +ProjectileOutlines::Panel::Panel(vgui::Panel *parent, const char *panelName, std::function updateFunction, std::function updateFadesFunction) : vgui::Panel(parent, panelName) { + g_pVGui->AddTickSignal(GetVPanel()); + + try { + doPostScreenSpaceEffectsHook = Funcs::AddHook_IClientMode_DoPostScreenSpaceEffects(Interfaces::GetClientMode(), SH_MEMBER(this, &ProjectileOutlines::Panel::DoPostScreenSpaceEffectsHook), false); + } + catch (bad_pointer &e) { + Warning("%s\n", e.what()); + doPostScreenSpaceEffectsHook = 0; + } + + updateGlows = updateFunction; + updateGlowFades = updateFadesFunction; +} + +void ProjectileOutlines::Panel::OnTick() { + if (!doPostScreenSpaceEffectsHook) { + try { + doPostScreenSpaceEffectsHook = Funcs::AddHook_IClientMode_DoPostScreenSpaceEffects(Interfaces::GetClientMode(), SH_MEMBER(this, &ProjectileOutlines::Panel::DoPostScreenSpaceEffectsHook), false); + } + catch (bad_pointer &e) { + Warning("%s\n", e.what()); } } + + updateGlows(); +} + +GlowManager *ProjectileOutlines::Panel::GetGlowManager() { + return &glowManager; +} + +bool ProjectileOutlines::Panel::DoPostScreenSpaceEffectsHook(const CViewSetup *pSetup) { + updateGlowFades(pSetup->origin); + + glowManager.RenderGlowEffects(pSetup); + + RETURN_META_VALUE(MRES_IGNORED, false); } \ No newline at end of file diff --git a/src/modules/projectileoutlines.h b/src/modules/projectileoutlines.h index df7c2a6..7f7ac6f 100644 --- a/src/modules/projectileoutlines.h +++ b/src/modules/projectileoutlines.h @@ -2,7 +2,7 @@ * projectileoutlines.h * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -19,18 +19,23 @@ class ProjectileOutlines : public Module { public: - ProjectileOutlines(std::string name); + ProjectileOutlines(); - static bool CheckDependencies(std::string name); - - bool DoPostScreenSpaceEffectsHook(const CViewSetup *pSetup); - void FrameHook(ClientFrameStage_t curStage); + static bool CheckDependencies(); private: + void UpdateGlowFades(Vector origin); + void UpdateGlows(); + + struct ColorConCommand { + Color color; + ConCommand *command; + }; + std::map colors; - int doPostScreenSpaceEffectsHook; - int frameHook; std::map glows; - GlowManager glowManager; + + class Panel; + Panel *panel; Color GetGlowColor(IClientEntity *entity); void SetGlowEffect(IClientEntity *entity, bool enabled, Vector color = Vector(1.0f, 1.0f, 1.0f), float alpha = 1.0f); diff --git a/src/modules/specguiorder.cpp b/src/modules/specguiorder.cpp deleted file mode 100644 index 8cda723..0000000 --- a/src/modules/specguiorder.cpp +++ /dev/null @@ -1,202 +0,0 @@ -/* - * specguiorder.cpp - * StatusSpec project - * - * Copyright (c) 2014 thesupremecommander - * BSD 2-Clause License - * http://opensource.org/licenses/BSD-2-Clause - * - */ - -#include "specguiorder.h" - -#include "convar.h" -#include "filesystem.h" -#include "KeyValues.h" -#include "tier3/tier3.h" -#include "vgui/IPanel.h" -#include "vgui_controls/EditablePanel.h" - -#include "../common.h" -#include "../funcs.h" -#include "../ifaces.h" - -SpecGUIOrder::SpecGUIOrder(std::string name) : Module(name) { - frameHook = 0; - setPosHook = 0; - specguiSettings = new KeyValues("Resource/UI/SpectatorTournament.res"); - specguiSettings->LoadFromFile(Interfaces::pFileSystem, "resource/ui/spectatortournament.res", "mod"); - - enabled = new ConVar("statusspec_specguiorder_enabled", "0", FCVAR_NONE, "enable ordering of spec GUI", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule("Spec GUI Order")->ToggleEnabled(var, pOldValue, flOldValue); }); - reverse_blu = new ConVar("statusspec_specguiorder_reverse_blu", "0", FCVAR_NONE, "reverse order for BLU players"); - reverse_red = new ConVar("statusspec_specguiorder_reverse_red", "0", FCVAR_NONE, "reverse order for RED players"); -} - -bool SpecGUIOrder::CheckDependencies(std::string name) { - bool ready = true; - - if (!Interfaces::pClientDLL) { - PRINT_TAG(); - Warning("Required interface IBaseClientDLL for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!Interfaces::pFileSystem) { - PRINT_TAG(); - Warning("Required interface IFileSystem for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!g_pVGuiPanel) { - PRINT_TAG(); - Warning("Required interface vgui::IPanel for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!g_pVGuiSchemeManager) { - PRINT_TAG(); - Warning("Required interface vgui::ISchemeManager for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!Player::CheckDependencies()) { - PRINT_TAG(); - Warning("Required player helper class for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!Player::comparisonAvailable) { - PRINT_TAG(); - Warning("Required player comparison for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!Player::nameRetrievalAvailable) { - PRINT_TAG(); - Warning("Required player name retrieval for module %s not available!\n", name.c_str()); - - ready = false; - } - - return ready; -} - -void SpecGUIOrder::FrameHook(ClientFrameStage_t curStage) { - if (curStage == FRAME_NET_UPDATE_END) { - bluPlayers.clear(); - redPlayers.clear(); - - for (auto iterator = Player::begin(); iterator != Player::end(); ++iterator) { - Player player = *iterator; - - TFTeam team = player.GetTeam(); - - if (team == TFTeam_Red) { - redPlayers.insert(player); - } - else if (team == TFTeam_Blue) { - bluPlayers.insert(player); - } - } - } - - RETURN_META(MRES_IGNORED); -} - -void SpecGUIOrder::SetPosOverride(vgui::VPANEL vguiPanel, int x, int y) { - if (strcmp(g_pVGuiPanel->GetClassName(vguiPanel), "CTFPlayerPanel") == 0) { - vgui::EditablePanel *panel = dynamic_cast(g_pVGuiPanel->GetPanel(vguiPanel, "ClientDLL")); - - if (panel) { - KeyValues *dialogVariables = panel->GetDialogVariables(); - - if (dialogVariables) { - const char *name = dialogVariables->GetString("playername"); - - for (auto iterator = Player::begin(); iterator != Player::end(); ++iterator) { - Player player = *iterator; - - if (player.GetName().compare(name) == 0) { - TFTeam team = player.GetTeam(); - - if (team == TFTeam_Red) { - int position; - - if (!reverse_red->GetBool()) { - position = std::distance(redPlayers.begin(), std::find(redPlayers.begin(), redPlayers.end(), player)); - } - else { - position = std::distance(redPlayers.rbegin(), std::find(redPlayers.rbegin(), redPlayers.rend(), player)); - } - - int baseX = g_pVGuiSchemeManager->GetProportionalScaledValue(specguiSettings->FindKey("specgui")->GetInt("team2_player_base_offset_x")); - int baseY = g_pVGuiSchemeManager->GetProportionalScaledValue(specguiSettings->FindKey("specgui")->GetInt("team2_player_base_y")); - int deltaX = g_pVGuiSchemeManager->GetProportionalScaledValue(specguiSettings->FindKey("specgui")->GetInt("team2_player_delta_x")); - int deltaY = g_pVGuiSchemeManager->GetProportionalScaledValue(specguiSettings->FindKey("specgui")->GetInt("team2_player_delta_y")); - - int newX = baseX + (position * deltaX); - int newY = baseY + (position * deltaY); - - RETURN_META_NEWPARAMS(MRES_HANDLED, &vgui::IPanel::SetPos, (vguiPanel, newX, newY)); - } - else if (team == TFTeam_Blue) { - int position; - - if (!reverse_blu->GetBool()) { - position = std::distance(bluPlayers.begin(), std::find(bluPlayers.begin(), bluPlayers.end(), player)); - } - else { - position = std::distance(bluPlayers.rbegin(), std::find(bluPlayers.rbegin(), bluPlayers.rend(), player)); - } - - int baseX = g_pVGuiSchemeManager->GetProportionalScaledValue(specguiSettings->FindKey("specgui")->GetInt("team1_player_base_offset_x")); - int baseY = g_pVGuiSchemeManager->GetProportionalScaledValue(specguiSettings->FindKey("specgui")->GetInt("team1_player_base_y")); - int deltaX = g_pVGuiSchemeManager->GetProportionalScaledValue(specguiSettings->FindKey("specgui")->GetInt("team1_player_delta_x")); - int deltaY = g_pVGuiSchemeManager->GetProportionalScaledValue(specguiSettings->FindKey("specgui")->GetInt("team1_player_delta_y")); - - int newX = baseX + (position * deltaX); - int newY = baseY + (position * deltaY); - - RETURN_META_NEWPARAMS(MRES_HANDLED, &vgui::IPanel::SetPos, (vguiPanel, newX, newY)); - } - - break; - } - } - } - } - } - - RETURN_META(MRES_IGNORED); -} - -void SpecGUIOrder::ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue) { - if (enabled->GetBool()) { - if (!frameHook) { - frameHook = Funcs::AddHook_IBaseClientDLL_FrameStageNotify(Interfaces::pClientDLL, SH_MEMBER(this, &SpecGUIOrder::FrameHook), true); - } - - if (!setPosHook) { - setPosHook = Funcs::AddHook_IPanel_SetPos(g_pVGuiPanel, SH_MEMBER(this, &SpecGUIOrder::SetPosOverride), false); - } - } - else { - if (frameHook) { - if (Funcs::RemoveHook(frameHook)) { - frameHook = 0; - } - } - - if (setPosHook) { - if (Funcs::RemoveHook(setPosHook)) { - setPosHook = 0; - } - } - } -} \ No newline at end of file diff --git a/src/modules/specguiorder.h b/src/modules/specguiorder.h deleted file mode 100644 index bc98965..0000000 --- a/src/modules/specguiorder.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * specguiorder.h - * StatusSpec project - * - * Copyright (c) 2014 thesupremecommander - * BSD 2-Clause License - * http://opensource.org/licenses/BSD-2-Clause - * - */ - -#pragma once - -#include - -#include "cdll_int.h" -#include "vgui/VGUI.h" - -#include "../modules.h" -#include "../player.h" - -class ConVar; -class IConVar; -class KeyValues; - -class SpecGUIOrder : public Module { -public: - SpecGUIOrder(std::string name); - - static bool CheckDependencies(std::string name); - - void FrameHook(ClientFrameStage_t curStage); - void SetPosOverride(vgui::VPANEL vguiPanel, int x, int y); -private: - std::set bluPlayers; - int frameHook; - int setPosHook; - KeyValues *specguiSettings; - std::set redPlayers; - - ConVar *enabled; - ConVar *reverse_blu; - ConVar *reverse_red; - void ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue); -}; \ No newline at end of file diff --git a/src/modules/statusicons.cpp b/src/modules/statusicons.cpp deleted file mode 100644 index cb83b7b..0000000 --- a/src/modules/statusicons.cpp +++ /dev/null @@ -1,379 +0,0 @@ -/* - * statusicons.cpp - * StatusSpec project - * - * Copyright (c) 2014 thesupremecommander - * BSD 2-Clause License - * http://opensource.org/licenses/BSD-2-Clause - * - */ - -#include "statusicons.h" - -#include "convar.h" -#include "iclientmode.h" -#include "KeyValues.h" -#include "tier3/tier3.h" -#include "vgui/IPanel.h" -#include "vgui_controls/EditablePanel.h" -#include "vgui_controls/ImagePanel.h" -#include "vgui_controls/Panel.h" - -#include "../common.h" -#include "../funcs.h" -#include "../ifaces.h" -#include "../player.h" - -StatusIcons::StatusIcons(std::string name) : Module(name) { - frameHook = 0; - - delta_x = new ConVar("statusspec_statusicons_delta_x", "15", FCVAR_NONE, "change in the x direction for each icon"); - delta_y = new ConVar("statusspec_statusicons_delta_y", "0", FCVAR_NONE, "change in the y direction for each icon"); - enabled = new ConVar("statusspec_statusicons_enabled", "0", FCVAR_NONE, "enable status icons", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule("Status Icons")->ToggleEnabled(var, pOldValue, flOldValue); }); -} - -bool StatusIcons::CheckDependencies(std::string name) { - bool ready = true; - - if (!Interfaces::pClientDLL) { - PRINT_TAG(); - Warning("Required interface IBaseClientDLL for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!Interfaces::vguiLibrariesAvailable) { - PRINT_TAG(); - Warning("Required VGUI library for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!g_pVGui) { - PRINT_TAG(); - Warning("Required interface vgui::IVGui for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!g_pVGuiPanel) { - PRINT_TAG(); - Warning("Required interface vgui::IPanel for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!g_pVGuiSchemeManager) { - PRINT_TAG(); - Warning("Required interface vgui::ISchemeManager for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!Player::CheckDependencies()) { - PRINT_TAG(); - Warning("Required player helper class for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!Player::conditionsRetrievalAvailable) { - PRINT_TAG(); - Warning("Required player condition retrieval for module %s not available!\n", name.c_str()); - - ready = false; - } - - if (!Player::nameRetrievalAvailable) { - PRINT_TAG(); - Warning("Required player name retrieval for module %s not available!\n", name.c_str()); - - ready = false; - } - - try { - Interfaces::GetClientMode(); - } - catch (bad_pointer) { - PRINT_TAG(); - Warning("Module %s requires IClientMode, which cannot be verified at this time!\n", name.c_str()); - } - - return ready; -} - -void StatusIcons::FrameHook(ClientFrameStage_t curStage) { - if (curStage == FRAME_NET_UPDATE_END) { - if (Interfaces::GetClientMode() && Interfaces::GetClientMode()->GetViewport()) { - vgui::VPANEL viewport = Interfaces::GetClientMode()->GetViewport()->GetVPanel(); - - for (int i = 0; i < g_pVGuiPanel->GetChildCount(viewport); i++) { - vgui::VPANEL specgui = g_pVGuiPanel->GetChild(viewport, i); - - if (strcmp(g_pVGuiPanel->GetName(specgui), "specgui") == 0) { - for (int i = 0; i < g_pVGuiPanel->GetChildCount(specgui); i++) { - vgui::VPANEL playerPanel = g_pVGuiPanel->GetChild(specgui, i); - - if (strcmp(g_pVGuiPanel->GetClassName(playerPanel), "CTFPlayerPanel") == 0) { - for (int i = 0; i < g_pVGuiPanel->GetChildCount(playerPanel); i++) { - vgui::VPANEL statusIconsVPanel = g_pVGuiPanel->GetChild(playerPanel, i); - - if (strcmp(g_pVGuiPanel->GetName(statusIconsVPanel), "StatusIcons") == 0) { - vgui::EditablePanel *statusIcons = dynamic_cast(g_pVGuiPanel->GetPanel(statusIconsVPanel, "ClientDLL")); - - if (statusIcons) { - statusIcons->SetEnabled(true); - statusIcons->SetVisible(true); - - DisplayIcons(playerPanel); - } - - break; - } - } - } - } - - break; - } - } - } - } -} - -void StatusIcons::ClearIcons(vgui::VPANEL statusIconsPanel) { - while (g_pVGuiPanel->GetChildCount(statusIconsPanel) != 0) { - vgui::VPANEL child = g_pVGuiPanel->GetChild(statusIconsPanel, 0); - g_pVGuiPanel->DeletePanel(child); - } -} - -void StatusIcons::DisableHUD() { - if (Interfaces::GetClientMode() && Interfaces::GetClientMode()->GetViewport()) { - vgui::VPANEL viewport = Interfaces::GetClientMode()->GetViewport()->GetVPanel(); - - for (int i = 0; i < g_pVGuiPanel->GetChildCount(viewport); i++) { - vgui::VPANEL specgui = g_pVGuiPanel->GetChild(viewport, i); - - if (strcmp(g_pVGuiPanel->GetName(specgui), "specgui") == 0) { - for (int i = 0; i < g_pVGuiPanel->GetChildCount(specgui); i++) { - vgui::VPANEL playerPanel = g_pVGuiPanel->GetChild(specgui, i); - - if (strcmp(g_pVGuiPanel->GetClassName(playerPanel), "CTFPlayerPanel") == 0) { - for (int i = 0; i < g_pVGuiPanel->GetChildCount(playerPanel); i++) { - vgui::VPANEL statusIconsVPanel = g_pVGuiPanel->GetChild(playerPanel, i); - - if (strcmp(g_pVGuiPanel->GetName(statusIconsVPanel), "StatusIcons") == 0) { - ClearIcons(statusIconsVPanel); - - break; - } - } - } - } - - break; - } - } - } -} - -void StatusIcons::DisplayIcon(vgui::EditablePanel *panel, const char *iconTexture) { - if (panel) { - int offset = panel->GetChildCount(); - - vgui::EditablePanel *iconContainer = new vgui::EditablePanel(panel, "StatusIcon"); - vgui::ImagePanel *icon = new vgui::ImagePanel(iconContainer, "StatusIconImage"); - - iconContainer->LoadControlSettings("Resource/UI/StatusIcon.res"); - - iconContainer->SetEnabled(true); - iconContainer->SetVisible(true); - - int deltaX = g_pVGuiSchemeManager->GetProportionalScaledValue(delta_x->GetInt()); - int deltaY = g_pVGuiSchemeManager->GetProportionalScaledValue(delta_y->GetInt()); - - iconContainer->SetPos(offset * deltaX, offset * deltaY); - - icon->SetEnabled(true); - icon->SetVisible(true); - - icon->SetImage(GetVGUITexturePath(iconTexture).c_str()); - } -} - -void StatusIcons::DisplayIcons(vgui::VPANEL playerPanel) { - if (strcmp(g_pVGuiPanel->GetClassName(playerPanel), "CTFPlayerPanel") == 0) { - vgui::EditablePanel *panel = dynamic_cast(g_pVGuiPanel->GetPanel(playerPanel, "ClientDLL")); - - if (panel) { - KeyValues *dialogVariables = panel->GetDialogVariables(); - - if (dialogVariables) { - const char *name = dialogVariables->GetString("playername"); - - for (auto iterator = Player::begin(); iterator != Player::end(); ++iterator) { - Player player = *iterator; - - if (player.GetName().compare(name) == 0) { - for (int i = 0; i < g_pVGuiPanel->GetChildCount(playerPanel); i++) { - vgui::VPANEL statusIconsVPanel = g_pVGuiPanel->GetChild(playerPanel, i); - - if (strcmp(g_pVGuiPanel->GetName(statusIconsVPanel), "StatusIcons") == 0) { - ClearIcons(statusIconsVPanel); - - vgui::EditablePanel *statusIcons = dynamic_cast(g_pVGuiPanel->GetPanel(statusIconsVPanel, "ClientDLL")); - - if (statusIcons) { - TFTeam team = player.GetTeam(); - - if (player.CheckCondition(TFCond_Ubercharged)) { - DisplayIcon(statusIcons, TEXTURE_UBERCHARGE); - } - - if (player.CheckCondition(TFCond_Kritzkrieged)) { - DisplayIcon(statusIcons, TEXTURE_CRITBOOST); - } - - if (player.CheckCondition(TFCond_MegaHeal)) { - if (team == TFTeam_Red) { - DisplayIcon(statusIcons, TEXTURE_MEGAHEALRED); - } - else if (team == TFTeam_Blue) { - DisplayIcon(statusIcons, TEXTURE_MEGAHEALBLU); - } - } - - if (player.CheckCondition(TFCond_UberBulletResist)) { - if (team == TFTeam_Red) { - DisplayIcon(statusIcons, TEXTURE_RESISTSHIELDRED); - DisplayIcon(statusIcons, TEXTURE_BULLETRESISTRED); - } - else if (team == TFTeam_Blue) { - DisplayIcon(statusIcons, TEXTURE_RESISTSHIELDBLU); - DisplayIcon(statusIcons, TEXTURE_BULLETRESISTBLU); - } - } - else if (player.CheckCondition(TFCond_SmallBulletResist)) { - if (team == TFTeam_Red) { - DisplayIcon(statusIcons, TEXTURE_BULLETRESISTRED); - } - else if (team == TFTeam_Blue) { - DisplayIcon(statusIcons, TEXTURE_BULLETRESISTBLU); - } - } - - if (player.CheckCondition(TFCond_UberBlastResist)) { - if (team == TFTeam_Red) { - DisplayIcon(statusIcons, TEXTURE_RESISTSHIELDRED); - DisplayIcon(statusIcons, TEXTURE_BLASTRESISTRED); - } - else if (team == TFTeam_Blue) { - DisplayIcon(statusIcons, TEXTURE_RESISTSHIELDBLU); - DisplayIcon(statusIcons, TEXTURE_BLASTRESISTBLU); - } - } - else if (player.CheckCondition(TFCond_SmallBlastResist)) { - if (team == TFTeam_Red) { - DisplayIcon(statusIcons, TEXTURE_BLASTRESISTRED); - } - else if (team == TFTeam_Blue) { - DisplayIcon(statusIcons, TEXTURE_BLASTRESISTBLU); - } - } - - if (player.CheckCondition(TFCond_UberFireResist)) { - if (team == TFTeam_Red) { - DisplayIcon(statusIcons, TEXTURE_RESISTSHIELDRED); - DisplayIcon(statusIcons, TEXTURE_FIRERESISTRED); - } - else if (team == TFTeam_Blue) { - DisplayIcon(statusIcons, TEXTURE_RESISTSHIELDBLU); - DisplayIcon(statusIcons, TEXTURE_FIRERESISTBLU); - } - } - else if (player.CheckCondition(TFCond_SmallFireResist)) { - if (team == TFTeam_Red) { - DisplayIcon(statusIcons, TEXTURE_FIRERESISTRED); - } - else if (team == TFTeam_Blue) { - DisplayIcon(statusIcons, TEXTURE_FIRERESISTBLU); - } - } - - if (player.CheckCondition(TFCond_Buffed)) { - if (team == TFTeam_Red) { - DisplayIcon(statusIcons, TEXTURE_BUFFBANNERRED); - } - else if (team == TFTeam_Blue) { - DisplayIcon(statusIcons, TEXTURE_BUFFBANNERBLU); - } - } - - if (player.CheckCondition(TFCond_DefenseBuffed)) { - if (team == TFTeam_Red) { - DisplayIcon(statusIcons, TEXTURE_BATTALIONSBACKUPRED); - } - else if (team == TFTeam_Blue) { - DisplayIcon(statusIcons, TEXTURE_BATTALIONSBACKUPBLU); - } - } - - if (player.CheckCondition(TFCond_RegenBuffed)) { - if (team == TFTeam_Red) { - DisplayIcon(statusIcons, TEXTURE_CONCHERORRED); - } - else if (team == TFTeam_Blue) { - DisplayIcon(statusIcons, TEXTURE_CONCHERORBLU); - } - } - - if (player.CheckCondition(TFCond_Jarated)) { - DisplayIcon(statusIcons, TEXTURE_JARATE); - } - - if (player.CheckCondition(TFCond_Milked)) { - DisplayIcon(statusIcons, TEXTURE_MADMILK); - } - - if (player.CheckCondition(TFCond_MarkedForDeath) || player.CheckCondition(TFCond_MarkedForDeathSilent)) { - DisplayIcon(statusIcons, TEXTURE_MARKFORDEATH); - } - - if (player.CheckCondition(TFCond_Bleeding)) { - DisplayIcon(statusIcons, TEXTURE_BLEEDING); - } - - if (player.CheckCondition(TFCond_OnFire)) { - DisplayIcon(statusIcons, TEXTURE_FIRE); - } - } - - break; - } - } - - break; - } - } - } - } - } -} - -void StatusIcons::ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue) { - if (enabled->GetBool()) { - if (!frameHook) { - frameHook = Funcs::AddHook_IBaseClientDLL_FrameStageNotify(Interfaces::pClientDLL, SH_MEMBER(this, &StatusIcons::FrameHook), true); - } - } - else { - DisableHUD(); - - if (frameHook) { - if (Funcs::RemoveHook(frameHook)) { - frameHook = 0; - } - } - } -} \ No newline at end of file diff --git a/src/modules/statusicons.h b/src/modules/statusicons.h deleted file mode 100644 index 8e57d9c..0000000 --- a/src/modules/statusicons.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * statusicons.h - * StatusSpec project - * - * Copyright (c) 2014 thesupremecommander - * BSD 2-Clause License - * http://opensource.org/licenses/BSD-2-Clause - * - */ - -#pragma once - -#include "cdll_int.h" -#include "vgui/VGUI.h" - -#include "../modules.h" - -class ConVar; -class IConVar; - -namespace vgui { - class EditablePanel; -}; - -class StatusIcons : public Module { -public: - StatusIcons(std::string name); - - static bool CheckDependencies(std::string name); - - void FrameHook(ClientFrameStage_t curStage); -private: - int frameHook; - - void ClearIcons(vgui::VPANEL statusIconsPanel); - void DisableHUD(); - void DisplayIcon(vgui::EditablePanel *panel, const char *iconTexture); - void DisplayIcons(vgui::VPANEL playerPanel); - - ConVar *delta_x; - ConVar *delta_y; - ConVar *enabled; - void ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue); -}; \ No newline at end of file diff --git a/src/modules/steamtools.cpp b/src/modules/steamtools.cpp new file mode 100644 index 0000000..c2358dd --- /dev/null +++ b/src/modules/steamtools.cpp @@ -0,0 +1,40 @@ +/* + * steamtools.cpp + * StatusSpec project + * + * Copyright (c) 2014-2015 Forward Command Post + * BSD 2-Clause License + * http://opensource.org/licenses/BSD-2-Clause + * + */ + +#include "steamtools.h" + +#include "convar.h" +#include "steam/steam_api.h" + +#include "../common.h" +#include "../funcs.h" +#include "../ifaces.h" + +SteamTools::SteamTools() { + rich_presence_status = new ConVar("statusspec_steamtools_rich_presence_status", "", FCVAR_NONE, "the rich presence status displayed to Steam", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule()->ChangeRichPresenceStatus(var, pOldValue, flOldValue); }); +} + +bool SteamTools::CheckDependencies() { + bool ready = true; + + if (!Interfaces::steamLibrariesAvailable) { + PRINT_TAG(); + Warning("Required Steam libraries for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); + + ready = false; + } + + return ready; +} + +void SteamTools::ChangeRichPresenceStatus(IConVar *var, const char *pOldValue, float flOldValue) { + Interfaces::pSteamAPIContext->SteamFriends()->ClearRichPresence(); + Interfaces::pSteamAPIContext->SteamFriends()->SetRichPresence("status", rich_presence_status->GetString()); +} \ No newline at end of file diff --git a/src/modules/steamtools.h b/src/modules/steamtools.h new file mode 100644 index 0000000..29ee0fe --- /dev/null +++ b/src/modules/steamtools.h @@ -0,0 +1,28 @@ +/* + * steamtools.h + * StatusSpec project + * + * Copyright (c) 2014-2015 Forward Command Post + * BSD 2-Clause License + * http://opensource.org/licenses/BSD-2-Clause + * + */ + +#pragma once + +#include "../modules.h" + +#include "steam/steamclientpublic.h" + +class ConVar; +class IConVar; + +class SteamTools : public Module { +public: + SteamTools(); + + static bool CheckDependencies(); +private: + ConVar *rich_presence_status; + void ChangeRichPresenceStatus(IConVar *var, const char *pOldValue, float flOldValue); +}; \ No newline at end of file diff --git a/src/modules/teamhealthcomparison.cpp b/src/modules/teamhealthcomparison.cpp index fe9921a..3e36499 100644 --- a/src/modules/teamhealthcomparison.cpp +++ b/src/modules/teamhealthcomparison.cpp @@ -2,7 +2,7 @@ * teamhealthcomparison.cpp * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -13,6 +13,7 @@ #include "cbase.h" #include "convar.h" #include "iclientmode.h" +#include "vgui/IVGui.h" #include "vgui_controls/EditablePanel.h" #include "vgui_controls/Panel.h" @@ -21,33 +22,42 @@ #include "../ifaces.h" #include "../player.h" -TeamHealthComparison::TeamHealthComparison(std::string name) : Module(name) { - frameHook = 0; +class TeamHealthComparison::Panel : public vgui::EditablePanel { +public: + Panel(vgui::Panel *parent, const char *panelName); - enabled = new ConVar("statusspec_teamhealthcomparison_enabled", "0", FCVAR_NONE, "enable team health comparison", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule("Team Health Comparison")->ToggleEnabled(var, pOldValue, flOldValue); }); - reload_settings = new ConCommand("statusspec_teamhealthcomparison_reload_settings", []() { g_ModuleManager->GetModule("Team Health Comparison")->ReloadSettings(); }, "reload settings for the team health comparison HUD from the resource file", FCVAR_NONE); + virtual void OnTick(); +private: + std::map teamHealthAggregate; +}; + +TeamHealthComparison::TeamHealthComparison() { + panel = nullptr; + + enabled = new ConVar("statusspec_teamhealthcomparison_enabled", "0", FCVAR_NONE, "enable team health comparison", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule()->ToggleEnabled(var, pOldValue, flOldValue); }); + reload_settings = new ConCommand("statusspec_teamhealthcomparison_reload_settings", []() { g_ModuleManager->GetModule()->ReloadSettings(); }, "reload settings for the team health comparison HUD from the resource file", FCVAR_NONE); } -bool TeamHealthComparison::CheckDependencies(std::string name) { +bool TeamHealthComparison::CheckDependencies() { bool ready = true; - if (!Interfaces::pClientDLL) { + if (!g_pVGui) { PRINT_TAG(); - Warning("Required interface IBaseClientDLL for module %s not available!\n", name.c_str()); + Warning("Required interface IVGui for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Interfaces::vguiLibrariesAvailable) { PRINT_TAG(); - Warning("Required VGUI library for module %s not available!\n", name.c_str()); + Warning("Required VGUI library for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } if (!Player::CheckDependencies()) { PRINT_TAG(); - Warning("Required player helper class for module %s not available!\n", name.c_str()); + Warning("Required player helper class for module %s not available!\n", g_ModuleManager->GetModuleName().c_str()); ready = false; } @@ -57,99 +67,82 @@ bool TeamHealthComparison::CheckDependencies(std::string name) { } catch (bad_pointer) { PRINT_TAG(); - Warning("Module %s requires IClientMode, which cannot be verified at this time!\n", name.c_str()); + Warning("Module %s requires IClientMode, which cannot be verified at this time!\n", g_ModuleManager->GetModuleName().c_str()); } return ready; } -void TeamHealthComparison::FrameHook(ClientFrameStage_t curStage) { - if (curStage == FRAME_NET_UPDATE_END) { - teamHealthAggregate.clear(); - - for (auto iterator = Player::begin(); iterator != Player::end(); ++iterator) { - Player player = *iterator; +void TeamHealthComparison::ReloadSettings() { + if (panel) { + panel->LoadControlSettings("Resource/UI/TeamHealthComparison.res"); + } +} - if (!player.IsAlive()) { - continue; +void TeamHealthComparison::ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue) { + if (enabled->GetBool()) { + if (!panel) { + try { + vgui::Panel *viewport = Interfaces::GetClientMode()->GetViewport(); + + if (viewport) { + panel = new Panel(viewport, "TeamHealthComparison"); + } + else { + Warning("Could not initialize the panel!\n"); + var->SetValue(0); + } + } + catch (bad_pointer) { + Warning("Could not initialize the panel!\n"); + var->SetValue(0); } - - teamHealthAggregate[player.GetTeam()] += player.GetHealth(); } - Paint(); + if (panel) { + panel->SetEnabled(true); + } } - - RETURN_META(MRES_IGNORED); -} - -void TeamHealthComparison::InitHUD() { - if (panels.find("TeamHealthComparison") == panels.end()) { - vgui::Panel *viewport = Interfaces::GetClientMode()->GetViewport(); - - if (viewport) { - vgui::EditablePanel *teamHealthComparisonPanel = new vgui::EditablePanel(viewport, "TeamHealthComparison"); - panels["TeamHealthComparison"] = teamHealthComparisonPanel; - - teamHealthComparisonPanel->LoadControlSettings("Resource/UI/TeamHealthComparison.res"); + else { + if (panel) { + delete panel; + panel = nullptr; } } } -void TeamHealthComparison::Paint() { - panels["TeamHealthComparison"]->SetVisible(true); +TeamHealthComparison::Panel::Panel(vgui::Panel *parent, const char *panelName) : vgui::EditablePanel(parent, panelName) { + g_pVGui->AddTickSignal(GetVPanel()); - if (teamHealthAggregate[TFTeam_Red] != 0 || teamHealthAggregate[TFTeam_Blue] != 0) { - panels["TeamHealthComparison"]->SetVisible(true); + LoadControlSettings("Resource/UI/TeamHealthComparison.res"); +} - int totalHealth = teamHealthAggregate[TFTeam_Red] + teamHealthAggregate[TFTeam_Blue]; +void TeamHealthComparison::Panel::OnTick() { + teamHealthAggregate.clear(); - float bluPercentage = float(teamHealthAggregate[TFTeam_Blue]) / float(totalHealth); - float redPercentage = float(teamHealthAggregate[TFTeam_Red]) / float(totalHealth); + for (Player player : Player::Iterable()) { + if (player) { + if (!player.IsAlive()) { + continue; + } - ((vgui::EditablePanel *) panels["TeamHealthComparison"])->SetDialogVariable("blupercentage", bluPercentage * 100.0f); - ((vgui::EditablePanel *) panels["TeamHealthComparison"])->SetDialogVariable("redpercentage", redPercentage * 100.0f); + teamHealthAggregate[player.GetTeam()] += player.GetHealth(); + } } - else { - panels["TeamHealthComparison"]->SetVisible(false); - ((vgui::EditablePanel *) panels["TeamHealthComparison"])->SetDialogVariable("blupercentage", 0); - ((vgui::EditablePanel *) panels["TeamHealthComparison"])->SetDialogVariable("redpercentage", 0); - } + float redPercentage = 0.0f; + float bluPercentage = 0.0f; - ((vgui::EditablePanel *) panels["TeamHealthComparison"])->SetDialogVariable("redhealth", teamHealthAggregate[TFTeam_Red]); - ((vgui::EditablePanel *) panels["TeamHealthComparison"])->SetDialogVariable("bluhealth", teamHealthAggregate[TFTeam_Blue]); -} + if (teamHealthAggregate[TFTeam_Red] != 0 || teamHealthAggregate[TFTeam_Blue] != 0) { + int totalHealth = teamHealthAggregate[TFTeam_Red] + teamHealthAggregate[TFTeam_Blue]; -void TeamHealthComparison::ReloadSettings() { - if (panels.find("TeamHealthComparison") != panels.end()) { - ((vgui::EditablePanel *) panels["TeamHealthComparison"])->LoadControlSettings("Resource/UI/TeamHealthComparison.res"); + redPercentage = (float(teamHealthAggregate[TFTeam_Red]) / float(totalHealth)) * 100.0f; + bluPercentage = (float(teamHealthAggregate[TFTeam_Blue]) / float(totalHealth)) * 100.0f; } -} -void TeamHealthComparison::ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue) { - if (enabled->GetBool()) { - InitHUD(); - - if (!frameHook) { - frameHook = Funcs::AddHook_IBaseClientDLL_FrameStageNotify(Interfaces::pClientDLL, SH_MEMBER(this, &TeamHealthComparison::FrameHook), true); - } + SetDialogVariable("redpercentage", redPercentage); + SetDialogVariable("blupercentage", bluPercentage); - if (panels.find("TeamHealthComparison") != panels.end()) { - panels["TeamHealthComparison"]->SetEnabled(true); - panels["TeamHealthComparison"]->SetVisible(true); - } - } - else { - if (frameHook) { - if (Funcs::RemoveHook(frameHook)) { - frameHook = 0; - } - } - - if (panels.find("TeamHealthComparison") != panels.end()) { - panels["TeamHealthComparison"]->SetEnabled(false); - panels["TeamHealthComparison"]->SetVisible(false); - } - } + SetDialogVariable("redhealth", teamHealthAggregate[TFTeam_Red]); + SetDialogVariable("bluhealth", teamHealthAggregate[TFTeam_Blue]); } \ No newline at end of file diff --git a/src/modules/teamhealthcomparison.h b/src/modules/teamhealthcomparison.h index 0710b49..31e2e1b 100644 --- a/src/modules/teamhealthcomparison.h +++ b/src/modules/teamhealthcomparison.h @@ -2,7 +2,7 @@ * teamhealthcomparison.h * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -25,18 +25,12 @@ namespace vgui { class TeamHealthComparison : public Module { public: - TeamHealthComparison(std::string name); + TeamHealthComparison(); - static bool CheckDependencies(std::string name); - - void FrameHook(ClientFrameStage_t curStage); + static bool CheckDependencies(); private: - int frameHook; - std::map panels; - std::map teamHealthAggregate; - - void InitHUD(); - void Paint(); + class Panel; + Panel *panel; ConVar *enabled; ConCommand *reload_settings; diff --git a/src/modules/teamoverrides.cpp b/src/modules/teamoverrides.cpp deleted file mode 100644 index 898ca54..0000000 --- a/src/modules/teamoverrides.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * teamoverrides.cpp - * StatusSpec project - * - * Copyright (c) 2014 thesupremecommander - * BSD 2-Clause License - * http://opensource.org/licenses/BSD-2-Clause - * - */ - -#include "teamoverrides.h" - -#include "cbase.h" -#include "convar.h" -#include "iclientmode.h" -#include "KeyValues.h" -#include "tier3/tier3.h" -#include "vgui_controls/EditablePanel.h" - -#include "../common.h" -#include "../funcs.h" - -TeamOverrides::TeamOverrides(std::string name) : Module(name) { - sendMessageHook = 0; - - enabled = new ConVar("statusspec_teamoverrides_enabled", "0", FCVAR_NONE, "enable team overrides", [](IConVar *var, const char *pOldValue, float flOldValue) { g_ModuleManager->GetModule("Team Overrides")->ToggleEnabled(var, pOldValue, flOldValue); }); - name_blu = new ConVar("statusspec_teamoverrides_name_blu", "BLU", FCVAR_NONE, "BLU team name"); - name_red = new ConVar("statusspec_teamoverrides_name_red", "RED", FCVAR_NONE, "RED team name"); - names = new ConVar("statusspec_teamoverrides_names", "0", FCVAR_NONE, "enable overrides for team names"); - score_blu = new ConVar("statusspec_teamoverrides_score_blu", "0", FCVAR_NONE, "BLU team score"); - score_red = new ConVar("statusspec_teamoverrides_score_red", "0", FCVAR_NONE, "RED team score"); - scores = new ConVar("statusspec_teamoverrides_scores", "0", FCVAR_NONE, "enable overrides for team scores"); - switch_teams = new ConCommand("statusspec_teamoverrides_switch_teams", []() { g_ModuleManager->GetModule("Team Overrides")->SwitchTeams(); }, "switch names and scores for both teams", FCVAR_NONE); -} - -bool TeamOverrides::CheckDependencies(std::string name) { - bool ready = true; - - if (!g_pVGuiPanel) { - PRINT_TAG(); - Warning("Required interface vgui::IPanel for module %s not available!\n", name.c_str()); - - ready = false; - } - - return ready; -} - -void TeamOverrides::SendMessageOverride(vgui::VPANEL vguiPanel, KeyValues *params, vgui::VPANEL ifromPanel) { - if (strcmp(params->GetName(), "DialogVariables") == 0) { - if (names->GetBool()) { - if (strcmp(params->GetString("blueteamname"), "") != 0) { - params->SetString("blueteamname", name_blu->GetString()); - } - - if (strcmp(params->GetString("redteamname"), "") != 0) { - params->SetString("redteamname", name_red->GetString()); - } - } - - if (scores->GetBool()) { - if (strcmp(params->GetString("blueteamscore"), "") != 0) { - params->SetInt("blueteamscore", score_blu->GetInt()); - } - - if (strcmp(params->GetString("redteamscore"), "") != 0) { - params->SetInt("redteamscore", score_red->GetInt()); - } - } - - RETURN_META(MRES_HANDLED); - } - - RETURN_META(MRES_IGNORED); -} - -void TeamOverrides::SwitchTeams() { - std::string newBluName = name_red->GetString(); - std::string newRedName = name_blu->GetString(); - int newBluScore = score_red->GetInt(); - int newRedScore = score_blu->GetInt(); - - name_blu->SetValue(newBluName.c_str()); - name_red->SetValue(newRedName.c_str()); - score_blu->SetValue(newBluScore); - score_red->SetValue(newRedScore); -} - -void TeamOverrides::ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue) { - if (enabled->GetBool()) { - if (!sendMessageHook) { - sendMessageHook = Funcs::AddHook_IPanel_SendMessage(g_pVGuiPanel, SH_MEMBER(this, &TeamOverrides::SendMessageOverride), false); - } - } - else { - if (sendMessageHook) { - if (Funcs::RemoveHook(sendMessageHook)) { - sendMessageHook = 0; - } - } - } -} \ No newline at end of file diff --git a/src/modules/teamoverrides.h b/src/modules/teamoverrides.h deleted file mode 100644 index 3e850d8..0000000 --- a/src/modules/teamoverrides.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * teamoverrides.h - * StatusSpec project - * - * Copyright (c) 2014 thesupremecommander - * BSD 2-Clause License - * http://opensource.org/licenses/BSD-2-Clause - * - */ - -#pragma once - -#include "vgui/VGUI.h" - -#include "../modules.h" - -class ConCommand; -class ConVar; -class IConVar; -class KeyValues; - -class TeamOverrides : public Module { -public: - TeamOverrides(std::string name); - - static bool CheckDependencies(std::string name); - - void SendMessageOverride(vgui::VPANEL vguiPanel, KeyValues *params, vgui::VPANEL ifromPanel); -private: - int sendMessageHook; - - ConVar *enabled; - ConVar *name_blu; - ConVar *name_red; - ConVar *names; - ConVar *score_blu; - ConVar *score_red; - ConVar *scores; - ConCommand *switch_teams; - void SwitchTeams(); - void ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue); -}; \ No newline at end of file diff --git a/src/player.cpp b/src/player.cpp index 3df254c..ec1bdfc 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -2,7 +2,7 @@ * player.cpp * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -13,12 +13,14 @@ #include #include "cbase.h" +#include "c_basecombatcharacter.h" #include "c_baseentity.h" #include "cdll_int.h" #include "globalvars_base.h" #include "icliententity.h" #include "icliententitylist.h" #include "steam/steam_api.h" +#include "toolframework/ienginetool.h" #include "common.h" #include "entities.h" @@ -218,7 +220,7 @@ Player::operator bool() const { } bool Player::IsValid() const { - return playerEntity.IsValid() && playerEntity.Get() && playerEntity->entindex() >= 1 && playerEntity->entindex() <= Interfaces::GetGlobalVars()->maxClients && Entities::CheckEntityBaseclass(playerEntity, "TFPlayer"); + return playerEntity.IsValid() && playerEntity.Get() && playerEntity->entindex() >= 1 && playerEntity->entindex() <= Interfaces::pEngineTool->GetMaxClients() && Entities::CheckEntityBaseclass(playerEntity, "TFPlayer"); } Player::operator IClientEntity *() const { @@ -376,6 +378,14 @@ int Player::GetUserID() const { return 0; } +C_BaseCombatWeapon *Player::GetWeapon(int i) const { + if (IsValid()) { + return dynamic_cast(playerEntity.Get())->GetWeapon(i); + } + + return nullptr; +} + bool Player::IsAlive() const { if (IsValid()) { return dynamic_cast(playerEntity.Get())->IsAlive(); @@ -395,7 +405,7 @@ Player::Iterator& Player::Iterator::operator=(const Player::Iterator& old) { }; Player::Iterator& Player::Iterator::operator++() { - for (int i = index + 1; i <= Interfaces::GetGlobalVars()->maxClients; i++) { + for (int i = index + 1; i <= Interfaces::pEngineTool->GetMaxClients(); i++) { if (Player(i)) { index = i; @@ -403,7 +413,7 @@ Player::Iterator& Player::Iterator::operator++() { } } - index = Interfaces::GetGlobalVars()->maxClients + 1; + index = Interfaces::pEngineTool->GetMaxClients() + 1; return *this; }; @@ -420,7 +430,7 @@ void swap(Player::Iterator& lhs, Player::Iterator& rhs) { Player::Iterator Player::Iterator::operator++(int) { Player::Iterator current(*this); - for (int i = index + 1; i <= Interfaces::GetGlobalVars()->maxClients; i++) { + for (int i = index + 1; i <= Interfaces::pEngineTool->GetMaxClients(); i++) { if (Player(i)) { index = i; @@ -428,7 +438,7 @@ Player::Iterator Player::Iterator::operator++(int) { } } - index = Interfaces::GetGlobalVars()->maxClients + 1; + index = Interfaces::pEngineTool->GetMaxClients() + 1; return current; } @@ -446,7 +456,7 @@ bool operator!=(const Player::Iterator& lhs, const Player::Iterator& rhs) { } Player::Iterator::Iterator() { - for (int i = 1; i <= Interfaces::GetGlobalVars()->maxClients; i++) { + for (int i = 1; i <= Interfaces::pEngineTool->GetMaxClients(); i++) { if (Player(i)) { index = i; @@ -454,7 +464,7 @@ Player::Iterator::Iterator() { } } - index = Interfaces::GetGlobalVars()->maxClients + 1; + index = Interfaces::pEngineTool->GetMaxClients() + 1; return; } @@ -498,7 +508,15 @@ Player::Iterator Player::begin() { } Player::Iterator Player::end() { - return Player::Iterator(Interfaces::GetGlobalVars()->maxClients + 1); + return Player::Iterator(Interfaces::pEngineTool->GetMaxClients() + 1); +} + +Player::Iterator Player::Iterable::begin() { + return Player::begin(); +} + +Player::Iterator Player::Iterable::end() { + return Player::end(); } bool Player::classRetrievalAvailable = false; @@ -518,12 +536,9 @@ bool Player::CheckDependencies() { ready = false; } - try { - Interfaces::GetGlobalVars(); - } - catch (bad_pointer) { + if (!Interfaces::pEngineTool) { PRINT_TAG(); - Warning("Required interface CGlobalVarsBase for player helper class not available!\n"); + Warning("Required interface IEngineTool for player helper class not available!\n"); ready = false; } diff --git a/src/player.h b/src/player.h index fd2eae4..48e1bf1 100644 --- a/src/player.h +++ b/src/player.h @@ -2,7 +2,7 @@ * player.h * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -12,6 +12,7 @@ #include "ehandle.h" +class C_BaseCombatWeapon; class C_BaseEntity; class CSteamID; class IClientEntity; @@ -69,6 +70,7 @@ class Player { CSteamID GetSteamID() const; TFTeam GetTeam() const; int GetUserID() const; + C_BaseCombatWeapon *GetWeapon(int i) const; bool IsAlive() const; class Iterator { @@ -97,6 +99,12 @@ class Player { static Iterator begin(); static Iterator end(); + class Iterable { + public: + Iterator begin(); + Iterator end(); + }; + static bool CheckDependencies(); static bool classRetrievalAvailable; static bool comparisonAvailable; diff --git a/src/statusspec.cpp b/src/statusspec.cpp index 50ec27c..63acfd3 100644 --- a/src/statusspec.cpp +++ b/src/statusspec.cpp @@ -2,7 +2,7 @@ * statusspec.cpp * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * @@ -18,24 +18,25 @@ #include "modules.h" #include "modules/antifreeze.h" +#include "modules/cameraautoswitch.h" +#include "modules/camerasmooths.h" +#include "modules/camerastate.h" #include "modules/cameratools.h" +#include "modules/consoletools.h" #include "modules/custommaterials.h" #include "modules/custommodels.h" #include "modules/customtextures.h" #include "modules/fovoverride.h" +#include "modules/freezeinfo.h" #include "modules/killstreaks.h" -#include "modules/loadouticons.h" #include "modules/localplayer.h" #include "modules/mediguninfo.h" #include "modules/multipanel.h" #include "modules/playeraliases.h" #include "modules/playermodels.h" -#include "modules/playeroutlines.h" #include "modules/projectileoutlines.h" -#include "modules/specguiorder.h" -#include "modules/statusicons.h" +#include "modules/steamtools.h" #include "modules/teamhealthcomparison.h" -#include "modules/teamoverrides.h" ModuleManager *g_ModuleManager = nullptr; @@ -58,25 +59,26 @@ bool StatusSpecPlugin::Load(CreateInterfaceFn interfaceFactory, CreateInterfaceF g_ModuleManager = new ModuleManager(); - g_ModuleManager->LoadModule("AntiFreeze"); - g_ModuleManager->LoadModule("Camera Tools"); - g_ModuleManager->LoadModule("Custom Materials"); - g_ModuleManager->LoadModule("Custom Models"); - g_ModuleManager->LoadModule("Custom Textures"); - g_ModuleManager->LoadModule("FOV Override"); - g_ModuleManager->LoadModule("Killstreaks"); - g_ModuleManager->LoadModule("Loadout Icons"); - g_ModuleManager->LoadModule("Local Player"); - g_ModuleManager->LoadModule("Medigun Info"); - g_ModuleManager->LoadModule("MultiPanel"); - g_ModuleManager->LoadModule("Player Aliases"); - g_ModuleManager->LoadModule("Player Models"); - g_ModuleManager->LoadModule("Player Outlines"); - g_ModuleManager->LoadModule("Projectile Outlines"); - g_ModuleManager->LoadModule("Spec GUI Order"); - g_ModuleManager->LoadModule("Status Icons"); - g_ModuleManager->LoadModule("Team Health Comparison"); - g_ModuleManager->LoadModule("Team Overrides"); + g_ModuleManager->RegisterAndLoadModule("AntiFreeze"); + g_ModuleManager->RegisterAndLoadModule("Camera Auto Switch"); + g_ModuleManager->RegisterAndLoadModule("Camera Smooths"); + g_ModuleManager->RegisterAndLoadModule("Camera State"); + g_ModuleManager->RegisterAndLoadModule("Camera Tools"); + g_ModuleManager->RegisterAndLoadModule("Console Tools"); + g_ModuleManager->RegisterAndLoadModule("Custom Materials"); + g_ModuleManager->RegisterAndLoadModule("Custom Models"); + g_ModuleManager->RegisterAndLoadModule("Custom Textures"); + g_ModuleManager->RegisterAndLoadModule("FOV Override"); + g_ModuleManager->RegisterAndLoadModule("Freeze Info"); + g_ModuleManager->RegisterAndLoadModule("Killstreaks"); + g_ModuleManager->RegisterAndLoadModule("Local Player"); + g_ModuleManager->RegisterAndLoadModule("Medigun Info"); + g_ModuleManager->RegisterAndLoadModule("MultiPanel"); + g_ModuleManager->RegisterAndLoadModule("Player Aliases"); + g_ModuleManager->RegisterAndLoadModule("Player Models"); + g_ModuleManager->RegisterAndLoadModule("Projectile Outlines"); + g_ModuleManager->RegisterAndLoadModule("Steam Tools"); + g_ModuleManager->RegisterAndLoadModule("Team Health Comparison"); ConVar_Register(); diff --git a/src/statusspec.h b/src/statusspec.h index 8f68776..7236bf4 100644 --- a/src/statusspec.h +++ b/src/statusspec.h @@ -2,7 +2,7 @@ * statusspec.h * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * diff --git a/src/tfdefs.cpp b/src/tfdefs.cpp index a2058a9..676df37 100644 --- a/src/tfdefs.cpp +++ b/src/tfdefs.cpp @@ -2,7 +2,7 @@ * tfdefs.cpp * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * diff --git a/src/tfdefs.h b/src/tfdefs.h index 613e3ea..2eebaf7 100644 --- a/src/tfdefs.h +++ b/src/tfdefs.h @@ -2,7 +2,7 @@ * tfdefs.h * StatusSpec project * - * Copyright (c) 2014 thesupremecommander + * Copyright (c) 2014-2015 Forward Command Post * BSD 2-Clause License * http://opensource.org/licenses/BSD-2-Clause * diff --git a/statusspec.vpc b/statusspec.vpc index d85c326..7efafe7 100644 --- a/statusspec.vpc +++ b/statusspec.vpc @@ -10,7 +10,7 @@ $Macro OUTBINDIR ".\addons" $Macro MMSOURCE_DEV "..\..\..\..\..\metamod-source" $Macro MINHOOK "..\..\..\..\..\minhook" $Macro MINHOOK_BUILD "$MINHOOK\build\VC12" -$Macro JSONCPP "..\..\..\..\..\jsoncpp\dist" +$Macro RAPIDJSON "..\..\..\..\..\rapidjson\include" $Include "$SRCDIR\vpc_scripts\source_dll_base.vpc" @@ -18,7 +18,7 @@ $Configuration { $Compiler { - $AdditionalIncludeDirectories "$BASE;$SRCDIR\game\client;$SRCDIR\game\shared;$SRCDIR\public;$MMSOURCE_DEV\core\sourcehook;$MINHOOK\include;$JSONCPP" + $AdditionalIncludeDirectories "$BASE;$SRCDIR\game\client;$SRCDIR\game\shared;$SRCDIR\public;$MMSOURCE_DEV\core\sourcehook;$MINHOOK\include;$RAPIDJSON" $PreprocessorDefinitions "$BASE;statusspecONLY;_MBCS;CLIENT_DLL;GLOWS_ENABLE;TF_CLIENT_DLL;TF_DLL;VERSION_SAFE_STEAM_API_INTERFACES" $TreatWarningsAsErrors "No (/WX-)" } @@ -51,30 +51,29 @@ $Project "StatusSpec" { $File "src\statusspec.cpp" $File "src\modules\antifreeze.cpp" + $File "src\modules\cameraautoswitch.cpp" + $File "src\modules\camerasmooths.cpp" + $File "src\modules\camerastate.cpp" $File "src\modules\cameratools.cpp" + $File "src\modules\consoletools.cpp" $File "src\modules\custommaterials.cpp" $File "src\modules\custommodels.cpp" $File "src\modules\customtextures.cpp" $File "src\modules\fovoverride.cpp" + $File "src\modules\freezeinfo.cpp" $File "src\modules\killstreaks.cpp" - $File "src\modules\loadouticons.cpp" $File "src\modules\localplayer.cpp" $File "src\modules\mediguninfo.cpp" $File "src\modules\multipanel.cpp" $File "src\modules\playeraliases.cpp" $File "src\modules\playermodels.cpp" - $File "src\modules\playeroutlines.cpp" $File "src\modules\projectileoutlines.cpp" - $File "src\modules\specguiorder.cpp" - $File "src\modules\statusicons.cpp" + $File "src\modules\steamtools.cpp" $File "src\modules\teamhealthcomparison.cpp" - $File "src\modules\teamoverrides.cpp" $File "src\entities.cpp" $File "src\funcs.cpp" $File "src\glows.cpp" $File "src\ifaces.cpp" - $File "src\itemschema.cpp" - $File "src\modules.cpp" $File "src\player.cpp" $File "src\tfdefs.cpp" $File "$MMSOURCE_DEV\core\sourcehook\sourcehook.cpp" @@ -83,7 +82,6 @@ $Project "StatusSpec" $File "$MMSOURCE_DEV\core\sourcehook\sourcehook_impl_chookmaninfo.cpp" $File "$MMSOURCE_DEV\core\sourcehook\sourcehook_impl_cproto.cpp" $File "$MMSOURCE_DEV\core\sourcehook\sourcehook_impl_cvfnptr.cpp" - $File "$JSONCPP\jsoncpp.cpp" $File "$SRCDIR\public\filesystem_init.cpp" $File "$SRCDIR\public\vgui_controls\vgui_controls.cpp" $File "src\vgui_controls\gameconsoledialog.cpp" @@ -95,24 +93,25 @@ $Project "StatusSpec" { $File "src\statusspec.h" $File "src\modules\antifreeze.h" + $File "src\modules\cameraautoswitch.h" + $File "src\modules\camerasmooths.h" + $File "src\modules\camerastate.h" $File "src\modules\cameratools.h" + $File "src\modules\consoletools.h" $File "src\modules\custommaterials.h" $File "src\modules\custommodels.h" $File "src\modules\customtextures.h" $File "src\modules\fovoverride.h" + $File "src\modules\freezeinfo.h" $File "src\modules\killstreaks.h" - $File "src\modules\loadouticons.h" $File "src\modules\localplayer.h" $File "src\modules\mediguninfo.h" $File "src\modules\multipanel.h" $File "src\modules\playeraliases.h" $File "src\modules\playermodels.h" - $File "src\modules\playeroutlines.h" $File "src\modules\projectileoutlines.h" - $File "src\modules\specguiorder.h" - $File "src\modules\statusicons.h" + $File "src\modules\steamtools.h" $File "src\modules\teamhealthcomparison.h" - $File "src\modules\teamoverrides.h" $File "src\common.h" $File "src\entities.h" $File "src\exceptions.h" @@ -120,7 +119,6 @@ $Project "StatusSpec" $File "src\gamedata.h" $File "src\glows.h" $File "src\ifaces.h" - $File "src\itemschema.h" $File "src\modules.h" $File "src\player.h" $File "src\tfdefs.h"