Участник
Пользователь
iPlague
♿️
- Сообщения
- 230
- Реакции
- 130
- Помог
- 2 раз(а)
Поскольку у меня было немного свободного времени, захотел доделать плагин Flag mode, а именно определить момент, когда игрок возвращается с флагом на свою базу.
Как мне подсказали, есть несколько способов, один из них я придумал сам.
Итак, первый способ самый простой, годится для стандартных карт, где есть buy_zone:
Однако, такой способ исключает такие карты как aim_ awp_ etc. Так же в чате подсказали, что на de_ cs_ и прочих картах сложно играть в режим flag mod, т.к. карты не симметричны. К тому же, есть плагины которые удаляют/отключают байзоны.
Второй способ, как раз для таких карт - определить центральную точку на каждом респе и там размещать энтити. Отловив тач можно засчитывать флаг. Возможно я там сделал не всё верно в плане логичности, оптимизации и т.д., однако это работает, ниже много скринов.
Этот способ в принципе подходит для подавляющего большинства карт, но опять таки есть исключения:
Ну и третий способ, который настойчиво советовали в чате - руками расставлять боксы на респах, сохранять в файл и не иметь проблем.
Спасибо всем, кто помогал в тг чате форума, хотелось бы услышать мнения и советы на форуме.
Как мне подсказали, есть несколько способов, один из них я придумал сам.
Итак, первый способ самый простой, годится для стандартных карт, где есть buy_zone:
Код:
public msgBuyZoneIcon(msgid, msgdest, id){
if(!isGameStarted) // проверка в плагине
return PLUGIN_CONTINUE;
if(!is_user_alive(id))
return PLUGIN_CONTINUE;
static szIcon[8];
get_msg_arg_string(2, szIcon, 7);
if(equal(szIcon, "buyzone") && get_msg_arg_int(1)){
//#define OFFSET_MAPZONE 235
//#define PLAYER_IN_BUYZONE (1<<0)
if(hasflag[id] && is_entity(g_Flag2Ent)) // если у игрока есть флаг, то засчитываю его как доставленый на респ
respawn_flag(id);
set_pdata_int(id, 235, get_pdata_int(id, 235) & ~(1<<0)); // отключаю тут же байзону
return PLUGIN_HANDLED;
}
return PLUGIN_CONTINUE;
}
Второй способ, как раз для таких карт - определить центральную точку на каждом респе и там размещать энтити. Отловив тач можно засчитывать флаг. Возможно я там сделал не всё верно в плане логичности, оптимизации и т.д., однако это работает, ниже много скринов.
Код:
#include <amxmodx>
#include <reapi>
#include <fakemeta>
#define FLAG_MDL "models/warcraft3/flag.mdl"
new g_iModel_flag;
//#define AURA_MODEL "models/aura8.mdl"
#define BEAM_SPR "sprites/zbeam4.spr"
new g_iSprites;
#if defined AURA_MODEL
new g_iModel;
#endif
new g_EntCT[32], g_EntTT[32];
new Float:coordsCT[32][3];
new Float:coordsTT[32][3];
public plugin_init(){
register_clcmd("say test", "create");
}
public plugin_precache(){
#if defined AURA_MODEL
g_iModel = precache_model(AURA_MODEL);
#endif
g_iSprites = precache_model(BEAM_SPR);
g_iModel_flag = precache_model(FLAG_MDL);
}
public create(id){
new Ent1 = NULLENT, numCT = 0;
while((Ent1 = rg_find_ent_by_class(Ent1, "info_player_start")) != 0){ // Ищем спавны КТ, записываем координаты, пишем инфу в консоль.
g_EntCT[numCT] = Ent1;
new Float:forigin1[3]; get_entvar(g_EntCT[numCT], var_origin, forigin1);
// Ставим модель
set_entvar(g_EntCT[numCT], var_model, FLAG_MDL);
set_entvar(g_EntCT[numCT], var_modelindex, g_iModel_flag);
set_entvar(g_EntCT[numCT], var_movetype, MOVETYPE_TOSS);
set_entvar(g_EntCT[numCT], var_solid, SOLID_NOT);
set_entvar(g_EntCT[numCT], var_body, 2);
//
server_print("%d. CT Entity ID: %d | Entity Origins: %f %f %f", numCT + 1, g_EntCT[numCT], forigin1[0],forigin1[1],forigin1[2]);
coordsCT[numCT][0] = forigin1[0];
coordsCT[numCT][1] = forigin1[1];
coordsCT[numCT][2] = forigin1[2];
numCT++;
}
Ent1 = NULLENT; new numTT = 0;
while((Ent1 = rg_find_ent_by_class(Ent1, "info_player_deathmatch")) != 0){ // Ищем спавны ТТ, записываем координаты, пишем инфу в консоль.
g_EntTT[numTT] = Ent1;
new Float:forigin1[3]; get_entvar(g_EntTT[numTT], var_origin, forigin1);
// Ставим модель
set_entvar(g_EntTT[numTT], var_model, FLAG_MDL);
set_entvar(g_EntTT[numTT], var_modelindex, g_iModel_flag);
set_entvar(g_EntTT[numTT], var_movetype, MOVETYPE_TOSS);
set_entvar(g_EntTT[numTT], var_solid, SOLID_NOT);
set_entvar(g_EntTT[numTT], var_body, 1);
//
server_print("%d. TT Entity ID: %d | Entity Origins: %f %f %f", numTT + 1, g_EntTT[numTT], forigin1[0],forigin1[1],forigin1[2]);
coordsTT[numTT][0] = forigin1[0];
coordsTT[numTT][1] = forigin1[1];
coordsTT[numTT][2] = forigin1[2];
numTT++;
}
//{ Нужно найти средину куба, который задан двумя точками по аналогии с min/max
// Находим наименьшую координату, наибольшую координату, находим средину получившегося отрезка.
// Для КТ
new Float:MaxXCT = coordsCT[0][0], Float:MinXCT = coordsCT[0][0];
new Float:MaxYCT = coordsCT[0][1], Float:MinYCT = coordsCT[0][1];
new Float:MaxZCT = coordsCT[0][2], Float:MinZCT = coordsCT[0][2];
// Находим наибольшее и наименьшее значение в массиве циклом для КТ
for(new i = 0; i < numCT; i ++){
// наибольшее
if(coordsCT[i][0] > MaxXCT)
MaxXCT = coordsCT[i][0];
if(coordsCT[i][1] > MaxYCT)
MaxYCT = coordsCT[i][1];
if(coordsCT[i][2] > MaxZCT)
MaxZCT = coordsCT[i][2];
// наименьшее
if(coordsCT[i][0] <= MinXCT)
MinXCT = coordsCT[i][0];
if(coordsCT[i][1] <= MinYCT)
MinYCT = coordsCT[i][1];
if(coordsCT[i][2] <= MinZCT)
MinZCT = coordsCT[i][2];
}
// Для ТТ
new Float:MaxXTT = coordsTT[0][0], Float:MinXTT = coordsTT[0][0]
new Float:MaxYTT = coordsTT[0][1], Float:MinYTT = coordsTT[0][1];
new Float:MaxZTT = coordsTT[0][2], Float:MinZTT = coordsTT[0][2];
// Находим наибольшее и наименьшее значение в массиве циклом для ТТ
for(new i = 0; i < numTT; i ++){
// наибольшее
if(coordsTT[i][0] > MaxXTT)
MaxXTT = coordsTT[i][0];
if(coordsTT[i][1] > MaxYTT)
MaxYTT = coordsTT[i][1];
if(coordsTT[i][2] > MaxZTT)
MaxZTT = coordsTT[i][2];
// наименьшее
if(coordsTT[i][0] <= MinXTT)
MinXTT = coordsTT[i][0];
if(coordsTT[i][1] <= MinYTT)
MinYTT = coordsTT[i][1];
if(coordsTT[i][2] <= MinZTT)
MinZTT = coordsTT[i][2];
}
// Пишем в консоль
server_print("MinXCT %.0f MinYCT %.0f MinZCT %.0f", MinXCT, MinYCT, MinZCT);
server_print("MaxXCT %.0f MaxYCT %.0f MaxZCT %.0f", MaxXCT, MaxYCT, MaxZCT);
server_print("MinXTT %.0f MinYTT %.0f MinZTT %.0f", MinXTT, MinYTT, MinZTT);
server_print("MaxXTT %.0f MaxYTT %.0f MaxZTT %.0f", MaxXTT, MaxYTT, MaxZTT);
// находим центральную точку среди спавнов КТ
new Float:CentralPointCT[3];
CentralPointCT[0] = (MaxXCT + MinXCT) / 2.0;
CentralPointCT[1] = (MaxYCT + MinYCT) / 2.0;
CentralPointCT[2] = (MaxZCT + MinZCT) / 2.0;
// находим центральную точку среди спавнов ТТ
new Float:CentralPointTT[3];
CentralPointTT[0] = (MaxXTT + MinXTT) / 2.0;
CentralPointTT[1] = (MaxYTT + MinYTT) / 2.0;
CentralPointTT[2] = (MaxZTT + MinZTT) / 2.0;
// Выводим инфо о центральной точке в консоль
server_print("CENTRAL CT %0.f %0.f %0.f CENTRAL TT %0.f %0.f %0.f", CentralPointCT[0], CentralPointCT[1], CentralPointCT[2], CentralPointTT[0], CentralPointTT[1],CentralPointTT[2]);
//{ Поставим в центральной точке КТ белый флаг
new ct_flag = rg_create_entity("info_target", false); // создаем энтити
if(!is_nullent(ct_flag)){
set_entvar(ct_flag, var_origin, CentralPointCT);
set_entvar(ct_flag, var_model, FLAG_MDL);
set_entvar(ct_flag, var_modelindex, g_iModel_flag);
set_entvar(ct_flag, var_movetype, MOVETYPE_TOSS);
set_entvar(ct_flag, var_solid, SOLID_NOT);
set_entvar(ct_flag, var_body, 0);
set_entvar(ct_flag, var_renderfx, kRenderFxGlowShell);
set_entvar(ct_flag, var_rendercolor, {0.0,0.0,255.0});
set_entvar(ct_flag, var_rendermode, kRenderNormal);
set_entvar(ct_flag, var_renderamt, 32);
}
//}
//{ Поставим в центральной точке TТ белый флаг
new tt_flag = rg_create_entity("info_target", false); // создаем энтити
if(!is_nullent(tt_flag)){
set_entvar(tt_flag, var_origin, CentralPointTT);
set_entvar(tt_flag, var_model, FLAG_MDL);
set_entvar(tt_flag, var_modelindex, g_iModel_flag);
set_entvar(tt_flag, var_movetype, MOVETYPE_TOSS);
set_entvar(tt_flag, var_solid, SOLID_NOT);
set_entvar(tt_flag, var_body, 0);
set_entvar(tt_flag, var_renderfx, kRenderFxGlowShell);
set_entvar(tt_flag, var_rendercolor, {255.0,0.0,0.0});
set_entvar(tt_flag, var_rendermode, kRenderNormal);
set_entvar(tt_flag, var_renderamt, 32);
}
// }
// Находим ближайший к центральной точке спавн КТ
new Float:MidDistCT = get_distance_f(coordsCT[0], CentralPointCT);
new NearestPointCT = 0;
for(new i = 0; i < numCT; i++){
if(get_distance_f(coordsCT[i], CentralPointCT) < MidDistCT){
MidDistCT = get_distance_f(coordsCT[i], CentralPointCT);
NearestPointCT = i;
}
}
// Находим ближайший к центральной точке спавн ТТ
new Float:MidDistTT = get_distance_f(coordsTT[0], CentralPointTT);
new NearestPointTT = 0;
for(new i = 0; i < numTT; i++){
if(get_distance_f(coordsTT[i], CentralPointTT) < MidDistTT){
MidDistTT = get_distance_f(coordsTT[i], CentralPointTT);
NearestPointTT = i;
}
}
// Напишем в консоль
server_print("Nearest CT entity %d %.0f points away", g_EntCT[NearestPointCT], MidDistCT);
server_print("Nearest TT entity %d %.0f points away", g_EntTT[NearestPointTT], MidDistTT);
// set glowshell over nearest spawn point
set_entvar(g_EntCT[NearestPointCT], var_renderfx, kRenderFxGlowShell);
set_entvar(g_EntCT[NearestPointCT], var_rendercolor, {0.0,255.0,0.0});
set_entvar(g_EntCT[NearestPointCT], var_rendermode, kRenderNormal);
set_entvar(g_EntCT[NearestPointCT], var_renderamt, 32);
set_entvar(g_EntTT[NearestPointTT], var_renderfx, kRenderFxGlowShell);
set_entvar(g_EntTT[NearestPointTT], var_rendercolor, {0.0,255.0,0.0});
set_entvar(g_EntTT[NearestPointTT], var_rendermode, kRenderNormal);
set_entvar(g_EntTT[NearestPointTT], var_renderamt, 32);
}
- 35hp - там на видимом респе нет спавнов, они находятся вне видимой карты, игрок попадает на респ через триггер_телепорт
- какая то карта со спавнами в вертолёте
- спецкарты типа gg_ zm_ где спавны расставляются плагинами.
Ну и третий способ, который настойчиво советовали в чате - руками расставлять боксы на респах, сохранять в файл и не иметь проблем.
Спасибо всем, кто помогал в тг чате форума, хотелось бы услышать мнения и советы на форуме.
Последнее редактирование: