Данный раздел предназначен для обсуждения, а также решения технических проблем связанных с серверной частью. Обсуждения касательно игровых клиентов ведутся здесь.
1. Во время создания новой темы аккуратно оформляйте её, не допускайте грамматических ошибок. 2. Описывая проблему старайтесь, как можно больше рассказать о ней, а так же о действиях с сервером после которых она возникла, по возможности подкрепите информацию логами. 3. Если вопрос касается проблемы в работе сервера, то обязательно прикрепляйте список плагинов (введите в консоли сервера: meta list и amxx plugins), настройки server.cfg, логи. Так же указывайте операционную систему, версию HLDS (введите к консоли сервера: version) и где хостится сервер.
// CS Player PData Offsets (win32) const OFFSET_CSMENUCODE = 205
// For class list menu handlers #define MENU_PAGE_CLASS g_menu_data[id] new g_menu_data[MAXPLAYERS+1]
enum _:TOTAL_FORWARDS { FW_CLASS_SELECT_PRE = 0, FW_CLASS_SELECT_POST } new g_Forwards[TOTAL_FORWARDS] new g_ForwardResult
new g_ZombieClassCount new Array:g_ZombieClassRealName new Array:g_ZombieClassName new Array:g_ZombieClassDesc new Array:g_ZombieClassHealth new Array:g_ZombieClassSpeed new Array:g_ZombieClassGravity new Array:g_ZombieClassKnockbackFile new Array:g_ZombieClassKnockback new Array:g_ZombieClassModelsFile new Array:g_ZombieClassModelsHandle new Array:g_ZombieClassClawsFile new Array:g_ZombieClassClawsHandle new g_ZombieClass[MAXPLAYERS+1] new g_ZombieClassNext[MAXPLAYERS+1] new g_AdditionalMenuText[32]
public plugin_init() { register_plugin("[ZP] Class: Zombie", ZP_VERSION_STRING, "ZP Dev Team")
public menu_zombieclass(id, menuid, item) { // Menu was closed if (item == MENU_EXIT) { MENU_PAGE_CLASS = 0 menu_destroy(menuid) return PLUGIN_HANDLED; }
// Remember class menu page MENU_PAGE_CLASS = item / 7
// Retrieve class index new itemdata[2], dummy, index menu_item_getinfo(menuid, item, dummy, itemdata, charsmax(itemdata), _, _, dummy) index = itemdata[0]
// Execute class select attempt forward ExecuteForward(g_Forwards[FW_CLASS_SELECT_PRE], g_ForwardResult, id, index)
// Class available to player? if (g_ForwardResult >= ZP_CLASS_NOT_AVAILABLE) { menu_destroy(menuid) return PLUGIN_HANDLED; }
// Make selected class next class for player g_ZombieClassNext[id] = index
new name[32], transkey[64] new Float:maxspeed = Float:ArrayGetCell(g_ZombieClassSpeed, g_ZombieClassNext[id]) ArrayGetString(g_ZombieClassName, g_ZombieClassNext[id], name, charsmax(name)) // ML support for class name formatex(transkey, charsmax(transkey), "ZOMBIENAME %s", name) if (GetLangTransKey(transkey) != TransKey_Bad) formatex(name, charsmax(name), "%L", id, transkey)
// Execute class select post forward ExecuteForward(g_Forwards[FW_CLASS_SELECT_POST], g_ForwardResult, id, index)
menu_destroy(menuid) return PLUGIN_HANDLED; }
public zp_fw_core_infect_post(id, attacker) { // Show zombie class menu if they haven't chosen any (e.g. just connected) if (g_ZombieClassNext[id] == ZP_INVALID_ZOMBIE_CLASS) { if (g_ZombieClassCount > 1) show_menu_zombieclass(id) else // If only one class is registered, choose it automatically g_ZombieClassNext[id] = 0 }
// Bots pick class automatically if (is_user_bot(id)) { // Try choosing class new index, start_index = random_num(0, g_ZombieClassCount - 1) for (index = start_index + 1; /* no condition */; index++) { // Start over when we reach the end if (index >= g_ZombieClassCount) index = 0
// Execute class select attempt forward ExecuteForward(g_Forwards[FW_CLASS_SELECT_PRE], g_ForwardResult, id, index)
// Class available to player? if (g_ForwardResult < ZP_CLASS_NOT_AVAILABLE) { g_ZombieClassNext[id] = index break; }
// Loop completed, no class could be chosen if (index == start_index) break; } }
// Set selected zombie class. If none selected yet, use the first one g_ZombieClass[id] = g_ZombieClassNext[id] if (g_ZombieClass[id] == ZP_INVALID_ZOMBIE_CLASS) g_ZombieClass[id] = 0
// Apply zombie player model new Array:class_models = ArrayGetCell(g_ZombieClassModelsHandle, g_ZombieClass[id]) if (class_models != Invalid_Array) { new index = random_num(0, ArraySize(class_models) - 1) new player_model[32] ArrayGetString(class_models, index, player_model, charsmax(player_model)) cs_set_player_model(id, player_model) } else { // No models registered for current class, use default model cs_set_player_model(id, ZOMBIES_DEFAULT_MODEL) }
// Apply zombie claw model new claw_model[64], Array:class_claws = ArrayGetCell(g_ZombieClassClawsHandle, g_ZombieClass[id]) if (class_claws != Invalid_Array) { new index = random_num(0, ArraySize(class_claws) - 1) ArrayGetString(class_claws, index, claw_model, charsmax(claw_model)) cs_set_player_view_model(id, CSW_KNIFE, claw_model) } else { // No models registered for current class, use default model cs_set_player_view_model(id, CSW_KNIFE, ZOMBIES_DEFAULT_CLAWMODEL) } cs_set_player_weap_model(id, CSW_KNIFE, "")
public native_class_zombie_register(plugin_id, num_params) { new name[32] get_string(1, name, charsmax(name))
if (strlen(name) < 1) { log_error(AMX_ERR_NATIVE, "[ZP] Can't register zombie class with an empty name") return ZP_INVALID_ZOMBIE_CLASS; }
new index, zombieclass_name[32] for (index = 0; index < g_ZombieClassCount; index++) { ArrayGetString(g_ZombieClassRealName, index, zombieclass_name, charsmax(zombieclass_name)) if (equali(name, zombieclass_name)) { log_error(AMX_ERR_NATIVE, "[ZP] Zombie class already registered (%s)", name) return ZP_INVALID_ZOMBIE_CLASS; } }
new description[32] get_string(2, description, charsmax(description)) new health = get_param(3) new Float:speed = get_param_f(4) new Float:gravity = get_param_f(5)
// Load settings from zombie classes file new real_name[32] copy(real_name, charsmax(real_name), name) ArrayPushString(g_ZombieClassRealName, real_name)
// Name if (!amx_load_setting_string(ZP_ZOMBIECLASSES_FILE, real_name, "NAME", name, charsmax(name))) amx_save_setting_string(ZP_ZOMBIECLASSES_FILE, real_name, "NAME", name) ArrayPushString(g_ZombieClassName, name)
public _class_zombie_register_model(plugin_id, num_params) { new classid = get_param(1)
if (classid < 0 || classid >= g_ZombieClassCount) { log_error(AMX_ERR_NATIVE, "[ZP] Invalid zombie class id (%d)", classid) return false; }
// Player models already loaded from file if (ArrayGetCell(g_ZombieClassModelsFile, classid)) return true;
new player_model[32] get_string(2, player_model, charsmax(player_model))
new model_path[128] formatex(model_path, charsmax(model_path), "models/player/%s/%s.mdl", player_model, player_model)
precache_model(model_path)
// Support modelT.mdl files formatex(model_path, charsmax(model_path), "models/player/%s/%sT.mdl", player_model, player_model) if (file_exists(model_path)) precache_model(model_path)
new Array:class_models = ArrayGetCell(g_ZombieClassModelsHandle, classid)
// No models registered yet? if (class_models == Invalid_Array) { class_models = ArrayCreate(32, 1) ArraySetCell(g_ZombieClassModelsHandle, classid, class_models) } ArrayPushString(class_models, player_model)
// Save models to file new real_name[32] ArrayGetString(g_ZombieClassRealName, classid, real_name, charsmax(real_name)) amx_save_setting_string_arr(ZP_ZOMBIECLASSES_FILE, real_name, "MODELS", class_models)
return true; }
public _class_zombie_register_claw(plugin_id, num_params) { new classid = get_param(1)
if (classid < 0 || classid >= g_ZombieClassCount) { log_error(AMX_ERR_NATIVE, "[ZP] Invalid zombie class id (%d)", classid) return false; }
// Claw models already loaded from file if (ArrayGetCell(g_ZombieClassClawsFile, classid)) return true;
new claw_model[64] get_string(2, claw_model, charsmax(claw_model))
precache_model(claw_model)
new Array:class_claws = ArrayGetCell(g_ZombieClassClawsHandle, classid)
// No models registered yet? if (class_claws == Invalid_Array) { class_claws = ArrayCreate(64, 1) ArraySetCell(g_ZombieClassClawsHandle, classid, class_claws) } ArrayPushString(class_claws, claw_model)
// Save models to file new real_name[32] ArrayGetString(g_ZombieClassRealName, classid, real_name, charsmax(real_name)) amx_save_setting_string_arr(ZP_ZOMBIECLASSES_FILE, real_name, "CLAWMODEL", class_claws)
return true; }
public native_class_zombie_register_kb(plugin_id, num_params) { new classid = get_param(1)
if (classid < 0 || classid >= g_ZombieClassCount) { log_error(AMX_ERR_NATIVE, "[ZP] Invalid zombie class id (%d)", classid) return false; }
// Knockback already loaded from file if (ArrayGetCell(g_ZombieClassKnockbackFile, classid)) return true;
new Float:knockback = get_param_f(2)
// Set zombie class knockback ArraySetCell(g_ZombieClassKnockback, classid, knockback)
// Save to file new real_name[32] ArrayGetString(g_ZombieClassRealName, classid, real_name, charsmax(real_name)) amx_save_setting_float(ZP_ZOMBIECLASSES_FILE, real_name, "KNOCKBACK", knockback)
return true; }
public native_class_zombie_get_id(plugin_id, num_params) { new real_name[32] get_string(1, real_name, charsmax(real_name))
// Loop through every class new index, zombieclass_name[32] for (index = 0; index < g_ZombieClassCount; index++) { ArrayGetString(g_ZombieClassRealName, index, zombieclass_name, charsmax(zombieclass_name)) if (equali(real_name, zombieclass_name)) return index; }
return ZP_INVALID_ZOMBIE_CLASS; }
public native_class_zombie_get_name(plugin_id, num_params) { new classid = get_param(1)
if (classid < 0 || classid >= g_ZombieClassCount) { log_error(AMX_ERR_NATIVE, "[ZP] Invalid zombie class id (%d)", classid) return false; }
new name[32] ArrayGetString(g_ZombieClassName, classid, name, charsmax(name))
new len = get_param(3) set_string(2, name, len) return true; }
public _class_zombie_get_real_name(plugin_id, num_params) { new classid = get_param(1)
if (classid < 0 || classid >= g_ZombieClassCount) { log_error(AMX_ERR_NATIVE, "[ZP] Invalid zombie class id (%d)", classid) return false; }
new real_name[32] ArrayGetString(g_ZombieClassRealName, classid, real_name, charsmax(real_name))
new len = get_param(3) set_string(2, real_name, len) return true; }
public native_class_zombie_get_desc(plugin_id, num_params) { new classid = get_param(1)
if (classid < 0 || classid >= g_ZombieClassCount) { log_error(AMX_ERR_NATIVE, "[ZP] Invalid zombie class id (%d)", classid) return false; }
new description[32] ArrayGetString(g_ZombieClassDesc, classid, description, charsmax(description))
new len = get_param(3) set_string(2, description, len) return true; }
public Float:native_class_zombie_get_kb(plugin_id, num_params) { new classid = get_param(1)
if (classid < 0 || classid >= g_ZombieClassCount) { log_error(AMX_ERR_NATIVE, "[ZP] Invalid zombie class id (%d)", classid) return ZOMBIES_DEFAULT_KNOCKBACK; }
// Return zombie class knockback) return ArrayGetCell(g_ZombieClassKnockback, classid); }
public native_class_zombie_get_count(plugin_id, num_params) { return g_ZombieClassCount; }
public native_class_zombie_show_menu(plugin_id, num_params) { new id = get_param(1)
if (!is_user_connected(id)) { log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id) return false; }