#define MAX_ZOMBIES 40// максимальное кол-во зомби
new zhealth[MAX_ZOMBIES];
new zombie[MAX_ZOMBIES][7];
new Float:Zspeed = 5.5;
new ZTimerSpeed = 500;
enum zombiParts
{
partModel,
Float:RelX,
Float:RelY,
Float:RelZ,
Float:RelrX,
Float:RelrY,
Float:RelrZ
}
new z11[6][zombiParts]=
{
{2905,-0.115479,-0.023924, -1.280131, -90.000000, 90.000000,0.000000}, // нога
{2906, -0.218995, 0.200928, -0.253135, 0.000000, 180.000000, 0.000000}, // рука
{2907, -0.032227, -0.045897, -0.544213, 270.000000, 0.000000, 0.000000}, // туловище
{2906, 0.187987, 0.158448, -0.265793, 0.000000, 0.000000, 0.000000}, // рука
{2908, 0.000000, 0.000000, 0.000000, 270.000000, 90.000000, 0.000000},//голова
{2905, 0.101074, -0.012694, -1.288253, 270.000000, 90.000000, 0.000000} // нога
};
new z21[6][zombiParts]=
{
{2905, 0.005614, -0.110107, -1.280131, -90.000000, 90.000000, 90.000000},
{2906, -0.148926, -0.180663, -0.253135, 0.000000, 180.000000, 90.000000},
{2907, 0.047852, -0.039061, -0.544213, 270.000000, 0.000000, 90.000000},
{2906, -0.152343, 0.171387, -0.265793, 0.000000, 0.000000, 90.000000},
{2908, 0.000000, 0.000000, 0.000000, 270.000000, 90.000000, 90.000000},
{2905, 0.000977, 0.090332, -1.288253, 270.000000, 90.000000, 90.000000}
};
new usedzombi[MAX_ZOMBIES];
new TimerAtaca=-1;
forward ZombieAtaca(playerid);
if (TimerAtaca!=-1)
{
TKillTimer(TimerAtaca);
}
TimerAtaca=TSetTimer("ZombieAtaca",ZTimerSpeed,1);
new Float:X8,Float:Y8,Float:Z8,proveren,rand2,rand3;
new Float:X8,Float:Y8,Float:Z8,proveren,rand2,rand3;
public ZombieAtaca()
{
new playerid,Float:pX,Float:pY,Float:pZ,Float:angle;
new Float:pX3,Float:pY3,Float:pZ3,Float:PEPE,Float:PIPO;
for (new j=0;j< getmaxzombieid();j++)
{
/// printf("зомби id %d проходит обработку",j);
if(usedzombi[j] != 1)continue;
playerid = GetClosestPlay(zombie[j][4]);
if(playerid == INVALID_PLAYER_ID) continue;
pX3 = X8,pY3 = Y8,pZ3= Z8;
//printf("зомби id %d прошел обработку",j);
GetPlayerPos(playerid,pX,pY,pZ);
GetObjectPos(zombie[j][4],X8,Y8,Z8);
angle = 180.0-atan2(X8-pX,Y8-pY);
PEPE = floatsin((angle*3.14159/180.0));
PIPO = floatcos((angle*3.14159/180.0));
SetObjectRot( zombie[j][4], z11[4][RelrX],z11[4][RelrY],angle );
if ( (floatabs(pX3-X8) + floatabs(pY3-Y8) + floatabs(pZ3-Z8) )<2.5)
{
if( j != proveren)
{
rand2 = random(4);
rand3 = random(3);
switch(rand2)
{
case 0:pX-=rand3;
case 1:pX+=rand3;
case 2:pY-=rand3;
case 3:pY+=rand3;
}
}
}
proveren = j;
if(!IsPlayerInAnyVehicle(playerid))
{
if ( (floatabs(pX-X8) + floatabs(pY-Y8) + floatabs(pZ-Z8) )>2.8)
{
MoveObject(zombie[j][4],pX+z11[4][RelX]*PIPO+PEPE*z21[4][RelX],pY+z11[4][RelY]*PIPO+PEPE*z21[4][RelY],pZ+z21[4][RelZ]+0.7,Zspeed);
}
else OnZombieGiveDamage(playerid,7);
continue;
}
else
{
if ( (floatabs(pX-X8) + floatabs(pY-Y8) + floatabs(pZ-Z8) )>5.0)
{
MoveObject(zombie[j][4],pX+z11[4][RelX]*PIPO+PEPE*z21[4][RelX],pY+z11[4][RelY]*PIPO+PEPE*z21[4][RelY],pZ+z21[4][RelZ]+0.7,Zspeed);
}
else OnZombieGiveDamage(playerid,7);
}
}
return 1;
}
OnZombieGiveDamage(playerid,Float:damage)
{
new Float:pX,Float:pY,Float:pZ;
GetPlayerPos(playerid,pX,pY,pZ);
if ( !IsPlayerInAnyVehicle(playerid))
{
new Float:H;
GetPlayerHealth(playerid,H);
if(H <= 0.0) return true;
SetPlayerHealthAC(playerid,H-damage);
//lasttouch[playerid] = 1;
return PlaySoundForPlayersInRange(19602, 30, pX,pY,pZ);
}
else
{
new veh,Float:vehp;
veh = GetPlayerVehicleID(playerid);
GetVehicleHealth(veh, vehp);
SetVehicleHealth(veh, vehp-damage);
PlaySoundForPlayersInRange(19401, 30, pX,pY,pZ);
}
return true;
}
getmaxzombies()
{
new x;
for (new j=0;j<getmaxzombieid();j++)
{
if(usedzombi[j] == 1)x ++;
}
return x;
}
getmaxzombieid()
{
new x = -1;
for (new j=0;j<MAX_ZOMBIES;j++)
{
if(usedzombi[j] == 1)x =j;
continue;
}
return x+1;
}
GetClosestPlay(objectid)
{
new Float:min_dis = 99999.99,
Float:player_dis,
player = INVALID_PLAYER_ID;
new Float:object_x, Float:object_y, Float:object_z, Float:temp_z;
GetObjectPos(objectid, object_x, object_y, object_z);
MapAndreas_FindAverageZ(object_x, object_y, temp_z);
if (object_z > temp_z + 2.0 || object_z-1 < temp_z)
{
SetObjectPos(objectid, object_x, object_y, (object_z = temp_z + 2.0));
}
foreach (new playerid : Player)
{
if (GetPlayerState(playerid) == PLAYER_STATE_SPECTATING) continue;
if (GetPlayerInterior(playerid)) continue;
player_dis = GetPlayerDistanceFromPoint(playerid, object_x, object_y, object_z);
if (player_dis < min_dis)
{
min_dis = player_dis;
player = playerid;
}
}
return player;
}
GetClosestPlay(objectid)
{
new Float:min_dis = 99999.99,
Float:player_dis,
player = INVALID_PLAYER_ID;
new Float:object_x, Float:object_y, Float:object_z, Float:temp_z;
GetObjectPos(objectid, object_x, object_y, object_z);
GetPointZPos(object_x, object_y, temp_z);
if (object_z > temp_z + 2.0 || object_z-1 < temp_z)
{
SetObjectPos(objectid, object_x, object_y, (object_z = temp_z + 2.0));
}
foreach (new playerid : Player)
{
if (GetPlayerState(playerid) == PLAYER_STATE_SPECTATING) continue;
if (GetPlayerInterior(playerid) || Isahitman(playerid)) continue;
if (!ISAZOMBIESPAWN(playerid) && !zombiespawn2(playerid)) continue;
player_dis = GetPlayerDistanceFromPoint(playerid, object_x, object_y, object_z);
if (player_dis < min_dis)
{
min_dis = player_dis;
player = playerid;
}
}
return player;
}
public OnPlayerWeaponShot(playerid, weaponid, hittype, hitid, Float:fX, Float:fY, Float:fZ)
{
if(hittype == BULLET_HIT_TYPE_OBJECT)
{
new zombieid2 = IsThisAZombie2(hitid);
if(zombieid2 != -1)
{
new damage;
if(weaponid > 10) {damage = random(50);}// по сути эти строки зря сделал, сам решайте оставлять ли
else {damage = random(20);}
if(Headshot(zombieid2,hitid))
{
damage = 70;
GameTextForPlayer(playerid, "~r~Headshot", 1000, 6);
}
zhealth[zombieid2] -= damage;
if(zhealth[zombieid2] < 1)
{
for (new i=0;i<6;i++)
{
StopObject(zombie[zombieid2][i]);
DestroyObject(zombie[zombieid2][i]);
usedzombi[zombieid2] =0;
}
SendClientMessage(playerid,COLOR_WHITE, "Вы убили зомби! +500 вирт");
PlayerInfo[playerid][pCash] += 500;// даём ему денег
}
// format(string3[playerid],180,"Damage -%d",damage);
// GameTextForPlayer(playerid, string3[playerid], 1000, 1);
PlayerPlaySound(playerid, 6401, 0.0, 0.0, 0.0);
}
}
return true;
}
createzombie(playerid) // ориентация на место положение игрока и его Angle
{
new Float:pX,Float:pY,Float:pZ,Float:Ang;
GetPlayerPos(playerid,pX,pY,pZ);
GetPlayerFacingAngle(playerid,Ang);
pX=pX+3.0*floatsin(-Ang,degrees);
pY=pY+3.0*floatcos(-Ang,degrees);
pZ=pZ+0.7;
return CrearZombie(pX,pY,pZ,Ang+180.0);
}
CrearZombie(Float:pX,Float:pY,Float:pZ,Float:angle)
{
if (getmaxzombies() <MAX_ZOMBIES)
{
for (new j=0;j<MAX_ZOMBIES;j++)
{
if(usedzombi[j] == 0)
{
zhealth[j] = 100;
usedzombi[j] =1;
new Float:PEPE = floatsin((angle*3.14159/180.0));
new Float:PIPO = floatcos((angle*3.14159/180.0));
for (new i=0;i<6;i++)
{
zombie[j][i]=CreateObject(z11[i][partModel],pX+z11[i][RelX]*PIPO+PEPE*z21[i][RelX],pY+z11[i][RelY]*PIPO+PEPE*z21[i][RelY],pZ+z21[i][RelZ],z11[i][RelrX],z11[i][RelrY],angle);
}
AttachObjectToObject(zombie[j][5],zombie[j][4],0.01, 1.3, 0.09, 0, 0, 0);
AttachObjectToObject(zombie[j][3],zombie[j][4],-0.1 ,0.25,0.15, 0, 270, 90);
AttachObjectToObject(zombie[j][2],zombie[j][4],0.05, 0.55, -0.032, 0, 270, 0);
AttachObjectToObject(zombie[j][1],zombie[j][4],-0.15, 0.25, -0.19, 0, 90, 90);
AttachObjectToObject(zombie[j][0],zombie[j][4],0, 1.30, -0.10, 0, 0, 0);
break;
}
}
}
return 1;
}
IsThisAZombie2(object)
{
for (new j=0;j< getmaxzombieid();j++)
{
if(usedzombi[j] != 1)continue;
for (new i=0;i<6;i++)
{
if(object == zombie[j][i]) return j;
}
}
return -1;
}
IsThisAZombie2(object)
{
for (new j=0;j< getmaxzombieid();j++)
{
if(usedzombi[j] != 1)continue;
for (new i=0;i<6;i++)
{
if(object == zombie[j][i]) return j;
}
}
return -1;
}
Headshot(zombieid,objectid)
{
if(objectid == zombie[zombieid][4]) return true;
return false;
}
-Не увидел решения если НПС движется из точки в точку Б а между ними обрыв. |
-Любят сливаться в одного. |
if ( (floatabs(pX3-X8) + floatabs(pY3-Y8) + floatabs(pZ3-Z8) )<2.5) { if( j != proveren) { rand2 = random(4); rand3 = random(3); switch(rand2) { case 0:pX-=rand3; case 1:pX+=rand3; case 2:pY-=rand3; case 3:pY+=rand3; } } } proveren = j; |
-Зомби всегда бежит за близжайшим игроком. Ннт разделения. 10 игроков заставят одного к ним подойти и пока НПС бегут за ним то будут их расстреливать. |
-Объекты по мере приближения всегда поворачиваются и ложатся. |
-Зачем всегда пересоздавать объекты? |
Вся проблема в том что не существует функции SetObjectFacingAngle |
- Максимальное количество с стримером: 334 |
Смысл тогда вообще в таких зомби? 300 слотов не много, можно и плагином воспользоваться, по функциональней будет.
|
Здесь сидят люди которые не ленятся изучать то с чем работают и внимательно читать документацию, а те кто в упор не хотят этого делать обычно получают очень много негативных комментариев и просто предпочитают не оставаться тут. |
GetClosestPlay(objectid) {
new Float:min_dis = 99999.99,
Float:player_dis,
player = INVALID_PLAYER_ID;
new Float:object_x, Float:object_y, Float:object_z, Float:temp_z;
GetObjectPos(objectid, object_x, object_y, object_z);
MapAndreas_FindZ_For2DCoord(object_x, object_y, temp_z);
if (object_z > temp_z + 2.0 || object_z < temp_z) {
SetObjectPos(objectid, object_x, object_y, (object_z = temp_z + 2.0)));
}
foreach (new playerid : Player)
{
if (GetPlayerState(playerid) == PLAYER_STATE_SPECTATING) continue;
if (GetPlayerInterior(playerid) || Isahitman(playerid)) continue; // Обрати внимание какой вид имеют стандартные функции!
if (!ISAZOMBIESPAWN(playerid) && !zombiespawn2(playerid)) continue; // А где сами функции и почему имена у них разные? И предыдущий комментарий сюда применим.
player_dis = GetPlayerDistanceFromPoint(playerid, object_x, object_y, object_z);
if (player_dis < min_dis) {
min_dis = player_dis;
player = playerid;
}
}
return player;
}
Да ты прав,но разве зомби в фильмах себя так же не ведут? Или стоит сделать проверку на афк ли игрок и сколько зомби за ним гонются?
|
Пара вопросов:
1. Почему не использовать однобуквенные переменные? 2. if (GetPlayerInterior(playerid)) Тут разве не проверка на равен ли GetPlayerInterior(playerid) одному? |