
Half-Life sprite plugin for GIMP
GIMP plugin that allows you to import and export sprites from a Half-Life game. This plugin can also open new version sprites containing DDS textures used in Counter-Strike Online (Experimantal feature).
As you know, showing a page generated by your plugin in the MOTD is fairly simple, but achieving two-way interaction with the MOTD is not such a trivial task. In this article you will learn how to do it. So why is this needed? For example, for creating your own cool shop or choosing a class…
As you know, showing a page generated by your plugin in the MOTD is fairly simple, but achieving two-way interaction with the MOTD is not such a trivial task. In this article you will learn how to do it.
So why is this needed? For example, for creating your own cool shop or choosing a player's class; there are plenty of uses.
Here's an example:

To make the interaction work, you will need:
You should also have some knowledge of:
This article describes how to make a MOTD for choosing a player's class.
Article outline:
We will show the player a menu in the MOTD, where they can click on something.
When the player takes an action (clicks a link), the website sends all the needed information to the server (hlds), and then the plugin processes that information.
To do this, we register a server command via register_concmd.
For example, register_concmd("php_result", "callback").
When the command php_result is executed via RCON, we pass it some parameters, which we then read in the function callback.
So the interaction looks like this:
Server -> Website -> Server
The script receives the following information:
So, let's start:
<html><head><title>Class Chooser</title></head><body>
<?php
$s_index = $_GET[ 'index' ];
$s_ip = $_GET[ 'ip' ];
$s_class = $_GET[ 'class' ];
$ip = $_SERVER[ 'REMOTE_ADDR' ];
/*
Если полученный IP с сервера не совпадает с реальным IP игрока,
то прекращаем работу скрипта.
*/
if( $ip != $s_ip )
{
die( );
}
?>
</body></html>After this check, we can show the player a menu:
<html><head><title>Class Chooser</title></head><body>
<?php
$s_index = $_GET[ 'index' ];
$s_ip = $_GET[ 'ip' ];
$s_class = $_GET[ 'class' ];
$ip = $_SERVER[ 'REMOTE_ADDR' ];
if( $ip != $s_ip )
{
die( );
}
else
{
// Создаём массив из доступных классов
$classesName = array( "M4A1 + USP", "Ak47 + GLOCK", "FAMAS + DEAGLE", "GALIL + DEAGLE" );
// Теперь в цикле создаём элементы меню
for( $x = 0; $x < count( $classesName ); $x ++ )
{
Echo "<a href="". $_SERVER[ 'PHP_SELF' ] ."?item=". ( $x + 1 ) ."&index=". $s_index ."&class=". $s_class ."&ip=". $s_ip ."">". $classesName[ $x ] ."</a><br/><br/>";
}
}
?>
</body></html>Now we have to send the server information about which class the player chose.
But we will send the command only if the player's current class differs from the one they chose.
Now it's time to include SourceQuery.class.php in the script.
Final version of the code: (the code has defines that need to be changed)
<html><head><title>Class Chooser</title></head><body>
<?php
define( 'TIME_OUT', 3 );
define( 'SERV_PORT', port_of_your_server ); // Сменить на порт сервера
define( 'SERV_IP', 'ip_of_your_server' ); // Сменить на ip сервера
define( 'SERV_RCON', 'rcon_of_your_server' ); // Сменить на RCON сервер
// Не забудьте залить класс SourceQuery на FTP
require 'SourceQuery.class.php';
$s_index = $_GET[ 'index' ];
$s_ip = $_GET[ 'ip' ];
$s_class = $_GET[ 'class' ];
$item = $_GET[ 'item' ];
$ip = $_SERVER[ 'REMOTE_ADDR' ];
if( $ip != $s_ip )
{
die( );
}
else if( $item ) // Если был выбран пункт меню, то отсылаем команду ...
{
if( $class != $item ) // ... продолжаем только если текущий класс игрока не совпадает с выбранным.
{
$query = new SourceQuery( );
try
{
$query -> Connect( SERV_IP, SERV_PORT, TIME_OUT, SourceQuery :: GOLDSOURCE ); // Подключяемся к серверу
$query -> SetRconPassword( SERV_RCON ); // Задаём RCON
$query -> Rcon( 'php_results '. $s_index .' '. $item.' '. $ip ); // Отсылаем команду
}
catch( SQueryException $e )
{
echo $e -> getMessage( );
}
$query -> Disconnect( ); // Завершаем соединение
}
else // ... выбранный класс равен текущему классу игрока, редирект на страницу выбора класса (по сути на эту же станицу)
{
header( 'Location: '. $_SERVER[ 'PHP_SELF' ] .'?index='. $s_index .'&class='. $s_class .'&ip='. $s_ip .'' );
}
}
else
{
$classesName = array( "M4A1 + USP", "Ak47 + GLOCK", "FAMAS + DEAGLE", "GALIL + DEAGLE" );
for( $x = 0; $x < count( $classesName ); $x ++ )
{
Echo "<a href="". $_SERVER[ 'PHP_SELF' ] ."?item=". ( $x + 1 ) ."&index=". $s_index ."&class=". $s_class ."&ip=". $s_ip ."">". $classesName[ $x ] ."</a><br/><br/>";
}
}
?>
</body></html>That's it for PHP.
To begin, we get the information sent from the website (via RCON).
We used the php_result command.
#include < amxmodx >
new MaxServerSlots;
public plugin_init( )
{
register_plugin( "AMXX/PHP MOTD", "1.0.0", "Bboy Grun" );
register_concmd( "php_results", "OnResultShop" );
MaxServerSlots = get_maxplayers( );
}
public OnResultShop( const idServer )
{
if( !idServer ) // idServer должен быть равен 0 (нельзя допустить чтоб игрок мог использовать эту команду)
{
new arguments[ 25 ];
if( read_args( arguments, charsmax( arguments ) ) ) // Получаем аргументы, если их нет, то прекращаем работу
{
new ipPHP[ 16 ], idStr[ 3 ], itemStr[ 3 ];
// Парсим 3 аргумента, если их не 3, то прекращаем работу
if( parse( arguments, idStr, charsmax( idStr ), itemStr, charsmax( itemStr ), ipPHP, charsmax( ipPHP ) ) == 3 )
{
new const player = str_to_num( idStr );
// Проверка на то, что в player содержится id игрока
if( 1 <= player <= MaxServerSlots )
{
new ip[ 16 ];
get_user_ip( player, ip, charsmax( ip ), 1 );
// Как и в PHP, мы должны сверить IP адреса
if( equal( ip, ipPHP ) )
{
// Можем продолжать
}
}
}
}
}
}Great, we have all the information we need.
Now let's finish the plugin and add the following functionality:
We will also give the player weapons right away when they choose a class, if they had no class before.
#include < amxmodx >
#include < fun >
#include < cstrike >
#include < hamsandwich >
const MaxClients = 32;
new PlayerClass[ MaxClients + 1 ];
new PlayerNextClass[ MaxClients + 1 ];
new MaxServerSlots;
// Путь до скрипта
new const URL[ ] = "http://my-website.com/index.php";
public plugin_init( )
{
register_plugin( "AMXX/PHP MOTD", "1.0.0", "Bboy Grun" );
RegisterHam( Ham_Spawn, "player", "OnPlayerSpawn", .Post = true );
register_clcmd( "say /class", "OnChooseClass" );
register_concmd( "php_results", "OnResultShop" );
MaxServerSlots = get_maxplayers( );
}
public OnPlayerSpawn( const player )
{
if( is_user_alive( player ) )
{
if( !PlayerClass[ player ] )
{
OnChooseClass( player );
}
else
{
new const nextClass = PlayerNextClass[ player ];
if( nextClass )
{
PlayerClass[ player ] = nextClass;
PlayerNextClass[ player ] = 0;
}
give_weapons( player, nextClass );
}
}
}
public client_disconnect( client )
{
PlayerNextClass[ client ] = 0;
PlayerClass[ client ] = 0;
}
public OnChooseClass( const player )
{
new infos[ 128 ], ip[ 16 ];
get_user_ip( player, ip, charsmax( ip ), 1 );
formatex( infos, charsmax( infos ), "%s?index=%d&ip=%s&class=%d", URL, player, ip, PlayerClass[ player ] );
show_motd( player, infos );
}
public OnResultShop( const idServer )
{
if( !idServer )
{
new arguments[ 25 ];
if( read_args( arguments, charsmax( arguments ) ) )
{
new ipPHP[ 16 ], idStr[ 3 ], itemStr[ 3 ];
if( parse( arguments, idStr, charsmax( idStr ), itemStr, charsmax( itemStr ), ipPHP, charsmax( ipPHP ) ) == 3 )
{
new const player = str_to_num( idStr );
if( 1 <= player <= MaxServerSlots )
{
new ip[ 16 ];
get_user_ip( player, ip, charsmax( ip ), 1 );
if( equal( ip, ipPHP ) )
{
new const item = str_to_num( itemStr );
new const currentClass = PlayerClass[ player ];
if( currentClass )
{
if( currentClass != item )
{
PlayerNextClass[ player ] = item;
}
}
else
{
PlayerClass[ player ] = item;
if( is_user_alive( player ) )
{
give_weapons( player, item );
}
}
}
}
}
}
}
}
give_weapons( const player, const item )
{
#define give_items(%1,%2,%3,%4) ( give_item( %1, %2 ), cs_set_user_bpammo( %1, %3, %4 ) )
strip_user_weapons( player );
give_item( player, "weapon_knife" );
switch( item )
{
case 1:
{
give_items( player, "weapon_m4a1", CSW_M4A1, 90 );
give_items( player, "weapon_usp", CSW_USP, 100 );
}
case 2:
{
give_items( player, "weapon_ak47", CSW_AK47, 90 );
give_items( player, "weapon_glock18", CSW_GLOCK18, 120 );
}
case 3:
{
give_items( player, "weapon_famas", CSW_FAMAS, 90 );
give_items( player, "weapon_deagle", CSW_DEAGLE, 35 );
}
case 4:
{
give_items( player, "weapon_galil", CSW_GALIL, 90 );
give_items( player, "weapon_deagle", CSW_DEAGLE, 35 );
}
}
}The only other thing to mention: don't make images larger than 600x350 in the MOTD.
An image of that size will look acceptable on all screen resolutions.
Now you can create your own shop or anything else, with your own design and so on.
Translation: Polarhigh
Source: http://forums.alliedmods.net/showthread.php?t=198774
Report any inaccuracies or mistakes in the translation in the comments.
Authors: Arkshine & xPaw

GIMP plugin that allows you to import and export sprites from a Half-Life game. This plugin can also open new version sprites containing DDS textures used in Counter-Strike Online (Experimantal feature).

Update to 1.1.3: added support for angled sprites (import only), added the Force 256 Pallete option to expand the palette to 256 colors, fixed a bug when saving a sprite whose width is not a multiple of 4. A plugin for importing and exporting HL sprites for the Paint.net raster graphics editor…
GoldSrc model decompiler written in Go. Supports vertex weights used in Xash3D FWGS.