├── .editorconfig ├── .gitattributes ├── .github ├── CODE_OF_CONDUCT.md ├── FUNDING.yml ├── LICENSE ├── README.md └── workflows │ └── CI.yml ├── .gitignore └── cstrike └── addons └── amxmodx ├── configs ├── plugins-ChatAdditions.ini └── plugins │ └── ChatAdditions │ ├── CA_Addon_DeathMute.cfg │ ├── CA_Addon_RankRestrictions.cfg │ ├── CA_Addon_RequestUnGag.cfg │ ├── CA_AntiFlood.cfg │ ├── CA_Gag.cfg │ ├── CA_Mute.cfg │ ├── CA_Storage_CSBans.cfg │ ├── CA_Storage_GameCMS.cfg │ ├── CA_Storage_PGBans.cfg │ ├── ChatAdditions_core.cfg │ ├── ca_gag_chat_whitelist_cmds.cfg │ └── ca_gag_reasons.cfg ├── data └── lang │ ├── CA_Addon_DeathMute.txt │ ├── CA_Addon_RankRestrictions.txt │ ├── CA_Addon_RequestUngag.txt │ ├── CA_AntiFlood.txt │ ├── CA_Gag.txt │ └── CA_Mute.txt └── scripting ├── ChatAdditions ├── Addons │ ├── CA_Addon_DeathMute.sma │ ├── CA_Addon_RankRestrictions.sma │ ├── CA_Addon_RequestUnGag.sma │ └── CA_Addon_VoteGag.sma ├── CA_AntiFlood.sma ├── CA_Gag.sma ├── CA_Mute.sma ├── ChatAdditions_Core.sma └── Storage │ ├── CA_Storage_CSBans.sma │ ├── CA_Storage_GameCMS.sma │ ├── CA_Storage_PGBans.sma │ └── CA_Storage_SQLite.sma └── include ├── CA_GAG_API.inc ├── CA_StorageAPI.inc ├── CA_StorageAPI_endpoint.inc ├── ChatAdditions.inc ├── cellqueue.inc └── easy_http.inc /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | charset = utf-8 11 | 12 | # Set default charset 13 | [*.{sma,inc,sh}] 14 | indent_style = space 15 | indent_size = 4 16 | trim_trailing_whitespace = true 17 | 18 | [{.vscode/*,.github/*}] 19 | indent_style = space 20 | indent_size = 4 21 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | wopox1337@ya.ru 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | custom: [ 'https://www.paypal.me/wopox1337', 'https://yoomoney.ru/to/410011388660403'] 14 | 15 | -------------------------------------------------------------------------------- /.github/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Chat Additions 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/README.md: -------------------------------------------------------------------------------- 1 |

2 | Chat Additions 3 |

4 | 5 |

AMXModX plugin chat control tool with rich functionality and API.

6 | 7 |

8 | 9 | Build status 11 | 12 | Build status 14 | 15 | Release 17 | 18 | AMXModX dependency 20 | 21 | Telegram 23 |

24 | 25 |

26 | About • 27 | Requirements • 28 | Installation • 29 | Updating • 30 | Downloads • 31 | Features • 32 | Wiki • 33 | Contributing • 34 | Credits 35 |

36 | 37 | --- 38 | 39 | ## About 40 | Chat Additions is a set of tools for managing voice as well as text chat, for your HLDS server. 41 | Allows you to fully or selectively limit the player to use any chat (voice, general, team, admin). 42 | Modular system, allows you to use only the necessary tasks capabilities, thereby saving server resources. 43 | Rich API capabilities allow the system to connect any functionality (work with player statistics, automation of decisions on blocking). 44 |

45 | Chat Additions in work 46 |

