Внимание! Начиная с обновления 1.1.0, папка DIR_NAME должна быть скопирована (создана) сразу, по пути: 'addons/configs/'
Так как, там находятся файлы символов для каждого спрайта. (помимо файлов сохраненных координат)
//Значение интервала между спрайтами по разным осям. (если уменьшать, то спрайты будут накладываться друг на друга)
MESSAGEMODE_ARRAY_BUFFER = 256,
SPRITES_ARRAY_BUFFER = 64,
new const MOVE_COORDS[][] =
new const PLUGIN_VER[] = "1.1.1";
new const SETTINGS_FILE_NAME[] = "text_with_sprites.ini"
new const DIR_NAME[] = "text_with_sprites";
new const ENTITY_CLASSNAME[] = "tws_sprite";
new Array:SaveSprites, Array:SaveSymbols, Array:SaveIndex, CheckSprites[MAX_PLAYERS+1];
new CheckMenu1[MAX_PLAYERS+1], CheckMenu2[MAX_PLAYERS+1], CheckMenu3[MAX_PLAYERS+1], bool:Check[MAX_PLAYERS+1];
new Map[MAX_MAPNAME_LENGTH], Dir[MAX_RESOURCE_PATH_LENGTH], SavePath[MAX_RESOURCE_PATH_LENGTH], CheckCoords[MAX_PLAYERS+1];
new Float:SaveOrigin[MAX_PLAYERS+1][3], Float:Move[MAX_PLAYERS+1], Sign1[MAX_PLAYERS+1], Sign2[MAX_PLAYERS+1];
register_plugin("Text with sprites", PLUGIN_VER, "wellasgood");
SaveSprites = ArrayCreate(SPRITES_ARRAY_BUFFER);
SaveSymbols = ArrayCreate(SYMBOL_ARRAY_BUFFER);
SaveIndex = ArrayCreate(6);
get_localinfo("amxx_configsdir", Dir, charsmax(Dir));
new Path[MAX_RESOURCE_PATH_LENGTH];
formatex(Path, charsmax(Path), "%s/%s", Dir, SETTINGS_FILE_NAME);
set_fail_state("Error! no file: %s", Path);
new Data[SPRITES_ARRAY_BUFFER], f = fopen(Path, "rt"), Section;
fgets(f, Data, charsmax(Data));
if(!Data[0] || Data[0] == ';')
if(containi(Data[1], "СПРАЙТЫ-SPRITES") == 0)
else if(containi(Data[1], "КОМАНДЫ-COMMANDS") == 0)
ArrayPushString(SaveSprites, Data);
new index = precache_model(Data);
ArrayPushCell(SaveIndex, index);
register_clcmd(Data, "@TwsMenu");
register_dictionary("tws.txt");
register_menu("@TwsMenu", 1023, "@HandleTwsMenu", 0);
register_concmd("CmdActivateDisplay", "@ActivateHandler");
register_menu("@MoveMenu", 1023, "@Handle_MoveMenu", 0);
register_concmd("MoveValue", "@MoveHandler");
register_menu("@DeleteMenu", 1023, "@Handle_DeleteMenu", 0);
register_cvar("text_with_sprites_version", PLUGIN_VER, FCVAR_SERVER|FCVAR_SPONLY|FCVAR_UNLOGGED);
new PlDir[MAX_RESOURCE_PATH_LENGTH];
formatex(PlDir, charsmax(PlDir), "%s/%s", Dir, DIR_NAME);
set_fail_state("Error! no dir: %s", PlDir);
get_mapname(Map, charsmax(Map));
formatex(SavePath, charsmax(SavePath), "%s/%s/%s-coord.cfg", Dir, DIR_NAME, Map);
public client_connect(id)
if(~get_user_flags(id) & ACCESS_FLAG) return;
if(~get_user_flags(id) & ACCESS_FLAG) return 0;
new Menu[MAX_MENU_LENGTH], Keys = MENU_KEY_1|MENU_KEY_2|MENU_KEY_3|MENU_KEY_4|MENU_KEY_5|MENU_KEY_6|MENU_KEY_7|MENU_KEY_0;
new Len = formatex(Menu, charsmax(Menu), "\r[\y%L\r] \w%L^n^n", id, "TWS_PREFIX", id, "TWS_MAIN_MENU_TITLE");
new Buffer[SPRITES_ARRAY_BUFFER];
ArrayGetString(SaveSprites, CheckSprites[id], Buffer, charsmax(Buffer));
new Size = ArraySize(SaveSymbols);
Len += formatex(Menu[Len], charsmax(Menu) - Len, "\r[1] \y# \w%L: \r[\y%s\r]^n^n", id, "TWS_MENU_ITEM_SPRITES", Buffer);
Len += formatex(Menu[Len], charsmax(Menu) - Len, "\r[2] \y# \w%L \r[\y%L\r]^n^n", id, "TWS_MENU_ITEM_SPRITES_READ_FILES", id, !Size ? "TWS_MENU_ITEM_SPRITES_READ_FILES_NO" : "TWS_MENU_ITEM_SPRITES_READ_FILES_YES");
Len += formatex(Menu[Len], charsmax(Menu) - Len, !Size ? "\r[3] \y# \d%L^n^n" : "\r[3] \y# \w%L^n^n", id, "TWS_MENU_ITEM_DELETE");
Len += formatex(Menu[Len], charsmax(Menu) - Len, CheckMenu2[id] == 2 ? "\r[4] \y# \w%L \r[\yZ\r]^n^n" : (CheckMenu2[id] == 0 ? "\r[3] \y# \w%L \r[\yX\r]^n^n" : "\r[3] \y# \w%L \r[\yY\r]^n^n"), id, "TWS_MAIN_MENU_ITEM3");
Len += formatex(Menu[Len], charsmax(Menu) - Len, "\r[5] \y# \w%L \r[\y%L\r]^n^n", id, "TWS_MAIN_MENU_ITEM4", id, fmt("TWS_MAIN_MENU_ITEM4_%d_%d", CheckMenu2[id], CheckMenu3[id]));
Len += formatex(Menu[Len], charsmax(Menu) - Len, !Size ? "\r[6] \y# \d%L^n^n" : "\r[6] \y# \w%L^n^n", id, "TWS_MENU_ITEM_MOVE");
Len += formatex(Menu[Len], charsmax(Menu) - Len, !Size ? "\r[7] \y# \d%L^n^n" : "\r[7] \y# \w%L^n^n", id, "TWS_MAIN_MENU_ITEM6");
formatex(Menu[Len], charsmax(Menu) - Len, "\r[0] \y# \w%L", id, "TWS_MENU_EXIT");
return show_menu(id, Keys, Menu, -1, "@TwsMenu");
new SizeSymbols = ArraySize(SaveSymbols);
new SizeSprites = ArraySize(SaveSprites);
CheckSprites[id] = (CheckSprites[id] + 1) % SizeSprites;
if(!SizeSymbols) ReadSpriteFiles(id);
CheckMenu2[id] = (CheckMenu2[id] + 1) % 3;
CheckMenu3[id] = (CheckMenu3[id] + 1) % 2;
client_cmd(id, "messagemode ^"CmdActivateDisplay^"");
new Menu[MAX_MENU_LENGTH], Keys = MENU_KEY_1|MENU_KEY_2|MENU_KEY_3|MENU_KEY_4|MENU_KEY_0;
new Len = formatex(Menu, charsmax(Menu), "\r[\y%L\r] \w%L^n^n", id, "TWS_PREFIX", id, "TWS_MENU_ITEM_DELETE");
Len += formatex(Menu[Len], charsmax(Menu) - Len, "\r[1] \y# \w%L \r[\y%L\r]^n", id, "TWS_MENU_DELETE_ITEM1", id, fmt("TWS_MENU_DELETE_ITEM1_%d", CheckMenu1[id]));
Len += formatex(Menu[Len], charsmax(Menu) - Len, "\r[2] \y# \w%L^n^n", id, "TWS_MENU_DELETE_ITEM2");
formatex(Menu[Len], charsmax(Menu) - Len, "\r[0] \y# \w%L", id, "TWS_MENU_BACK");
return show_menu(id, Keys, Menu, -1, "@DeleteMenu");
@Handle_DeleteMenu(id, Keys)
CheckMenu1[id] = (CheckMenu1[id] + 1) % 2;
get_user_aiming(id, Entity, body, 9999);
if(FClassnameIs(Entity, fmt("%s-%d", ENTITY_CLASSNAME, i)))
SaveSprite(Entity, CheckSprites[id], 0, 1);
DeleteAllHandler(Entity, i++);
DeleteAllHandler(Entity, num)
Entity = rg_find_ent_by_class(NULLENT, fmt("%s-%d", ENTITY_CLASSNAME, num), false);
set_entvar(Entity, var_flags, FL_KILLME);
set_entvar(Entity, var_nextthink, get_gametime() + 0.01);
Entity = rg_find_ent_by_class(Entity, fmt("%s-%d", ENTITY_CLASSNAME, num), false);
if(~get_user_flags(id) & ACCESS_FLAG) return;
new Data[MESSAGEMODE_ARRAY_BUFFER];
read_args(Data, charsmax(Data));
new num = SymbolsHandler(Data[i++]);
new i, Buffer[SYMBOL_ARRAY_BUFFER];
while(i < ArraySize(SaveSymbols))
ArrayGetString(SaveSymbols, i, Buffer, charsmax(Buffer));
if(contain(data[0], Buffer) == 0) return i;
get_entvar(id, var_origin, SaveOrigin[id]);
SaveOrigin[id][0] += 30.0;
SaveOrigin[id][1] += 30.0;
SaveOrigin[id][2] += 15.0;
CreateSprite(id, num, 0);
SaveSprite(id, 0, num, 0, class_num);
if(CheckMenu3[id] == 0) SaveOrigin[id][0] -= INTERVAL_VALUE_X;
else SaveOrigin[id][0] += INTERVAL_VALUE_X;
if(CheckMenu3[id] == 0) SaveOrigin[id][1] -= INTERVAL_VALUE_Y;
else SaveOrigin[id][1] += INTERVAL_VALUE_Y;
if(CheckMenu3[id] == 0) SaveOrigin[id][2] -= INTERVAL_VALUE_Z;
else SaveOrigin[id][2] += INTERVAL_VALUE_Z;
CreateSprite(id, num, cl_num, Float:Origin[3]={0.0, 0.0, 0.0}, Float:Angles=0.0, SaveSpr=0)
new Buffer[SPRITES_ARRAY_BUFFER];
ArrayGetString(SaveSprites, id ? CheckSprites[id] : SaveSpr, Buffer, charsmax(Buffer));
new Index = ArrayGetCell(SaveIndex, id ? CheckSprites[id] : SaveSpr);
new Entity = rg_create_entity("info_target", false);
set_entvar(Entity, var_classname, fmt("%s-%d", ENTITY_CLASSNAME, id ? class_num : cl_num));
set_entvar(Entity, var_model, Buffer);
set_entvar(Entity, var_modelindex, Index);
set_entvar(Entity, var_chain, num);
set_entvar(Entity, var_rendermode, kRenderTransAdd);
set_entvar(Entity, var_renderamt, 255.0);
set_entvar(Entity, var_frame, float(num));
set_entvar(Entity, var_movetype, MOVETYPE_FLY);
set_entvar(Entity, var_solid, SOLID_SLIDEBOX);
new Float:Mins[3] = {-5.0, -5.0, -5.0};
set_entvar(Entity, var_mins, Mins);
new Float:Maxs[3] = {5.0, 5.0, 5.0};
set_entvar(Entity, var_maxs, Maxs);
Size[0] = Maxs[0] - Mins[0];
Size[1] = Maxs[1] - Mins[1];
Size[2] = Maxs[2] - Mins[2];
set_entvar(Entity, var_size, Size);
set_entvar(Entity, var_scale, SCALE);
set_entvar(Entity, var_scale, random_float(SCALE_MIN, SCALE_MAX));
set_entvar(Entity, var_origin, id ? SaveOrigin[id] : Origin);
set_entvar(Entity, var_angles, EntAngles);
SaveSprite(id, check_sprite, num, value, cls_num = 0, Float:Origin[3]={0.0, 0.0, 0.0}, Float:Angles=0.0)
new Buffer[SYMBOL_ARRAY_BUFFER], Data[128];
ArrayGetString(SaveSymbols, num, Buffer, charsmax(Buffer));
formatex(Data, charsmax(Data), "%d %d %s %d %f %f %f %f", id ? CheckSprites[id] : check_sprite, cls_num, Buffer, num, id ? SaveOrigin[id][0] : Origin[0], id ? SaveOrigin[id][1] : Origin[1], id ? SaveOrigin[id][2] : Origin[2], Angles);
write_file(SavePath, Data);
SaveAllHandler(id, i++, check_sprite);
SaveAllHandler(id, num, check_sprite)
new Entity = rg_find_ent_by_class(NULLENT, fmt("%s-%d", ENTITY_CLASSNAME, num), false);
set_entvar(Entity, var_flags, FL_KILLME);
set_entvar(Entity, var_nextthink, get_gametime() + 0.01);
Entity = rg_find_ent_by_class(Entity, fmt("%s-%d", ENTITY_CLASSNAME, num), false);
new Float:EntOrigin[3], Float:EntAngles[3];
get_entvar(Entity, var_origin, EntOrigin);
get_entvar(Entity, var_angles, EntAngles);
new ent_num = get_entvar(Entity, var_chain);
get_entvar(Entity, var_classname, Class, charsmax(Class));
strtok(Class, Part1[0], charsmax(Part1[]), Part1[1], charsmax(Part1[]), '-');
SaveSprite(0, check_sprite, ent_num, 0, str_to_num(Part1[1]), EntOrigin, EntAngles[2]);
Entity = rg_find_ent_by_class(Entity, fmt("%s-%d", ENTITY_CLASSNAME, num), false);
if(!file_exists(SavePath)) return;
new Data[128], SaveSpr[6], class_number[6], Symbol[6], num[6], Coord_X[13], Coord_Y[13], Coord_Z[13], Angles[13], Float:DataCoord[3];
new f = fopen(SavePath, "rt");
fgets(f, Data, charsmax(Data));
parse(Data, SaveSpr, charsmax(SaveSpr), class_number, charsmax(class_number), Symbol, charsmax(Symbol), num, charsmax(num), Coord_X, charsmax(Coord_X), Coord_Y, charsmax(Coord_Y), Coord_Z, charsmax(Coord_Z), Angles, charsmax(Angles));
DataCoord[0] = str_to_float(Coord_X);
DataCoord[1] = str_to_float(Coord_Y);
DataCoord[2] = str_to_float(Coord_Z);
CreateSprite(0, str_to_num(num), str_to_num(class_number), DataCoord, str_to_float(Angles), str_to_num(SaveSpr));
class_num = str_to_num(class_number);
if(~get_user_flags(id) & ACCESS_FLAG) return;
read_argv(1, String, charsmax(String));
new Part1[32], Part2[32];
strtok(String, Part1, charsmax(Part1), Part2, charsmax(Part2), '.');
if(is_str_num(Part1) && is_str_num(Part2))
Move[id] = str_to_float(String);
new Menu[MAX_MENU_LENGTH], Keys = MENU_KEY_1|MENU_KEY_2|MENU_KEY_3|MENU_KEY_4|MENU_KEY_5|MENU_KEY_6|MENU_KEY_7|MENU_KEY_0;
new Len = formatex(Menu, charsmax(Menu), "\r[\y%L\r] \w%L^n^n", id, "TWS_PREFIX", id, "TWS_MENU_ITEM_MOVE");
Len1 += formatex(BuffText[Len1], charsmax(BuffText) - Len1, "%L", id, "TWS_MENU_MOVE_ERROR");
new Entity = rg_find_ent_by_class(NULLENT, fmt("%s-%d", ENTITY_CLASSNAME, Sign1[id]), false);
new ent_num = get_entvar(Entity, var_chain);
new Buffer[SYMBOL_ARRAY_BUFFER];
ArrayGetString(SaveSymbols, ent_num, Buffer, charsmax(Buffer));
Len1 += formatex(BuffText[Len1], charsmax(BuffText) - Len1, "%s", Buffer);
Entity = rg_find_ent_by_class(Entity, fmt("%s-%d", ENTITY_CLASSNAME, Sign1[id]), false);
Len += formatex(Menu[Len], charsmax(Menu) - Len, "\r[1] \y# \w%L \r[\y%s\r]^n", id, "TWS_MENU_MOVE_ITEM1", BuffText);
Len += formatex(Menu[Len], charsmax(Menu) - Len, "\r[2] \y# \w%L^n^n", id, "TWS_MENU_MOVE_ITEM2");
Len += formatex(Menu[Len], charsmax(Menu) - Len, "\r[3] \y# \w%L \r[\y%L\r]^n", id, "TWS_MENU_MOVE_ITEM3", id, fmt("TWS_MENU_MOVE_ITEM3_%d", Sign2[id]));
Len += formatex(Menu[Len], charsmax(Menu) - Len, "\r[4] \y# \w%L \r[\y%.2f\r]^n^n", id, "TWS_MENU_MOVE_ITEM4", Move[id]);
Len += formatex(Menu[Len], charsmax(Menu) - Len, "\r[5] \y# \w%L \r[\y%s\r]^n^n", id, "TWS_MENU_MOVE_ITEM5", MOVE_COORDS[Sign2[id] == 0 ? CheckCoords[id] + 4 : CheckCoords[id]]);
Len += formatex(Menu[Len], charsmax(Menu) - Len, "\r[6] \y# \w%L^n^n", id, "TWS_MENU_MOVE_ITEM6");
Len += formatex(Menu[Len], charsmax(Menu) - Len, "\r[7] \y# \w%L^n^n", id, "TWS_MENU_MOVE_ITEM7");
formatex(Menu[Len], charsmax(Menu) - Len, "\r[0] \y# \w%L", id, "TWS_MENU_BACK");
return show_menu(id, Keys, Menu, -1, "@MoveMenu");
@Handle_MoveMenu(id, Keys)
if(Sign1[id] == class_num) Sign1[id] = 1;
new Entity = rg_find_ent_by_class(NULLENT, fmt("%s-%d", ENTITY_CLASSNAME, Sign1[id]), false);
get_entvar(Entity, var_origin, DataCoord);
set_entvar(id, var_origin, DataCoord);
Sign2[id] = (Sign2[id] + 1) % 2;
client_cmd(id, "messagemode ^"MoveValue^"");
CheckCoords[id] = (CheckCoords[id] + 1) % 2;
CheckCoords[id] = (CheckCoords[id] + 1) % sizeof MOVE_COORDS;
MoveEntity(id, Sign2[id] == 0 ? CheckCoords[id] + 5 : CheckCoords[id] + 1);
SaveAllHandler(0, i++, CheckSprites[id]);
new Entity = rg_find_ent_by_class(NULLENT, fmt("%s-%d", ENTITY_CLASSNAME, Sign1[id]), false);
get_entvar(Entity, Sign2[id] == 1 ? var_origin : var_angles, DataCoord);
case 1: DataCoord[0] += Move[id];
case 2: DataCoord[0] -= Move[id];
case 3: DataCoord[1] += Move[id];
case 4: DataCoord[1] -= Move[id];
case 5: DataCoord[2] += Move[id];
case 6: DataCoord[2] -= Move[id];
set_entvar(Entity, Sign2[id] == 1 ? var_origin : var_angles, DataCoord);
Entity = rg_find_ent_by_class(Entity, fmt("%s-%d", ENTITY_CLASSNAME, Sign1[id]), false);
new Buffer[SPRITES_ARRAY_BUFFER];
ArrayGetString(SaveSprites, CheckSprites[id], Buffer, charsmax(Buffer));
replace(Buffer, charsmax(Buffer), "sprites/tws/", "");
replace(Buffer, charsmax(Buffer), ".spr", "");
new SpritePath[MAX_RESOURCE_PATH_LENGTH * 2]
formatex(SpritePath, charsmax(SpritePath), "%s/%s/%s_%s.ini", Dir, DIR_NAME, DIR_NAME, Buffer);
if(!file_exists(SpritePath))
set_fail_state("Error! no file: %s", SpritePath);
new Data[SYMBOL_ARRAY_BUFFER], f = fopen(SpritePath, "rt");
fgets(f, Data, charsmax(Data));
ArrayPushString(SaveSymbols, Data);