47 | 48 | ## Requirements 49 | - HLDS installed; 50 | - [ReGameDLL](https://github.com/s1lentq/ReGameDLL_CS) installed; 51 | - Installed AMXModX ([`v1.9`](https://www.amxmodx.org/downloads-new.php) or [`v1.10`](https://www.amxmodx.org/downloads-new.php?branch=master)); 52 | - Installed [ReAPI](https://github.com/s1lentq/reapi) module (optional, but not required); 53 | - Installed [AmxxEasyHttp](https://github.com/Next21Team/AmxxEasyHttp) module (optional, but not required); 54 | 55 | ## Installation 56 | - [Download the latest](https://github.com/ChatAdditions/ChatAdditions_AMXX/releases/latest) stable version from the release section. 57 | - Extract the `cstrike` folder to the root folder of the HLDS server; 58 | - Make sure that all plugins are running and in the correct order, using the `amxx list` command. 59 | 60 | ## Updating 61 | - Put new plugins and lang-files (`plugins/*.amxx` & `data/lang/*.txt`) into `amxmodx/` folder on the HLDS server; 62 | - Restart the server (command `restart` or change the map); 63 | - Make sure that the versions of the plugins are up to date with the command `amxx list`. 64 | 65 | ## Downloads 66 | - [Release builds](https://github.com/ChatAdditions/ChatAdditions_AMXX/releases) 67 | - [Dev builds](https://github.com/ChatAdditions/ChatAdditions_AMXX/actions/workflows/CI.yml) 68 | 69 | ## Features 70 | - Compatibility with any chat manager; 71 | - No [`VoiceTranscoder`](https://github.com/WPMGPRoSToTeMa/VoiceTranscoder) or [`ReVoice`](https://github.com/s1lentq/revoice/) required; 72 | - Flexible system of access rights and immunities for players; 73 | - Modular system, rich API capabilities, and flexibility; 74 | - Simple, intuitive interface (UX); 75 | - Multi-language support; 76 | - Simple, user-friendly configuration; 77 | - `CA_Gag`: Simple, flexible templates system (reasons, times, punishment type); 78 | - `CA_Gag`: Support for SQLite, MySQL, CSBans, GameCMS; 79 | - User-friendly logging system with good customization; 80 | - Up-to-date support and updates. 81 | 82 | ## Wiki 83 | Do you **need some help**? Check the _articles_ from the [wiki](https://github.com/ChatAdditions/ChatAdditions_AMXX/wiki). 84 | 85 | ## Contributing 86 | Got **something interesting** you'd like to **share**? Learn about [contributing](CONTRIBUTING.md). 87 | 88 | ## Credits 89 | I would like to thank the creators of AMXModX and ReAPI and everyone who helps me in developing and testing this system, who supports my interest. 90 | 91 | **Thank you guys! 👍** 92 | 93 | ## Support 94 | Reach out to me at one of the following places: 95 | - Github issues; 96 | - Github discussions; 97 | - [Telegram](https://t.me/ShorokhovSergey); 98 | - [Telegram group](https://t.me/ChatAdditions_group); 99 | - E-Mail; 100 | 101 | ## License 102 | [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](LICENSE) 103 | Copyright © Sergey Shorokhov 104 | -------------------------------------------------------------------------------- /.github/workflows/CI.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | paths-ignore: 7 | - "**.md" 8 | 9 | pull_request: 10 | types: [opened, reopened, synchronize] 11 | release: 12 | types: [published] 13 | 14 | jobs: 15 | build: 16 | name: "Build" 17 | runs-on: ubuntu-latest 18 | outputs: 19 | sha: ${{ steps.declare_sha.outputs.sha }} 20 | semver: ${{ steps.declare_sha.outputs.semver }} 21 | steps: 22 | - name: Checkout 23 | uses: actions/checkout@v4.1.1 24 | with: 25 | fetch-depth: 0 26 | 27 | - name: Parse SemVer string (release) 28 | id: semver_parser 29 | if: | 30 | github.event_name == 'release' && 31 | github.event.action == 'published' && 32 | startsWith(github.ref, 'refs/tags/') 33 | uses: booxmedialtd/ws-action-parse-semver@v1.4.7 34 | with: 35 | input_string: ${{ github.ref }} 36 | version_extractor_regex: '\/v(.*)$' 37 | 38 | - name: Declare SHA & package name 39 | id: declare_sha 40 | shell: bash 41 | run: | 42 | SHA=$(git rev-parse --short HEAD) 43 | echo "COMMIT_SHA=${SHA}" >> $GITHUB_ENV 44 | 45 | echo "sha=$SHA" >> $GITHUB_OUTPUT 46 | echo "semver=${{ steps.semver_parser.outputs.fullversion }}" >> $GITHUB_OUTPUT 47 | 48 | - name: Setup latest ReAPI includes 49 | env: 50 | REPO: "s1lentq/reapi" 51 | run: | 52 | mkdir -p dep/reapi 53 | cd dep/reapi 54 | 55 | curl \ 56 | --silent \ 57 | https://api.github.com/repos/$REPO/releases/latest | \ 58 | grep "browser_download_url" | \ 59 | grep -Eo 'https://[^\"]*' | \ 60 | xargs wget 61 | 62 | 7z x *.zip 63 | 64 | echo "REAPI_INCLUDE_PATH=$(pwd)/addons/amxmodx/scripting/include" >> $GITHUB_ENV 65 | 66 | - name: Update versions for plugins (release) 67 | working-directory: cstrike/addons/amxmodx/scripting/include/ 68 | if: | 69 | github.event_name == 'release' && 70 | github.event.action == 'published' && 71 | startsWith(github.ref, 'refs/tags/') 72 | env: 73 | PLUGIN_VERSION: "v${{ steps.semver_parser.outputs.fullversion }}" 74 | run: sed -i "s|%CA_VERSION%|$PLUGIN_VERSION|g" ChatAdditions.inc 75 | 76 | - name: Update versions for plugins (only for artifacts builds) 77 | working-directory: cstrike/addons/amxmodx/scripting/include/ 78 | env: 79 | PLUGIN_VERSION: "${{ env.COMMIT_SHA }}" 80 | run: sed -i "s|%CA_VERSION%|$PLUGIN_VERSION|g" ChatAdditions.inc 81 | 82 | - name: Setup AMXXPawn Compiler 83 | uses: wopox1337/setup-amxxpawn@v1.1.0 84 | with: 85 | version: "1.10.5466" 86 | 87 | - name: Compile AMXX plugins 88 | working-directory: cstrike/addons/amxmodx/scripting/ 89 | env: 90 | REAPI_INCLUDE: ${{env.REAPI_INCLUDE_PATH}} 91 | run: | 92 | mkdir ../plugins/ 93 | 94 | compile() { 95 | sourcefile=$1 96 | amxxfile="$(echo $sourcefile | sed -e 's/\.sma$/.amxx/')" 97 | output_path="../plugins/$amxxfile" 98 | 99 | mkdir -p $(dirname $output_path) 100 | 101 | echo -n "Compiling $sourcefile ... " 102 | amxxpc $sourcefile -o"$output_path" \ 103 | -i"include" \ 104 | -i"$REAPI_INCLUDE" 105 | } 106 | export -f compile 107 | 108 | find * -type f -name "*.sma" -exec bash -c 'compile "$0"' {} \; 109 | 110 | - name: Move files 111 | run: | 112 | mkdir publish 113 | mv cstrike/ publish/ 114 | 115 | - name: Upload artifact 116 | uses: actions/upload-artifact@v4.3.1 117 | with: 118 | name: ChatAdditions-${{ env.COMMIT_SHA }}-dev 119 | path: publish/* 120 | 121 | publish: 122 | name: "Publish" 123 | runs-on: ubuntu-latest 124 | needs: [build] 125 | if: | 126 | github.event_name == 'release' && 127 | github.event.action == 'published' && 128 | startsWith(github.ref, 'refs/tags/') 129 | steps: 130 | - name: Download artifacts 131 | uses: actions/download-artifact@v4.1.4 132 | with: 133 | name: ChatAdditions-${{needs.build.outputs.sha}}-dev 134 | 135 | - name: Packaging binaries 136 | id: packaging 137 | run: 7z a -mm=Deflate -mfb=258 -mpass=15 -r ChatAdditions-v${{needs.build.outputs.semver}}.zip cstrike/ 138 | 139 | - name: Publish artifacts 140 | uses: softprops/action-gh-release@v2.0.4 141 | id: publish-job 142 | if: | 143 | startsWith(github.ref, 'refs/tags/') && 144 | steps.packaging.outcome == 'success' 145 | env: 146 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 147 | with: 148 | files: | 149 | *.zip 150 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.amxx 2 | .vscode/* 3 | *publish/ 4 | /.temp 5 | /.compiler -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/configs/plugins-ChatAdditions.ini: -------------------------------------------------------------------------------- 1 | ; A core plugin for control different types of chat. 2 | ChatAdditions/ChatAdditions_Core.amxx debug 3 | 4 | ; Storage choose (disable not used storages) 5 | ; IMPORTANT: you must leave ONLY ONE plugin to manage the storage. 6 | ChatAdditions/Storage/CA_Storage_SQLite.amxx debug ; SQLite storage provider 7 | ; ChatAdditions/Storage/CA_Storage_CSBans.amxx debug ; CSBans (MySQL) storage provider 8 | ; ChatAdditions/Storage/CA_Storage_GameCMS.amxx debug ; GameCMS (MySQL) storage provider 9 | 10 | ; Extensions 11 | ChatAdditions/CA_AntiFlood.amxx debug ; Antiflood for chat 12 | ChatAdditions/CA_Mute.amxx debug ; Players can choose who they can hear. 13 | ChatAdditions/Addons/CA_Addon_DeathMute.amxx debug ; Alive players don't hear dead players after 5 secs 14 | ChatAdditions/Addons/CA_Addon_RankRestrictions.amxx debug ; Restrict chat until you reach the rank of a statistic. 15 | ChatAdditions/Addons/CA_Addon_VoteGag.amxx debug ; Ability for players to vote for gag. 16 | ChatAdditions/Addons/CA_Addon_RequestUnGag.amxx debug ; A player can apologize to the administration. 17 | ChatAdditions/CA_Gag.amxx debug ; Manage player chats for the admin. 18 | 19 | ; IMPORTANT: Place you chat manager below (Chat RBS plugins, Lite Translit, Colored Translit etc..) 20 | ; Most chat managers are not written using the correct chat handling, 21 | ; for this reason player messages may not be blocked. 22 | ; It is necessary to place the chat manager below the chat blocking plugins, 23 | ; to avoid blocking problems. 24 | ; chat_rbs.amxx 25 | ; crx_chatmanager.amxx 26 | ; lite_translit.amxx 27 | ; colored_translit.amxx 28 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/configs/plugins/ChatAdditions/CA_Addon_DeathMute.cfg: -------------------------------------------------------------------------------- 1 | // Time (in seconds) for killed players, during which they can report information to living players. 2 | // 0 - disabled functionality 3 | // - 4 | // Default: "5.0" 5 | // Minimum: "0.000000" 6 | // Maximum: "240.000000" 7 | ca_deathmute_time "5.0" 8 | 9 | // Death mute mode 10 | // 0 - alive hear only alive, dead hear all 11 | // 1 - alive hear only alive, dead hear only dead 12 | // - 13 | // Default: "1" 14 | // Minimum: "0.000000" 15 | // Maximum: "1.000000" 16 | ca_deathmute_dead_hear_alive "1" 17 | 18 | // Notification type for dead players 19 | // 0 - disabled functionality 20 | // 1 - chat message 21 | // 2 - HUD message 22 | // - 23 | // Default: "1" 24 | ca_deathmute_notify_type "1" 25 | 26 | // Show progressbar 27 | // 0 - disabled functionality 28 | // - 29 | // Default: "1" 30 | ca_deathmute_notify_show_progressbar "1" 31 | 32 | // X position for HUD message 33 | // -1.0 - center 34 | // - 35 | // Default: "-1.0" 36 | // Minimum: "-1.000000" 37 | // Maximum: "1.000000" 38 | ca_deathmute_notify_hud_x "-1.0" 39 | 40 | // Y position for HUD message 41 | // -1.0 - center 42 | // - 43 | // Default: "0.15" 44 | // Minimum: "-1.000000" 45 | // Maximum: "1.000000" 46 | ca_deathmute_notify_hud_y "0.15" 47 | 48 | // Red color value (in RGB) [0...255] 49 | // - 50 | // Default: "200" 51 | // Minimum: "0.000000" 52 | // Maximum: "255.000000" 53 | ca_deathmute_notify_hud_r "200" 54 | 55 | // Green color value (in RGB) [0...255] 56 | // - 57 | // Default: "50" 58 | // Minimum: "0.000000" 59 | // Maximum: "255.000000" 60 | ca_deathmute_notify_hud_g "50" 61 | 62 | // Blue color value (in RGB) [0...255] 63 | // - 64 | // Default: "0" 65 | // Minimum: "0.000000" 66 | // Maximum: "255.000000" 67 | ca_deathmute_notify_hud_b "0" 68 | 69 | // User immunity flag 70 | // - 71 | // Default: "a" 72 | ca_deathmute_immunity_flags "a" 73 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/configs/plugins/ChatAdditions/CA_Addon_RankRestrictions.cfg: -------------------------------------------------------------------------------- 1 | // Restrictions Type 2 | // 0 - Disable restrictions 3 | // 1 - Level restrictions 4 | // 2 - Kills count restrictions 5 | // - 6 | // Default: "1" 7 | // Minimum: "0.000000" 8 | // Maximum: "2.000000" 9 | ca_rankrestrictions_type "1" 10 | 11 | // Kill System Types 12 | // 0 - CSStats MySQL 13 | // 1 - CSX Module 14 | // - 15 | // Default: "1" 16 | // Minimum: "0.000000" 17 | // Maximum: "1.000000" 18 | ca_rankrestrictions_type_kills "1" 19 | 20 | // Min kills count to access VOICE chat 21 | // - 22 | // Default: "10" 23 | // Minimum: "0.000000" 24 | ca_rankrestrictions_min_kills_voice_chat "10" 25 | 26 | // Min kills count to access TEXT chat 27 | // - 28 | // Default: "10" 29 | // Minimum: "0.000000" 30 | ca_rankrestrictions_min_kills_text_chat "10" 31 | 32 | // Level System Types 33 | // 0 - Advanced Experience System 34 | // 1 - Army Ranks Ultimate 35 | // 2 - OciXCrom's Rank System 36 | // 3 - CMSStats Ranks 37 | // 4 - CMSStats MySQL 38 | // 5 - CSstatsX SQL 39 | // 6 - CSX Module 40 | // - 41 | // Default: "1" 42 | // Minimum: "0.000000" 43 | // Maximum: "6.000000" 44 | ca_rankrestrictions_type_level "1" 45 | 46 | // Min Level to access VOICE chat 47 | // - 48 | // Default: "2" 49 | // Minimum: "0.000000" 50 | ca_rankrestrictions_min_level_voice_chat "2" 51 | 52 | // Min Level to access TEXT chat 53 | // - 54 | // Default: "2" 55 | // Minimum: "0.000000" 56 | ca_rankrestrictions_min_level_text_chat "2" 57 | 58 | // User immunity flag 59 | // - 60 | // Default: "a" 61 | ca_rankrestrictions_immunity_flag "a" 62 | 63 | // Enable immunity for steam players 64 | // - 65 | // Default: "0" 66 | // Minimum: "0.000000" 67 | // Maximum: "1.000000" 68 | ca_rankrestrictions_steam_immunity "0" 69 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/configs/plugins/ChatAdditions/CA_Addon_RequestUnGag.cfg: -------------------------------------------------------------------------------- 1 | // Request ungag command 2 | // - 3 | // Default: "/sorry" 4 | ca_requestungag_cmd "/sorry" 5 | 6 | // delay time request ungag 7 | // - 8 | // Default: "40.0" 9 | // Minimum: "1.000000" 10 | ca_requestungag_delay "40.0" 11 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/configs/plugins/ChatAdditions/CA_AntiFlood.cfg: -------------------------------------------------------------------------------- 1 | // Time between messages 2 | // 0.0 - no limit 3 | // - 4 | // Default: "0.75" 5 | // Minimum: "0.000000" 6 | ca_anti_flood_time "0.75" 7 | 8 | // How many identical messages can be written in a row 9 | // 0 - no limit 10 | // - 11 | // Default: "2" 12 | // Minimum: "0.000000" 13 | ca_equal_messages "2" 14 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/configs/plugins/ChatAdditions/CA_Gag.cfg: -------------------------------------------------------------------------------- 1 | // Gag time values for choose 2 | // format: 1 = 1 second, 1i = 1 minute, 1h = 1 hour, 1d = 1 day, 1w = 1 week, 1m = 1 month, 1y = 1 year 3 | // NOTE: Changes will be applied only after reloading the map (or command `ca_gag_reload_config`) 4 | // - 5 | // Default: "1i, 5i, 10i, 30i, 1h, 1d, 1w, 1m" 6 | ca_gag_times "1i, 5i, 10i, 30i, 1h, 1d, 1w, 1m" 7 | 8 | // User immunity flag 9 | // users with this flag can't be gagged 10 | // NOTE: `ca_gag_access_flags_high` can gag this users 11 | // - 12 | // Default: "a" 13 | ca_gag_immunity_flags "a" 14 | 15 | // Admin flag 16 | // users with this flag can gag users with flag `z`, but can't with flag `ca_gag_immunity_flags` 17 | // users with this flag can't be gagged by same flags users (immunity) 18 | // NOTE: `ca_gag_access_flags_high` can gag this users 19 | // - 20 | // Default: "c" 21 | ca_gag_access_flags "c" 22 | 23 | // Admin flag 24 | // users with this flag can enter their own gag reason 25 | // - 26 | // Default: "d" 27 | ca_gag_access_flags_own_reason "d" 28 | 29 | // Admin flag 30 | // users with this flag can enter their own gag time 31 | // - 32 | // Default: "e" 33 | ca_gag_access_flags_own_time "e" 34 | 35 | // High admin flag 36 | // users with this flag can everyone 37 | // users with this flag can't be gagged 38 | // NOTE: `ca_gag_access_flags_high` can gag this users 39 | // - 40 | // Default: "l" 41 | ca_gag_access_flags_high "l" 42 | 43 | // Remove gag access control 44 | // 1 = remove only own gags 45 | // 0 = no restrictions 46 | // NOTE: `ca_gag_access_flags_high` can remove every gag 47 | // - 48 | // Default: "1" 49 | ca_gag_remove_only_own_gag "1" 50 | 51 | // Sound for success action 52 | // NOTE: Changes will be applied only after reloading the map 53 | // - 54 | // Default: "buttons/blip2.wav" 55 | ca_gag_sound_ok "buttons/blip2.wav" 56 | 57 | // Sound for error action 58 | // NOTE: Changes will be applied only after reloading the map 59 | // - 60 | // Default: "buttons/button2.wav" 61 | ca_gag_sound_error "buttons/button2.wav" 62 | 63 | // Block nickname change for gagged player 64 | // 0 = no restrictions 65 | // - 66 | // Default: "1" 67 | ca_gag_block_nickname_change "1" 68 | 69 | // Also block adminchat if admin gagged 70 | // 0 = no restrictions 71 | // - 72 | // Default: "1" 73 | ca_gag_block_admin_chat "1" 74 | 75 | // Don't separate `say` & `say_team` chats 76 | // 0 = disabled 77 | // - 78 | // Default: "1" 79 | ca_gag_common_chat_block "1" 80 | 81 | // Enable own gag reason 82 | // 0 = disabled (excluding when there are no reasons) 83 | // 1 = enabled, at first position in reasons list 84 | // 2 = enabled, at last position in reasons list 85 | // - 86 | // Default: "1" 87 | ca_gag_own_reason_enabled "1" 88 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/configs/plugins/ChatAdditions/CA_Mute.cfg: -------------------------------------------------------------------------------- 1 | // How often players can use menu. (in seconds) 2 | // - 3 | // Default: "3" 4 | // Minimum: "0.000000" 5 | // Maximum: "120.000000" 6 | ca_mute_use_delay "3" 7 | 8 | // Save the player's individual preferences in the vault. 9 | // - 10 | // Default: "1" 11 | // Minimum: "0.000000" 12 | // Maximum: "1.000000" 13 | ca_mute_use_storage "1" 14 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/configs/plugins/ChatAdditions/CA_Storage_CSBans.cfg: -------------------------------------------------------------------------------- 1 | // CSBans MySQL database host address 2 | // - 3 | // Default: "127.0.0.1" 4 | ca_storage_host "127.0.0.1" 5 | 6 | // CSBans MySQL database user 7 | // - 8 | // Default: "root" 9 | ca_storage_user "root" 10 | 11 | // CSBans MySQL database host password 12 | // - 13 | // Default: "" 14 | ca_storage_pass "" 15 | 16 | // CSBans MySQL database name 17 | // - 18 | // Default: "" 19 | ca_storage_dbname "" 20 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/configs/plugins/ChatAdditions/CA_Storage_GameCMS.cfg: -------------------------------------------------------------------------------- 1 | // GameCMS MySQL database host address 2 | // - 3 | // Default: "127.0.0.1" 4 | ca_storage_host "127.0.0.1" 5 | 6 | // GameCMS MySQL database user 7 | // - 8 | // Default: "root" 9 | ca_storage_user "root" 10 | 11 | // GameCMS MySQL database host password 12 | // - 13 | // Default: "" 14 | ca_storage_pass "" 15 | 16 | // GameCMS MySQL database name 17 | // - 18 | // Default: "" 19 | ca_storage_dbname "" 20 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/configs/plugins/ChatAdditions/CA_Storage_PGBans.cfg: -------------------------------------------------------------------------------- 1 | // PGBans MySQL database host address 2 | // - 3 | // Default: "127.0.0.1" 4 | pgb_storage_host "127.0.0.1" 5 | 6 | // PGBans MySQL database user 7 | // - 8 | // Default: "root" 9 | pgb_storage_user "root" 10 | 11 | // PGBans MySQL database host password 12 | // - 13 | // Default: "" 14 | pgb_storage_pass "" 15 | 16 | // PGBans MySQL database name 17 | // - 18 | // Default: "" 19 | pgb_storage_dbname "" 20 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/configs/plugins/ChatAdditions/ChatAdditions_core.cfg: -------------------------------------------------------------------------------- 1 | // Log file type 2 | // 0 = log to common amxx log file (logs/L*.log) 3 | // 1 = log to plugins folder (logs/ChatAdditions/[plugin name]/*.log) 4 | // 2 = silent log to plugins folder (logs/%s/[plugin name]/L*.log) 5 | // - 6 | // Default: "1" 7 | // Minimum: "0.000000" 8 | // Maximum: "2.000000" 9 | ca_log_type "1" 10 | 11 | // Log level 12 | // 0 = disable logs 13 | // 1 = add info messages logs 14 | // 2 = add warinigs info 15 | // 3 = add debug messages 16 | // - 17 | // Default: "3" 18 | // Minimum: "0.000000" 19 | // Maximum: "3.000000" 20 | ca_log_level "1" 21 | 22 | // Enable update check? 23 | // 0 = disable update checks 24 | // - 25 | // Default: "1" 26 | // Minimum: "0.000000" 27 | // Maximum: "1.000000" 28 | ca_update_notify "1" 29 | 30 | // The time in days after which the log files should be deleted. 31 | // 0 - The logs won't be deleted. 32 | // > 0 - The logs will be deleted at the time inserted. 33 | // - 34 | // Default: "7" 35 | // Minimum: "0.000000" 36 | ca_log_autodelete_time "7" 37 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/configs/plugins/ChatAdditions/ca_gag_chat_whitelist_cmds.cfg: -------------------------------------------------------------------------------- 1 | // Usage: ca_gag_add_chat_whitelist_cmd 2 | // - a chat command that will be allowed to be executed even if the player is gagged 3 | 4 | ca_gag_add_chat_whitelist_cmd "/rs" 5 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/configs/plugins/ChatAdditions/ca_gag_reasons.cfg: -------------------------------------------------------------------------------- 1 | // Usage: ca_gag_add_reason [flags] [time] 2 | // - reason text message 3 | // [flags] - gag flags. (optional) 4 | // a = text chat, b = text team chat, c = voice chat 5 | // [time] - time in minutes (optional) 6 | // format: 1 = 1 second, 1i = 1 minute, 1h = 1 hour, 1d = 1 day, 1w = 1 week, 1m = 1 month, 1y = 1 year 7 | // Examples: 8 | // ca_gag_add_reason "Flood" "abc" "3h" - will add reason template with "Flood" reason, block all chat type, on 3 hours 9 | // ca_gag_add_reason "Flood" - will add reason template with "Flood" reason only 10 | // 11 | // NOTE: Set `time` or `flags` argument empty for allow to make your own choices. 12 | // 13 | // https://github.com/ChatAdditions/ChatAdditions_AMXX/wiki 14 | 15 | ca_gag_add_reason "Foul language / insults" "abc" "" 16 | ca_gag_add_reason "Flooding" "" "10i" 17 | ca_gag_add_reason "Monitoring" "abc" "10i" 18 | ca_gag_add_reason "Bad microphone" "c" "1h" 19 | ca_gag_add_reason "Chat ads" "ab" "1h" 20 | ca_gag_add_reason "Inappropriate behavior" "abc" "1d" 21 | ca_gag_add_reason "Microphone from 18+ age" "c" "1w" 22 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/data/lang/CA_Addon_DeathMute.txt: -------------------------------------------------------------------------------- 1 | [ru] 2 | DeathMute_ChatMessage = У Вас есть ^3%.0f сек^1, чтобы дать информацию тиммейтам, далее живые Вас ^3не услышат^1. 3 | DeathMute_YouMuted = Живые игроки Вас ^3не слышат^1. 4 | DeathMute_prefix = [^3Death mute^1] 5 | 6 | [en] 7 | DeathMute_ChatMessage = You have ^3%.0f seconds^1 to give information to your teammates, then the living ^3will not hear you^1. 8 | DeathMute_YouMuted = Live players ^3can't hear you^1. 9 | DeathMute_prefix = [^3Death mute^1] 10 | 11 | [es] 12 | DeathMute_ChatMessage = Tienes ^3%.0f segundos^1, para comunicarte con el equipo, después de eso tu equipo no ^3te oirá más^1. 13 | DeathMute_YouMuted = Jugadores vivos ^3no pueden oírte^1. 14 | DeathMute_prefix = [^3Death mute^1] 15 | 16 | [de] 17 | DeathMute_ChatMessage = ^3%.0f Sekunden^1 für die Team-Kommunikation, anschliessend kann Dich ^3niemand mehr hören^1. 18 | DeathMute_YouMuted = Lebende Spieler können Dich ^3nicht hören^1. 19 | DeathMute_prefix = [^3Death mute^1] 20 | 21 | [pl] 22 | DeathMute_ChatMessage = Masz ^3%.0f sekund^1 na podanie informacji kolegom z druzyny, ^3pozniej Cie nie uslysza.^1. 23 | DeathMute_YouMuted = Zywi gracze Cie^3 nie slysza^1. 24 | DeathMute_prefix = [^3Death mute^1] 25 | 26 | [ua] 27 | DeathMute_ChatMessage = У Вас є ^3%.0f сек^1, щоб надати інформацію тіммейтам, далі живі Вас ^3не почують^1. 28 | DeathMute_YouMuted = Живі гравці Вас ^3не чують^1. 29 | DeathMute_prefix = [^3Death mute^1] 30 | 31 | [ro] 32 | DeathMute_ChatMessage = Ai la dispozitie ^3%.0f secunde^1 sa le dai informatii coechipierilor, dupa aceea, cei vii ^3nu te vor mai auzi^1. 33 | DeathMute_YouMuted = Jucatorii in viata ^3nu te pot auzi^1. 34 | DeathMute_prefix = [^3Mut celor morti^1] -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/data/lang/CA_Addon_RankRestrictions.txt: -------------------------------------------------------------------------------- 1 | [ru] 2 | RankRestrictions_Warning_MinLevel = ^4* ^1Доступ к чату запрещен! Необходимо получить ^4%i ^1уровень. 3 | RankRestrictions_Warning_MinKills = ^4* ^1Доступ к чату запрещен! Необходимо убить ^4%i ^1противников. 4 | 5 | [en] 6 | RankRestrictions_Warning_MinLevel = ^4* ^1Chat access denied! It is necessary to get ^4%i ^1level. 7 | RankRestrictions_Warning_MinKills = ^4* ^1Chat access denied! You must kill ^4%i ^1opponents. 8 | 9 | [ua] 10 | RankRestrictions_Warning_MinLevel = ^4* ^1Доступ до чату заборонений! Необхідно отримати ^4%i ^1рівень. 11 | RankRestrictions_Warning_MinKills = ^4* ^1Доступ до чату заборонений! Необхідно вбити ^4%i ^1супротивників. 12 | 13 | [ro] 14 | RankRestrictions_Warning_MinLevel = ^4* ^1Accesul la chat este interzis! Ai nevoie de nivelul ^4%i^1. 15 | RankRestrictions_Warning_MinKills = ^4* ^1Accesul la chat este interzis! Trebuie sa ucizi ^4%i ^1inamici. -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/data/lang/CA_Addon_RequestUngag.txt: -------------------------------------------------------------------------------- 1 | [ru] 2 | RequestUnGag_NoAccess = ^4* ^1У вас не заблокирован чат. 3 | RequestUnGag_TimeOut = ^4* ^1Попробуйте через %i сек. 4 | RequestUnGag_Requested = ^4* ^1Игрок ^4%n ^1просит снять гаг. Чтобы снять гаг, напишите: ^4/ungag %d^1. 5 | RequestUnGag_YouRequested = ^4* ^1Вы попросили снять гаг. 6 | 7 | [en] 8 | RequestUnGag_NoAccess = ^4* ^1You don't have a chat block. 9 | RequestUnGag_TimeOut = ^4* ^1Try it in %i seconds. 10 | RequestUnGag_Requested = ^4* ^1The player ^4%n ^1asks to remove the gag. To remove it write: ^4/ungag %i^1. 11 | RequestUnGag_YouRequested = ^4* ^1You asked to take off the gag. 12 | 13 | [ro] 14 | RequestUnGag_NoAccess = ^4* ^1Chat-ul tau nu este blocat. 15 | RequestUnGag_TimeOut = ^4* ^1Incearca-l in %i secunde. 16 | RequestUnGag_Requested = ^4* ^1Jucatorul ^4%n ^1cere permisiunea de a i se inlatura gag-ul. Pentru a-i scoate gag-ul scrie: ^4/ungag %i^1. 17 | RequestUnGag_YouRequested = ^4* ^1Ai cerut permisiunea de a ti se inlatura gag-ul. -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/data/lang/CA_AntiFlood.txt: -------------------------------------------------------------------------------- 1 | [en] 2 | CA_ANTIFLOOD_CHAT_PREFIX = ^1[^4AntiFlood^1] 3 | 4 | CA_ANTIFLOOD_CHAT_STOP_FLOODING = ^1Stop ^3flooding. 5 | CA_ANTIFLOOD_CHAT_EQUAL_MESSAGE = ^1Your message ^3is repeated! ^4Exercise your imagination^1. 6 | 7 | [ru] 8 | CA_ANTIFLOOD_CHAT_PREFIX = ^1[^4AntiFlood^1] 9 | 10 | CA_ANTIFLOOD_CHAT_STOP_FLOODING = ^1Прекратите ^3флудить. 11 | CA_ANTIFLOOD_CHAT_EQUAL_MESSAGE = ^1Сообщение ^3повторяется! ^4Проявите фантазию^1. 12 | 13 | [ro] 14 | CA_ANTIFLOOD_CHAT_PREFIX = ^1[^4AntiFlood^1] 15 | 16 | CA_ANTIFLOOD_CHAT_STOP_FLOODING = ^1Opreste-te din ^3flood. 17 | CA_ANTIFLOOD_CHAT_EQUAL_MESSAGE = ^1Mesajul tau ^3se repeta! ^4Exerseaza-ti imaginatia^1. -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/data/lang/CA_Gag.txt: -------------------------------------------------------------------------------- 1 | [ru] 2 | Gag_MenuTitle_PlayersList = Заглушить игрока 3 | Gag_MenuTitle_SelectReason = Выберите причину: 4 | Gag_MenuTitle_SelectTime = Выберите время для заглушки: 5 | Gag_MenuItem_RemoveGag = \rСнять\w 6 | Gag_MenuItem_EditGag = Редактировать 7 | Gag_MenuItem_ShowGag = Заглушка игрока [\r%s\y]: 8 | Gag_MenuItem_PropSay = Чат: 9 | Gag_MenuItem_PropSayTeam = Командный чат: 10 | Gag_MenuItem_PropVoice = Голосовое общение: 11 | Gag_MenuItem_Time = Время: 12 | Gag_MenuItem_Confirm = Подтвердить! 13 | Gag_MenuItem_Reason = Причина: 14 | Gag_MenuItem_Resolution = Время: \y%s\w (причина: \y%s\w) 15 | Gag_MenuItem_Admin = Назначил: 16 | Gag_MenuItem_Type = Тип: 17 | Gag_MenuItem_Length = Длительность: 18 | Gag_MenuItem_Expire = Истекает: 19 | Gag_MenuItem_Left = Осталось: 20 | 21 | Gag_SelectFlags = Параметры заглушки игрока: [ \r%n\y ] 22 | Gag_EnterReason = Ввести свою ->\n 23 | Gag_EnterTime = Указать время -> 24 | 25 | Gag_Immunity = Иммунитет 26 | Gag_Gagged = *МОЛЧУН* 27 | 28 | Gag_ChatMsg_Reason = ^4Причина:^1 29 | Gag_NotSet = Не задано 30 | Gag_Permanent = *НАВСЕГДА* 31 | 32 | Gag_AdminGagPlayer = ^3заглушил ^1игрока ^4%s^1 33 | Gag_AdminUngagPlayer = ^3снял ^1заглушку с игрока ^4%s^1 34 | Gag_PlayerNotConnected = ^3Игрок недоступен!^1 35 | Gag_PlayerAlreadyRemoved = ^3Игрок ^4%n^1 уже удалён!^1 36 | Gag_PlayerExpiredGag = ^3У игрока ^4%n^1 истекло время заглушки. 37 | 38 | Gag_NotEnoughPlayers = ^3Недостаточно игроков, чтобы открыть меню! 39 | Gag_NoTemplatesAvailable_Reasons = ^3Нет шаблонов выбора причин. 40 | Gag_NoTemplatesAvailable_Times = ^3Нет шаблонов выбора времени. 41 | 42 | Gag_YouSetManual_Time = ^3Вы установили своё время:^1 43 | Gag_YouSetManual_Reason = ^3Вы установили причину заглушки:^1 44 | Gag_NotValidTimeEntered = ^3Время указано неверно:^1 45 | 46 | Gag_NotifyPlayer_BlockedChat = ^1Вам ^3заблокировали чат^1. 47 | 48 | Gag_prefix = [^3GAG^1] 49 | 50 | Gag_BackToPlayersMenu = К списку игроков 51 | 52 | [en] 53 | Gag_MenuTitle_PlayersList = Gag player 54 | Gag_MenuTitle_SelectReason = Choose reason: 55 | Gag_MenuTitle_SelectTime = Choose gag time: 56 | Gag_MenuItem_RemoveGag = \rRemove\w 57 | Gag_MenuItem_EditGag = Edit 58 | Gag_MenuItem_ShowGag = Player gag [\r%s\y]: 59 | Gag_MenuItem_PropSay = Chat: 60 | Gag_MenuItem_PropSayTeam = Team chat: 61 | Gag_MenuItem_PropVoice = Voice chat: 62 | Gag_MenuItem_Time = Time: 63 | Gag_MenuItem_Confirm = Confirm! 64 | Gag_MenuItem_Reason = Reason: 65 | Gag_MenuItem_Resolution = Time: \y%s\w (reason: \y%s\w) 66 | Gag_MenuItem_Admin = Admin: 67 | Gag_MenuItem_Type = Type: 68 | Gag_MenuItem_Length = Duration: 69 | Gag_MenuItem_Expire = Expire at: 70 | Gag_MenuItem_Left = Left: 71 | 72 | Gag_SelectFlags = Gag parameters: [ \r%n\y ] 73 | Gag_EnterReason = Enter gag reason ->\n 74 | Gag_EnterTime = Enter gag time -> 75 | 76 | Gag_Immunity = Gag_Immunity 77 | Gag_Gagged = *GAG* 78 | 79 | Gag_ChatMsg_Reason = ^4Reason:^1 80 | Gag_NotSet = Not selected 81 | Gag_Permanent = *PERMANENT* 82 | 83 | Gag_AdminGagPlayer = ^3gag ^1player ^4%s^1 84 | Gag_AdminUngagPlayer = ^3remove ^1gag from player ^4%s^1 85 | Gag_PlayerNotConnected = ^3Player not connected! 86 | Gag_PlayerAlreadyRemoved = ^3Player ^4%n^1 already removed!^1 87 | Gag_PlayerExpiredGag = ^3Player ^4%n^1 has expired gag. 88 | 89 | Gag_NotEnoughPlayers = ^3Not enough players to open menu! 90 | Gag_NoTemplatesAvailable_Reasons = No have reasons templates. 91 | Gag_NoTemplatesAvailable_Times = No have time templates. 92 | 93 | Gag_YouSetManual_Time = ^3You set custom time:^1 94 | Gag_YouSetManual_Reason = ^3You set custom reason:^1 95 | Gag_NotValidTimeEntered = ^3Entered time not valid:^1 96 | 97 | Gag_NotifyPlayer_BlockedChat = ^1Your ^3chat has been blocked^1. 98 | 99 | Gag_prefix = [^3GAG^1] 100 | 101 | Gag_BackToPlayersMenu = To players list 102 | 103 | [es] 104 | Gag_MenuTitle_PlayersList = Silenciar Jugador 105 | Gag_MenuTitle_SelectReason = Elegir Motivo: 106 | Gag_MenuTitle_SelectTime = Elegir Tiempo: 107 | Gag_MenuItem_RemoveGag = \rQuitar\w 108 | Gag_MenuItem_EditGag = Editar 109 | Gag_MenuItem_ShowGag = Jugador Silenciado [\r%s\y]: 110 | Gag_MenuItem_PropSay = Chat: 111 | Gag_MenuItem_PropSayTeam = Team Chat: 112 | Gag_MenuItem_PropVoice = Voz Chat: 113 | Gag_MenuItem_Time = Tiempo: 114 | Gag_MenuItem_Confirm = Confirmar! 115 | Gag_MenuItem_Reason = Motivo: 116 | Gag_MenuItem_Resolution = Tiempo: \y%s\w (Motivo: \y%s\w) 117 | Gag_MenuItem_Admin = Admin: 118 | Gag_MenuItem_Type = Tipo: 119 | Gag_MenuItem_Length = Duracion: 120 | Gag_MenuItem_Expire = Expira: 121 | Gag_MenuItem_Left = Restante: 122 | 123 | Gag_GagProperties = Parametros Silencio: [ \r%n\y ] 124 | Gag_EnterReason = Ingresar Motivo ->\n 125 | Gag_EnterTime = Ingresar Tiempo-> 126 | 127 | Gag_Immunity = Inmunidad 128 | Gag_Gagged = Silenciado 129 | 130 | Gag_ChatMsg_Reason = ^4Motivo:^1 131 | Gag_NotSet = No Definido 132 | Gag_Permanent = Permanente 133 | 134 | Gag_AdminGagPlayer = ^3silencio ^1a jugador ^4%s^1 135 | Gag_AdminUngagPlayer = ^3quito ^1silencio a jugador ^4%s^1 136 | Gag_PlayerNotConnected = ^3Jugador no conectado! 137 | Gag_PlayerAlreadyRemoved = ^3Jugador ^4%n^1 ya quitado!^1 138 | Gag_PlayerExpiredGag = ^3Jugador ^4%n^1 ha expirado el silencio. 139 | 140 | Gag_NotEnoughPlayers = ^3No hay suficiente jugadores! 141 | Gag_NoTemplatesAvailable_Reasons = No hay plantillas de motivos. 142 | Gag_NoTemplatesAvailable_Times = No hay plantillas de tiempo. 143 | 144 | Gag_YouSetManual_Time = ^3Tiempo Personalizado:^1 145 | Gag_YouSetManual_Reason = ^3Motivo Personalizado:^1 146 | Gag_NotValidTimeEntered = ^3Tiempo ingresado no es valido:^1 147 | 148 | Gag_NotifyPlayer_BlockedChat = ^1Tu ^3chat ha sido bloqueado^1. 149 | 150 | Gag_prefix = [^3GAG^1] 151 | 152 | [de] 153 | Gag_MenuTitle_PlayersList = Spieler stummschalten 154 | Gag_MenuTitle_SelectReason = Wählen einen Grund: 155 | Gag_MenuTitle_SelectTime = Wähle die Dauer: 156 | Gag_MenuItem_RemoveGag = \gEntfernen\w 157 | Gag_MenuItem_EditGag = Bearbeiten 158 | Gag_MenuItem_ShowGag = Muted Spieler [\r%s\y]: 159 | Gag_MenuItem_PropSay = Chat: 160 | Gag_MenuItem_PropSayTeam = Team Chat: 161 | Gag_MenuItem_PropVoice = Voice: 162 | Gag_MenuItem_Time = Dauer: 163 | Gag_MenuItem_Confirm = Bestätigen! 164 | Gag_MenuItem_Reason = Grund: 165 | Gag_MenuItem_Resolution = Dauer: \y%s\w (Grund: \y%s\w) 166 | Gag_MenuItem_Admin = Admin: 167 | Gag_MenuItem_Type = Typ: 168 | Gag_MenuItem_Length = Dauer: 169 | Gag_MenuItem_Expire = Läuft ab: 170 | Gag_MenuItem_Left = Verbleibend: 171 | 172 | Gag_SelectFlags = Mute-Parameter: [ \r%n\y ] 173 | Gag_EnterReason = Der Grund ist ->\n 174 | Gag_EnterTime = Dauer setzen -> 175 | 176 | Gag_Immunity = Immunität 177 | Gag_Gagged = Stummgeschaltet 178 | 179 | Gag_ChatMsg_Reason = ^4Grund:^1 180 | Gag_NotSet = N/A 181 | Gag_Permanent = Permanent 182 | 183 | Gag_AdminGagPlayer = ^3Mute ^4%s^1 184 | Gag_AdminUngagPlayer = ^3Mute ^1von ^4%s^1 aufheben 185 | Gag_PlayerNotConnected = ^3Spieler nicht verbunden! 186 | Gag_PlayerAlreadyRemoved = ^3Spieler ^4%n^1 bereits entfernt! 187 | Gag_PlayerExpiredGag = ^3Mute des Spielers ^4%n^1 abgelaufen. 188 | 189 | Gag_NotEnoughPlayers = ^3Nicht genug Spieler 190 | Gag_NoTemplatesAvailable_Reasons = ^3Keine Gründe vorhanden. 191 | Gag_NoTemplatesAvailable_Times = ^3Keine Dauer vorhanden. 192 | 193 | Gag_YouSetManual_Time = ^3Dauer:^1 194 | Gag_YouSetManual_Reason = ^3Grund für Muten:^1 195 | Gag_NotValidTimeEntered = ^3Die Dauer stimmt nicht:^1 196 | 197 | Gag_NotifyPlayer_BlockedChat = ^1Dein ^3Chat wurde blockeriert^1. 198 | 199 | Gag_prefix = [^3GAG^1] 200 | 201 | [pl] 202 | Gag_MenuTitle_PlayersList = Zgaguj gracza 203 | Gag_MenuTitle_SelectReason = Wybrany gracz: 204 | Gag_MenuTitle_SelectTime = Wybierz czas: 205 | Gag_MenuItem_RemoveGag = \rUsun\w 206 | Gag_MenuItem_EditGag = Edytuj 207 | Gag_MenuItem_ShowGag = Zgagowany gracz [\r%s\y]: 208 | Gag_MenuItem_PropSay = Czat: 209 | Gag_MenuItem_PropSayTeam = Team czat: 210 | Gag_MenuItem_PropVoice = Voice czat: 211 | Gag_MenuItem_Time = Czas: 212 | Gag_MenuItem_Confirm = Potwierdz! 213 | Gag_MenuItem_Reason = Powod: 214 | Gag_MenuItem_Resolution = Czas:\y %s\w (powod:\y %s\w) 215 | Gag_MenuItem_Admin = Admin: 216 | Gag_MenuItem_Type = Typ: 217 | Gag_MenuItem_Length = Czas trwania: 218 | Gag_MenuItem_Expire = Wygasa: 219 | Gag_MenuItem_Left = Pozostalo: 220 | 221 | Gag_SelectFlags = Flagi gagowania: [\r %n\y] 222 | Gag_EnterReason = Podaj powod gaga ->\n 223 | Gag_EnterTime = Podaj czas gaga -> 224 | 225 | Gag_Immunity = Immunitet 226 | Gag_Gagged = *GAG* 227 | 228 | Gag_ChatMsg_Reason = ^4Powod:^1 229 | Gag_NotSet = Nie wybrano 230 | Gag_Permanent = permanentny 231 | 232 | Gag_AdminGagPlayer = ^3Zgagowany ^1gracz ^4%s^1 233 | Gag_AdminUngagPlayer = ^3Odgagowal ^1gracza ^4%s^1 234 | Gag_PlayerNotConnected = ^3Gracz nie jest polaczony! 235 | Gag_PlayerAlreadyRemoved = ^3Gracz ^4%n^1 zostal juz usuniety!^1 236 | Gag_PlayerExpiredGag = ^3Graczowi ^4%n^1 wlasnie wygasla blokada. 237 | 238 | Gag_NotEnoughPlayers = ^4Na serwerze nie ma nikogo^1, kogo bys mogl zgagowac! 239 | Gag_NoTemplatesAvailable_Reasons = Brak powodow 240 | Gag_NoTemplatesAvailable_Times = Brak czasow. 241 | 242 | Gag_YouSetManual_Time = ^4Ustawiles wlasny czas:^3 243 | Gag_YouSetManual_Reason = ^3Ustawiles wlasny powod:^3 244 | Gag_NotValidTimeEntered = ^3Wprowadzony czas jest nieprawidlowy:^1 245 | 246 | Gag_NotifyPlayer_BlockedChat = ^3Zostales zgagowany^1. 247 | 248 | Gag_prefix = [^3GAG^1] 249 | 250 | [ua] 251 | Gag_MenuTitle_PlayersList = Заглушити гравця 252 | Gag_MenuTitle_SelectReason = Оберіть причину: 253 | Gag_MenuTitle_SelectTime = Оберіть час для заглушки: 254 | Gag_MenuItem_RemoveGag = \rЗняти\w 255 | Gag_MenuItem_EditGag = Редагувати 256 | Gag_MenuItem_ShowGag = Заглушка гравця [\r%s\y]: 257 | Gag_MenuItem_PropSay = Чат: 258 | Gag_MenuItem_PropSayTeam = Командний чат: 259 | Gag_MenuItem_PropVoice = Голосове спілкування: 260 | Gag_MenuItem_Time = Час: 261 | Gag_MenuItem_Confirm = Підтвердити! 262 | Gag_MenuItem_Reason = Причина: 263 | Gag_MenuItem_Resolution = Час: \y%s\w (причина: \y%s\w) 264 | Gag_MenuItem_Admin = Призначив: 265 | Gag_MenuItem_Type = Тип: 266 | Gag_MenuItem_Length = Тривалість: 267 | Gag_MenuItem_Expire = Спливає: 268 | Gag_MenuItem_Left = Залишилося: 269 | 270 | Gag_SelectFlags = Параметри заглушки гравця: [ \r%n\y ] 271 | Gag_EnterReason = Ввести свою ->\n 272 | Gag_EnterTime = Вказати час -> 273 | 274 | Gag_Immunity = Іммунітет 275 | Gag_Gagged = *МОЛЧУН* 276 | 277 | Gag_ChatMsg_Reason = ^4Причина:^1 278 | Gag_NotSet = Не задано 279 | Gag_Permanent = *НАЗАВЖДИ* 280 | 281 | Gag_AdminGagPlayer = ^3заглушив ^1гравця ^4%s^1 282 | Gag_AdminUngagPlayer = ^3зняв ^1заглушку із гравця ^4%s^1 283 | Gag_PlayerNotConnected = ^3Гравець недоступний!^1 284 | Gag_PlayerAlreadyRemoved = ^3Гравець ^4%n^1 вже видалений!^1 285 | Gag_PlayerExpiredGag = ^3У гравця ^4%n^1 сплив час заглушки. 286 | 287 | Gag_NotEnoughPlayers = ^3Недостатньо гравців, щоб відкрити меню! 288 | Gag_NoTemplatesAvailable_Reasons = ^3Не має шаблонів вибору причин. 289 | Gag_NoTemplatesAvailable_Times = ^3Не має шаблонів вибору часу. 290 | 291 | Gag_YouSetManual_Time = ^3Ви встановили свій час:^1 292 | Gag_YouSetManual_Reason = ^3Ви встановили причину заглушки:^1 293 | Gag_NotValidTimeEntered = ^3Час вказаний невірно:^1 294 | 295 | Gag_NotifyPlayer_BlockedChat = ^1Вам ^1заблокували чат^1. 296 | 297 | Gag_prefix = [^3GAG^1] 298 | 299 | [ro] 300 | Gag_MenuTitle_PlayersList = Gag unui jucator 301 | Gag_MenuTitle_SelectReason = Alege motivul: 302 | Gag_MenuTitle_SelectTime = Alege timpul gag-ului: 303 | Gag_MenuItem_RemoveGag = \rInlatura\w 304 | Gag_MenuItem_EditGag = Editeaza 305 | Gag_MenuItem_ShowGag = Jucatorul cu gag [\r%s\y]: 306 | Gag_MenuItem_PropSay = Chat: 307 | Gag_MenuItem_PropSayTeam = Chat Echipa: 308 | Gag_MenuItem_PropVoice = Chat vocal: 309 | Gag_MenuItem_Time = Timp: 310 | Gag_MenuItem_Confirm = Confirma! 311 | Gag_MenuItem_Reason = Motiv: 312 | Gag_MenuItem_Resolution = Timp: \y%s\w (motiv: \y%s\w) 313 | Gag_MenuItem_Admin = Admin: 314 | Gag_MenuItem_Type = Tip: 315 | Gag_MenuItem_Length = Durata: 316 | Gag_MenuItem_Expire = Expira la: 317 | Gag_MenuItem_Left = Ramas: 318 | 319 | Gag_SelectFlags = Parametrii gag: [ \r%n\y ] 320 | Gag_EnterReason = Insereaza motivul gag-ului ->\n 321 | Gag_EnterTime = Insereaza timpul gag-ului -> 322 | 323 | Gag_Immunity = Imunitate_Gag 324 | Gag_Gagged = *GAG* 325 | 326 | Gag_ChatMsg_Reason = ^4Motiv:^1 327 | Gag_NotSet = Neselectat 328 | Gag_Permanent = *PERMANENT* 329 | 330 | Gag_AdminGagPlayer = ^3gag ^1jucatorul ^4%s^1 331 | Gag_AdminUngagPlayer = ^3inlaturare ^1gag jucatorului ^4%s^1 332 | Gag_PlayerNotConnected = ^3Jucatorul nu este conectat! 333 | Gag_PlayerAlreadyRemoved = ^3Jucatorul ^4%n^1 deja inlaturat!^1 334 | Gag_PlayerExpiredGag = ^3Jucaotrului ^4%n^1 i-a expirat gag-ul. 335 | 336 | Gag_NotEnoughPlayers = ^3Nu sunt suficienti jucatori pentru a deschide meniul! 337 | Gag_NoTemplatesAvailable_Reasons = Nu exista sabloane pentru motive. 338 | Gag_NoTemplatesAvailable_Times = Nu exista sabloane pentru timp. 339 | 340 | Gag_YouSetManual_Time = ^3Ai setat timpul personalizat:^1 341 | Gag_YouSetManual_Reason = ^3Ai setat motivul personalizat:^1 342 | Gag_NotValidTimeEntered = ^3Timpul inserat nu este valid:^1 343 | 344 | Gag_NotifyPlayer_BlockedChat = ^3Chat-ul ^1tau a fost ^4blocat^1. 345 | 346 | Gag_prefix = [^3GAG^1] -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/data/lang/CA_Mute.txt: -------------------------------------------------------------------------------- 1 | [ru] 2 | Mute_MenuTitle = Заглушить игрока: 3 | Mute_MuteAll = Заглушить всех 4 | 5 | Mute_YouMutePlayer = Вы НЕ слышите игрока 6 | Mute_YouUnmutePlayer = Вы снова слышите игрока 7 | 8 | Mute_NotEnoughPlayers = ^3Недостаточно игроков! 9 | Mute_PlayerNotConnected = ^3Игрок не подключен! 10 | 11 | Mute_PlayerMutedYou = Не слышит Вас 12 | 13 | Mute_PlayerNowMutedYou = теперь НЕ слышит Вас. 14 | Mute_PlayerNowUnmutedYou = вновь слышит Вас. 15 | 16 | Mute_UseTooOften = ^3Вы используете слишком часто! 17 | 18 | Mute_PlayerNowMutedAll = теперь НЕ слышит никого! 19 | Mute_PlayerNowUnmutedAll = снова слышит всех. 20 | 21 | Mute_prefix = [^3MUTE^1] 22 | 23 | [en] 24 | Mute_MenuTitle = Players mute menu: 25 | Mute_MuteAll = Mute all 26 | 27 | Mute_YouMutePlayer = Now you can't hear the player 28 | Mute_YouUnmutePlayer = You hear the player again 29 | 30 | Mute_NotEnoughPlayers = ^3Not enough players! 31 | Mute_PlayerNotConnected = ^3Player not connected! 32 | 33 | Mute_PlayerMutedYou = Muted you 34 | 35 | Mute_PlayerNowMutedYou = CAN'T hear you now. 36 | Mute_PlayerNowUnmutedYou = can hear you now. 37 | 38 | Mute_UseTooOften = ^3You use very often! 39 | 40 | Mute_PlayerNowMutedAll = CAN'T hear anybody now! 41 | Mute_PlayerNowUnmutedAll = can hear anybody now. 42 | 43 | Mute_prefix = [^3MUTE^1] 44 | 45 | [es] 46 | Mute_MenuTitle = Menu de Muteo de Jugadores: 47 | Mute_MuteAll = Mutear a Todos 48 | 49 | Mute_YouMutePlayer = Ahora no podes oir a ese jugador. 50 | Mute_YouUnmutePlayer = Ahora podes oir a ese jugador. 51 | 52 | Mute_NotEnoughPlayers = No hay suficiente jugadores! 53 | Mute_PlayerNotConnected = ^3Jugador no esta conectado! 54 | 55 | Mute_PlayerMutedYou = Te Muteo 56 | 57 | Mute_PlayerNowMutedYou = No puede oirte. 58 | Mute_PlayerNowUnmutedYou = Ahora puede oirte. 59 | 60 | Mute_UseTooOften = ^3Espera unos segundos antes de volver a usar! 61 | 62 | Mute_PlayerNowMutedAll = Ahora no escuchas a nadie. 63 | Mute_PlayerNowUnmutedAll = Ahora podes escuchar a todos. 64 | 65 | Mute_prefix = [^3MUTE^1] 66 | 67 | [de] 68 | Mute_MenuTitle = Spieler muten: 69 | Mute_MuteAll = Alle muten 70 | 71 | Mute_YouMutePlayer = Der Spieler ist gemuted 72 | Mute_YouUnmutePlayer = Du kannst den Spieler wieder hören 73 | 74 | Mute_NotEnoughPlayers = ^3Nicht genug Spieler! 75 | Mute_PlayerNotConnected = ^3Spieler nicht verbunden! 76 | 77 | Mute_PlayerMutedYou = hat Dich gemuted 78 | 79 | Mute_PlayerNowMutedYou = hat Dich jetzt gemuted. 80 | Mute_PlayerNowUnmutedYou = kann Dich wieder hören. 81 | 82 | Mute_UseTooOften = ^3Warte ein paar Sekunden! 83 | 84 | Mute_PlayerNowMutedAll = Du hörst NIEMANDEN! 85 | Mute_PlayerNowUnmutedAll = Du hörst ALLE! 86 | 87 | Mute_prefix = [^3MUTE^1] 88 | 89 | [pl] 90 | Mute_MenuTitle = Menu mutowania graczy: 91 | Mute_MuteAll = Zmutuj wszystkich 92 | 93 | Mute_YouMutePlayer = Zmutowales 94 | Mute_YouUnmutePlayer = Odmutowales 95 | 96 | Mute_NotEnoughPlayers = ^4Brak graczy, ktorych mozesz zmutowac! 97 | Mute_PlayerNotConnected = ^3Gracz nie jest polaczony! 98 | 99 | Mute_PlayerMutedYou = Zmutowany 100 | 101 | Mute_PlayerNowMutedYou = Zmutowal Cie. 102 | Mute_PlayerNowUnmutedYou = Odmutowal Cie 103 | 104 | Mute_UseTooOften = ^3Bardzo czesto tego uzywasz 105 | 106 | Mute_PlayerNowMutedAll = Zmutowales wszystkich! 107 | Mute_PlayerNowUnmutedAll = Odmutowales wszystkich 108 | 109 | Mute_prefix = [^3MUTE^1] 110 | 111 | [ua] 112 | Mute_MenuTitle = Заглушити гравця: 113 | Mute_MuteAll = Заглушити всіх 114 | 115 | Mute_YouMutePlayer = Ви НЕ чуєте гравця 116 | Mute_YouUnmutePlayer = Ви знову чуєте гравця 117 | 118 | Mute_NotEnoughPlayers = ^3Недостатньо гравців! 119 | Mute_PlayerNotConnected = ^3Гравець не підключений! 120 | 121 | Mute_PlayerMutedYou = Не чує Вас 122 | 123 | Mute_PlayerNowMutedYou = тепер НЕ чує Вас. 124 | Mute_PlayerNowUnmutedYou = знову чує Вас. 125 | 126 | Mute_UseTooOften = ^3Ви використовуєте занадто часто! 127 | 128 | Mute_PlayerNowMutedAll = тепер НЕ чує нікого! 129 | Mute_PlayerNowUnmutedAll = знову чує всіх. 130 | 131 | Mute_prefix = [^3MUTE^1] 132 | 133 | [ro] 134 | Mute_MenuTitle = Meniul pentru mut al jucatorilor: 135 | Mute_MuteAll = Dezactiveaza tuturor 136 | 137 | Mute_YouMutePlayer = Nu mai auzi jucatorul 138 | Mute_YouUnmutePlayer = Auzi din nou jucatorul 139 | 140 | Mute_NotEnoughPlayers = ^3Nu sunt suficienti jucatori! 141 | Mute_PlayerNotConnected = ^3Jucatorul nu este conectat! 142 | 143 | Mute_PlayerMutedYou = Te-a restrictionat 144 | 145 | Mute_PlayerNowMutedYou = Nu te mai poate auzi. 146 | Mute_PlayerNowUnmutedYou = te poate auzi. 147 | 148 | Mute_UseTooOften = ^3Folosesti prea des! 149 | 150 | Mute_PlayerNowMutedAll = Nu poate auzi pe nimeni! 151 | Mute_PlayerNowUnmutedAll = poate sa ii auda pe toti. 152 | 153 | Mute_prefix = [^3MUTE^1] -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/scripting/ChatAdditions/Addons/CA_Addon_DeathMute.sma: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #pragma tabsize 4 8 | 9 | new Float: ca_deathmute_time, 10 | bool: ca_deathmute_dead_hear_alive, 11 | NotifyType_s: ca_deathmute_notify_type, 12 | bool: ca_deathmute_notify_show_progressbar, 13 | Float: ca_deathmute_notify_hud_x, 14 | Float: ca_deathmute_notify_hud_y, 15 | ca_deathmute_notify_hud_r, 16 | ca_deathmute_notify_hud_g, 17 | ca_deathmute_notify_hud_b, 18 | ca_deathmute_immunity_flags[16] 19 | 20 | enum NotifyType_s: { 21 | notify_Disabled, 22 | notify_Chat, 23 | notify_HUD 24 | } 25 | 26 | new bool: g_canSpeakWithAlive[MAX_PLAYERS + 1] 27 | 28 | new g_syncHudOj 29 | 30 | public stock const PluginName[] = "CA Addon: Death mute" 31 | public stock const PluginVersion[] = CA_VERSION 32 | public stock const PluginAuthor[] = "Sergey Shorokhov" 33 | public stock const PluginURL[] = "https://github.com/ChatAdditions/" 34 | public stock const PluginDescription[] = "Alive players don't hear dead players after 5 secs" 35 | 36 | public plugin_init() { 37 | register_plugin(PluginName, PluginVersion, PluginAuthor) 38 | 39 | register_dictionary("CA_Addon_DeathMute.txt") 40 | 41 | Create_CVars() 42 | 43 | AutoExecConfig(true, "CA_Addon_DeathMute", "ChatAdditions") 44 | 45 | // RegisterHam(Ham_TFC_Killed, "player", "CBasePlayer_Killed", .Post = true) // Does it need ?! 46 | RegisterHam(Ham_Killed, "player", "CBasePlayer_Killed", .Post = true) 47 | RegisterHam(Ham_Spawn, "player", "CBasePlayer_Spawn", .Post = true) 48 | 49 | g_syncHudOj = CreateHudSyncObj() 50 | } 51 | 52 | Create_CVars() { 53 | bind_pcvar_float(create_cvar("ca_deathmute_time", "5.0", 54 | .description = "Time (in seconds) for killed players, during which they can report information to living players.^n\ 55 | 0 - disabled functionality", 56 | .has_min = true, .min_val = 0.0, 57 | .has_max = true, .max_val = 240.0 58 | ), ca_deathmute_time 59 | ) 60 | 61 | bind_pcvar_num(create_cvar("ca_deathmute_dead_hear_alive", "1", 62 | .description = "Death mute mode^n\ 63 | 0 - alive hear only alive, dead hear all^n\ 64 | 1 - alive hear only alive, dead hear only dead", 65 | .has_min = true, .min_val = 0.0, 66 | .has_max = true, .max_val = 1.0 67 | ), ca_deathmute_dead_hear_alive 68 | ) 69 | 70 | bind_pcvar_num(create_cvar("ca_deathmute_notify_type", "1", 71 | .description = "Notification type for dead players ^n\ 72 | 0 - disabled functionality^n\ 73 | 1 - chat message^n\ 74 | 2 - HUD message" 75 | ), ca_deathmute_notify_type 76 | ) 77 | 78 | bind_pcvar_num(create_cvar("ca_deathmute_notify_show_progressbar", "1", 79 | .description = "Show progressbar ^n\ 80 | 0 - disabled functionality" 81 | ), ca_deathmute_notify_show_progressbar 82 | ) 83 | 84 | bind_pcvar_float(create_cvar("ca_deathmute_notify_hud_x", "-1.0", 85 | .description = "X position for HUD message^n\ 86 | -1.0 - center", 87 | .has_min = true, .min_val = -1.0, 88 | .has_max = true, .max_val = 1.0 89 | ), ca_deathmute_notify_hud_x 90 | ) 91 | 92 | bind_pcvar_float(create_cvar("ca_deathmute_notify_hud_y", "0.15", 93 | .description = "Y position for HUD message^n\ 94 | -1.0 - center", 95 | .has_min = true, .min_val = -1.0, 96 | .has_max = true, .max_val = 1.0 97 | ), ca_deathmute_notify_hud_y 98 | ) 99 | 100 | bind_pcvar_num(create_cvar("ca_deathmute_notify_hud_r", "200", 101 | .description = "Red color value (in RGB) [0...255]", 102 | .has_min = true, .min_val = 0.0, 103 | .has_max = true, .max_val = 255.0 104 | ), ca_deathmute_notify_hud_r 105 | ) 106 | 107 | bind_pcvar_num(create_cvar("ca_deathmute_notify_hud_g", "50", 108 | .description = "Green color value (in RGB) [0...255]", 109 | .has_min = true, .min_val = 0.0, 110 | .has_max = true, .max_val = 255.0 111 | ), ca_deathmute_notify_hud_g 112 | ) 113 | 114 | bind_pcvar_num(create_cvar("ca_deathmute_notify_hud_b", "0", 115 | .description = "Blue color value (in RGB) [0...255]", 116 | .has_min = true, .min_val = 0.0, 117 | .has_max = true, .max_val = 255.0 118 | ), ca_deathmute_notify_hud_b 119 | ) 120 | 121 | bind_pcvar_string(create_cvar("ca_deathmute_immunity_flags", "a", 122 | .description = "User immunity flag" 123 | ), 124 | ca_deathmute_immunity_flags, charsmax(ca_deathmute_immunity_flags) 125 | ) 126 | } 127 | 128 | public client_disconnected(id) { 129 | g_canSpeakWithAlive[id] = false 130 | 131 | remove_task(id) 132 | } 133 | 134 | public CBasePlayer_Spawn(const id) { 135 | if (!is_user_alive(id)) 136 | return 137 | 138 | g_canSpeakWithAlive[id] = true 139 | 140 | remove_task(id) 141 | } 142 | 143 | public CBasePlayer_Killed(const id, const attacker) { 144 | if (ca_deathmute_time <= 0.0) { 145 | return 146 | } 147 | 148 | set_task_ex(ca_deathmute_time, "DisableSpeakWithAlive", .id = id) 149 | 150 | switch (ca_deathmute_notify_type) { 151 | case notify_Disabled: return 152 | 153 | case notify_Chat: client_print_color(id, print_team_red, "%L %L", id, "DeathMute_prefix", id, "DeathMute_ChatMessage", ca_deathmute_time) 154 | 155 | case notify_HUD: { 156 | set_hudmessage( 157 | ca_deathmute_notify_hud_r, 158 | ca_deathmute_notify_hud_g, 159 | ca_deathmute_notify_hud_b, 160 | ca_deathmute_notify_hud_x, 161 | ca_deathmute_notify_hud_y, 162 | .fadeouttime = 0.0, 163 | .holdtime = ca_deathmute_time - 1.0 164 | ) 165 | 166 | static clearedMessage[256] 167 | 168 | formatex(clearedMessage, charsmax(clearedMessage), "%L", id, "DeathMute_ChatMessage", ca_deathmute_time) 169 | ReplaceColors(clearedMessage, charsmax(clearedMessage)) 170 | 171 | ShowSyncHudMsg(id, g_syncHudOj, clearedMessage) 172 | } 173 | } 174 | 175 | if (ca_deathmute_notify_show_progressbar) { 176 | UTIL_BarTime(id, floatround(ca_deathmute_time)) 177 | } 178 | } 179 | 180 | public DisableSpeakWithAlive(const id) { 181 | g_canSpeakWithAlive[id] = false 182 | 183 | switch (ca_deathmute_notify_type) { 184 | case notify_Chat: client_print_color(id, print_team_red, "%L %L", id, "DeathMute_prefix", id, "DeathMute_YouMuted") 185 | 186 | case notify_HUD: { 187 | set_hudmessage( 188 | ca_deathmute_notify_hud_r, 189 | ca_deathmute_notify_hud_g, 190 | ca_deathmute_notify_hud_b, 191 | ca_deathmute_notify_hud_x, 192 | ca_deathmute_notify_hud_y, 193 | .fadeouttime = 0.0, 194 | .holdtime = ca_deathmute_time - 1.0 195 | ) 196 | 197 | static clearedMessage[256] 198 | 199 | formatex(clearedMessage, charsmax(clearedMessage), "%L", id, "DeathMute_YouMuted", ca_deathmute_time) 200 | ReplaceColors(clearedMessage, charsmax(clearedMessage)) 201 | 202 | ShowSyncHudMsg(id, g_syncHudOj, clearedMessage) 203 | } 204 | } 205 | } 206 | 207 | public CA_Client_Voice(const listener, const sender) { 208 | if (ca_deathmute_time <= 0.0) { 209 | return CA_CONTINUE 210 | } 211 | 212 | new bool: listenerHasImmunity = bool: (get_user_flags(listener) & read_flags(ca_deathmute_immunity_flags)) 213 | 214 | if (listenerHasImmunity) { 215 | return CA_CONTINUE 216 | } 217 | 218 | new bool: listenerAlive = bool: is_user_alive(listener) 219 | new bool: senderAlive = bool: is_user_alive(sender) 220 | 221 | if (!g_canSpeakWithAlive[sender] && !senderAlive && listenerAlive) { 222 | return CA_SUPERCEDE 223 | } 224 | 225 | if (!ca_deathmute_dead_hear_alive && !listenerAlive && senderAlive) { 226 | return CA_SUPERCEDE 227 | } 228 | 229 | return CA_CONTINUE 230 | } 231 | 232 | stock ReplaceColors(text[], len) 233 | { 234 | replace_string(text, len, "^1", "") 235 | replace_string(text, len, "^3", "") 236 | replace_string(text, len, "^4", "") 237 | } 238 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/scripting/ChatAdditions/Addons/CA_Addon_RankRestrictions.sma: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #tryinclude 4 | 5 | #include 6 | 7 | #pragma tabsize 4 8 | 9 | // Natives 10 | native aes_get_player_level(const player) 11 | native ar_get_user_level(const player, rankName[] = "", len = 0) 12 | native crxranks_get_user_level(const player) 13 | native cmsranks_get_user_level(player, level[] = "", len = 0) 14 | native csstats_get_user_stats(const player, const stats[22]) 15 | native Float:cmsstats_get_user_skill(player, skillname[] = "", namelen = 0, &skill_level = 0) 16 | native get_user_skill(player, &Float: skill) 17 | native get_user_stats(player, stats[STATSX_MAX_STATS], bodyhits[MAX_BODYHITS]) 18 | // 19 | 20 | 21 | enum any: eChatType { 22 | voice_chat, 23 | text_chat 24 | } 25 | 26 | enum any: eRankRestrictionsType { 27 | rr_type_none, 28 | rr_type_level, 29 | rr_type_frags 30 | } 31 | 32 | const Float: STATS_THINKER_FREQ = 30.0 33 | 34 | enum Stats_s { 35 | Stats_Level, 36 | Stats_Kills, 37 | Float: Stats_NextUpdate, 38 | } 39 | 40 | new g_playersStats[MAX_PLAYERS + 1][Stats_s] 41 | 42 | new ca_rankrestrictions_type, 43 | ca_rankrestrictions_type_kills, 44 | ca_rankrestrictions_min_kills_voice_chat, 45 | ca_rankrestrictions_min_kills_text_chat, 46 | ca_rankrestrictions_type_level, 47 | ca_rankrestrictions_min_level_voice_chat, 48 | ca_rankrestrictions_min_level_text_chat, 49 | ca_rankrestrictions_immunity_flag[16], 50 | ca_rankrestrictions_steam_immunity 51 | 52 | public stock const PluginName[] = "CA Addon: Rank restrictions" 53 | public stock const PluginVersion[] = CA_VERSION 54 | public stock const PluginAuthor[] = "steelzzz" 55 | public stock const PluginURL[] = "https://github.com/ChatAdditions/" 56 | public stock const PluginDescription[] = "Restrict chat until you reach the rank of a statistic" 57 | 58 | public plugin_init() { 59 | register_plugin(PluginName, PluginVersion, PluginAuthor) 60 | register_dictionary("CA_Addon_RankRestrictions.txt") 61 | 62 | Create_CVars() 63 | 64 | AutoExecConfig(true, "CA_Addon_RankRestrictions", "ChatAdditions") 65 | } 66 | 67 | public plugin_natives() { 68 | set_native_filter("native_filter") 69 | } 70 | 71 | public native_filter(const name[], index, trap) { 72 | new const na[][] = { 73 | "aes_get_player_level", 74 | "ar_get_user_level", 75 | "crxranks_get_user_level", 76 | "csstats_get_user_stats", 77 | "cmsranks_get_user_level", 78 | "cmsstats_get_user_skill", 79 | "get_user_stats" 80 | } 81 | 82 | for (new i; i < sizeof(na); i++) { 83 | if (strcmp(na[i], name) != 0) 84 | return PLUGIN_HANDLED 85 | } 86 | 87 | return PLUGIN_CONTINUE 88 | } 89 | 90 | Create_CVars() { 91 | bind_pcvar_num(create_cvar("ca_rankrestrictions_type", "1", 92 | .description = "Restrictions Type^n\ 93 | 0 - Disable restrictions^n\ 94 | 1 - Level restrictions^n\ 95 | 2 - Kills count restrictions", 96 | .has_min = true, .min_val = 0.0, 97 | .has_max = true, .max_val = 2.0 98 | ), ca_rankrestrictions_type 99 | ) 100 | 101 | bind_pcvar_num(create_cvar("ca_rankrestrictions_type_kills", "1", 102 | .description = "Kill System Types^n\ 103 | 0 - CSStats MySQL^n\ 104 | 1 - CSX Module", 105 | .has_min = true, .min_val = 0.0, 106 | .has_max = true, .max_val = 1.0 107 | ), ca_rankrestrictions_type_kills 108 | ) 109 | 110 | bind_pcvar_num(create_cvar("ca_rankrestrictions_min_kills_voice_chat", "10", 111 | .description = "Min kills count to access VOICE chat", 112 | .has_min = true, .min_val = 0.0 113 | ), ca_rankrestrictions_min_kills_voice_chat 114 | ) 115 | 116 | bind_pcvar_num(create_cvar("ca_rankrestrictions_min_kills_text_chat", "10", 117 | .description = "Min kills count to access TEXT chat", 118 | .has_min = true, .min_val = 0.0 119 | ), ca_rankrestrictions_min_kills_text_chat 120 | ) 121 | 122 | bind_pcvar_num(create_cvar("ca_rankrestrictions_type_level", "1", 123 | .description = "Level System Types^n\ 124 | 0 - Advanced Experience System^n\ 125 | 1 - Army Ranks Ultimate^n\ 126 | 2 - OciXCrom's Rank System^n\ 127 | 3 - CMSStats Ranks^n\ 128 | 4 - CMSStats MySQL^n\ 129 | 5 - CSstatsX SQL^n\ 130 | 6 - CSX Module", 131 | .has_min = true, .min_val = 0.0, 132 | .has_max = true, .max_val = 6.0 133 | ), ca_rankrestrictions_type_level 134 | ) 135 | 136 | bind_pcvar_num(create_cvar("ca_rankrestrictions_min_level_voice_chat", "2", 137 | .description = "Min Level to access VOICE chat", 138 | .has_min = true, .min_val = 0.0 139 | ), ca_rankrestrictions_min_level_voice_chat 140 | ) 141 | 142 | bind_pcvar_num(create_cvar("ca_rankrestrictions_min_level_text_chat", "2", 143 | .description = "Min Level to access TEXT chat", 144 | .has_min = true, .min_val = 0.0 145 | ), ca_rankrestrictions_min_level_text_chat 146 | ) 147 | 148 | bind_pcvar_string(create_cvar("ca_rankrestrictions_immunity_flag", "a", 149 | .description = "User immunity flag" 150 | ), 151 | ca_rankrestrictions_immunity_flag, charsmax(ca_rankrestrictions_immunity_flag) 152 | ) 153 | 154 | bind_pcvar_num(create_cvar("ca_rankrestrictions_steam_immunity", "0", 155 | .description = "Enable immunity for steam players", 156 | .has_min = true, .min_val = 0.0, 157 | .has_max = true, .max_val = 1.0 158 | ), ca_rankrestrictions_steam_immunity 159 | ) 160 | } 161 | 162 | public client_putinserver(player) { 163 | Stats_Update(player) 164 | } 165 | 166 | public client_remove(player) { 167 | Stats_Update(player) 168 | } 169 | 170 | public CA_Client_Say(player, const bool: isTeamMessage, const message[]) { 171 | if (!CanCommunicate(player, true, text_chat)) { 172 | return CA_SUPERCEDE 173 | } 174 | 175 | return CA_CONTINUE 176 | } 177 | 178 | public CA_Client_Voice(const listener, const sender) { 179 | if (!CanCommunicate(sender, false, voice_chat)) { 180 | // need chat notification? 181 | return CA_SUPERCEDE 182 | } 183 | 184 | return CA_CONTINUE 185 | } 186 | 187 | bool: CanCommunicate(const player, const bool: print, chatType) { 188 | if (ca_rankrestrictions_type <= rr_type_none) { 189 | return true 190 | } 191 | 192 | // check is gagged? 193 | if (get_user_flags(player) & read_flags(ca_rankrestrictions_immunity_flag)) { 194 | return true 195 | } 196 | 197 | if (ca_rankrestrictions_steam_immunity && _is_user_steam(player)) { 198 | return true 199 | } 200 | 201 | switch (chatType) { 202 | case voice_chat: { 203 | if (ca_rankrestrictions_type == rr_type_level && g_playersStats[player][Stats_Level] < ca_rankrestrictions_min_level_voice_chat) { 204 | if (print) { 205 | client_print_color(player, print_team_red, "%L", 206 | player, "RankRestrictions_Warning_MinLevel", ca_rankrestrictions_min_level_voice_chat 207 | ) 208 | } 209 | 210 | return false 211 | } 212 | 213 | if (ca_rankrestrictions_type == rr_type_frags && g_playersStats[player][Stats_Kills] < ca_rankrestrictions_min_kills_voice_chat) { 214 | if (print) { 215 | client_print_color(player, print_team_red, "%L", 216 | player, "RankRestrictions_Warning_MinKills", ca_rankrestrictions_min_kills_voice_chat 217 | ) 218 | } 219 | 220 | return false 221 | } 222 | } 223 | 224 | case text_chat: { 225 | if (ca_rankrestrictions_type == rr_type_level && g_playersStats[player][Stats_Level] < ca_rankrestrictions_min_level_text_chat) { 226 | if (print) { 227 | client_print_color(player, print_team_red, "%L", 228 | player, "RankRestrictions_Warning_MinLevel", ca_rankrestrictions_min_level_text_chat 229 | ) 230 | } 231 | 232 | return false 233 | } 234 | 235 | if (ca_rankrestrictions_type == rr_type_frags && g_playersStats[player][Stats_Kills] < ca_rankrestrictions_min_kills_text_chat) { 236 | if (print) { 237 | client_print_color(player, print_team_red, "%L", 238 | player, "RankRestrictions_Warning_MinKills", ca_rankrestrictions_min_kills_text_chat 239 | ) 240 | } 241 | 242 | return false 243 | } 244 | } 245 | } 246 | 247 | return true 248 | } 249 | 250 | Stats_ReadUserLevel(const player) { 251 | switch (ca_rankrestrictions_type_level) { 252 | case 0: return aes_get_player_level(player) 253 | case 1: return ar_get_user_level(player) 254 | case 2: return crxranks_get_user_level(player) 255 | case 3: return cmsranks_get_user_level(player) 256 | case 4: { 257 | new iSkill 258 | cmsstats_get_user_skill(player, .skill_level = iSkill) 259 | return iSkill 260 | } 261 | case 5: { 262 | new Float:iSkill 263 | get_user_skill(player, iSkill) 264 | return floatround(iSkill) 265 | } 266 | case 6: { 267 | new stats[STATSX_MAX_STATS], hits[MAX_BODYHITS] 268 | get_user_stats(player, stats, hits) 269 | return stats[STATSX_RANK] 270 | } 271 | } 272 | 273 | return 0 274 | } 275 | 276 | Stats_ReadUserFrags(const player) { 277 | enum { stats_Frags/* , stats_Deaths, stats_Rounds = 16 */ } 278 | 279 | switch (ca_rankrestrictions_type_kills) { 280 | case 0: { 281 | new stats[22] 282 | csstats_get_user_stats(player, stats) 283 | return stats[stats_Frags] 284 | } 285 | case 1: { 286 | new stats[STATSX_MAX_STATS], hits[MAX_BODYHITS] 287 | get_user_stats(player, stats, hits) 288 | return stats[STATSX_KILLS] 289 | } 290 | } 291 | 292 | return 0 293 | } 294 | 295 | public Stats_Update(player) { 296 | if (!is_user_connected(player) || is_user_bot(player)) { 297 | g_playersStats[player][Stats_Level] = 0 298 | g_playersStats[player][Stats_Kills] = 0 299 | g_playersStats[player][Stats_NextUpdate] = 0.0 300 | 301 | remove_task(player) 302 | return 303 | } 304 | 305 | if (!task_exists(player)) 306 | set_task_ex(STATS_THINKER_FREQ, "Stats_Update", .id = player, .flags = SetTask_Repeat) 307 | 308 | new Float: gametime = get_gametime() 309 | if (g_playersStats[player][Stats_NextUpdate] > gametime) 310 | return 311 | 312 | g_playersStats[player][Stats_Level] = Stats_ReadUserLevel(player) 313 | g_playersStats[player][Stats_Kills] = Stats_ReadUserFrags(player) 314 | g_playersStats[player][Stats_NextUpdate] = gametime + STATS_THINKER_FREQ 315 | } 316 | 317 | static stock bool: _is_user_steam(const player) { 318 | #if (defined _reapi_reunion_included) 319 | if (has_reunion()) 320 | return (REU_GetAuthtype(player) == CA_TYPE_STEAM) 321 | #endif 322 | 323 | static dp_r_id_provider 324 | if (dp_r_id_provider || (dp_r_id_provider = get_cvar_pointer("dp_r_id_provider"))) { 325 | server_cmd("dp_clientinfo %i", player) 326 | server_exec() 327 | 328 | #define DP_AUTH_STEAM 2 329 | if (get_pcvar_num(dp_r_id_provider) == DP_AUTH_STEAM) 330 | return true 331 | 332 | return false 333 | } 334 | 335 | return false 336 | } 337 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/scripting/ChatAdditions/Addons/CA_Addon_RequestUnGag.sma: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #pragma tabsize 4 8 | 9 | new Float: g_userNextRequestTime[MAX_PLAYERS + 1] 10 | 11 | new ca_requestungag_cmd[32], 12 | Float: ca_requestungag_delay, 13 | ca_gag_access_flags_high[32], 14 | ca_gag_access_flags[32] 15 | 16 | public stock const PluginName[] = "CA Addon: Request UnGAG" 17 | public stock const PluginVersion[] = CA_VERSION 18 | public stock const PluginAuthor[] = "steelzzz" 19 | public stock const PluginURL[] = "https://github.com/ChatAdditions/" 20 | public stock const PluginDescription[] = "A player can apologize to the administration" 21 | 22 | public plugin_init() { 23 | register_plugin(PluginName, PluginVersion, PluginAuthor) 24 | register_dictionary("CA_Addon_RequestUngag.txt") 25 | 26 | Create_CVars() 27 | 28 | AutoExecConfig(true, "CA_Addon_RequestUnGag", "ChatAdditions") 29 | } 30 | 31 | public Create_CVars() { 32 | bind_pcvar_string(create_cvar("ca_requestungag_cmd", "/sorry", 33 | .description = "Request ungag command"), 34 | ca_requestungag_cmd, charsmax(ca_requestungag_cmd) 35 | ) 36 | 37 | bind_pcvar_float(create_cvar("ca_requestungag_delay", "40.0", 38 | .description = "delay time request ungag", 39 | .has_min = true, .min_val = 1.0), 40 | ca_requestungag_delay 41 | ) 42 | 43 | bind_pcvar_string(get_cvar_pointer("ca_gag_access_flags_high"), 44 | ca_gag_access_flags_high, charsmax(ca_gag_access_flags_high) 45 | ) 46 | 47 | bind_pcvar_string(get_cvar_pointer("ca_gag_access_flags"), 48 | ca_gag_access_flags, charsmax(ca_gag_access_flags) 49 | ) 50 | } 51 | 52 | // TODO: Create `_PRE` hook forward instead this. 53 | public CA_Client_Say(player, const bool: isTeamMessage, const message[]) { 54 | if (strcmp(message, ca_requestungag_cmd) != 0) 55 | return CA_CONTINUE 56 | 57 | if (!ca_has_user_gag(player)) { 58 | client_print_color(player, print_team_default, "%L", player, "RequestUnGag_NoAccess") 59 | 60 | return CA_SUPERCEDE 61 | } 62 | 63 | new Float: gametime = get_gametime() 64 | if (g_userNextRequestTime[player] > gametime) { 65 | new timeLeft = floatround(g_userNextRequestTime[player] - gametime, floatround_ceil) 66 | client_print_color(player, print_team_default, "%L", player, "RequestUnGag_TimeOut", timeLeft) 67 | 68 | return CA_SUPERCEDE 69 | } 70 | 71 | new userID = get_user_userid(player) 72 | 73 | new players[MAX_PLAYERS], count 74 | get_players_ex(players, count, (GetPlayers_ExcludeBots | GetPlayers_ExcludeHLTV)) 75 | 76 | new accessFlagsHigh = read_flags(ca_gag_access_flags_high) 77 | new accessFlags = read_flags(ca_gag_access_flags) 78 | 79 | for(new i; i < count; i++) { 80 | new receiver = players[i] 81 | 82 | if (receiver == player) 83 | continue 84 | 85 | if (!(get_user_flags(receiver) & (accessFlags | accessFlagsHigh))) 86 | continue 87 | 88 | client_print_color(receiver, print_team_default, "%L", 89 | receiver, "RequestUnGag_Requested", 90 | player, userID 91 | ) 92 | } 93 | 94 | g_userNextRequestTime[player] = gametime + ca_requestungag_delay 95 | 96 | client_print_color(player, print_team_default, "%L", player, "RequestUnGag_YouRequested") 97 | return CA_SUPERCEDE 98 | } 99 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/scripting/ChatAdditions/Addons/CA_Addon_VoteGag.sma: -------------------------------------------------------------------------------- 1 | /* 2 | * The plugin is based on an existing plugin from UCC by neygomon. 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | 9 | /* ======== SETTINGS ======== */ 10 | #define PREFIX "CA: VoteGAG" // Префикс сообщений в чате 11 | #define REPEAT_VOTE_MIN 2 // Частота повторных голосований 12 | #define PERCENT_VOTE_OK 60 // Процент голосов для успешного голосования 13 | #define BLOCK_TIME_MIN 3 // Время GAG'a игрока 14 | #define CHECK_VOTE_TIME 15.0 // Продолжительность голосования 15 | const IMMUNITY_FLAGS = ADMIN_IMMUNITY; // Иммунитет к функциям VoteGAG'а 16 | /* ======== LANG ======== */ 17 | #define MSG_PLMENU_TITLE "\d[\rVoteGag\d] \yВыберите игрока" 18 | #define MSG_VMENU_TITLE "\d[\rVoteGag\d] \yЗаткнуть игрока \r%s\y?" 19 | #define MSG_MENU_YES "\rДа" 20 | #define MSG_MENU_NO "\yНет" 21 | #define MSG_MENU_NEXT "\yДалее" 22 | #define MSG_MENU_BACK "\rНазад" 23 | #define MSG_MENU_EXIT "\rВыход" 24 | 25 | #define MSG_VOTE_START "^1[^4%s^1] ^3%n^4 Запустил голосование за ^1gag ^4игрока ^3%n^1!" 26 | #define MSG_VOTE_EXISTS "^1[^4%s^1] ^4Голосование за ^1gag ^4игрока ^3уже запужено!" 27 | #define MSG_VOTE_BLOCK "^1[^4%s^1] ^4Голосование будет доступно через ^3%d сек." 28 | #define MSG_VOTING_FAIL "^1[^4%s^1] ^4Голосование завершилось ^3неудачно^4. Недостаточно голосов ^1[^3%d^1/^3%d^1]" 29 | #define MSG_VOTING_OK_ALL "^1[^4%s^1] ^4Голосование завершилось ^3удачно^4. Игрок ^3%s ^4GAG'нут на ^3%d ^4мин." 30 | #define MSG_VOTING_OK_PL "^1[^4%s^1] ^4Голосование за Ваш GAG завершилось ^3удачно^4. Вам отключены чаты на ^3%d ^4мин." 31 | #define MSG_VOTING_DISC "^1[^4%s^1] ^4Игрок, за которого Вы запускали GAG голосование, покинул сервер" 32 | /* ======== EndLANG ======== */ 33 | 34 | 35 | #if !defined MAX_PLAYERS 36 | const MAX_PLAYERS = 32 37 | #endif 38 | 39 | new g_VotingMenu 40 | new g_iVotingIndex, g_iVotingLasttime 41 | new g_arrPlayers[MAX_PLAYERS], g_iPnum 42 | new bool:g_bPlayerVoted[MAX_PLAYERS + 1], g_iPlayersVotedCount 43 | 44 | 45 | public plugin_init() 46 | { 47 | register_plugin("CA: VoteGAG", "1.0.1-alpha", "Sergey Shorokhov") 48 | 49 | register_clcmd("say /votegag", "clcmd_VoteGag") 50 | register_clcmd("say_team /votegag", "clcmd_VoteGag") 51 | register_clcmd("votegag", "clcmd_VoteGag") 52 | } 53 | 54 | public plugin_cfg() 55 | { 56 | g_VotingMenu = menu_create("Title", "voting_handler") 57 | menu_setprop(g_VotingMenu, MPROP_EXIT, MEXIT_NEVER) 58 | menu_additem(g_VotingMenu, MSG_MENU_YES, "1") 59 | menu_additem(g_VotingMenu, MSG_MENU_NO, "0") 60 | } 61 | 62 | public client_disconnected(id) 63 | { 64 | if (g_bPlayerVoted[id]) 65 | { 66 | g_bPlayerVoted[id] = false 67 | g_iPlayersVotedCount-- 68 | } 69 | } 70 | 71 | public clcmd_VoteGag(id) 72 | { 73 | if (g_iVotingIndex) 74 | { 75 | ChatColor(id, 0, MSG_VOTE_EXISTS, PREFIX) 76 | return PLUGIN_HANDLED 77 | } 78 | new time = g_iVotingLasttime + REPEAT_VOTE_MIN * 60 - get_systime() 79 | if (time > 0) 80 | { 81 | ChatColor(id, 0, MSG_VOTE_BLOCK, PREFIX, time % 60) 82 | return PLUGIN_HANDLED 83 | } 84 | 85 | new szName[32], num[3], menu, callback 86 | menu = menu_create(MSG_PLMENU_TITLE, "players_handler") 87 | callback = menu_makecallback("players_callback") 88 | 89 | menu_setprop(menu, MPROP_NEXTNAME, MSG_MENU_NEXT) 90 | menu_setprop(menu, MPROP_BACKNAME, MSG_MENU_BACK) 91 | menu_setprop(menu, MPROP_EXITNAME, MSG_MENU_EXIT) 92 | 93 | get_players(g_arrPlayers, g_iPnum, "h") 94 | 95 | for(new i; i < g_iPnum; i++) 96 | { 97 | if (g_arrPlayers[i] == id) 98 | continue 99 | 100 | get_user_name(g_arrPlayers[i], szName, charsmax(szName)) 101 | num_to_str(g_arrPlayers[i], num, charsmax(num)) 102 | menu_additem(menu, szName, num, .callback = callback) 103 | } 104 | 105 | menu_display(id, menu) 106 | return PLUGIN_HANDLED 107 | } 108 | 109 | public players_callback(id, menu, item) 110 | { 111 | new _access, item_data[3], callback 112 | menu_item_getinfo(menu, item, _access, item_data, charsmax(item_data), .callback = callback) 113 | 114 | new index = str_to_num(item_data) 115 | if (!is_user_connected(index)) 116 | return ITEM_DISABLED 117 | if (ca_has_user_gag(index)) 118 | return ITEM_DISABLED 119 | if (get_user_flags(index) & IMMUNITY_FLAGS) 120 | return ITEM_DISABLED 121 | 122 | return ITEM_ENABLED 123 | } 124 | 125 | public players_handler(id, menu, item) 126 | { 127 | if (item == MENU_EXIT) 128 | { 129 | menu_destroy(menu) 130 | return PLUGIN_HANDLED 131 | } 132 | 133 | new _access, item_data[3], callback 134 | menu_item_getinfo(menu, item, _access, item_data, charsmax(item_data), .callback = callback) 135 | g_iVotingIndex = str_to_num(item_data) 136 | menu_destroy(menu) 137 | 138 | new szTitle[128], szName[32] 139 | get_user_name(g_iVotingIndex, szName, charsmax(szName)) 140 | 141 | formatex(szTitle, charsmax(szTitle), MSG_VMENU_TITLE, szName) 142 | menu_setprop(g_VotingMenu, MPROP_TITLE, szTitle) 143 | 144 | ChatColor(0, g_iVotingIndex, MSG_VOTE_START, PREFIX, id, g_iVotingIndex) 145 | 146 | for(new i; i < g_iPnum; i++) 147 | { 148 | if (g_arrPlayers[i] == g_iVotingIndex) 149 | continue 150 | 151 | if (is_user_connected(g_arrPlayers[i])) 152 | menu_display(g_arrPlayers[i], g_VotingMenu) 153 | } 154 | 155 | set_task(CHECK_VOTE_TIME, "task__CheckVotes", id) 156 | return PLUGIN_HANDLED 157 | } 158 | 159 | public voting_handler(id, menu, item) 160 | { 161 | if (item == MENU_EXIT) 162 | return PLUGIN_HANDLED 163 | 164 | new _access, item_data[3], callback 165 | menu_item_getinfo(menu, item, _access, item_data, charsmax(item_data), .callback = callback) 166 | 167 | if (str_to_num(item_data)) 168 | { 169 | g_iPlayersVotedCount++ 170 | g_bPlayerVoted[id] = true 171 | } 172 | return PLUGIN_HANDLED 173 | } 174 | 175 | public task__CheckVotes(id) 176 | { 177 | for(new i; i < g_iPnum; i++) 178 | { 179 | if (is_user_connected(g_arrPlayers[i])) 180 | show_menu(g_arrPlayers[i], 0, "^n") 181 | } 182 | 183 | new iVoteCount = floatround(g_iPnum * PERCENT_VOTE_OK / 100.0) 184 | 185 | if (g_iPlayersVotedCount >= iVoteCount) 186 | { 187 | if (is_user_connected(g_iVotingIndex)) 188 | { 189 | ca_set_user_gag(g_iVotingIndex, PREFIX, BLOCK_TIME_MIN, (gagFlag_Say | gagFlag_SayTeam | gagFlag_Voice)) 190 | 191 | new szName[32] 192 | get_user_name(g_iVotingIndex, szName, charsmax(szName)) 193 | ChatColor(0, g_iVotingIndex, MSG_VOTING_OK_ALL, PREFIX, szName, BLOCK_TIME_MIN) 194 | ChatColor(g_iVotingIndex, 0, MSG_VOTING_OK_PL, PREFIX, BLOCK_TIME_MIN) 195 | } 196 | else ChatColor(id, 0, MSG_VOTING_DISC, PREFIX) 197 | } 198 | else ChatColor(0, g_iVotingIndex, MSG_VOTING_FAIL, PREFIX, g_iPlayersVotedCount, iVoteCount) 199 | 200 | arrayset(g_bPlayerVoted, false, sizeof g_bPlayerVoted) 201 | g_iPlayersVotedCount = 0 202 | g_iVotingIndex = 0 203 | g_iVotingLasttime = get_systime() 204 | } 205 | 206 | stock ChatColor(id, id2, const szMessage[], any:...) 207 | { 208 | new szMsg[190] 209 | vformat(szMsg, charsmax(szMsg), szMessage, 4) 210 | 211 | if (id) 212 | { 213 | client_print_color(id, print_team_default, szMsg) 214 | } 215 | else 216 | { 217 | new players[32], pnum 218 | get_players(players, pnum, "c") 219 | for(new i; i < pnum; ++i) 220 | { 221 | if (players[i] != id2) 222 | { 223 | client_print_color(players[i], print_team_default, szMsg) 224 | } 225 | } 226 | } 227 | } 228 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/scripting/ChatAdditions/CA_AntiFlood.sma: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #pragma tabsize 4 5 | 6 | new g_OldMessage[MAX_PLAYERS + 1][CA_MAX_MESSAGE_SIZE] 7 | 8 | new Float: ca_anti_flood_time, 9 | ca_equal_messages 10 | 11 | public stock const PluginName[] = "CA: Anti Flood" 12 | public stock const PluginVersion[] = CA_VERSION 13 | public stock const PluginAuthor[] = "Nordic Warrior" 14 | public stock const PluginURL[] = "https://github.com/ChatAdditions/" 15 | public stock const PluginDescription[] = "Antiflood for text chat" 16 | 17 | public plugin_init() { 18 | register_plugin(PluginName, PluginVersion, PluginAuthor) 19 | 20 | register_dictionary("CA_AntiFlood.txt") 21 | 22 | Create_CVars() 23 | 24 | AutoExecConfig(true, "CA_AntiFlood", "ChatAdditions") 25 | } 26 | 27 | public plugin_cfg() { 28 | if (find_plugin_byfile("antiflood.amxx") != INVALID_PLUGIN_ID) { 29 | log_amx("Default plugin was found. It has been stopped.") 30 | pause("acd", "antiflood.amxx") 31 | } 32 | } 33 | 34 | public CA_Client_Say(id, const bool: isTeamMessage, const message[]) { 35 | return CheckMessage(id, message) 36 | } 37 | 38 | 39 | CheckMessage(id, const message[]) { 40 | if (message[0] == '/') { 41 | return CA_CONTINUE 42 | } 43 | 44 | static Float:nextMessage[MAX_PLAYERS + 1] 45 | static equalMessage[MAX_PLAYERS + 1] 46 | 47 | new Float:nextSay = get_gametime() 48 | 49 | if (nextMessage[id] > nextSay) { 50 | client_print_color(id, print_team_red, "%L %L", id, "CA_ANTIFLOOD_CHAT_PREFIX", id, "CA_ANTIFLOOD_CHAT_STOP_FLOODING") 51 | nextMessage[id] = nextSay + ca_anti_flood_time 52 | 53 | return CA_SUPERCEDE 54 | } 55 | 56 | if (strcmp(message, g_OldMessage[id], true) == 0) { 57 | if (++equalMessage[id] >= ca_equal_messages) { 58 | client_print_color(id, print_team_red, "%L %L", id, "CA_ANTIFLOOD_CHAT_PREFIX", id, "CA_ANTIFLOOD_CHAT_EQUAL_MESSAGE") 59 | 60 | return CA_SUPERCEDE 61 | } 62 | } else { 63 | equalMessage[id] = 0 64 | } 65 | 66 | nextMessage[id] = nextSay + ca_anti_flood_time 67 | copy(g_OldMessage[id], charsmax(g_OldMessage[]), message) 68 | 69 | return CA_CONTINUE 70 | } 71 | 72 | public client_disconnected(id) { 73 | g_OldMessage[id][0] = EOS 74 | } 75 | 76 | Create_CVars() { 77 | bind_pcvar_float( 78 | create_cvar( 79 | .name = "ca_anti_flood_time", 80 | .string = "0.75", 81 | .description = "Time between messages^n 0.0 - no limit", 82 | .has_min = true, 83 | .min_val = 0.0 84 | ), 85 | 86 | ca_anti_flood_time 87 | ) 88 | 89 | bind_pcvar_num( 90 | create_cvar( 91 | .name = "ca_equal_messages", 92 | .string = "2", 93 | .description = "How many identical messages can be written in a row^n 0 - no limit", 94 | .has_min = true, 95 | .min_val = 0.0 96 | ), 97 | 98 | ca_equal_messages 99 | ) 100 | } 101 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/scripting/ChatAdditions/CA_Mute.sma: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #pragma tabsize 4 8 | 9 | #pragma reqlib sqlite 10 | #if !defined AMXMODX_NOAUTOLOAD 11 | #pragma loadlib sqlite 12 | #endif 13 | 14 | new bool: g_playersMute[MAX_PLAYERS + 1][MAX_PLAYERS + 1] 15 | new bool: g_globalMute[MAX_PLAYERS + 1] 16 | 17 | new Float: g_nextUse[MAX_PLAYERS + 1] 18 | 19 | new Float: ca_mute_use_delay, 20 | bool: ca_mute_use_storage 21 | 22 | new g_dummy, g_itemInfo[64], g_itemName[128] 23 | 24 | enum { 25 | ITEM_NOT_ENOUTH_PLAYERS = -2, 26 | ITEM_MUTE_ALL = -1 27 | } 28 | 29 | const QUERY_LENGTH = 4096 30 | new const g_mute_table[] = "ca_players_mute" 31 | new Handle: g_tuple = Empty_Handle 32 | 33 | public stock const PluginName[] = "CA: Mute" 34 | public stock const PluginVersion[] = CA_VERSION 35 | public stock const PluginAuthor[] = "Sergey Shorokhov" 36 | public stock const PluginURL[] = "https://github.com/ChatAdditions/" 37 | public stock const PluginDescription[] = "Players can choose who they can hear." 38 | 39 | public plugin_init() { 40 | register_plugin(PluginName, PluginVersion, PluginAuthor) 41 | 42 | register_dictionary("CA_Mute.txt") 43 | register_dictionary("common.txt") 44 | 45 | Create_CVars() 46 | 47 | new const CMDS_Mute[][] = { "mute" } 48 | 49 | for(new i; i < sizeof(CMDS_Mute); i++) { 50 | register_trigger_clcmd(CMDS_Mute[i], "ClCmd_Mute", ADMIN_ALL, .FlagManager = false) 51 | } 52 | 53 | AutoExecConfig(true, "CA_Mute", "ChatAdditions") 54 | 55 | Storage_Init() 56 | 57 | CA_Log(logLevel_Debug, "[CA]: Mute initialized!") 58 | } 59 | 60 | public plugin_end() { 61 | if (g_tuple != Empty_Handle) 62 | SQL_FreeHandle(g_tuple) 63 | } 64 | 65 | Create_CVars() { 66 | bind_pcvar_float(create_cvar("ca_mute_use_delay", "3", 67 | .description = "How often players can use menu. (in seconds)", 68 | .has_min = true, .min_val = 0.0, 69 | .has_max = true, .max_val = 120.0 70 | ), 71 | ca_mute_use_delay 72 | ) 73 | 74 | bind_pcvar_num(create_cvar("ca_mute_use_storage", "1", 75 | .description = "Save the player's individual preferences in the vault.", 76 | .has_min = true, .min_val = 0.0, 77 | .has_max = true, .max_val = 1.0 78 | ), 79 | ca_mute_use_storage 80 | ) 81 | } 82 | 83 | public ClCmd_Mute(const id) { 84 | if (!is_user_connected(id)) { 85 | return PLUGIN_CONTINUE 86 | } 87 | 88 | if (get_playersnum_ex(GetPlayers_ExcludeBots | GetPlayers_ExcludeHLTV) < 2) { 89 | client_print_color(id, print_team_default, "%L %L", id, "Mute_prefix", id, "Mute_NotEnoughPlayers") 90 | return PLUGIN_HANDLED 91 | } 92 | 93 | MenuShow_PlayersList(id) 94 | 95 | return PLUGIN_HANDLED 96 | } 97 | 98 | static MenuShow_PlayersList(const id) { 99 | if (!is_user_connected(id)) { 100 | return 101 | } 102 | 103 | new menu = menu_create(fmt("%L", id, "Mute_MenuTitle"), "MenuHandler_PlayersList") 104 | 105 | static callback 106 | 107 | if (!callback) { 108 | callback = menu_makecallback("MenuCallback_PlayersList") 109 | } 110 | 111 | new players[MAX_PLAYERS], count 112 | get_players_ex(players, count, .flags = (GetPlayers_ExcludeBots | GetPlayers_ExcludeHLTV)) 113 | 114 | if (count < 2) { 115 | menu_additem(menu, fmt("\r %L", id, "Mute_NotEnoughPlayers"), fmt("%i", ITEM_NOT_ENOUTH_PLAYERS), .callback = callback) 116 | } else { 117 | menu_additem(menu, fmt("\y %L %s^n", id, "Mute_MuteAll", g_globalMute[id] ? "\w[ \r+\w ]" : ""), fmt("%i", ITEM_MUTE_ALL)) 118 | 119 | new name[128] 120 | for(new i; i < count; i++) { 121 | new target = players[i] 122 | 123 | if (target == id) { 124 | continue 125 | } 126 | 127 | get_user_name(target, name, charsmax(name)) 128 | 129 | if (g_playersMute[id][target] || CA_PlayerHasBlockedPlayer(id, target)) { 130 | strcat(name, " \d[ \r+\d ]", charsmax(name)) 131 | } 132 | 133 | if (g_globalMute[target] || g_playersMute[target][id] || CA_PlayerHasBlockedPlayer(target, id)) { 134 | strcat(name, fmt(" \d(\y%L\d)", id, "Mute_PlayerMutedYou"), charsmax(name)) 135 | } 136 | 137 | menu_additem(menu, name, fmt("%i", get_user_userid(target)), .callback = callback) 138 | } 139 | } 140 | 141 | menu_setprop(menu, MPROP_BACKNAME, fmt("%L", id, "BACK")) 142 | menu_setprop(menu, MPROP_NEXTNAME, fmt("%L", id, "MORE")) 143 | menu_setprop(menu, MPROP_EXITNAME, fmt("%L", id, "EXIT")) 144 | 145 | menu_display(id, menu) 146 | } 147 | 148 | public MenuCallback_PlayersList(const id, const menu, const item) { 149 | menu_item_getinfo(menu, item, g_dummy, g_itemInfo, charsmax(g_itemInfo), g_itemName, charsmax(g_itemName), g_dummy) 150 | 151 | new userID = strtol(g_itemInfo) 152 | 153 | if (userID == ITEM_NOT_ENOUTH_PLAYERS) { 154 | return ITEM_DISABLED 155 | } 156 | 157 | // Disable all players in menu when local user muted all 158 | if (userID != ITEM_MUTE_ALL && g_globalMute[id]) { 159 | return ITEM_DISABLED 160 | } 161 | 162 | new target = find_player_ex((FindPlayer_MatchUserId | FindPlayer_ExcludeBots), userID) 163 | 164 | if (CA_PlayerHasBlockedPlayer(id, target)) { 165 | return ITEM_DISABLED 166 | } 167 | 168 | return ITEM_ENABLED 169 | } 170 | 171 | public MenuHandler_PlayersList(const id, const menu, const item) { 172 | if (item == MENU_EXIT || item < 0) { 173 | menu_destroy(menu) 174 | return PLUGIN_HANDLED 175 | } 176 | 177 | menu_item_getinfo(menu, item, g_dummy, g_itemInfo, charsmax(g_itemInfo), g_itemName, charsmax(g_itemName), g_dummy) 178 | menu_destroy(menu) 179 | 180 | new Float: gametime = get_gametime() 181 | 182 | if (g_nextUse[id] > gametime) { 183 | client_print_color(id, print_team_red, "%L %L", id, "Mute_prefix", id, "Mute_UseTooOften") 184 | MenuShow_PlayersList(id) 185 | return PLUGIN_HANDLED 186 | } 187 | 188 | g_nextUse[id] = gametime + ca_mute_use_delay 189 | 190 | new userID = strtol(g_itemInfo) 191 | 192 | if (userID == ITEM_MUTE_ALL) { 193 | g_globalMute[id] ^= true 194 | Storage_Update(id, ITEM_MUTE_ALL) 195 | 196 | client_print_color(0, print_team_default, "%L ^3%n^1 %L ", id, "Mute_prefix", 197 | id, LANG_PLAYER, g_globalMute[id] ? "Mute_PlayerNowMutedAll" : "Mute_PlayerNowUnmutedAll" 198 | ) 199 | 200 | CA_Log(logLevel_Info, "Mute: ^"%N^" %sMuted everyone", id, g_globalMute[id] ? "" : "Un") 201 | MenuShow_PlayersList(id) 202 | return PLUGIN_HANDLED 203 | } 204 | 205 | new player = find_player_ex((FindPlayer_MatchUserId | FindPlayer_ExcludeBots), userID) 206 | 207 | if (player == 0) { 208 | client_print_color(id, print_team_red, "%L %L", id, "Mute_prefix", id, "Mute_PlayerNotConnected") 209 | MenuShow_PlayersList(id) 210 | return PLUGIN_HANDLED 211 | } 212 | 213 | g_playersMute[id][player] ^= true 214 | Storage_Update(id, player) 215 | 216 | client_print_color(id, print_team_default, "%L %L ^3%n^1", id, "Mute_prefix", 217 | id, g_playersMute[id][player] ? "Mute_YouMutePlayer" : "Mute_YouUnmutePlayer", player 218 | ) 219 | 220 | client_print_color(player, print_team_default, "%L ^3%n^1 %L ", id, "Mute_prefix", 221 | id, player, g_playersMute[id][player] ? "Mute_PlayerNowMutedYou" : "Mute_PlayerNowUnmutedYou" 222 | ) 223 | 224 | CA_Log(logLevel_Info, "Mute: '%N' %smuted '%N'", id, g_playersMute[id][player] ? "" : "Un", player) 225 | MenuShow_PlayersList(id) 226 | return PLUGIN_HANDLED 227 | } 228 | 229 | 230 | public client_disconnected(id) { 231 | arrayset(g_playersMute[id], false, sizeof(g_playersMute[])) 232 | g_globalMute[id] = false 233 | g_nextUse[id] = 0.0 234 | 235 | for(new i; i < sizeof(g_playersMute[]); i++) { 236 | if (!g_playersMute[i][id]) 237 | continue 238 | 239 | g_playersMute[i][id] = false 240 | } 241 | } 242 | 243 | public CA_Client_Voice(const listener, const sender) { 244 | if (g_globalMute[listener]) { 245 | return CA_SUPERCEDE 246 | } 247 | 248 | if (g_globalMute[sender]) { 249 | return CA_SUPERCEDE 250 | } 251 | 252 | if (g_playersMute[listener][sender] == true) { 253 | return CA_SUPERCEDE 254 | } 255 | 256 | return CA_CONTINUE 257 | } 258 | 259 | Storage_Init() { 260 | if (!SQL_SetAffinity("sqlite")) { 261 | set_fail_state("Can't user 'SQLite'. Check modules.ini") 262 | } 263 | 264 | g_tuple = SQL_MakeDbTuple("", "", "", g_mute_table) 265 | 266 | Storage_Create() 267 | } 268 | 269 | Storage_Create() { 270 | new query[QUERY_LENGTH / 2] 271 | 272 | formatex(query, charsmax(query), "CREATE TABLE IF NOT EXISTS %s", g_mute_table); { 273 | strcat(query, " ( id INTEGER PRIMARY KEY AUTOINCREMENT,", charsmax(query)) 274 | strcat(query, "authid VARCHAR NOT NULL,", charsmax(query)) 275 | strcat(query, "authid_target VARCHAR NOT NULL); ", charsmax(query)) 276 | strcat(query, fmt("CREATE UNIQUE INDEX IF NOT EXISTS authid_target_idx1 ON %s (authid, authid_target)", g_mute_table), charsmax(query)) 277 | } 278 | 279 | SQL_ThreadQuery(g_tuple, "handle_StorageCreated", query) 280 | } 281 | 282 | public handle_StorageCreated(failstate, Handle: query, error[], errnum, data[], size, Float: queuetime) { 283 | if (IsSQLQueryFailed(failstate, query, error, errnum)) { 284 | return 285 | } 286 | 287 | CA_Log(logLevel_Debug, "Table '%s' created! (queryTime: '%.3f' sec)", g_mute_table, queuetime) 288 | } 289 | 290 | public client_putinserver(player) { 291 | Storage_Load(player) 292 | } 293 | 294 | Storage_Update(const player, const target) { 295 | if (!ca_mute_use_storage) 296 | return 297 | 298 | new query[QUERY_LENGTH / 2] 299 | 300 | new authId[MAX_AUTHID_LENGTH] 301 | get_user_authid(player, authId, charsmax(authId)) 302 | 303 | if (target == ITEM_MUTE_ALL) { 304 | if (g_globalMute[player]) { 305 | formatex(query, charsmax(query), "INSERT INTO %s (authid, authid_target)", g_mute_table) 306 | strcat(query, fmt(" VALUES ('%s', '%s') ON CONFLICT DO NOTHING", authId, "GLOBAL"), charsmax(query)) 307 | } else { 308 | formatex(query, charsmax(query), "DELETE FROM %s", g_mute_table) 309 | strcat(query, fmt(" WHERE authid='%s' AND authid_target = '%s'", authId, "GLOBAL"), charsmax(query)) 310 | } 311 | 312 | SQL_ThreadQuery(g_tuple, "handle_Saved", query) 313 | return 314 | } 315 | 316 | new authId_target[MAX_AUTHID_LENGTH] 317 | get_user_authid(target, authId_target, charsmax(authId_target)) 318 | 319 | if (g_playersMute[player][target]) { 320 | formatex(query, charsmax(query), "INSERT INTO %s (authid, authid_target)", g_mute_table) 321 | strcat(query, fmt(" VALUES ('%s', '%s') ON CONFLICT DO NOTHING", authId, authId_target), charsmax(query)) 322 | } else { 323 | formatex(query, charsmax(query), "DELETE FROM %s", g_mute_table) 324 | strcat(query, fmt(" WHERE authid ='%s' AND authid_target = '%s'", authId, authId_target), charsmax(query)) 325 | } 326 | 327 | SQL_ThreadQuery(g_tuple, "handle_Saved", query) 328 | } 329 | 330 | public handle_Saved(failstate, Handle: query, error[], errnum, data[], size, Float: queuetime) { 331 | if (IsSQLQueryFailed(failstate, query, error, errnum)) { 332 | return 333 | } 334 | } 335 | 336 | Storage_Load(const player) { 337 | if (!ca_mute_use_storage) 338 | return 339 | 340 | new authId[MAX_AUTHID_LENGTH] 341 | get_user_authid(player, authId, charsmax(authId)) 342 | 343 | new query[QUERY_LENGTH / 2] 344 | formatex(query, charsmax(query), "SELECT authid, authid_target FROM %s", g_mute_table) 345 | strcat(query, fmt(" WHERE authid ='%s' OR authid_target = '%s'", authId, authId), charsmax(query)) 346 | 347 | SQL_ThreadQuery(g_tuple, "handle_LoadedMute", query) 348 | } 349 | 350 | public handle_LoadedMute(failstate, Handle: query, error[], errnum, data[], size, Float: queuetime) { 351 | if (IsSQLQueryFailed(failstate, query, error, errnum)) { 352 | return 353 | } 354 | 355 | if (!SQL_NumResults(query)) 356 | return 357 | 358 | while (SQL_MoreResults(query)) { 359 | new authId[MAX_AUTHID_LENGTH], authId_target[MAX_AUTHID_LENGTH] 360 | SQL_ReadResult(query, 0, authId, charsmax(authId)) 361 | SQL_ReadResult(query, 1, authId_target, charsmax(authId_target)) 362 | 363 | new player = find_player_ex(FindPlayer_MatchAuthId, authId) 364 | if (player == 0) { 365 | goto next 366 | } 367 | 368 | if (strcmp(authId_target, "GLOBAL") == 0) { 369 | g_globalMute[player] = true 370 | goto next 371 | } 372 | 373 | new target = find_player_ex(FindPlayer_MatchAuthId, authId_target) 374 | if (target == 0) { 375 | goto next 376 | } 377 | 378 | g_playersMute[player][target] = true 379 | 380 | next: 381 | SQL_NextRow(query) 382 | } 383 | } 384 | 385 | static stock bool: IsSQLQueryFailed(const failstate, const Handle: query, const error[], const errNum) { 386 | switch (failstate) { 387 | case TQUERY_CONNECT_FAILED: { 388 | log_amx("SQL: connection failed [%i] `%s`", errNum, error) 389 | return true 390 | } 391 | case TQUERY_QUERY_FAILED: { 392 | log_amx("SQL: query failed [%i] %s", errNum, error) 393 | 394 | server_print("^n^n ===> Query:") 395 | new buffer[1024]; SQL_GetQueryString(query, buffer, charsmax(buffer)) 396 | for(new i, len = strlen(buffer); i < len; i+=255) { 397 | server_print(fmt("%-255s", buffer[i])) 398 | } 399 | 400 | return true 401 | } 402 | } 403 | 404 | return false 405 | } 406 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/scripting/ChatAdditions/ChatAdditions_Core.sma: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #pragma tabsize 4 9 | #pragma dynamic (8192 + 4096) 10 | 11 | 12 | enum logType_s { 13 | _Default, 14 | _LogToDir, 15 | _LogToDirSilent, 16 | _LogToAlertMessage, 17 | } 18 | 19 | new logType_s: ca_log_type, 20 | logLevel_s: ca_log_level = logLevel_Debug, 21 | bool: ca_update_notify, 22 | ca_log_autodelete_time 23 | 24 | new const LOG_FOLDER[] = "ChatAdditions" 25 | 26 | new g_fwdClientSay, 27 | g_fwdClientVoice, 28 | g_fwdClientChangeName, 29 | g_retVal 30 | 31 | // FROM https://github.com/s1lentq/ReGameDLL_CS/blob/master/regamedll/game_shared/voice_gamemgr.cpp 32 | 33 | // Set to 1 for each player if the player wants to use voice in this mod. 34 | // (If it's zero, then the server reports that the game rules are saying the player can't hear anyone). 35 | new bool: g_PlayerModEnable[MAX_PLAYERS + 1] 36 | 37 | // Tells which players don't want to hear each other. 38 | // These are indexed as clients and each bit represents a client (so player entity is bit + 1). 39 | new g_BanMasks[MAX_PLAYERS + 1] 40 | 41 | new const g_versionLink[] = "https://api.github.com/repos/" 42 | + "ChatAdditions/ChatAdditions_AMXX" 43 | + "/releases/latest" 44 | 45 | public stock const PluginName[] = "ChatAdditions: Core" 46 | public stock const PluginVersion[] = CA_VERSION 47 | public stock const PluginAuthor[] = "Sergey Shorokhov" 48 | public stock const PluginURL[] = "https://github.com/ChatAdditions/" 49 | public stock const PluginDescription[] = "A core plugin for control different types of chat." 50 | 51 | public plugin_precache() { 52 | register_plugin(PluginName, PluginVersion, PluginAuthor) 53 | 54 | create_cvar("ChatAdditions_version", PluginVersion, FCVAR_SERVER) 55 | 56 | Create_CVars() 57 | CheckUpdate() 58 | } 59 | 60 | public plugin_init() { 61 | register_clcmd("say", "ClCmd_Say", ADMIN_ALL) 62 | register_clcmd("say_team", "ClCmd_Say", ADMIN_ALL) 63 | 64 | register_forward(FM_Voice_SetClientListening, "Voice_SetClientListening_Pre", ._post = false) 65 | register_forward(FM_ClientUserInfoChanged, "ClientUserInfoChanged_Pre", ._post = false) 66 | 67 | register_clcmd("VModEnable", "ClCmd_VModEnable", ADMIN_ALL, .FlagManager = false) 68 | register_clcmd("vban", "ClCmd_vban", ADMIN_ALL, .FlagManager = false) 69 | 70 | g_fwdClientSay = CreateMultiForward("CA_Client_Say", ET_STOP, FP_CELL, FP_CELL, FP_STRING) 71 | g_fwdClientVoice = CreateMultiForward("CA_Client_Voice", ET_STOP, FP_CELL, FP_CELL) 72 | g_fwdClientChangeName = CreateMultiForward("CA_Client_ChangeName", ET_STOP, FP_CELL, FP_STRING) 73 | 74 | CheckAutoDelete() 75 | 76 | CA_Log(logLevel_Debug, "Chat Additions: Core initialized!") 77 | } 78 | 79 | public plugin_end() { 80 | DestroyForward(g_fwdClientSay) 81 | DestroyForward(g_fwdClientVoice) 82 | DestroyForward(g_fwdClientChangeName) 83 | } 84 | 85 | CheckAutoDelete() { 86 | if (ca_log_autodelete_time <= 0) 87 | return 88 | 89 | new logsPath[PLATFORM_MAX_PATH] 90 | GetLogsFilePath(logsPath, .dir = LOG_FOLDER) 91 | 92 | if (!dir_exists(logsPath)) 93 | return 94 | 95 | new logFile[PLATFORM_MAX_PATH] 96 | new dirHandle 97 | dirHandle = open_dir(logsPath, logFile, charsmax(logFile)) 98 | if (!dirHandle) 99 | return 100 | 101 | new subDirectory[PLATFORM_MAX_PATH] 102 | new deleteTime = get_systime() - (ca_log_autodelete_time * (60 * 60 * 24)) 103 | 104 | while (next_file(dirHandle, logFile, charsmax(logFile))) { 105 | if (logFile[0] == '.') 106 | continue 107 | 108 | if (containi(logFile, ".log") == -1) { 109 | formatex(subDirectory, charsmax(subDirectory), "%s/%s", logsPath, logFile) 110 | 111 | // TODO: refactor this 112 | ReadFolder(deleteTime, subDirectory) 113 | 114 | continue 115 | } 116 | } 117 | 118 | close_dir(dirHandle) 119 | } 120 | 121 | ReadFolder(deleteTime, logPath[]) { 122 | new logFile[PLATFORM_MAX_PATH] 123 | new dirHandle = open_dir(logPath, logFile, charsmax(logFile)) 124 | new fileTime 125 | 126 | if (dirHandle) { 127 | do 128 | { 129 | if (logFile[0] == '.') { 130 | continue 131 | } 132 | 133 | if (containi(logFile, ".log") != -1) { 134 | fileTime = 0 135 | format(logFile, charsmax(logFile), "%s/%s", logPath, logFile) 136 | 137 | fileTime = GetFileTime(logFile, FileTime_Created) 138 | if (fileTime < deleteTime) { 139 | unlink(logFile) 140 | } 141 | } 142 | } while (next_file(dirHandle, logFile, charsmax(logFile))) 143 | } 144 | close_dir(dirHandle) 145 | } 146 | 147 | Create_CVars() { 148 | 149 | bind_pcvar_num(create_cvar("ca_log_type", "1", 150 | .description = fmt("Log file type^n \ 151 | 0 = log to common amxx log file (logs/L*.log)^n \ 152 | 1 = log to plugins folder (logs/%s/[plugin name]/L*.log)^n \ 153 | 2 = silent log to plugins folder (logs/%s/[plugin name]/L*.log)^n \ 154 | 3 = use elog_message) \ 155 | ", 156 | LOG_FOLDER, LOG_FOLDER), 157 | .has_min = true, .min_val = 0.0, 158 | .has_max = true, .max_val = float(logType_s) - 1.0 159 | ), 160 | ca_log_type 161 | ) 162 | 163 | bind_pcvar_num(create_cvar("ca_log_level", "1", 164 | .description = "Log level^n \ 165 | 0 = disable logs^n \ 166 | 1 = add info messages logs^n \ 167 | 2 = add warinigs info^n \ 168 | 3 = add debug messages", 169 | .has_min = true, .min_val = 0.0, 170 | .has_max = true, .max_val = float(logLevel_s) - 1.0 171 | ), 172 | ca_log_level 173 | ) 174 | 175 | bind_pcvar_num(create_cvar("ca_update_notify", "1", 176 | .description = "Enable update check?^n 0 = disable update checks", 177 | .has_min = true, .min_val = 0.0, 178 | .has_max = true, .max_val = 1.0 179 | ), 180 | ca_update_notify 181 | ) 182 | 183 | bind_pcvar_num(create_cvar("ca_log_autodelete_time", "7", 184 | .description = "The time in days after which the log files should be deleted.^n \ 185 | 0 - The logs won't be deleted.^n \ 186 | > 0 - The logs will be deleted at the time inserted.", 187 | .has_min = true, .min_val = 0.0 188 | ), 189 | ca_log_autodelete_time 190 | ) 191 | 192 | AutoExecConfig(true, "ChatAdditions_core", LOG_FOLDER) 193 | 194 | new configsDir[PLATFORM_MAX_PATH] 195 | get_configsdir(configsDir, charsmax(configsDir)) 196 | 197 | server_cmd("exec %s/plugins/%s/ChatAdditions_core.cfg", configsDir, LOG_FOLDER) 198 | server_exec() 199 | } 200 | 201 | public plugin_natives() { 202 | register_library("ChatAdditions_Core") 203 | 204 | set_module_filter("ModuleFilter") 205 | set_native_filter("NativeFilter") 206 | 207 | register_native("CA_Log", "native_CA_Log") 208 | register_native("CA_PlayerHasBlockedPlayer", "native_CA_PlayerHasBlockedPlayer") 209 | } 210 | 211 | public ModuleFilter(const library[], LibType: type) { 212 | return strcmp("easy_http", library) == 0 ? PLUGIN_HANDLED : PLUGIN_CONTINUE 213 | } 214 | 215 | public NativeFilter(const nativeName[], index, trap) { 216 | if (strncmp(nativeName, "ezhttp_", 7) == 0) 217 | return PLUGIN_HANDLED 218 | 219 | if (strncmp(nativeName, "ezjson_", 7) == 0) 220 | return PLUGIN_HANDLED 221 | 222 | return PLUGIN_CONTINUE 223 | } 224 | 225 | public ClCmd_Say(const id) { 226 | static message[CA_MAX_MESSAGE_SIZE] 227 | read_argv(0, message, charsmax(message)) 228 | new isTeamMessage = (message[3] == '_') 229 | read_args(message, charsmax(message)) 230 | remove_quotes(message) 231 | 232 | ExecuteForward(g_fwdClientSay, g_retVal, id, isTeamMessage, message) 233 | 234 | return (g_retVal == CA_SUPERCEDE) ? PLUGIN_HANDLED : PLUGIN_CONTINUE 235 | } 236 | 237 | public Voice_SetClientListening_Pre(const receiver, const sender, bool: canListen) { 238 | if (receiver == sender) 239 | return FMRES_IGNORED 240 | 241 | if (!g_PlayerModEnable[receiver]) 242 | return FMRES_IGNORED 243 | 244 | if (!is_user_connected(receiver) || !is_user_connected(sender)) 245 | return FMRES_IGNORED 246 | 247 | ExecuteForward(g_fwdClientVoice, g_retVal, receiver, sender) 248 | if (g_retVal != CA_SUPERCEDE) 249 | return FMRES_IGNORED 250 | 251 | // Block voice 252 | engfunc(EngFunc_SetClientListening, receiver, sender, (canListen = false)) 253 | return FMRES_SUPERCEDE 254 | } 255 | 256 | public ClientUserInfoChanged_Pre(const player, const infobuffer) { 257 | new currentName[32] 258 | get_user_name(player, currentName, charsmax(currentName)) 259 | 260 | new newName[32] 261 | engfunc(EngFunc_InfoKeyValue, infobuffer, "name", newName, charsmax(newName)) 262 | 263 | if (strcmp(currentName, newName) == 0) 264 | return 265 | 266 | ExecuteForward(g_fwdClientChangeName, g_retVal, player, newName) 267 | if (g_retVal != CA_SUPERCEDE) 268 | return 269 | 270 | // Change back name 271 | engfunc(EngFunc_SetClientKeyValue, player, infobuffer, "name", currentName) 272 | } 273 | 274 | public ClCmd_VModEnable(const id) { 275 | if (read_argc() < 2) { 276 | return 277 | } 278 | 279 | new arg[32]; read_argv(1, arg, charsmax(arg)) 280 | g_PlayerModEnable[id] = bool: (strtol(arg) != 0) 281 | } 282 | 283 | public ClCmd_vban(const id) { 284 | if (read_argc() < 2) { 285 | return 286 | } 287 | 288 | new arg[32]; read_argv(1, arg, charsmax(arg)) 289 | g_BanMasks[id] = strtol(arg, .base = 16) 290 | } 291 | 292 | public bool: native_CA_Log(const plugin_id, const argc) { 293 | enum { arg_level = 1, arg_msg, arg_format } 294 | 295 | new logLevel_s: level = logLevel_s: get_param(arg_level) 296 | 297 | if (ca_log_level < level) 298 | return false 299 | 300 | new msg[2048] 301 | vdformat(msg, charsmax(msg), arg_msg, arg_format) 302 | 303 | new logsFile[PLATFORM_MAX_PATH] 304 | 305 | if (ca_log_type == _LogToDir || ca_log_type == _LogToDirSilent) { 306 | new logsPath[PLATFORM_MAX_PATH] 307 | get_localinfo("amxx_logs", logsPath, charsmax(logsPath)) 308 | 309 | new pluginName[PLATFORM_MAX_PATH] 310 | get_plugin(plugin_id, pluginName, charsmax(pluginName)) 311 | 312 | replace(pluginName, charsmax(pluginName), ".amxx", "") 313 | 314 | formatex(logsPath, charsmax(logsPath), "%s/%s", logsPath, pluginName) 315 | 316 | if (!dir_exists(logsPath)) 317 | mkdir(logsPath) 318 | 319 | new year, month, day 320 | date(year, month, day) 321 | 322 | formatex(logsFile, charsmax(logsFile), "%s/%s__%i-%02i-%02i.log", 323 | logsPath, 324 | pluginName[sizeof(LOG_FOLDER)], 325 | year, month, day 326 | ) 327 | } 328 | 329 | switch (ca_log_type) { 330 | case _Default: log_amx(msg) 331 | case _LogToDir: log_to_file(logsFile, msg) 332 | case _LogToDirSilent: log_to_file_ex(logsFile, msg) 333 | case _LogToAlertMessage: elog_message(msg) 334 | } 335 | 336 | return true 337 | } 338 | 339 | public bool: native_CA_PlayerHasBlockedPlayer(const plugin_id, const argc) { 340 | enum { arg_receiver = 1, arg_sender } 341 | 342 | new receiver = get_param(arg_receiver) 343 | new sender = get_param(arg_sender) 344 | 345 | if (CVoiceGameMgr__PlayerHasBlockedPlayer(receiver, sender)) { 346 | return true 347 | } 348 | 349 | return false 350 | } 351 | 352 | static GetLogsFilePath(buffer[], len = PLATFORM_MAX_PATH, const dir[] = "ChatAdditions") { 353 | get_localinfo("amxx_logs", buffer, len) 354 | strcat(buffer, fmt("/%s", dir), len) 355 | 356 | if (!dir_exists(buffer) && mkdir(buffer) == -1) { 357 | set_fail_state("[Core API] Can't create folder! (%s)", buffer) 358 | } 359 | } 360 | 361 | static bool: CVoiceGameMgr__PlayerHasBlockedPlayer(const receiver, const sender) { 362 | #define CanPlayerHearPlayer(%0,%1) ( ~g_BanMasks[%0] & ( 1 << (%1 - 1) ) ) 363 | 364 | if (receiver <= 0 || receiver > MaxClients || sender <= 0 || sender > MaxClients) { 365 | return false 366 | } 367 | 368 | return bool: !CanPlayerHearPlayer(receiver, sender) 369 | } 370 | 371 | static CheckUpdate() { 372 | if (!ca_update_notify) 373 | return 374 | 375 | if (strcmp(CA_VERSION, "CA_VERSION") == 0 || contain(CA_VERSION, ".") == -1) // ignore custom builds 376 | return 377 | 378 | if (is_module_loaded("Amxx Easy Http") == -1) { 379 | CA_Log(logLevel_Warning, "The `AmxxEasyHttp` module is not loaded! The new version cannot be verified.") 380 | CA_Log(logLevel_Warning, "Please install AmxxEasyHttp: `https://github.com/Next21Team/AmxxEasyHttp` or disable update checks (`ca_update_notify `0`).") 381 | 382 | return 383 | } 384 | 385 | RequestNewVersion(g_versionLink) 386 | } 387 | 388 | static RequestNewVersion(const link[]) { 389 | ezhttp_get(link, "@RequestHandler") 390 | } 391 | 392 | @RequestHandler(EzHttpRequest: request_id) { 393 | if (ezhttp_get_error_code(request_id) != EZH_OK) { 394 | new error[64] 395 | ezhttp_get_error_message(request_id, error, charsmax(error)) 396 | server_print("Response error: %s", error) 397 | return 398 | } 399 | 400 | 401 | new response[8192] 402 | ezhttp_get_data(request_id, response, charsmax(response)) 403 | 404 | if (contain(response, "tag_name") == -1) { 405 | CA_Log(logLevel_Warning, " > Wrong response! (don't contain `tag_name`). res=`%s`", response) 406 | return 407 | } 408 | 409 | new EzJSON: json = ezjson_parse(response) 410 | if (json == EzInvalid_JSON) { 411 | CA_Log(logLevel_Warning, " > Can't parse response JSON!") 412 | goto END 413 | } 414 | 415 | new tag_name[32] 416 | ezjson_object_get_string(json, "tag_name", tag_name, charsmax(tag_name)) 417 | 418 | if (CmpVersions(CA_VERSION, tag_name) >= 0) 419 | goto END 420 | 421 | new html_url[256] 422 | ezjson_object_get_string(json, "html_url", html_url, charsmax(html_url)) 423 | 424 | NotifyUpdate(tag_name, html_url) 425 | 426 | END: 427 | ezjson_free(json) 428 | } 429 | 430 | static NotifyUpdate(const newVersion[], const URL[]) { 431 | CA_Log(logLevel_Info, "^n^t ChatAdditions (%s) has update! New version `%s`.^n\ 432 | Download link: `%s`", CA_VERSION, newVersion, URL 433 | ) 434 | } 435 | 436 | static stock CmpVersions(const a[], const b[]) { 437 | new segmentsA[32][32] 438 | new segmentsB[32][32] 439 | 440 | new countA = explode_string( 441 | a[!isdigit(a[0]) ? 1 : 0], 442 | ".", 443 | segmentsA, sizeof segmentsA, charsmax(segmentsA[]) 444 | ) 445 | 446 | new countB = explode_string( 447 | b[!isdigit(b[0]) ? 1 : 0], 448 | ".", 449 | segmentsB, sizeof segmentsB, charsmax(segmentsB[]) 450 | ) 451 | 452 | for(new i, l = min(countA, countB); i < l; i++) { 453 | new diff = strtol(segmentsA[i]) - strtol(segmentsB[i]) 454 | if (diff) 455 | return diff 456 | } 457 | 458 | return countA - countB 459 | } 460 | 461 | stock log_to_file_ex(const filePath[], message[]) { 462 | new file 463 | new bool:firstTime = true 464 | new date[32] 465 | 466 | format_time(date, charsmax(date), "%m/%d/%Y - %H:%M:%S") 467 | static modName[15], amxVersion[15] 468 | 469 | if (!modName[0]) { 470 | get_modname(modName, charsmax(modName)) 471 | } 472 | 473 | if (!amxVersion[0]) { 474 | get_amxx_verstring(amxVersion, charsmax(amxVersion)) 475 | } 476 | 477 | if ((file = fopen(filePath, "r"))) { 478 | firstTime = false 479 | fclose(file) 480 | } 481 | 482 | if (!(file = fopen(filePath, "at"))) { 483 | log_error(AMX_ERR_GENERAL, "Can't open ^"%s^" file for writing.", filePath) 484 | return PLUGIN_CONTINUE 485 | } 486 | 487 | if (firstTime) { 488 | fprintf(file, "L %s: Log file started (file ^"%s^") (game ^"%s^") (amx ^"%s^")^n", date, filePath, modName, amxVersion) 489 | } 490 | 491 | fprintf(file, "L %s: %s^n", date, message) 492 | 493 | fclose(file) 494 | 495 | return PLUGIN_HANDLED 496 | } 497 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/scripting/ChatAdditions/Storage/CA_Storage_CSBans.sma: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #pragma dynamic 131072 12 | #pragma tabsize 4 13 | 14 | #pragma reqlib mysql 15 | #if !defined AMXMODX_NOAUTOLOAD 16 | #pragma loadlib mysql 17 | #endif 18 | 19 | new const SQL_TBL_GAGS[] = "chatadditions_gags" 20 | 21 | const QUERY_LENGTH = 4096 22 | const MAX_REASON_LENGTH = 256 23 | new g_query[QUERY_LENGTH] 24 | 25 | new Handle: g_tuple = Empty_Handle 26 | new Queue: g_queueLoad = Invalid_Queue, 27 | Queue: g_queueSave = Invalid_Queue 28 | 29 | new ca_storage_host[64], 30 | ca_storage_user[128], 31 | ca_storage_pass[128], 32 | ca_storage_dbname[128] 33 | 34 | public stock const PluginName[] = "ChatAdditions: CSBans storage" 35 | public stock const PluginVersion[] = CA_VERSION 36 | public stock const PluginAuthor[] = "Sergey Shorokhov" 37 | public stock const PluginURL[] = "https://github.com/ChatAdditions/" 38 | public stock const PluginDescription[] = "CSBans (MySQL) storage provider for ChatAdditions" 39 | 40 | public plugin_init() { 41 | register_plugin(PluginName, PluginVersion, PluginAuthor) 42 | 43 | if (!SQL_SetAffinity("mysql")) { 44 | set_fail_state("Can't user 'MySQL'. Check modules.ini") 45 | } 46 | 47 | Create_CVars() 48 | 49 | AutoExecConfig(true, "CA_Storage_CSBans", "ChatAdditions") 50 | 51 | g_queueLoad = QueueCreate(MAX_AUTHID_LENGTH) 52 | g_queueSave = QueueCreate(gagData_s) 53 | 54 | set_task_ex(6.274, "_OnConfigsExecuted") 55 | } 56 | 57 | public _OnConfigsExecuted() { 58 | g_tuple = SQL_MakeDbTuple(ca_storage_host, ca_storage_user, ca_storage_pass, ca_storage_dbname) 59 | 60 | Storage_Create() 61 | } 62 | 63 | public plugin_end() { 64 | if (g_tuple != Empty_Handle) { 65 | SQL_FreeHandle(g_tuple) 66 | } 67 | 68 | QueueDestroy(g_queueLoad) 69 | QueueDestroy(g_queueSave) 70 | } 71 | 72 | public plugin_natives() { 73 | RegisterNatives() 74 | } 75 | 76 | public plugin_cfg() { 77 | RegisterForwards() 78 | } 79 | 80 | Create_CVars() { 81 | bind_pcvar_string(create_cvar("ca_storage_host", "127.0.0.1", FCVAR_PROTECTED, 82 | .description = "CSBans MySQL database host address" 83 | ), 84 | ca_storage_host, charsmax(ca_storage_host) 85 | ) 86 | 87 | bind_pcvar_string(create_cvar("ca_storage_user", "root", FCVAR_PROTECTED, 88 | .description = "CSBans MySQL database user" 89 | ), 90 | ca_storage_user, charsmax(ca_storage_user) 91 | ) 92 | 93 | bind_pcvar_string(create_cvar("ca_storage_pass", "", FCVAR_PROTECTED, 94 | .description = "CSBans MySQL database host password" 95 | ), 96 | ca_storage_pass, charsmax(ca_storage_pass) 97 | ) 98 | 99 | bind_pcvar_string(create_cvar("ca_storage_dbname", "players_gags", FCVAR_PROTECTED, 100 | .description = "CSBans MySQL database name (not recommended to change)" 101 | ), 102 | ca_storage_dbname, charsmax(ca_storage_dbname) 103 | ) 104 | } 105 | 106 | Storage_Create() { 107 | formatex(g_query, charsmax(g_query), "CREATE TABLE IF NOT EXISTS %s ", SQL_TBL_GAGS); { 108 | strcat(g_query, "( id INTEGER PRIMARY KEY AUTO_INCREMENT,", charsmax(g_query)) 109 | strcat(g_query, "name VARCHAR(32) NOT NULL,", charsmax(g_query)) 110 | strcat(g_query, "authid VARCHAR(64) NOT NULL,", charsmax(g_query)) 111 | strcat(g_query, "ip VARCHAR(22) NOT NULL,", charsmax(g_query)) 112 | strcat(g_query, "reason VARCHAR(256) NOT NULL,", charsmax(g_query)) 113 | strcat(g_query, "admin_name VARCHAR(32) NOT NULL,", charsmax(g_query)) 114 | strcat(g_query, "admin_authid VARCHAR(64) NOT NULL,", charsmax(g_query)) 115 | strcat(g_query, "admin_ip VARCHAR(22) NOT NULL,", charsmax(g_query)) 116 | strcat(g_query, "created_at DATETIME NOT NULL,", charsmax(g_query)) 117 | strcat(g_query, "expire_at DATETIME NOT NULL,", charsmax(g_query)) 118 | strcat(g_query, "flags INTEGER NOT NULL,", charsmax(g_query)) 119 | strcat(g_query, "UNIQUE INDEX authid_unique_idx (authid)", charsmax(g_query)) 120 | strcat(g_query, ") CHARACTER SET utf8 COLLATE utf8_general_ci;", charsmax(g_query)) 121 | } 122 | 123 | SQL_ThreadQuery(g_tuple, "handle_StorageCreated", g_query) 124 | } 125 | 126 | public handle_StorageCreated(failstate, Handle: query, error[], errnum, data[], size, Float: queuetime) { 127 | if (IsSQLQueryFailed(failstate, query, error, errnum)) { 128 | return 129 | } 130 | 131 | CA_Log(logLevel_Debug, "Table '%s' created! (queryTime: '%.3f' sec)", SQL_TBL_GAGS, queuetime) 132 | 133 | g_storageInitialized = true 134 | ExecuteForward(g_fwd_StorageInitialized, g_ret) 135 | 136 | // Load prepared data from storage 137 | new queueCounter 138 | 139 | for(new i, len = QueueSize(g_queueLoad); i < len; i++) { 140 | new authID[MAX_AUTHID_LENGTH]; QueuePopString(g_queueLoad, authID, charsmax(authID)) 141 | Storage_Load(authID) 142 | 143 | ++queueCounter 144 | } 145 | 146 | if (queueCounter) { 147 | CA_Log(logLevel_Warning, "Loaded %i queue gags from DB (slow DB connection issue)", queueCounter) 148 | queueCounter = 0 149 | } 150 | 151 | // Save prepared data to storage 152 | for(new i, len = QueueSize(g_queueSave); i < len; i++) { 153 | new gagData[gagData_s]; QueuePopArray(g_queueSave, gagData, sizeof(gagData)) 154 | 155 | Storage_Save(gagData[gd_name], gagData[gd_authID], gagData[gd_IP], 156 | gagData[gd_reason][r_name], gagData[gd_adminName], gagData[gd_adminAuthID], 157 | gagData[gd_adminIP], gagData[gd_expireAt], gagData[gd_reason][r_flags] 158 | ) 159 | 160 | ++queueCounter 161 | } 162 | 163 | if (queueCounter) { 164 | CA_Log(logLevel_Warning, "Saved %i queue gags to DB (slow DB connection issue)", queueCounter) 165 | queueCounter = 0 166 | } 167 | } 168 | 169 | 170 | Storage_Save(const name[], const authID[], const IP[], 171 | const reason[], const adminName[], const adminAuthID[], 172 | const adminIP[], const expireAt, const flags) { 173 | 174 | if (!g_storageInitialized) { 175 | new gagData[gagData_s]; { 176 | copy(gagData[gd_name], charsmax(gagData[gd_name]), name) 177 | copy(gagData[gd_authID], charsmax(gagData[gd_authID]), authID) 178 | copy(gagData[gd_IP], charsmax(gagData[gd_IP]), IP) 179 | 180 | copy(gagData[gd_adminName], charsmax(gagData[gd_adminName]), adminName) 181 | copy(gagData[gd_adminAuthID], charsmax(gagData[gd_adminAuthID]), adminAuthID) 182 | copy(gagData[gd_adminIP], charsmax(gagData[gd_adminIP]), adminIP) 183 | 184 | copy(gagData[gd_reason][r_name], charsmax(gagData[r_name]), reason) 185 | gagData[gd_reason][r_flags] = gag_flags_s: flags 186 | 187 | gagData[gd_expireAt] = expireAt 188 | } 189 | 190 | QueuePushArray(g_queueSave, gagData) 191 | 192 | return 193 | } 194 | 195 | new name_safe[MAX_NAME_LENGTH * 2] 196 | SQL_QuoteString(Empty_Handle, name_safe, charsmax(name_safe), name) 197 | 198 | new reason_safe[MAX_REASON_LENGTH * 2] 199 | SQL_QuoteString(Empty_Handle, reason_safe, charsmax(reason_safe), reason) 200 | 201 | new adminName_safe[MAX_NAME_LENGTH * 2] 202 | SQL_QuoteString(Empty_Handle, adminName_safe, charsmax(adminName_safe), adminName) 203 | 204 | // TODO: Optimize this EPIC QUERY 205 | formatex(g_query, charsmax(g_query), "INSERT INTO %s ", SQL_TBL_GAGS); { 206 | strcat(g_query, "( name,authid,ip,", charsmax(g_query)) 207 | strcat(g_query, "reason,admin_name,admin_authid,", charsmax(g_query)) 208 | strcat(g_query, "admin_ip,created_at,expire_at,flags )", charsmax(g_query)) 209 | 210 | strcat(g_query, fmt(" VALUES ( '%s',", name_safe), charsmax(g_query)) 211 | strcat(g_query, fmt("'%s',", authID), charsmax(g_query)) 212 | strcat(g_query, fmt("'%s',", IP), charsmax(g_query)) 213 | strcat(g_query, fmt("'%s',", reason_safe), charsmax(g_query)) 214 | strcat(g_query, fmt("'%s',", adminName_safe), charsmax(g_query)) 215 | strcat(g_query, fmt("'%s',", adminAuthID), charsmax(g_query)) 216 | strcat(g_query, fmt("'%s',", adminIP), charsmax(g_query)) 217 | strcat(g_query, fmt("NOW(),"), charsmax(g_query)) 218 | strcat(g_query, fmt("FROM_UNIXTIME(%i),", expireAt), charsmax(g_query)) 219 | strcat(g_query, fmt("%i ) ", flags), charsmax(g_query)) 220 | strcat(g_query, "ON DUPLICATE KEY UPDATE ", charsmax(g_query)) 221 | strcat(g_query, fmt("name='%s',", name_safe), charsmax(g_query)) 222 | strcat(g_query, fmt("ip='%s',", IP), charsmax(g_query)) 223 | strcat(g_query, fmt("reason='%s',", reason_safe), charsmax(g_query)) 224 | strcat(g_query, fmt("admin_name='%s',", adminName_safe), charsmax(g_query)) 225 | strcat(g_query, fmt("admin_authid='%s',", adminAuthID), charsmax(g_query)) 226 | strcat(g_query, fmt("admin_ip='%s',", adminIP), charsmax(g_query)) 227 | strcat(g_query, "created_at=NOW(),", charsmax(g_query)) 228 | strcat(g_query, fmt("expire_at=FROM_UNIXTIME(%i),", expireAt), charsmax(g_query)) 229 | strcat(g_query, fmt("flags=%i; ", flags), charsmax(g_query)) 230 | } 231 | 232 | SQL_ThreadQuery(g_tuple, "handle_Saved", g_query) 233 | } 234 | 235 | public handle_Saved(failstate, Handle: query, error[], errnum, data[], size, Float: queuetime) { 236 | if (IsSQLQueryFailed(failstate, query, error, errnum)) { 237 | return 238 | } 239 | 240 | formatex(g_query, charsmax(g_query), "SELECT \ 241 | name,authid,ip,reason,\ 242 | admin_name,admin_authid,admin_ip,\ 243 | UNIX_TIMESTAMP(created_at),UNIX_TIMESTAMP(expire_at),flags") 244 | strcat(g_query, fmt(" FROM %s", SQL_TBL_GAGS), charsmax(g_query)) 245 | strcat(g_query, fmt(" WHERE id=%i;", SQL_GetInsertId(query)), charsmax(g_query)) 246 | 247 | SQL_ThreadQuery(g_tuple, "handle_SavedResult", g_query) 248 | } 249 | 250 | public handle_SavedResult(failstate, Handle: query, error[], errnum, data[], size, Float: queuetime) { 251 | if (IsSQLQueryFailed(failstate, query, error, errnum)) { 252 | return 253 | } 254 | 255 | enum { res_name, res_authid, res_ip, res_reason, 256 | res_admin_name, res_admin_authid, res_admin_ip, 257 | res_created_at, res_expire_at, res_flags 258 | } 259 | 260 | new name[MAX_NAME_LENGTH]; SQL_ReadResult(query, res_name, name, charsmax(name)) 261 | new authID[MAX_AUTHID_LENGTH]; SQL_ReadResult(query, res_authid, authID, charsmax(authID)) 262 | new IP[MAX_IP_LENGTH]; SQL_ReadResult(query, res_ip, IP, charsmax(IP)) 263 | new reason[MAX_REASON_LENGTH]; SQL_ReadResult(query, res_reason, reason, charsmax(reason)) 264 | 265 | new adminName[MAX_NAME_LENGTH]; SQL_ReadResult(query, res_admin_name, adminName, charsmax(adminName)) 266 | new adminAuthID[MAX_AUTHID_LENGTH]; SQL_ReadResult(query, res_admin_authid, adminAuthID, charsmax(adminAuthID)) 267 | new adminIP[MAX_IP_LENGTH]; SQL_ReadResult(query, res_admin_ip, adminIP, charsmax(adminIP)) 268 | 269 | new createdAt = SQL_ReadResult(query, res_created_at) 270 | new expireAt = SQL_ReadResult(query, res_expire_at) 271 | new flags = SQL_ReadResult(query, res_flags) 272 | 273 | CA_Log(logLevel_Debug, "Player gag saved {'%s', '%s', '%s', '%s', '%s', '%s', '%s', %i, %i, %i} (queryTime: '%.3f' sec)", \ 274 | name, authID, IP, reason, adminName, adminAuthID, adminIP, createdAt, expireAt, flags,\ 275 | queuetime \ 276 | ) 277 | 278 | ExecuteForward(g_fwd_StorageSaved, g_ret, 279 | name, authID, IP, reason, 280 | adminName, adminAuthID, adminIP, 281 | createdAt, expireAt, flags 282 | ) 283 | } 284 | 285 | Storage_Load(const authID[]) { 286 | if (!g_storageInitialized) { 287 | QueuePushString(g_queueLoad, authID) 288 | 289 | return 290 | } 291 | 292 | formatex(g_query, charsmax(g_query), "SELECT name, authid, ip, reason,\ 293 | admin_name, admin_authid, admin_ip, \ 294 | UNIX_TIMESTAMP(created_at), UNIX_TIMESTAMP(expire_at), flags FROM %s", SQL_TBL_GAGS); { 295 | strcat(g_query, fmt(" WHERE (authid = '%s')", authID), charsmax(g_query)) 296 | strcat(g_query, " AND ( expire_at = FROM_UNIXTIME(9999999999) OR (expire_at > NOW()) ) LIMIT 1", charsmax(g_query)) 297 | } 298 | 299 | SQL_ThreadQuery(g_tuple, "handle_Loaded", g_query) 300 | } 301 | 302 | public handle_Loaded(failstate, Handle: query, error[], errnum, data[], size, Float: queuetime) { 303 | if (IsSQLQueryFailed(failstate, query, error, errnum)) { 304 | return 305 | } 306 | 307 | enum { res_name, res_authid, res_ip, res_reason, 308 | res_admin_name, res_admin_authid, res_admin_ip, 309 | res_created_at, res_expire_at, res_flags 310 | } 311 | 312 | new bool: found = (SQL_NumResults(query) != 0) 313 | 314 | if (!found) { 315 | return 316 | } 317 | 318 | new name[MAX_NAME_LENGTH]; SQL_ReadResult(query, res_name, name, charsmax(name)) 319 | new authID[MAX_AUTHID_LENGTH]; SQL_ReadResult(query, res_authid, authID, charsmax(authID)) 320 | new IP[MAX_IP_LENGTH]; SQL_ReadResult(query, res_ip, IP, charsmax(IP)) 321 | new reason[MAX_REASON_LENGTH]; SQL_ReadResult(query, res_reason, reason, charsmax(reason)) 322 | 323 | new adminName[MAX_NAME_LENGTH]; SQL_ReadResult(query, res_admin_name, adminName, charsmax(adminName)) 324 | new adminAuthID[MAX_AUTHID_LENGTH]; SQL_ReadResult(query, res_admin_authid, adminAuthID, charsmax(adminAuthID)) 325 | new adminIP[MAX_IP_LENGTH]; SQL_ReadResult(query, res_admin_ip, adminIP, charsmax(adminIP)) 326 | 327 | new createdAt = SQL_ReadResult(query, res_created_at) 328 | new expireAt = SQL_ReadResult(query, res_expire_at) 329 | new flags = SQL_ReadResult(query, res_flags) 330 | 331 | CA_Log(logLevel_Debug, "Player gag loaded {'%s', '%s', '%s', '%s', '%s', '%s', '%s', %i, %i, %i} (queryTime: '%.3f' sec)", \ 332 | name, authID, IP, reason, adminName, adminAuthID, adminIP, createdAt, expireAt, flags,\ 333 | queuetime \ 334 | ) 335 | 336 | ExecuteForward(g_fwd_StorageLoaded, g_ret, 337 | name, authID, IP, reason, 338 | adminName, adminAuthID, adminIP, 339 | createdAt, expireAt, flags 340 | ) 341 | } 342 | 343 | Storage_Remove(const authID[]) { 344 | if (!g_storageInitialized || g_tuple == Empty_Handle) { 345 | CA_Log(logLevel_Warning, "Storage_Remove(): Storage connection not initialized. Query not executed. (g_storageInitialized=%i, g_tuple=%i)", 346 | g_storageInitialized, g_tuple 347 | ) 348 | 349 | return 350 | } 351 | 352 | formatex(g_query, charsmax(g_query), "DELETE FROM %s ", SQL_TBL_GAGS); { 353 | strcat(g_query, fmt("WHERE (authid = '%s')", authID), charsmax(g_query)) 354 | } 355 | 356 | SQL_ThreadQuery(g_tuple, "handle_Removed", g_query) 357 | } 358 | 359 | public handle_Removed(failstate, Handle: query, error[], errnum, data[], size, Float: queuetime) { 360 | if (IsSQLQueryFailed(failstate, query, error, errnum)) { 361 | return 362 | } 363 | 364 | CA_Log(logLevel_Debug, "Player gag removed { } (queryTime: '%.3f' sec)", \ 365 | queuetime \ 366 | ) 367 | 368 | ExecuteForward(g_fwd_StorageRemoved, g_ret) 369 | } 370 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/scripting/ChatAdditions/Storage/CA_Storage_GameCMS.sma: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #pragma dynamic 131072 12 | #pragma tabsize 4 13 | 14 | #pragma reqlib mysql 15 | #if !defined AMXMODX_NOAUTOLOAD 16 | #pragma loadlib mysql 17 | #endif 18 | 19 | new const SQL_TBL_GAGS[] = "comms" 20 | 21 | const QUERY_LENGTH = 4096 22 | const MAX_REASON_LENGTH = 256 23 | new g_query[QUERY_LENGTH] 24 | 25 | new Handle: g_tuple = Empty_Handle 26 | new Queue: g_queueLoad = Invalid_Queue, 27 | Queue: g_queueSave = Invalid_Queue 28 | 29 | new g_serverID = -1 30 | new g_gamecmsAdminId[MAX_PLAYERS + 1] 31 | 32 | new ca_server_address[128], 33 | ca_storage_host[64], 34 | ca_storage_user[128], 35 | ca_storage_pass[128], 36 | ca_storage_dbname[128] 37 | 38 | public stock const PluginName[] = "ChatAdditions: GameCMS storage" 39 | public stock const PluginVersion[] = CA_VERSION 40 | public stock const PluginAuthor[] = "Sergey Shorokhov" 41 | public stock const PluginURL[] = "https://github.com/ChatAdditions/" 42 | public stock const PluginDescription[] = "GameCMS (MySQL) storage provider for ChatAdditions" 43 | 44 | public plugin_init() { 45 | register_plugin(PluginName, PluginVersion, PluginAuthor) 46 | 47 | if (!SQL_SetAffinity("mysql")) { 48 | set_fail_state("Can't user 'MySQL'. Check modules.ini") 49 | } 50 | 51 | Create_CVars() 52 | 53 | AutoExecConfig(true, "CA_Storage_GameCMS", "ChatAdditions") 54 | 55 | g_queueLoad = QueueCreate(MAX_AUTHID_LENGTH) 56 | g_queueSave = QueueCreate(gagData_s) 57 | 58 | set_task_ex(6.274, "_OnConfigsExecuted") 59 | } 60 | 61 | public _OnConfigsExecuted() { 62 | g_tuple = SQL_MakeDbTuple(ca_storage_host, ca_storage_user, ca_storage_pass, ca_storage_dbname) 63 | SQL_SetCharset(g_tuple, "utf8") 64 | 65 | ServerAddress_Check() 66 | Storage_Create() 67 | } 68 | 69 | public plugin_end() { 70 | if (g_tuple != Empty_Handle) { 71 | SQL_FreeHandle(g_tuple) 72 | } 73 | 74 | QueueDestroy(g_queueLoad) 75 | QueueDestroy(g_queueSave) 76 | } 77 | 78 | public plugin_natives() { 79 | RegisterNatives() 80 | } 81 | 82 | public plugin_cfg() { 83 | RegisterForwards() 84 | } 85 | 86 | public client_putinserver(id) { 87 | if (!g_storageInitialized) { 88 | return 89 | } 90 | 91 | GameCMS_GetAdminID(id) 92 | } 93 | 94 | public client_disconnected(id) { 95 | g_gamecmsAdminId[id] = 0 96 | } 97 | 98 | Create_CVars() { 99 | bind_pcvar_string(create_cvar("ca_server_address", "", 100 | .description = "Server address in the GameCMS database" 101 | ), 102 | ca_server_address, charsmax(ca_server_address) 103 | ) 104 | 105 | bind_pcvar_string(create_cvar("ca_storage_host", "127.0.0.1", FCVAR_PROTECTED, 106 | .description = "GameCMS MySQL database host address" 107 | ), 108 | ca_storage_host, charsmax(ca_storage_host) 109 | ) 110 | 111 | bind_pcvar_string(create_cvar("ca_storage_user", "root", FCVAR_PROTECTED, 112 | .description = "GameCMS MySQL database user" 113 | ), 114 | ca_storage_user, charsmax(ca_storage_user) 115 | ) 116 | 117 | bind_pcvar_string(create_cvar("ca_storage_pass", "", FCVAR_PROTECTED, 118 | .description = "GameCMS MySQL database host password" 119 | ), 120 | ca_storage_pass, charsmax(ca_storage_pass) 121 | ) 122 | 123 | bind_pcvar_string(create_cvar("ca_storage_dbname", "players_gags", FCVAR_PROTECTED, 124 | .description = "GameCMS MySQL database name (not recommended to change)" 125 | ), 126 | ca_storage_dbname, charsmax(ca_storage_dbname) 127 | ) 128 | } 129 | 130 | ServerAddress_Check() { 131 | if (ca_server_address[0] != EOS) 132 | return 133 | 134 | get_cvar_string("net_address", ca_server_address, charsmax(ca_server_address)) 135 | } 136 | 137 | Storage_Create() { 138 | formatex(g_query, charsmax(g_query), "CREATE TABLE IF NOT EXISTS %s ", SQL_TBL_GAGS); { 139 | strcat(g_query, "( bid int(6) NOT NULL AUTO_INCREMENT,", charsmax(g_query)) 140 | strcat(g_query, "authid varchar(32) COLLATE utf8_unicode_ci NOT NULL,", charsmax(g_query)) 141 | strcat(g_query, "name varchar(32) COLLATE utf8_unicode_ci NOT NULL,", charsmax(g_query)) 142 | strcat(g_query, "created int(11) NOT NULL,", charsmax(g_query)) 143 | strcat(g_query, "expired int(11) NOT NULL,", charsmax(g_query)) 144 | strcat(g_query, "length int(10) NOT NULL,", charsmax(g_query)) 145 | strcat(g_query, "reason varchar(64) COLLATE utf8_unicode_ci NOT NULL,", charsmax(g_query)) 146 | strcat(g_query, "admin_id int(6) NOT NULL,", charsmax(g_query)) 147 | strcat(g_query, "admin_nick varchar(32) COLLATE utf8_unicode_ci NOT NULL,", charsmax(g_query)) 148 | strcat(g_query, "server_id int(6) NOT NULL,", charsmax(g_query)) 149 | strcat(g_query, "modified_by varchar(32) COLLATE utf8_unicode_ci NOT NULL,", charsmax(g_query)) 150 | strcat(g_query, "type int(2) NOT NULL,", charsmax(g_query)) 151 | strcat(g_query, "PRIMARY KEY (bid),", charsmax(g_query)) 152 | strcat(g_query, "KEY sid (server_id),", charsmax(g_query)) 153 | strcat(g_query, "KEY type (type),", charsmax(g_query)) 154 | strcat(g_query, "KEY authid (authid),", charsmax(g_query)) 155 | strcat(g_query, "KEY created (created),", charsmax(g_query)) 156 | strcat(g_query, "KEY aid (admin_id)", charsmax(g_query)) 157 | strcat(g_query, ") ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=37 ;", charsmax(g_query)) 158 | } 159 | 160 | SQL_ThreadQuery(g_tuple, "handle_StorageCreated", g_query) 161 | } 162 | 163 | public handle_StorageCreated(failstate, Handle: query, error[], errnum, data[], size, Float: queuetime) { 164 | if (IsSQLQueryFailed(failstate, query, error, errnum)) { 165 | return 166 | } 167 | 168 | CA_Log(logLevel_Debug, "Table '%s' created! (queryTime: '%.3f' sec)", SQL_TBL_GAGS, queuetime) 169 | GameCMS_GetServerID() 170 | } 171 | 172 | 173 | Storage_Save(const name[], const authID[], const IP[], 174 | const reason[], const adminName[], const adminAuthID[], 175 | const adminIP[], const expireAt, const flags) { 176 | 177 | if (!g_storageInitialized) { 178 | new gagData[gagData_s]; { 179 | copy(gagData[gd_name], charsmax(gagData[gd_name]), name) 180 | copy(gagData[gd_authID], charsmax(gagData[gd_authID]), authID) 181 | copy(gagData[gd_IP], charsmax(gagData[gd_IP]), IP) 182 | 183 | copy(gagData[gd_adminName], charsmax(gagData[gd_adminName]), adminName) 184 | copy(gagData[gd_adminAuthID], charsmax(gagData[gd_adminAuthID]), adminAuthID) 185 | copy(gagData[gd_adminIP], charsmax(gagData[gd_adminIP]), adminIP) 186 | 187 | copy(gagData[gd_reason][r_name], charsmax(gagData[r_name]), reason) 188 | gagData[gd_reason][r_flags] = gag_flags_s: flags 189 | 190 | gagData[gd_expireAt] = expireAt 191 | } 192 | 193 | QueuePushArray(g_queueSave, gagData) 194 | 195 | return 196 | } 197 | 198 | #pragma unused adminIP, IP 199 | new name_safe[MAX_NAME_LENGTH * 2] 200 | SQL_QuoteString(Empty_Handle, name_safe, charsmax(name_safe), name) 201 | 202 | new reason_safe[MAX_REASON_LENGTH * 2] 203 | SQL_QuoteString(Empty_Handle, reason_safe, charsmax(reason_safe), reason) 204 | 205 | new adminName_safe[MAX_NAME_LENGTH * 2] 206 | SQL_QuoteString(Empty_Handle, adminName_safe, charsmax(adminName_safe), adminName) 207 | 208 | 209 | new admin_id = 0 210 | new admin = find_player_ex((FindPlayer_MatchUserId | FindPlayer_ExcludeBots), adminAuthID) 211 | if (admin) { 212 | admin_id = g_gamecmsAdminId[admin] 213 | } 214 | 215 | // TODO: Optimize this EPIC QUERY 216 | formatex(g_query, charsmax(g_query), "INSERT INTO %s ", SQL_TBL_GAGS); { 217 | strcat(g_query, "( authid,name,created,", charsmax(g_query)) 218 | strcat(g_query, "expired,length,reason,", charsmax(g_query)) 219 | strcat(g_query, "admin_id,admin_nick,server_id,modified_by,type )", charsmax(g_query)) 220 | 221 | 222 | strcat(g_query, " VALUES ( ", charsmax(g_query)) 223 | strcat(g_query, fmt("'%s',", authID), charsmax(g_query)) 224 | strcat(g_query, fmt("'%s',", name_safe), charsmax(g_query)) 225 | strcat(g_query, fmt("UNIX_TIMESTAMP(NOW()),"), charsmax(g_query)) 226 | strcat(g_query, fmt("%i,", expireAt), charsmax(g_query)) 227 | strcat(g_query, fmt("(%i - UNIX_TIMESTAMP(NOW())) / 60,", expireAt), charsmax(g_query)) 228 | strcat(g_query, fmt("'%s',", reason_safe), charsmax(g_query)) 229 | strcat(g_query, fmt("'%i',", admin_id), charsmax(g_query)) 230 | strcat(g_query, fmt("'%s',", adminName_safe), charsmax(g_query)) 231 | strcat(g_query, fmt("'%i',", g_serverID), charsmax(g_query)) 232 | strcat(g_query, fmt("'%s',", adminName_safe), charsmax(g_query)) 233 | strcat(g_query, fmt("%i ) ", CAGAGFlags_to_GCMS_Flags(gag_flags_s: flags)), charsmax(g_query)) 234 | strcat(g_query, "ON DUPLICATE KEY UPDATE ", charsmax(g_query)) 235 | strcat(g_query, fmt("name='%s',", name_safe), charsmax(g_query)) 236 | strcat(g_query, fmt("reason='%s',", reason_safe), charsmax(g_query)) 237 | strcat(g_query, fmt("admin_nick='%s',", adminName_safe), charsmax(g_query)) 238 | strcat(g_query, "created=UNIX_TIMESTAMP(NOW()),", charsmax(g_query)) 239 | strcat(g_query, fmt("expired=%i,", expireAt), charsmax(g_query)) 240 | strcat(g_query, fmt("type=%i; ", CAGAGFlags_to_GCMS_Flags(gag_flags_s: flags)), charsmax(g_query)) 241 | } 242 | 243 | SQL_ThreadQuery(g_tuple, "handle_Saved", g_query) 244 | } 245 | 246 | public handle_Saved(failstate, Handle: query, error[], errnum, data[], size, Float: queuetime) { 247 | if (IsSQLQueryFailed(failstate, query, error, errnum)) { 248 | return 249 | } 250 | 251 | formatex(g_query, charsmax(g_query), "SELECT \ 252 | name,authid,reason,\ 253 | admin_nick,\ 254 | created,expired,type") 255 | 256 | strcat(g_query, fmt(" FROM %s", SQL_TBL_GAGS), charsmax(g_query)) 257 | strcat(g_query, fmt(" WHERE bid=%i;", SQL_GetInsertId(query)), charsmax(g_query)) 258 | 259 | SQL_ThreadQuery(g_tuple, "handle_SavedResult", g_query) 260 | } 261 | 262 | public handle_SavedResult(failstate, Handle: query, error[], errnum, data[], size, Float: queuetime) { 263 | if (IsSQLQueryFailed(failstate, query, error, errnum)) { 264 | return 265 | } 266 | 267 | enum { res_name, res_authid, /* res_ip, */ res_reason, 268 | res_admin_name, /* res_admin_authid, res_admin_ip, */ 269 | res_created_at, res_expire_at, res_flags 270 | } 271 | 272 | new name[MAX_NAME_LENGTH]; SQL_ReadResult(query, res_name, name, charsmax(name)) 273 | new authID[MAX_AUTHID_LENGTH]; SQL_ReadResult(query, res_authid, authID, charsmax(authID)) 274 | new IP[MAX_IP_LENGTH]; /* SQL_ReadResult(query, res_ip, IP, charsmax(IP)) */ 275 | new reason[MAX_REASON_LENGTH]; SQL_ReadResult(query, res_reason, reason, charsmax(reason)) 276 | 277 | new adminName[MAX_NAME_LENGTH]; SQL_ReadResult(query, res_admin_name, adminName, charsmax(adminName)) 278 | new adminAuthID[MAX_AUTHID_LENGTH]; /* SQL_ReadResult(query, res_admin_authid, adminAuthID, charsmax(adminAuthID)) */ 279 | new adminIP[MAX_IP_LENGTH]; /* SQL_ReadResult(query, res_admin_ip, adminIP, charsmax(adminIP)) */ 280 | 281 | // HACK: for bad DB struct 282 | new target = find_player_ex((FindPlayer_MatchAuthId | FindPlayer_ExcludeBots), authID) 283 | if (target) 284 | get_user_ip(target, IP, charsmax(IP), true) 285 | 286 | new admin = find_player_ex((FindPlayer_MatchName | FindPlayer_ExcludeBots), adminName) 287 | if (admin) { 288 | get_user_authid(admin, adminAuthID, charsmax(adminAuthID)) 289 | get_user_ip(admin, adminIP, charsmax(adminIP), true) 290 | } 291 | 292 | new createdAt = SQL_ReadResult(query, res_created_at) 293 | new expireAt = SQL_ReadResult(query, res_expire_at) 294 | new flags = GCMS_FlagsTo_CAGAGFlags(SQL_ReadResult(query, res_flags)) 295 | 296 | CA_Log(logLevel_Debug, "Player gag saved {'%s', '%s', '%s', '%s', '%s', '%s', '%s', %i, %i, %i} (queryTime: '%.3f' sec)", \ 297 | name, authID, IP, reason, adminName, adminAuthID, adminIP, createdAt, expireAt, flags,\ 298 | queuetime \ 299 | ) 300 | 301 | ExecuteForward(g_fwd_StorageSaved, g_ret, 302 | name, authID, IP, reason, 303 | adminName, adminAuthID, adminIP, 304 | createdAt, expireAt, flags 305 | ) 306 | } 307 | 308 | Storage_Load(const authID[]) { 309 | if (!g_storageInitialized) { 310 | QueuePushString(g_queueLoad, authID) 311 | 312 | return 313 | } 314 | 315 | formatex(g_query, charsmax(g_query), "SELECT name, authid, reason,\ 316 | admin_nick, \ 317 | created, expired, type FROM %s", SQL_TBL_GAGS); { 318 | strcat(g_query, fmt(" WHERE (authid = '%s')", authID), charsmax(g_query)) 319 | strcat(g_query, " AND (expired > UNIX_TIMESTAMP(NOW())) LIMIT 1;", charsmax(g_query)) 320 | } 321 | 322 | SQL_ThreadQuery(g_tuple, "handle_Loaded", g_query) 323 | } 324 | 325 | public handle_Loaded(failstate, Handle: query, error[], errnum, data[], size, Float: queuetime) { 326 | if (IsSQLQueryFailed(failstate, query, error, errnum)) { 327 | return 328 | } 329 | 330 | enum { res_name, res_authid, /* res_ip, */res_reason, 331 | res_admin_name, /* res_admin_authid, res_admin_ip, */ 332 | res_created_at, res_expire_at, res_flags 333 | } 334 | 335 | new bool: found = (SQL_NumResults(query) != 0) 336 | 337 | if (!found) { 338 | return 339 | } 340 | 341 | new name[MAX_NAME_LENGTH]; SQL_ReadResult(query, res_name, name, charsmax(name)) 342 | new authID[MAX_AUTHID_LENGTH]; SQL_ReadResult(query, res_authid, authID, charsmax(authID)) 343 | new IP[MAX_IP_LENGTH]; /* SQL_ReadResult(query, res_ip, IP, charsmax(IP)) */ 344 | new reason[MAX_REASON_LENGTH]; SQL_ReadResult(query, res_reason, reason, charsmax(reason)) 345 | 346 | new adminName[MAX_NAME_LENGTH]; SQL_ReadResult(query, res_admin_name, adminName, charsmax(adminName)) 347 | new adminAuthID[MAX_AUTHID_LENGTH]; /* SQL_ReadResult(query, res_admin_authid, adminAuthID, charsmax(adminAuthID)) */ 348 | new adminIP[MAX_IP_LENGTH]; /* SQL_ReadResult(query, res_admin_ip, adminIP, charsmax(adminIP)) */ 349 | 350 | // HACK: for bad DB struct 351 | new target = find_player_ex((FindPlayer_MatchAuthId | FindPlayer_ExcludeBots), authID) 352 | if (target) 353 | get_user_ip(target, IP, charsmax(IP), true) 354 | 355 | new admin = find_player_ex((FindPlayer_MatchName | FindPlayer_ExcludeBots), adminName) 356 | if (admin) { 357 | get_user_authid(admin, adminAuthID, charsmax(adminAuthID)) 358 | get_user_ip(admin, adminIP, charsmax(adminIP), true) 359 | } 360 | 361 | new createdAt = SQL_ReadResult(query, res_created_at) 362 | new expireAt = SQL_ReadResult(query, res_expire_at) 363 | new flags = GCMS_FlagsTo_CAGAGFlags(SQL_ReadResult(query, res_flags)) 364 | 365 | CA_Log(logLevel_Debug, "Player gag loaded {'%s', '%s', '%s', '%s', '%s', '%s', '%s', %i, %i, %i} (queryTime: '%.3f' sec)", \ 366 | name, authID, IP, reason, adminName, adminAuthID, adminIP, createdAt, expireAt, flags,\ 367 | queuetime \ 368 | ) 369 | 370 | ExecuteForward(g_fwd_StorageLoaded, g_ret, 371 | name, authID, IP, reason, 372 | adminName, adminAuthID, adminIP, 373 | createdAt, expireAt, flags 374 | ) 375 | } 376 | 377 | Storage_Remove(const authID[]) { 378 | if (!g_storageInitialized || g_tuple == Empty_Handle) { 379 | CA_Log(logLevel_Warning, "Storage_Remove(): Storage connection not initialized. Query not executed. (g_storageInitialized=%i, g_tuple=%i)", 380 | g_storageInitialized, g_tuple 381 | ) 382 | 383 | return 384 | } 385 | 386 | formatex(g_query, charsmax(g_query), "DELETE FROM %s ", SQL_TBL_GAGS); { 387 | strcat(g_query, fmt("WHERE (authid = '%s')", authID), charsmax(g_query)) 388 | } 389 | 390 | SQL_ThreadQuery(g_tuple, "handle_Removed", g_query) 391 | } 392 | 393 | public handle_Removed(failstate, Handle: query, error[], errnum, data[], size, Float: queuetime) { 394 | if (IsSQLQueryFailed(failstate, query, error, errnum)) { 395 | return 396 | } 397 | 398 | CA_Log(logLevel_Debug, "Player gag removed { } (queryTime: '%.3f' sec)", \ 399 | queuetime \ 400 | ) 401 | 402 | ExecuteForward(g_fwd_StorageRemoved, g_ret) 403 | } 404 | 405 | GameCMS_GetServerID() { 406 | new serverAddress[2][128] 407 | explode_string(ca_server_address, ":", serverAddress, sizeof(serverAddress), charsmax(serverAddress[])) 408 | 409 | formatex(g_query, charsmax(g_query), "SELECT id FROM servers WHERE servers.ip = '%s' AND servers.port = '%s' LIMIT 1;", 410 | serverAddress[0], serverAddress[1] 411 | ) 412 | 413 | SQL_ThreadQuery(g_tuple, "handle_GetServerID", g_query) 414 | } 415 | 416 | public handle_GetServerID(failstate, Handle: query, error[], errnum, data[], size, Float: queuetime) { 417 | if (IsSQLQueryFailed(failstate, query, error, errnum)) { 418 | return 419 | } 420 | 421 | new bool: found = bool: (SQL_NumResults(query) != 0) 422 | 423 | if (!found) { 424 | set_fail_state("Server `%s` not found on db.", ca_server_address) 425 | 426 | return 427 | } 428 | 429 | g_serverID = SQL_ReadResult(query, 0) 430 | CA_Log(logLevel_Debug, "Found server `%s` in db. ServerID=%i", ca_server_address, g_serverID) 431 | 432 | g_storageInitialized = true 433 | ExecuteForward(g_fwd_StorageInitialized, g_ret) 434 | 435 | // Load prepared data from storage 436 | new queueCounter 437 | 438 | for(new i, len = QueueSize(g_queueLoad); i < len; i++) { 439 | new authID[MAX_AUTHID_LENGTH]; QueuePopString(g_queueLoad, authID, charsmax(authID)) 440 | Storage_Load(authID) 441 | 442 | ++queueCounter 443 | } 444 | 445 | if (queueCounter) { 446 | CA_Log(logLevel_Warning, "Loaded %i queue gags from DB (slow DB connection issue)", queueCounter) 447 | queueCounter = 0 448 | } 449 | 450 | // Save prepared data to storage 451 | for(new i, len = QueueSize(g_queueSave); i < len; i++) { 452 | new gagData[gagData_s]; QueuePopArray(g_queueSave, gagData, sizeof(gagData)) 453 | 454 | Storage_Save(gagData[gd_name], gagData[gd_authID], gagData[gd_IP], 455 | gagData[gd_reason][r_name], gagData[gd_adminName], gagData[gd_adminAuthID], 456 | gagData[gd_adminIP], gagData[gd_expireAt], gagData[gd_reason][r_flags] 457 | ) 458 | 459 | ++queueCounter 460 | } 461 | 462 | if (queueCounter) { 463 | CA_Log(logLevel_Warning, "Saved %i queue gags to DB (slow DB connection issue)", queueCounter) 464 | queueCounter = 0 465 | } 466 | 467 | new players[MAX_PLAYERS], count 468 | get_players_ex(players, count, .flags = (GetPlayers_ExcludeBots | GetPlayers_ExcludeHLTV)) 469 | 470 | for(new i; i < count; i++) { 471 | GameCMS_GetAdminID(players[i]) 472 | } 473 | } 474 | 475 | enum { 476 | GCMS_FLAG_NONE = -1, 477 | GCMS_FLAG_ALL, 478 | GCMS_FLAG_CHAT, 479 | GCMS_FLAG_VOICE 480 | } 481 | 482 | static stock gag_flags_s: GCMS_FlagsTo_CAGAGFlags(const flag) { 483 | switch (flag) { 484 | case GCMS_FLAG_NONE: return (gagFlag_Removed) 485 | case GCMS_FLAG_ALL: return (gagFlag_Say | gagFlag_SayTeam | gagFlag_Voice) 486 | case GCMS_FLAG_CHAT: return (gagFlag_Say | gagFlag_SayTeam) 487 | case GCMS_FLAG_VOICE: return (gagFlag_Voice) 488 | } 489 | 490 | CA_Log(logLevel_Warning, "[WARN]: GCMS_FlagsTo_CAGAGFlags() => Undefinded flag:%i", flag) 491 | return gagFlag_Removed 492 | } 493 | 494 | static stock CAGAGFlags_to_GCMS_Flags(const gag_flags_s: flags) { 495 | if (flags == gagFlag_Voice) { 496 | return GCMS_FLAG_VOICE 497 | } 498 | if (flags == (gagFlag_Say | gagFlag_SayTeam | gagFlag_Voice)) { 499 | return GCMS_FLAG_ALL 500 | } 501 | if (flags & (gagFlag_Say | gagFlag_SayTeam)) { 502 | return GCMS_FLAG_CHAT 503 | } 504 | 505 | return GCMS_FLAG_NONE 506 | } 507 | 508 | GameCMS_GetAdminID(const id) { 509 | new authID[MAX_AUTHID_LENGTH], name[MAX_NAME_LENGTH] 510 | get_user_authid(id, authID, charsmax(authID)) 511 | get_user_name(id, name, charsmax(name)) 512 | 513 | new name_safe[MAX_NAME_LENGTH * 2] 514 | SQL_QuoteString(Empty_Handle, name_safe, charsmax(name_safe), name) 515 | 516 | formatex(g_query, charsmax(g_query), "SELECT id FROM admins WHERE (name = '%s' or name = ^"%s^") LIMIT 1;", 517 | authID, name_safe 518 | ) 519 | 520 | new data[1]; data[0] = id 521 | SQL_ThreadQuery(g_tuple, "handle_GetAdminID", g_query, data, sizeof(data)) 522 | } 523 | 524 | public handle_GetAdminID(failstate, Handle: query, error[], errnum, data[], size, Float: queuetime) { 525 | enum { col_id } 526 | 527 | if (IsSQLQueryFailed(failstate, query, error, errnum)) { 528 | return 529 | } 530 | 531 | new bool: found = bool: (SQL_NumResults(query) != 0) 532 | if (!found) { 533 | return 534 | } 535 | 536 | g_gamecmsAdminId[data[0]] = SQL_ReadResult(query, col_id) 537 | CA_Log(logLevel_Debug, "Found admin `%N` in gameCMS DB. admins.id=%i", data[0], g_gamecmsAdminId[data[0]]) 538 | } 539 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/scripting/ChatAdditions/Storage/CA_Storage_PGBans.sma: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #pragma dynamic 131072 12 | #pragma tabsize 4 13 | 14 | #pragma reqlib mysql 15 | #if !defined AMXMODX_NOAUTOLOAD 16 | #pragma loadlib mysql 17 | #endif 18 | 19 | new const SQL_TBL_GAGS[] = "pgb_comms" 20 | 21 | const QUERY_LENGTH = 4096 22 | const MAX_REASON_LENGTH = 256 23 | new g_query[QUERY_LENGTH] 24 | 25 | new Handle: g_tuple = Empty_Handle 26 | new Queue: g_queueLoad = Invalid_Queue, 27 | Queue: g_queueSave = Invalid_Queue 28 | 29 | new pgb_storage_host[33], 30 | pgb_storage_user[33], 31 | pgb_storage_pass[64], 32 | pgb_storage_dbname[33] 33 | 34 | public stock const PluginName[] = "ChatAdditions: PGBans storage" 35 | public stock const PluginVersion[] = CA_VERSION 36 | public stock const PluginAuthor[] = "Sergey Shorokhov" 37 | public stock const PluginURL[] = "https://github.com/ChatAdditions/" 38 | public stock const PluginDescription[] = "PGBans (MySQL) storage provider for ChatAdditions" 39 | 40 | public plugin_init() { 41 | register_plugin(PluginName, PluginVersion, PluginAuthor) 42 | 43 | if (!SQL_SetAffinity("mysql")) { 44 | set_fail_state("Can't user 'MySQL'. Check modules.ini") 45 | } 46 | 47 | Create_CVars() 48 | 49 | AutoExecConfig(true, "CA_Storage_PGBans", "ChatAdditions") 50 | 51 | g_queueLoad = QueueCreate(MAX_AUTHID_LENGTH) 52 | g_queueSave = QueueCreate(gagData_s) 53 | 54 | set_task_ex(6.274, "_OnConfigsExecuted") 55 | } 56 | 57 | public _OnConfigsExecuted() { 58 | g_tuple = SQL_MakeDbTuple(pgb_storage_host, pgb_storage_user, pgb_storage_pass, pgb_storage_dbname) 59 | 60 | Storage_Create() 61 | } 62 | 63 | public plugin_end() { 64 | if (g_tuple != Empty_Handle) { 65 | SQL_FreeHandle(g_tuple) 66 | } 67 | 68 | QueueDestroy(g_queueLoad) 69 | QueueDestroy(g_queueSave) 70 | } 71 | 72 | public plugin_natives() { 73 | RegisterNatives() 74 | } 75 | 76 | public plugin_cfg() { 77 | RegisterForwards() 78 | } 79 | 80 | Create_CVars() { 81 | bind_pcvar_string(create_cvar("pgb_storage_host", "127.0.0.1", FCVAR_PROTECTED, 82 | .description = "PGBans MySQL database host address" 83 | ), 84 | pgb_storage_host, charsmax(pgb_storage_host) 85 | ) 86 | 87 | bind_pcvar_string(create_cvar("pgb_storage_user", "root", FCVAR_PROTECTED, 88 | .description = "PGBans MySQL database user" 89 | ), 90 | pgb_storage_user, charsmax(pgb_storage_user) 91 | ) 92 | 93 | bind_pcvar_string(create_cvar("pgb_storage_pass", "pass", FCVAR_PROTECTED, 94 | .description = "PGBans MySQL database host password" 95 | ), 96 | pgb_storage_pass, charsmax(pgb_storage_pass) 97 | ) 98 | 99 | bind_pcvar_string(create_cvar("pgb_storage_dbname", "db", FCVAR_PROTECTED, 100 | .description = "PGBans MySQL database name" 101 | ), 102 | pgb_storage_dbname, charsmax(pgb_storage_dbname) 103 | ) 104 | } 105 | 106 | Storage_Create() { 107 | formatex(g_query, charsmax(g_query), "CREATE TABLE IF NOT EXISTS %s ", SQL_TBL_GAGS); { 108 | strcat(g_query, "( id INTEGER PRIMARY KEY AUTO_INCREMENT,", charsmax(g_query)) 109 | strcat(g_query, "name VARCHAR(32) NOT NULL,", charsmax(g_query)) 110 | strcat(g_query, "authid VARCHAR(64) NOT NULL,", charsmax(g_query)) 111 | strcat(g_query, "ip VARCHAR(22) NOT NULL,", charsmax(g_query)) 112 | strcat(g_query, "reason VARCHAR(256) NOT NULL,", charsmax(g_query)) 113 | strcat(g_query, "admin_name VARCHAR(32) NOT NULL,", charsmax(g_query)) 114 | strcat(g_query, "admin_authid VARCHAR(64) NOT NULL,", charsmax(g_query)) 115 | strcat(g_query, "admin_ip VARCHAR(22) NOT NULL,", charsmax(g_query)) 116 | strcat(g_query, "created_at DATETIME NOT NULL,", charsmax(g_query)) 117 | strcat(g_query, "expire_at DATETIME NOT NULL,", charsmax(g_query)) 118 | strcat(g_query, "flags INTEGER NOT NULL,", charsmax(g_query)) 119 | strcat(g_query, "UNIQUE INDEX authid_unique_idx (authid)", charsmax(g_query)) 120 | strcat(g_query, ") CHARACTER SET utf8 COLLATE utf8_general_ci;", charsmax(g_query)) 121 | } 122 | 123 | SQL_ThreadQuery(g_tuple, "handle_StorageCreated", g_query) 124 | } 125 | 126 | public handle_StorageCreated(failstate, Handle: query, error[], errnum, data[], size, Float:queuetime) { 127 | if (IsSQLQueryFailed(failstate, query, error, errnum)) { 128 | return 129 | } 130 | 131 | CA_Log(logLevel_Debug, "Table '%s' created! (queryTime: '%.3f' sec)", SQL_TBL_GAGS, queuetime) 132 | 133 | g_storageInitialized = true 134 | ExecuteForward(g_fwd_StorageInitialized, g_ret) 135 | 136 | // Load prepared data from storage 137 | new queueCounter 138 | 139 | for(new i, len = QueueSize(g_queueLoad); i < len; i++) { 140 | new authID[MAX_AUTHID_LENGTH]; QueuePopString(g_queueLoad, authID, charsmax(authID)) 141 | Storage_Load(authID) 142 | 143 | ++queueCounter 144 | } 145 | 146 | if (queueCounter) { 147 | CA_Log(logLevel_Info, "Loaded %i queue gags from DB (slow DB connection issue)", queueCounter) 148 | queueCounter = 0 149 | } 150 | 151 | // Save prepared data to storage 152 | for(new i, len = QueueSize(g_queueSave); i < len; i++) { 153 | new gagData[gagData_s]; QueuePopArray(g_queueSave, gagData, sizeof(gagData)) 154 | 155 | Storage_Save(gagData[gd_name], gagData[gd_authID], gagData[gd_IP], 156 | gagData[gd_reason][r_name], gagData[gd_adminName], gagData[gd_adminAuthID], 157 | gagData[gd_adminIP], gagData[gd_expireAt], gagData[gd_reason][r_flags] 158 | ) 159 | 160 | ++queueCounter 161 | } 162 | 163 | if (queueCounter) { 164 | CA_Log(logLevel_Info, "Saved %i queue gags to DB (slow DB connection issue)", queueCounter) 165 | queueCounter = 0 166 | } 167 | } 168 | 169 | 170 | Storage_Save(const name[], const authID[], const IP[], 171 | const reason[], const adminName[], const adminAuthID[], 172 | const adminIP[], const expireAt, const flags) { 173 | 174 | if (!g_storageInitialized) { 175 | new gagData[gagData_s]; { 176 | copy(gagData[gd_name], charsmax(gagData[gd_name]), name) 177 | copy(gagData[gd_authID], charsmax(gagData[gd_authID]), authID) 178 | copy(gagData[gd_IP], charsmax(gagData[gd_IP]), IP) 179 | 180 | copy(gagData[gd_adminName], charsmax(gagData[gd_adminName]), adminName) 181 | copy(gagData[gd_adminAuthID], charsmax(gagData[gd_adminAuthID]), adminAuthID) 182 | copy(gagData[gd_adminIP], charsmax(gagData[gd_adminIP]), adminIP) 183 | 184 | copy(gagData[gd_reason][r_name], charsmax(gagData[r_name]), reason) 185 | gagData[gd_reason][r_flags] = gag_flags_s: flags 186 | 187 | gagData[gd_expireAt] = expireAt 188 | } 189 | 190 | QueuePushArray(g_queueSave, gagData) 191 | 192 | return 193 | } 194 | 195 | new name_safe[MAX_NAME_LENGTH * 2] 196 | SQL_QuoteString(Empty_Handle, name_safe, charsmax(name_safe), name) 197 | 198 | new reason_safe[MAX_REASON_LENGTH * 2] 199 | SQL_QuoteString(Empty_Handle, reason_safe, charsmax(reason_safe), reason) 200 | 201 | new adminName_safe[MAX_NAME_LENGTH * 2] 202 | SQL_QuoteString(Empty_Handle, adminName_safe, charsmax(adminName_safe), adminName) 203 | 204 | // TODO: Optimize this EPIC QUERY 205 | formatex(g_query, charsmax(g_query), "INSERT INTO %s ", SQL_TBL_GAGS); { 206 | strcat(g_query, "( name,authid,ip,", charsmax(g_query)) 207 | strcat(g_query, "reason,admin_name,admin_authid,", charsmax(g_query)) 208 | strcat(g_query, "admin_ip,created_at,expire_at,flags )", charsmax(g_query)) 209 | 210 | strcat(g_query, fmt(" VALUES ( '%s',", name_safe), charsmax(g_query)) 211 | strcat(g_query, fmt("'%s',", authID), charsmax(g_query)) 212 | strcat(g_query, fmt("'%s',", IP), charsmax(g_query)) 213 | strcat(g_query, fmt("'%s',", reason_safe), charsmax(g_query)) 214 | strcat(g_query, fmt("'%s',", adminName_safe), charsmax(g_query)) 215 | strcat(g_query, fmt("'%s',", adminAuthID), charsmax(g_query)) 216 | strcat(g_query, fmt("'%s',", adminIP), charsmax(g_query)) 217 | strcat(g_query, fmt("NOW(),"), charsmax(g_query)) 218 | strcat(g_query, fmt("FROM_UNIXTIME(%i),", expireAt), charsmax(g_query)) 219 | strcat(g_query, fmt("%i ) ", flags), charsmax(g_query)) 220 | strcat(g_query, "ON DUPLICATE KEY UPDATE ", charsmax(g_query)) 221 | strcat(g_query, fmt("name='%s',", name_safe), charsmax(g_query)) 222 | strcat(g_query, fmt("ip='%s',", IP), charsmax(g_query)) 223 | strcat(g_query, fmt("reason='%s',", reason_safe), charsmax(g_query)) 224 | strcat(g_query, fmt("admin_name='%s',", adminName_safe), charsmax(g_query)) 225 | strcat(g_query, fmt("admin_authid='%s',", adminAuthID), charsmax(g_query)) 226 | strcat(g_query, fmt("admin_ip='%s',", adminIP), charsmax(g_query)) 227 | strcat(g_query, "created_at=NOW(),", charsmax(g_query)) 228 | strcat(g_query, fmt("expire_at=FROM_UNIXTIME(%i),", expireAt), charsmax(g_query)) 229 | strcat(g_query, fmt("flags=%i;", flags), charsmax(g_query)) 230 | } 231 | 232 | SQL_ThreadQuery(g_tuple, "handle_Saved", g_query) 233 | } 234 | 235 | public handle_Saved(failstate, Handle: query, error[], errnum, data[], size, Float: queuetime) { 236 | if (IsSQLQueryFailed(failstate, query, error, errnum)) { 237 | return 238 | } 239 | 240 | formatex(g_query, charsmax(g_query), "SELECT \ 241 | name,authid,ip,reason,\ 242 | admin_name,admin_authid,admin_ip,\ 243 | UNIX_TIMESTAMP(created_at),UNIX_TIMESTAMP(expire_at),flags") 244 | strcat(g_query, fmt(" FROM %s", SQL_TBL_GAGS), charsmax(g_query)) 245 | strcat(g_query, fmt(" WHERE id=%i;", SQL_GetInsertId(query)), charsmax(g_query)) 246 | 247 | SQL_ThreadQuery(g_tuple, "handle_SavedResult", g_query) 248 | } 249 | 250 | public handle_SavedResult(failstate, Handle: query, error[], errnum, data[], size, Float: queuetime) { 251 | if (IsSQLQueryFailed(failstate, query, error, errnum)) { 252 | return 253 | } 254 | 255 | enum { res_name, res_authid, res_ip, res_reason, 256 | res_admin_name, res_admin_authid, res_admin_ip, 257 | res_created_at, res_expire_at, res_flags 258 | } 259 | 260 | new name[MAX_NAME_LENGTH]; SQL_ReadResult(query, res_name, name, charsmax(name)) 261 | new authID[MAX_AUTHID_LENGTH]; SQL_ReadResult(query, res_authid, authID, charsmax(authID)) 262 | new IP[MAX_IP_LENGTH]; SQL_ReadResult(query, res_ip, IP, charsmax(IP)) 263 | new reason[MAX_REASON_LENGTH]; SQL_ReadResult(query, res_reason, reason, charsmax(reason)) 264 | 265 | new adminName[MAX_NAME_LENGTH]; SQL_ReadResult(query, res_admin_name, adminName, charsmax(adminName)) 266 | new adminAuthID[MAX_AUTHID_LENGTH]; SQL_ReadResult(query, res_admin_authid, adminAuthID, charsmax(adminAuthID)) 267 | new adminIP[MAX_IP_LENGTH]; SQL_ReadResult(query, res_admin_ip, adminIP, charsmax(adminIP)) 268 | 269 | new createdAt = SQL_ReadResult(query, res_created_at) 270 | new expireAt = SQL_ReadResult(query, res_expire_at) 271 | new flags = SQL_ReadResult(query, res_flags) 272 | 273 | CA_Log(logLevel_Debug, "Player gag saved {'%s', '%s', '%s', '%s', '%s', '%s', '%s', %i, %i, %i} (queryTime: '%.3f' sec)", \ 274 | name, authID, IP, reason, adminName, adminAuthID, adminIP, createdAt, expireAt, flags,\ 275 | queuetime \ 276 | ) 277 | 278 | ExecuteForward(g_fwd_StorageSaved, g_ret, 279 | name, authID, IP, reason, 280 | adminName, adminAuthID, adminIP, 281 | createdAt, expireAt, flags 282 | ) 283 | } 284 | 285 | Storage_Load(const authID[]) { 286 | if (!g_storageInitialized) { 287 | QueuePushString(g_queueLoad, authID) 288 | 289 | return 290 | } 291 | 292 | formatex(g_query, charsmax(g_query), "SELECT name, authid, ip, reason,\ 293 | admin_name, admin_authid, admin_ip, \ 294 | UNIX_TIMESTAMP(created_at), UNIX_TIMESTAMP(expire_at), flags FROM %s", SQL_TBL_GAGS); { 295 | strcat(g_query, fmt(" WHERE (authid = '%s')", authID), charsmax(g_query)) 296 | strcat(g_query, " AND ( expire_at = FROM_UNIXTIME(9999999999) OR (expire_at > NOW())) LIMIT 1", charsmax(g_query)) 297 | } 298 | 299 | SQL_ThreadQuery(g_tuple, "handle_Loaded", g_query) 300 | } 301 | 302 | public handle_Loaded(failstate, Handle: query, error[], errnum, data[], size, Float:queuetime) { 303 | if (IsSQLQueryFailed(failstate, query, error, errnum)) { 304 | return 305 | } 306 | 307 | enum { res_name, res_authid, res_ip, res_reason, 308 | res_admin_name, res_admin_authid, res_admin_ip, 309 | res_created_at, res_expire_at, res_flags 310 | } 311 | 312 | new bool: found = (SQL_NumResults(query) != 0) 313 | 314 | if (!found) { 315 | return 316 | } 317 | 318 | new name[MAX_NAME_LENGTH]; SQL_ReadResult(query, res_name, name, charsmax(name)) 319 | new authID[MAX_AUTHID_LENGTH]; SQL_ReadResult(query, res_authid, authID, charsmax(authID)) 320 | new IP[MAX_IP_LENGTH]; SQL_ReadResult(query, res_ip, IP, charsmax(IP)) 321 | new reason[MAX_REASON_LENGTH]; SQL_ReadResult(query, res_reason, reason, charsmax(reason)) 322 | 323 | new adminName[MAX_NAME_LENGTH]; SQL_ReadResult(query, res_admin_name, adminName, charsmax(adminName)) 324 | new adminAuthID[MAX_AUTHID_LENGTH]; SQL_ReadResult(query, res_admin_authid, adminAuthID, charsmax(adminAuthID)) 325 | new adminIP[MAX_IP_LENGTH]; SQL_ReadResult(query, res_admin_ip, adminIP, charsmax(adminIP)) 326 | 327 | new createdAt = SQL_ReadResult(query, res_created_at) 328 | new expireAt = SQL_ReadResult(query, res_expire_at) 329 | new flags = SQL_ReadResult(query, res_flags) 330 | 331 | CA_Log(logLevel_Debug, "Player gag loaded {'%s', '%s', '%s', '%s', '%s', '%s', '%s', %i, %i, %i} (queryTime: '%.3f' sec)", \ 332 | name, authID, IP, reason, adminName, adminAuthID, adminIP, createdAt, expireAt, flags, \ 333 | queuetime \ 334 | ) 335 | 336 | ExecuteForward(g_fwd_StorageLoaded, g_ret, 337 | name, authID, IP, reason, 338 | adminName, adminAuthID, adminIP, 339 | createdAt, expireAt, flags 340 | ) 341 | } 342 | 343 | Storage_Remove(const authID[]) { 344 | if (!g_storageInitialized || g_tuple == Empty_Handle) { 345 | CA_Log(logLevel_Warning, "Storage_Remove(): Storage connection not initialized. Query not executed. (g_storageInitialized=%i, g_tuple=%i)", 346 | g_storageInitialized, g_tuple 347 | ) 348 | 349 | return 350 | } 351 | 352 | formatex(g_query, charsmax(g_query), "DELETE FROM %s ", SQL_TBL_GAGS); { 353 | strcat(g_query, fmt("WHERE (authid = '%s')", authID), charsmax(g_query)) 354 | } 355 | 356 | SQL_ThreadQuery(g_tuple, "handle_Removed", g_query) 357 | } 358 | 359 | public handle_Removed(failstate, Handle: query, error[], errnum, data[], size, Float: queuetime) { 360 | if (IsSQLQueryFailed(failstate, query, error, errnum)) { 361 | return 362 | } 363 | 364 | CA_Log(logLevel_Debug, "Player gag removed { } (queryTime: '%.3f' sec)", \ 365 | queuetime \ 366 | ) 367 | 368 | ExecuteForward(g_fwd_StorageRemoved, g_ret) 369 | } 370 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/scripting/ChatAdditions/Storage/CA_Storage_SQLite.sma: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #pragma dynamic 131072 8 | #pragma tabsize 4 9 | 10 | #pragma reqlib sqlite 11 | #if !defined AMXMODX_NOAUTOLOAD 12 | #pragma loadlib sqlite 13 | #endif 14 | 15 | new const SQL_DBNAME[] = "ChatAdditions" 16 | new const SQL_TBL_GAGS[] = "players_gags" 17 | 18 | const QUERY_LENGTH = 4096 19 | const MAX_REASON_LENGTH = 256 20 | 21 | new Handle: g_tuple = Empty_Handle 22 | 23 | public stock const PluginName[] = "ChatAdditions: SQLite storage" 24 | public stock const PluginVersion[] = CA_VERSION 25 | public stock const PluginAuthor[] = "Sergey Shorokhov" 26 | public stock const PluginURL[] = "https://github.com/ChatAdditions/" 27 | public stock const PluginDescription[] = "SQLite storage provider for ChatAdditions" 28 | 29 | public plugin_init() { 30 | register_plugin(PluginName, PluginVersion, PluginAuthor) 31 | 32 | if (!SQL_SetAffinity("sqlite")) { 33 | set_fail_state("Can't user 'SQLite'. Check modules.ini") 34 | } 35 | 36 | g_tuple = SQL_MakeDbTuple("", "", "", SQL_DBNAME) 37 | 38 | Storage_Create() 39 | } 40 | 41 | public plugin_end() { 42 | if (g_tuple != Empty_Handle) { 43 | SQL_FreeHandle(g_tuple) 44 | } 45 | } 46 | 47 | public plugin_natives() { 48 | RegisterNatives() 49 | } 50 | 51 | public plugin_cfg() { 52 | RegisterForwards() 53 | } 54 | 55 | Storage_Create() { 56 | new query[QUERY_LENGTH] 57 | 58 | formatex(query, charsmax(query), "CREATE TABLE IF NOT EXISTS %s ", SQL_TBL_GAGS); { 59 | strcat(query, "( id INTEGER PRIMARY KEY AUTOINCREMENT,", charsmax(query)) 60 | strcat(query, "name VARCHAR NOT NULL,", charsmax(query)) 61 | strcat(query, "authid VARCHAR NOT NULL,", charsmax(query)) 62 | strcat(query, "ip VARCHAR NOT NULL,", charsmax(query)) 63 | strcat(query, "reason VARCHAR NOT NULL,", charsmax(query)) 64 | strcat(query, "admin_name VARCHAR NOT NULL,", charsmax(query)) 65 | strcat(query, "admin_authid VARCHAR NOT NULL,", charsmax(query)) 66 | strcat(query, "admin_ip VARCHAR NOT NULL,", charsmax(query)) 67 | strcat(query, "created_at DATETIME NOT NULL,", charsmax(query)) 68 | strcat(query, "expire_at DATETIME NOT NULL,", charsmax(query)) 69 | strcat(query, "flags INTEGER NOT NULL", charsmax(query)) 70 | strcat(query, ");", charsmax(query)) 71 | } 72 | strcat(query, fmt("CREATE UNIQUE INDEX IF NOT EXISTS authid_unique_idx ON %s (authid)", SQL_TBL_GAGS), charsmax(query)) 73 | 74 | SQL_ThreadQuery(g_tuple, "handle_StorageCreated", query) 75 | } 76 | 77 | public handle_StorageCreated(failstate, Handle: query, error[], errnum, data[], size, Float: queuetime) { 78 | if (IsSQLQueryFailed(failstate, query, error, errnum)) { 79 | return 80 | } 81 | 82 | CA_Log(logLevel_Debug, "Table '%s' created! (queryTime: '%.3f' sec)", SQL_TBL_GAGS, queuetime) 83 | 84 | ExecuteForward(g_fwd_StorageInitialized, g_ret) 85 | } 86 | 87 | Storage_Save(const name[], const authID[], const IP[], 88 | const reason[], const adminName[], const adminAuthID[], 89 | const adminIP[], const expireAt, const flags) { 90 | 91 | new name_safe[MAX_NAME_LENGTH * 2] 92 | SQL_QuoteString(Empty_Handle, name_safe, charsmax(name_safe), name) 93 | 94 | new reason_safe[MAX_REASON_LENGTH * 2] 95 | SQL_QuoteString(Empty_Handle, reason_safe, charsmax(reason_safe), reason) 96 | 97 | new adminName_safe[MAX_NAME_LENGTH * 2] 98 | SQL_QuoteString(Empty_Handle, adminName_safe, charsmax(adminName_safe), adminName) 99 | 100 | new query[QUERY_LENGTH] 101 | formatex(query, charsmax(query), "INSERT OR REPLACE INTO %s ", SQL_TBL_GAGS); { 102 | strcat(query, "( name,authid,ip,", charsmax(query)) 103 | strcat(query, "reason,admin_name,admin_authid,", charsmax(query)) 104 | strcat(query, "admin_ip,created_at,expire_at,flags )", charsmax(query)) 105 | 106 | strcat(query, fmt("VALUES ( '%s',", name_safe), charsmax(query)) 107 | strcat(query, fmt("'%s',", authID), charsmax(query)) 108 | strcat(query, fmt("'%s',", IP), charsmax(query)) 109 | strcat(query, fmt("'%s',", reason_safe), charsmax(query)) 110 | strcat(query, fmt("'%s',", adminName_safe), charsmax(query)) 111 | strcat(query, fmt("'%s',", adminAuthID), charsmax(query)) 112 | strcat(query, fmt("'%s',", adminIP), charsmax(query)) 113 | strcat(query, fmt("DateTime('now'),"), charsmax(query)) 114 | strcat(query, fmt("DateTime(%i, 'unixepoch'),", expireAt), charsmax(query)) 115 | strcat(query, fmt("%i ); ", flags), charsmax(query)) 116 | } 117 | 118 | strcat(query, "SELECT \ 119 | name,authid,ip,reason,\ 120 | admin_name,admin_authid,admin_ip,\ 121 | strftime('%s',created_at),strftime('%s',expire_at),flags", charsmax(query)) 122 | strcat(query, fmt(" FROM %s", SQL_TBL_GAGS), charsmax(query)) 123 | strcat(query, fmt(" WHERE authid='%s'", authID), charsmax(query)) 124 | 125 | SQL_ThreadQuery(g_tuple, "handle_Saved", query) 126 | } 127 | 128 | public handle_Saved(failstate, Handle: query, error[], errnum, data[], size, Float: queuetime) { 129 | if (IsSQLQueryFailed(failstate, query, error, errnum)) { 130 | return 131 | } 132 | 133 | enum { res_name, res_authid, res_ip, res_reason, 134 | res_admin_name, res_admin_authid, res_admin_ip, 135 | res_created_at, res_expire_at, res_flags 136 | } 137 | 138 | new name[MAX_NAME_LENGTH]; SQL_ReadResult(query, res_name, name, charsmax(name)) 139 | new authID[MAX_AUTHID_LENGTH]; SQL_ReadResult(query, res_authid, authID, charsmax(authID)) 140 | new IP[MAX_IP_LENGTH]; SQL_ReadResult(query, res_ip, IP, charsmax(IP)) 141 | new reason[MAX_REASON_LENGTH]; SQL_ReadResult(query, res_reason, reason, charsmax(reason)) 142 | 143 | new adminName[MAX_NAME_LENGTH]; SQL_ReadResult(query, res_admin_name, adminName, charsmax(adminName)) 144 | new adminAuthID[MAX_AUTHID_LENGTH]; SQL_ReadResult(query, res_admin_authid, adminAuthID, charsmax(adminAuthID)) 145 | new adminIP[MAX_IP_LENGTH]; SQL_ReadResult(query, res_admin_ip, adminIP, charsmax(adminIP)) 146 | 147 | new createdAt = SQL_ReadResult(query, res_created_at) 148 | new expireAt = SQL_ReadResult(query, res_expire_at) 149 | new flags = SQL_ReadResult(query, res_flags) 150 | 151 | CA_Log(logLevel_Debug, "Player gag saved {'%s', '%s', '%s', '%s', '%s', '%s', '%s', %i, %i, %i} (queryTime: '%.3f' sec)", \ 152 | name, authID, IP, reason, adminName, adminAuthID, adminIP, createdAt, expireAt, flags,\ 153 | queuetime \ 154 | ) 155 | 156 | ExecuteForward(g_fwd_StorageSaved, g_ret, 157 | name, authID, IP, reason, 158 | adminName, adminAuthID, adminIP, 159 | createdAt, expireAt, flags 160 | ) 161 | } 162 | 163 | Storage_Load(const authID[]) { 164 | new query[QUERY_LENGTH] 165 | formatex(query, charsmax(query), "SELECT name, authid, ip, reason,\ 166 | admin_name, admin_authid, admin_ip, \ 167 | strftime('%%s', created_at), strftime('%%s', expire_at), flags FROM %s", SQL_TBL_GAGS); { 168 | strcat(query, fmt(" WHERE (authid = '%s')", authID), charsmax(query)) 169 | strcat(query, " AND ( expire_at = DateTime(9999999999, 'unixepoch') OR (expire_at > DateTime('now')) ) LIMIT 1", charsmax(query)) 170 | } 171 | 172 | SQL_ThreadQuery(g_tuple, "handle_Loaded", query) 173 | } 174 | 175 | public handle_Loaded(failstate, Handle: query, error[], errnum, data[], size, Float: queuetime) { 176 | if (IsSQLQueryFailed(failstate, query, error, errnum)) { 177 | return 178 | } 179 | 180 | enum { res_name, res_authid, res_ip, res_reason, 181 | res_admin_name, res_admin_authid, res_admin_ip, 182 | res_created_at, res_expire_at, res_flags 183 | } 184 | 185 | new bool: found = (SQL_NumResults(query) != 0) 186 | 187 | if (!found) { 188 | return 189 | } 190 | 191 | new name[MAX_NAME_LENGTH]; SQL_ReadResult(query, res_name, name, charsmax(name)) 192 | new authID[MAX_AUTHID_LENGTH]; SQL_ReadResult(query, res_authid, authID, charsmax(authID)) 193 | new IP[MAX_IP_LENGTH]; SQL_ReadResult(query, res_ip, IP, charsmax(IP)) 194 | new reason[MAX_REASON_LENGTH]; SQL_ReadResult(query, res_reason, reason, charsmax(reason)) 195 | 196 | new adminName[MAX_NAME_LENGTH]; SQL_ReadResult(query, res_admin_name, adminName, charsmax(adminName)) 197 | new adminAuthID[MAX_AUTHID_LENGTH]; SQL_ReadResult(query, res_admin_authid, adminAuthID, charsmax(adminAuthID)) 198 | new adminIP[MAX_IP_LENGTH]; SQL_ReadResult(query, res_admin_ip, adminIP, charsmax(adminIP)) 199 | 200 | new createdAt = SQL_ReadResult(query, res_created_at) 201 | new expireAt = SQL_ReadResult(query, res_expire_at) 202 | new flags = SQL_ReadResult(query, res_flags) 203 | 204 | CA_Log(logLevel_Debug, "Player gag loaded {'%s', '%s', '%s', '%s', '%s', '%s', '%s', %i, %i, %i} (queryTime: '%.3f' sec)", \ 205 | name, authID, IP, reason, adminName, adminAuthID, adminIP, createdAt, expireAt, flags,\ 206 | queuetime \ 207 | ) 208 | 209 | ExecuteForward(g_fwd_StorageLoaded, g_ret, 210 | name, authID, IP, reason, 211 | adminName, adminAuthID, adminIP, 212 | createdAt, expireAt, flags 213 | ) 214 | } 215 | 216 | Storage_Remove(const authID[]) { 217 | new query[QUERY_LENGTH] 218 | formatex(query, charsmax(query), "DELETE FROM %s ", SQL_TBL_GAGS); { 219 | strcat(query, fmt("WHERE (authid = '%s')", authID), charsmax(query)) 220 | } 221 | 222 | SQL_ThreadQuery(g_tuple, "handle_Removed", query) 223 | } 224 | 225 | public handle_Removed(failstate, Handle: query, error[], errnum, data[], size, Float: queuetime) { 226 | if (IsSQLQueryFailed(failstate, query, error, errnum)) { 227 | return 228 | } 229 | 230 | CA_Log(logLevel_Debug, "Player gag removed { } (queryTime: '%.3f' sec)", \ 231 | queuetime \ 232 | ) 233 | 234 | ExecuteForward(g_fwd_StorageRemoved, g_ret) 235 | } 236 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/scripting/include/CA_GAG_API.inc: -------------------------------------------------------------------------------- 1 | /** Copyright © 2021 Sergey Shorokhov 2 | * 3 | * Chat Additions: Gag [API] include file. 4 | * 5 | */ 6 | 7 | #if defined _CA_GAG_API_included 8 | #endinput 9 | #endif 10 | 11 | #define _CA_GAG_API_included 12 | 13 | enum any: gag_flags_s ( <<=1 ) { 14 | gagFlag_Removed = 0, 15 | gagFlag_Say = 1, // a 16 | gagFlag_SayTeam, // b 17 | gagFlag_Voice // c 18 | } 19 | 20 | const MAX_REASON_LEN = 128 21 | const MAX_WHITELIST_CMD_LEN = 32 22 | 23 | enum reason_s { 24 | r_name[MAX_REASON_LEN], 25 | r_time, 26 | gag_flags_s: r_flags 27 | } 28 | 29 | enum gagData_s { 30 | gd_target, 31 | gd_name[MAX_NAME_LENGTH], 32 | gd_authID[MAX_AUTHID_LENGTH], 33 | gd_IP[MAX_IP_LENGTH], 34 | 35 | gd_admin, 36 | gd_adminName[MAX_NAME_LENGTH], 37 | gd_adminAuthID[MAX_AUTHID_LENGTH], 38 | gd_adminIP[MAX_IP_LENGTH], 39 | 40 | gd_reason[reason_s], 41 | gd_expireAt 42 | } 43 | 44 | stock gag_flags_s: flags_to_bit(const flagsStr[]) { 45 | new gag_flags_s: bits = gagFlag_Removed 46 | 47 | if (containi(flagsStr, "a") != -1) bits |= gagFlag_Say 48 | if (containi(flagsStr, "b") != -1) bits |= gagFlag_SayTeam 49 | if (containi(flagsStr, "c") != -1) bits |= gagFlag_Voice 50 | 51 | return bits 52 | } 53 | 54 | stock bits_to_flags(const gag_flags_s: bits) { 55 | new flagsStr[4] 56 | if (bits & gagFlag_Say) add(flagsStr, charsmax(flagsStr), "a") 57 | if (bits & gagFlag_SayTeam) add(flagsStr, charsmax(flagsStr), "b") 58 | if (bits & gagFlag_Voice) add(flagsStr, charsmax(flagsStr), "c") 59 | 60 | return flagsStr 61 | } 62 | 63 | stock GagData_Reset(gagData[gagData_s]) { 64 | gagData[gd_target] = 0 65 | gagData[gd_name][0] = EOS 66 | gagData[gd_authID][0] = EOS 67 | gagData[gd_IP][0] = EOS 68 | 69 | gagData[gd_admin] = 0 70 | gagData[gd_adminName][0] = EOS 71 | gagData[gd_adminAuthID][0] = EOS 72 | gagData[gd_adminIP][0] = EOS 73 | 74 | gagData[gd_reason][r_name][0] = EOS 75 | gagData[gd_reason][r_time] = 0 76 | gagData[gd_reason][r_flags] = gagFlag_Removed 77 | 78 | gagData[gd_expireAt] = 0 79 | } 80 | 81 | stock GagData_Copy(to[gagData_s], const from[gagData_s]) { 82 | to[gd_target] = from[gd_target] 83 | copy(to[gd_name], charsmax(to[gd_name]), from[gd_name]) 84 | copy(to[gd_authID], charsmax(to[gd_authID]), from[gd_authID]) 85 | copy(to[gd_IP], charsmax(to[gd_IP]), from[gd_IP]) 86 | 87 | to[gd_admin] = from[gd_admin] 88 | copy(to[gd_adminName], charsmax(to[gd_adminName]), from[gd_adminName]) 89 | copy(to[gd_adminAuthID], charsmax(to[gd_adminAuthID]), from[gd_adminAuthID]) 90 | copy(to[gd_adminIP], charsmax(to[gd_adminIP]), from[gd_adminIP]) 91 | 92 | copy(to[gd_reason][r_name], charsmax(to[r_name]), from[gd_reason][r_name]) 93 | to[gd_reason][r_time] = from[gd_reason][r_time] 94 | to[gd_reason][r_flags] = from[gd_reason][r_flags] 95 | 96 | to[gd_expireAt] = from[gd_expireAt] 97 | } 98 | 99 | stock bool: GagData_IsEqual(const arr1[gagData_s], const arr2[gagData_s]) { 100 | if (arr1[gd_reason][r_time] != arr2[gd_reason][r_time]) { 101 | return false 102 | } 103 | 104 | if (arr1[gd_reason][r_flags] != arr2[gd_reason][r_flags]) { 105 | return false 106 | } 107 | 108 | if (strcmp(arr1[gd_reason][r_name], arr2[gd_reason][r_name]) != 0) { 109 | return false 110 | } 111 | 112 | return true 113 | } 114 | 115 | stock GagData_GetPersonalData(const admin = 0, const target, buffer[gagData_s]) { 116 | // get's target data 117 | buffer[gd_target] = target 118 | get_user_name(target, buffer[gd_name], charsmax(buffer[gd_name])) 119 | get_user_authid(target, buffer[gd_authID], charsmax(buffer[gd_authID])) 120 | get_user_ip(target, buffer[gd_IP], charsmax(buffer[gd_IP]), .without_port = true) 121 | 122 | // get's admin data 123 | buffer[gd_admin] = admin 124 | get_user_name(admin, buffer[gd_adminName], charsmax(buffer[gd_adminName])) 125 | get_user_authid(admin, buffer[gd_adminAuthID], charsmax(buffer[gd_adminAuthID])) 126 | get_user_ip(admin, buffer[gd_adminIP], charsmax(buffer[gd_adminIP]), .without_port = true) 127 | } 128 | 129 | 130 | 131 | 132 | 133 | /** 134 | * Sets client's gag data. 135 | * 136 | * @param index Client index 137 | * @param reason Reason 138 | * @param Minutes Minutes 139 | * @param Flags Flags 140 | * 141 | * @noreturn 142 | * @error If the client index is not within the range of 1 to 143 | * MaxClients, or the client is not connected, an error 144 | * will be thrown. 145 | */ 146 | native bool: ca_set_user_gag(const index, const reason[], const minutes, const gag_flags_s: flags) 147 | 148 | /** 149 | * Get client's gag data. 150 | * 151 | * @param index Client index 152 | * @param reason Gag reason 153 | * @param minutes minutes 154 | * @param flags flags 155 | * 156 | * @return True if has Gag. 157 | * @error If the client index is not within the range of 1 to 158 | * MaxClients, or the client is not connected, an error 159 | * will be thrown. 160 | */ 161 | native bool: ca_get_user_gag(const index, reason[], &minutes, &gag_flags_s: flags) 162 | 163 | /** 164 | * Has client gag? 165 | * 166 | * @param index Client index 167 | * 168 | * @return True if has Gag. 169 | * @error If the client index is not within the range of 1 to 170 | * MaxClients, or the client is not connected, an error 171 | * will be thrown. 172 | */ 173 | native bool: ca_has_user_gag(const index) 174 | 175 | /** 176 | * Remove client's gag data.. 177 | * 178 | * @param target Target Index 179 | * @param admin Admin Index (0 - server) 180 | * 181 | * @return True if gag has been removed. 182 | * @error If the client index is not within the range of 1 to 183 | * MaxClients, or the client is not connected, an error 184 | * will be thrown. 185 | */ 186 | native bool: ca_remove_user_gag(const target, admin = 0) 187 | 188 | /** 189 | * Called on Gag save. 190 | * 191 | * @param target Targed index 192 | * @param name Targed name 193 | * @param authID Targed AuthID 194 | * @param IP Targed IP 195 | * @param adminName Admin name 196 | * @param adminAuthID Admin authID 197 | * @param adminIP Admin IP 198 | * @param reason Reason 199 | * @param time Time (in seconds) 200 | * @param flags Flags (chat, teamChat, voice) 201 | * @param expireAt Time when gag expire 202 | * 203 | * @return Return CA_SUPERCEDE for prevent Gag. 204 | */ 205 | forward CA_gag_setted( 206 | const target, name[], authID[], IP[], 207 | adminName[], adminAuthID[], adminIP[], 208 | reason[], time, gag_flags_s: flags, 209 | expireAt) 210 | 211 | /** 212 | * Called on gag remove action. 213 | * 214 | * @param target Target index 215 | * @param target Reason 216 | * @param minutes Time (in seconds) 217 | * @param flags Flags (chat, teamChat, voice) 218 | * 219 | * @return Return CA_SUPERCEDE for prevent Gag remove. 220 | */ 221 | forward CA_gag_removed(const target, reason[], minutes, gag_flags_s: flags) 222 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/scripting/include/CA_StorageAPI.inc: -------------------------------------------------------------------------------- 1 | #if defined _CA_STORAGE_API_included 2 | #endinput 3 | #endif 4 | 5 | #define _CA_STORAGE_API_included 6 | 7 | /* 8 | * 9 | */ 10 | native CA_Storage_Save(const name[], const authID[], const IP[], const reason[], const adminName[], const adminAuthID[], const adminIP[], const expireAt, const flags) 11 | 12 | /* 13 | * 14 | */ 15 | native CA_Storage_Load(const authID[]) 16 | 17 | /* 18 | * 19 | */ 20 | native CA_Storage_Remove(const authID[]) 21 | 22 | 23 | /* 24 | * 25 | */ 26 | forward CA_Storage_Initialized() 27 | 28 | /* 29 | * 30 | */ 31 | forward CA_Storage_Saved(const name[], const authID[], const IP[], const reason[], 32 | const adminName[], const adminAuthID[], const adminIP[], 33 | const createdAt, const expireAt, const flags) 34 | 35 | /* 36 | * 37 | */ 38 | forward CA_Storage_Loaded(const name[], const authID[], const IP[], const reason[], 39 | const adminName[], const adminAuthID[], const adminIP[], 40 | const createdAt, const expireAt, const flags) 41 | 42 | /* 43 | * 44 | */ 45 | forward CA_Storage_Removed() 46 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/scripting/include/CA_StorageAPI_endpoint.inc: -------------------------------------------------------------------------------- 1 | #if defined _CA_STORAGE_API_ENDPOINT_included 2 | #endinput 3 | #endif 4 | 5 | #define _CA_STORAGE_API_ENDPOINT_included 6 | 7 | #pragma dynamic 131072 8 | 9 | new bool: g_storageInitialized 10 | 11 | stock bool: IsSQLQueryFailed(const failstate, const Handle: query, const error[], const errNum) { 12 | switch (failstate) { 13 | case TQUERY_CONNECT_FAILED: { 14 | log_amx("SQL: connection failed [%i] `%s`", errNum, error) 15 | return true 16 | } 17 | case TQUERY_QUERY_FAILED: { 18 | log_amx("SQL: query failed [%i] %s", errNum, error) 19 | 20 | server_print("^n^n ===> Query:") 21 | new buffer[8192]; SQL_GetQueryString(query, buffer, charsmax(buffer)) 22 | for(new i, len = strlen(buffer); i < len; i+=255) { 23 | server_print(fmt("%-255s", buffer[i])) 24 | } 25 | 26 | return true 27 | } 28 | } 29 | 30 | return false 31 | } 32 | 33 | // Should be realized in each storage 34 | RegisterNatives() { 35 | register_native("CA_Storage_Save", "native_Storage_Save") 36 | register_native("CA_Storage_Load", "native_Storage_Load") 37 | register_native("CA_Storage_Remove", "native_Storage_Remove") 38 | register_native("CA_Storage_IsInitialized", "native_Storage_IsInitialized") 39 | } 40 | public native_Storage_Save(const plugin_id, const argc) { 41 | enum { arg_name = 1, arg_authID, arg_IP, arg_reason, arg_adminName, arg_adminAuthID, arg_adminIP, arg_expireAt, arg_flags } 42 | 43 | new name[MAX_NAME_LENGTH]; get_string(arg_name, name, charsmax(name)) 44 | new authID[MAX_AUTHID_LENGTH]; get_string(arg_authID, authID, charsmax(authID)) 45 | new IP[MAX_IP_LENGTH]; get_string(arg_IP, IP, charsmax(IP)) 46 | new reason[256]; get_string(arg_reason, reason, charsmax(reason)) 47 | new adminName[MAX_NAME_LENGTH]; get_string(arg_adminName, adminName, charsmax(adminName)) 48 | new adminAuthID[MAX_AUTHID_LENGTH]; get_string(arg_adminAuthID, adminAuthID, charsmax(adminAuthID)) 49 | new adminIP[MAX_IP_LENGTH]; get_string(arg_adminIP, adminIP, charsmax(adminIP)) 50 | new expireAt = get_param(arg_expireAt) 51 | new flags = get_param(arg_flags) 52 | 53 | Storage_Save(name, authID, IP, reason, adminName, adminAuthID, adminIP, expireAt, flags) 54 | } 55 | public native_Storage_Load(const plugin_id, const argc) { 56 | enum { arg_authID = 1 } 57 | 58 | new authID[MAX_AUTHID_LENGTH]; get_string(arg_authID, authID, charsmax(authID)) 59 | Storage_Load(authID) 60 | } 61 | public native_Storage_Remove(const plugin_id, const argc) { 62 | enum { arg_authID = 1 } 63 | 64 | new authID[MAX_AUTHID_LENGTH]; get_string(arg_authID, authID, charsmax(authID)) 65 | Storage_Remove(authID) 66 | } 67 | public bool: native_Storage_IsInitialized(const plugin_id, const argc) { 68 | return g_storageInitialized 69 | } 70 | 71 | 72 | // Forwards handlers 73 | new g_fwd_StorageInitialized = INVALID_HANDLE 74 | new g_fwd_StorageSaved = INVALID_HANDLE 75 | new g_fwd_StorageLoaded = INVALID_HANDLE 76 | new g_fwd_StorageRemoved = INVALID_HANDLE 77 | new g_ret 78 | // Should be realized in each storage 79 | RegisterForwards() { 80 | g_fwd_StorageInitialized = CreateMultiForward("CA_Storage_Initialized", ET_IGNORE) 81 | g_fwd_StorageSaved = CreateMultiForward("CA_Storage_Saved", ET_IGNORE, 82 | FP_STRING, FP_STRING, FP_STRING, FP_STRING, 83 | FP_STRING, FP_STRING, FP_STRING, 84 | FP_CELL, FP_CELL, FP_CELL 85 | ) 86 | g_fwd_StorageLoaded = CreateMultiForward("CA_Storage_Loaded", ET_IGNORE, 87 | FP_STRING, FP_STRING, FP_STRING, FP_STRING, 88 | FP_STRING, FP_STRING, FP_STRING, 89 | FP_CELL, FP_CELL, FP_CELL 90 | ) 91 | g_fwd_StorageRemoved = CreateMultiForward("CA_Storage_Removed", ET_IGNORE) 92 | } 93 | 94 | 95 | 96 | /* TEST 97 | 98 | public CA_Storage_Initialized() { 99 | new name[] = "Some safe name" 100 | new authID[] = "0:1:2345678" 101 | new IP[] = "123.123.123.123" 102 | new reason[] = "Some safe reason" 103 | new adminName[] = "Some safe admin name" 104 | new adminAuthID[] = "Some safe admin authID" 105 | new adminIP[] = "Some safe admin IP" 106 | new expireAt = 1624232019 107 | new flags = 3 108 | 109 | CA_Storage_Save(name, authID, IP, reason, adminName, adminAuthID, adminIP, expireAt, flags) 110 | } 111 | public CA_Storage_Saved() { 112 | new authID[] = "0:1:2345678" 113 | CA_Storage_Load(authID) 114 | } 115 | public CA_Storage_Loaded(const name[], const authID[], const IP[], const reason[], 116 | const adminName[], const adminAuthID[], const adminIP[], 117 | const createdAt, const expireAt, const flags) { 118 | log_amx(" > CA_Storage_Loaded{`%s`,`%s`,%s`,`%s`,`%s`,`%s`,`%s`,%i,%i,%i}", 119 | name, authID, reason, IP, 120 | adminName, adminAuthID, adminIP, 121 | createdAt, expireAt, flags) 122 | CA_Storage_Remove(authID) 123 | } 124 | public CA_Storage_Removed() { 125 | 126 | } 127 | */ 128 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/scripting/include/ChatAdditions.inc: -------------------------------------------------------------------------------- 1 | /** Copyright © 2020 Sergey Shorokhov 2 | * 3 | * Chat Additions API include file. 4 | * 5 | */ 6 | 7 | #if defined _CA_API_included 8 | #endinput 9 | #endif 10 | 11 | #define _CA_API_included 12 | 13 | #pragma reqlib ChatAdditions_Core 14 | #if !defined AMXMODX_NOAUTOLOAD 15 | #pragma loadlib ChatAdditions_Core 16 | #endif 17 | 18 | #if !defined CA_VERSION 19 | #define CA_VERSION "%CA_VERSION%" 20 | #endif 21 | 22 | const CA_MAX_MESSAGE_SIZE = 188 23 | 24 | /** 25 | * Return types 26 | */ 27 | enum 28 | { 29 | CA_CONTINUE = 0, // Plugin didn't take any action 30 | CA_SUPERCEDE // Skip real function, use my return value 31 | } 32 | 33 | #define CHECK_NATIVE_ARGS_NUM(%1,%2,%3) \ 34 | if (%1 < %2) { \ 35 | log_error(AMX_ERR_NATIVE, "Invalid num of arguments %d. Expected %d", %1, %2); \ 36 | return %3; \ 37 | } 38 | 39 | #define CHECK_NATIVE_PLAYER(%1,%2) \ 40 | if (!is_user_connected(%1)) { \ 41 | log_error(AMX_ERR_NATIVE, "Invalid player %d", %1); \ 42 | return %2; \ 43 | } 44 | 45 | 46 | enum logLevel_s { 47 | logLevel_Off = 0, 48 | logLevel_Info = 1, 49 | logLevel_Warning, 50 | logLevel_Debug 51 | } 52 | 53 | #define register_trigger_clcmd(%0,%1) \ 54 | for (new iter = 0; iter < sizeof(BASE_CHAT_TRIGGERS); iter++) \ 55 | { \ 56 | register_clcmd(fmt("%s%s", BASE_CHAT_TRIGGERS[iter], %0), %1); \ 57 | register_clcmd(fmt("say %s%s", BASE_CHAT_TRIGGERS[iter], %0), %1); \ 58 | register_clcmd(fmt("say_team %s%s", BASE_CHAT_TRIGGERS[iter], %0), %1); \ 59 | } 60 | 61 | new stock const BASE_CHAT_TRIGGERS[][] = { /* "", */"/", "\", "!", "." } 62 | 63 | 64 | stock parseTime(const value[]) { 65 | const _SECONDS_IN_MINUTE = 60 66 | const _SECONDS_IN_HOUR = 3600 67 | const _SECONDS_IN_DAY = 86400 68 | const _SECONDS_IN_WEEK = 604800 69 | const _SECONDS_IN_MONTH = 2592000 70 | const _SECONDS_IN_YEAR = 31536000 71 | 72 | new t, k 73 | for (new i; value[i] != EOS; i++) { 74 | switch (value[i]) { 75 | case '0'..'9': { 76 | t = (t * 10) + (value[i] - '0') 77 | } 78 | 79 | case 'i': { 80 | k += t * _SECONDS_IN_MINUTE 81 | t = 0 82 | } 83 | 84 | case 'h': { 85 | k += t * _SECONDS_IN_HOUR 86 | t = 0 87 | } 88 | 89 | case 'd': { 90 | k += t * _SECONDS_IN_DAY 91 | t = 0 92 | } 93 | 94 | case 'w': { 95 | k += t * _SECONDS_IN_WEEK 96 | t = 0 97 | } 98 | 99 | case 'm': { 100 | k += t * _SECONDS_IN_MONTH 101 | t = 0 102 | } 103 | 104 | case 'y': { 105 | k += t * _SECONDS_IN_YEAR 106 | t = 0 107 | } 108 | 109 | default: { 110 | break 111 | } 112 | } 113 | } 114 | 115 | return k + t 116 | } 117 | 118 | stock show_activity_ex(const actorId, const actorName[], const message[], any: ...) { 119 | enum { arg_format = 4 } 120 | 121 | static _amx_show_activity 122 | if (!_amx_show_activity) { 123 | _amx_show_activity = get_cvar_pointer("amx_show_activity") 124 | if (!_amx_show_activity) { 125 | _amx_show_activity = create_cvar("amx_show_activity", "2") 126 | } 127 | } 128 | 129 | new prefix[] = "PLAYER" 130 | if (is_user_admin(actorId)) { 131 | copy(prefix, charsmax(prefix), "ADMIN") 132 | } 133 | 134 | static buffer[512] 135 | for(new i = 1; i <= MaxClients; i++) { 136 | if (!is_user_connected(i) && !is_user_bot(i)) { 137 | continue 138 | } 139 | 140 | new bool: isAdmin = bool: is_user_admin(i) 141 | SetGlobalTransTarget(i) 142 | vformat(buffer, charsmax(buffer), message, arg_format) 143 | 144 | switch (get_pcvar_num(_amx_show_activity)) { 145 | case 1: { // Hide name for all 146 | client_print_color(i, i, "%L %s", i, prefix, buffer) 147 | } 148 | case 2: { // Show name to all 149 | client_print_color(i, i, "%L %s: %s", i, prefix, actorName, buffer) 150 | } 151 | case 3: { // show name only to admins, hide name from normal users 152 | client_print_color(i, i, "%L %s: %s", i, prefix, isAdmin ? actorName : "", buffer) 153 | } 154 | case 4: { // show name only to admins, show nothing to normal users 155 | if (isAdmin) { 156 | client_print_color(i, i, "%L %s: %s", i, prefix, actorName, buffer) 157 | } 158 | } 159 | case 5: { // show only to admins without actor name 160 | if (isAdmin) { 161 | client_print_color(i, i, "%L: %s", i, prefix, buffer) 162 | } 163 | } 164 | } 165 | } 166 | } 167 | 168 | stock FindPlayerByTarget(const buffer[]) { 169 | if (buffer[0] == '#' && buffer[1]) { 170 | return find_player_ex(FindPlayer_MatchUserId, strtol(buffer[1])) 171 | } 172 | 173 | new result = find_player_ex(FindPlayer_MatchAuthId, buffer) 174 | if (!result) { 175 | result = find_player_ex(FindPlayer_MatchIP, buffer) 176 | } 177 | 178 | if (!result) { 179 | result = find_player_ex(FindPlayer_MatchNameSubstring | FindPlayer_CaseInsensitive | FindPlayer_LastMatched, buffer) 180 | } 181 | 182 | return result 183 | } 184 | 185 | stock UTIL_SendAudio(const id, const sample[]) { 186 | if (sample[0] == EOS) { 187 | return 188 | } 189 | 190 | static msgId_SendAudio 191 | if (!msgId_SendAudio) { 192 | msgId_SendAudio = get_user_msgid("SendAudio") 193 | } 194 | 195 | message_begin(MSG_ONE_UNRELIABLE, msgId_SendAudio, .player = id) 196 | write_byte(id) 197 | write_string(sample) 198 | write_short(PITCH_NORM) 199 | message_end() 200 | } 201 | 202 | stock UTIL_BarTime(const id, const time) { 203 | static msgId_BarTime 204 | if (!msgId_BarTime) { 205 | msgId_BarTime = get_user_msgid("BarTime") 206 | } 207 | 208 | message_begin(MSG_ONE_UNRELIABLE, msgId_BarTime, .player = id) 209 | write_short(time) 210 | message_end() 211 | } 212 | 213 | 214 | /** 215 | * Log a message for every ChatAdditions module. 216 | * 217 | * @param level Log level, see logLevel_* destination constants in ChatAdditions.inc 218 | * @param message Formatting rules. 219 | * @param ... Variable number of formatting parameters 220 | * 221 | * @return True if a message logged, false otherwise. 222 | */ 223 | 224 | native bool: CA_Log(logLevel_s: level, const message[], any:...) 225 | 226 | /** 227 | * Called to determine if the Receiver has muted (blocked) the Sender. 228 | * NOTE: Setting from client menu (Players list -> Mute) 229 | * 230 | * @param receiver Receiver client id. 231 | * @param sender Sender client id. 232 | * 233 | * @return Returns true if the receiver has blocked the sender 234 | */ 235 | 236 | native bool: CA_PlayerHasBlockedPlayer(const receiver, const sender) 237 | 238 | /** 239 | * Called when player say to chat. 240 | * 241 | * @param index Client index. 242 | * @param isTeamMessage Is team message (say_team). 243 | * @param message Client message. 244 | * 245 | * @return CA_CONTINUE to allow send message 246 | * CA_SUPERCEDE or higher to prevent message 247 | */ 248 | forward CA_Client_Say(index, const bool: isTeamMessage, const message[]) 249 | 250 | 251 | /** 252 | * Called when player begins to speak. 253 | * 254 | * @note 255 | * 256 | * @param listener Receiver index. 257 | * @param sender Sender index. 258 | * 259 | * @return CA_CONTINUE to allow send voice 260 | * CA_SUPERCEDE or higher to prevent the voice 261 | */ 262 | forward CA_Client_Voice(const listener, const sender) 263 | 264 | 265 | /** 266 | * Called when player change nickname. 267 | * 268 | * @note 269 | * 270 | * @param id Client index. 271 | * @param newName New name. 272 | * 273 | * @return CA_CONTINUE to allow change nickname 274 | * CA_SUPERCEDE or higher to prevent 275 | */ 276 | forward CA_Client_ChangeName(const id, const newName[]) 277 | -------------------------------------------------------------------------------- /cstrike/addons/amxmodx/scripting/include/cellqueue.inc: -------------------------------------------------------------------------------- 1 | #include "cellarray.inc" 2 | 3 | enum Queue { 4 | Invalid_Queue = 0 5 | } 6 | 7 | stock Queue: QueueCreate(const cellsize = 1) { 8 | return Queue: ArrayCreate(cellsize) 9 | } 10 | 11 | stock QueueDestroy(&Queue: which) { 12 | return ArrayDestroy(Array: which) 13 | } 14 | 15 | stock QueueClear(const &Queue: which) { 16 | ArrayClear(Array: which) 17 | } 18 | 19 | stock Queue: QueueClone(const &Queue: which) { 20 | return ArrayClone(Array: which) 21 | } 22 | 23 | stock QueuePushCell(const &Queue: which, const any: value) { 24 | return ArrayPushCell(Array: which, any: value) 25 | } 26 | 27 | stock QueuePushString(const &Queue: which, const value[]) { 28 | return ArrayPushString(Array: which, value) 29 | } 30 | 31 | stock QueuePushArray(const &Queue: which, const any: value[], const size = -1) { 32 | return ArrayPushArray(Array: which, value, size) 33 | } 34 | 35 | stock any: QueuePopCell(const &Queue: which) { 36 | new any: value = ArrayGetCell(Array: which, 0) 37 | ArrayDeleteItem(Array: which, 0) 38 | return value 39 | } 40 | 41 | stock QueuePopString(const &Queue: which, buffer[], const maxlength) { 42 | new charCount = ArrayGetString(Array: which, 0, buffer, maxlength) 43 | ArrayDeleteItem(Array: which, 0) 44 | return charCount 45 | } 46 | 47 | stock QueuePopArray(const &Queue: which, buffer[], const size) { 48 | new cellCount = ArrayGetArray(Array: which, 0, buffer, size) 49 | ArrayDeleteItem(Array: which, 0) 50 | return cellCount 51 | } 52 | 53 | stock any: QueueFrontCell(const &Queue: which) { 54 | new any: value = ArrayGetCell(Array: which, 0) 55 | return value 56 | } 57 | 58 | stock QueueFrontString(const &Queue: which, buffer[], const maxlength) { 59 | new charCount = ArrayGetString(Array: which, 0, buffer, maxlength) 60 | return charCount 61 | } 62 | 63 | stock QueueFrontArray(const &Queue: which, buffer[], const size) { 64 | new cellCount = ArrayGetArray(Array: which, 0, buffer, size) 65 | return cellCount 66 | } 67 | 68 | stock any: QueueRearCell(const &Queue: which) { 69 | new any: value = ArrayGetCell(Array: which, QueueSize(which) - 1) 70 | return value 71 | } 72 | 73 | stock QueueRearString(const &Queue: which, buffer[], const maxlength) { 74 | new charCount = ArrayGetString(Array: which, QueueSize(which) - 1, buffer, maxlength) 75 | return charCount 76 | } 77 | 78 | stock QueueRearArray(const &Queue: which, buffer[], const size) { 79 | new cellCount = ArrayGetArray(Array: which, QueueSize(which) - 1, buffer, size) 80 | return cellCount 81 | } 82 | 83 | stock QueueSize(const &Queue: which) { 84 | return ArraySize(Array: which) 85 | } 86 | --------------------------------------------------------------------------------