Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Author: Tab10id
- #include "_macros.fos"
- #define WALK_PERIOD (REAL_SECOND(Random(8,18)))
- #define MAXDIST (8) // Максимальное расстояние от HomePos
- #define MAXDISTEXT (3) // Максимальное расстояние, на которое может отойти криттер за один раз
- #define MAXTRY (10) // Количество попыток найти новую точку назначения
- import bool AddWalkPlane(Critter& npc, uint priority, uint16 hexX, uint16 hexY, uint8 dir, bool run, uint cut) from "npc_planes";
- void _CritInit(Critter& crit, bool firstTime)
- {
- uint8 run=0;
- InitWalkRandom(crit, run);
- crit.ModeBase[MODE_NO_HOME]=1; // Отменяем возвращение игрока на HomePos
- crit.SetEvent(CRITTER_EVENT_TALK,"_NpcTalk"); // Обрабатываем попытку игрока заговорить с нпц
- crit.SetEvent(CRITTER_EVENT_PLANE_END,"_PlaneEnd"); // Создаем новое событие для передвижения нпц (нпц дошел до точки назначения)
- crit.SetEvent(CRITTER_EVENT_RESPAWN,"_InitWalk"); // Возобновляем движение после респа
- crit.SetEvent(CRITTER_EVENT_DEAD,"_OnDead"); // Отменяем попытку передвижения, в случае смерти нпц
- }
- void InitWalkRandom(Critter& crit, uint8 run)
- {
- if(crit.IsDead())
- {
- return;
- }
- EraseTE(crit);
- crit.AddTimeEvent("cte_WalkRandom",WALK_PERIOD,CTE_WALK_RANDOM,run);
- }
- uint cte_WalkRandom(Critter& crit, int identifier, uint& run)
- {
- int incr=0; // Для избегания зацикливания в случае заблокированного пути
- if(!valid(crit))
- {
- return 0;
- }
- if(crit.IsDead())
- {
- return 0;
- }
- Map@ map=crit.GetMap();
- if(!valid(map))
- {
- return 0;
- }
- bool brun = false;
- uint16 x, y, homeX=0, homeY=0, homeM=0, homeD=0;
- uint8 dir;
- crit.GetHomePos(homeM,homeX,homeY,homeD);
- if(run==1)
- {
- brun = true;
- }
- if((int(crit.HexX)<int(homeX)-MAXDIST) or (int(crit.HexX)>int(homeX)+MAXDIST) or (int(crit.HexY)<int(homeY)-MAXDIST) or (int(crit.HexY)>int(homeY)+MAXDIST))
- {
- crit.ModeBase[MODE_NO_HOME]=0; // Заставляем нпц вернуться на HomePos, если он каким-то образом отошел от нее далеко (например, в результате атаки)
- }
- else
- {
- do
- {
- do
- {
- x=crit.HexX+Random(-MAXDISTEXT,MAXDISTEXT);
- }
- while((x>homeX+MAXDIST) or (x<homeX-MAXDIST));
- do
- {
- y=crit.HexY+Random(-MAXDISTEXT,MAXDISTEXT);
- }
- while((y>homeY+MAXDIST) or (y<homeY-MAXDIST));
- incr++;
- }
- while(((map.GetPathLength(crit.HexX,crit.HexY,x,y,0)==0) or (map.GetPathLength(crit.HexX,crit.HexY,x,y,0)>MAXDISTEXT)) and (incr<MAXTRY)); // Пытаемся найти новую точку назначения
- if(incr<MAXTRY)
- {
- dir=GetDirection(crit.HexX,crit.HexY,x,y);
- AddWalkPlane(crit, AI_PLANE_WALK_PRIORITY, x, y, dir, brun, 0);
- }
- else
- {
- StartWalkRandom(crit);
- }
- }
- return 0;
- }
- bool _NpcTalk(Critter& crit, Critter& player, bool attach, uint talkCount)
- {
- if(attach)
- {
- CancelWalkRandom(crit); // Отменяем все планы на передвижения
- crit.SetDir(GetDirection(crit.HexX,crit.HexY,player.HexX,player.HexY)); // Поворачиваемся лицом к игроку
- }
- else
- {
- StartWalkRandom(crit); // Возобновляем движение
- }
- return true;
- }
- void StartWalkRandom(Critter& crit)
- {
- uint8 run=0;
- /* if(crit.ModeBase[MODE_RUN_RANDOM]==1)
- {
- run=1;
- }*/
- if(crit.Mode[MODE_NO_HOME]==0)
- {
- crit.ModeBase[MODE_NO_HOME]=1;
- }
- InitWalkRandom(crit, run);
- }
- void CancelWalkRandom(Critter& crit)
- {
- _NpcEraseAllPlanesWalk(crit);
- EraseTE(crit);
- }
- int _PlaneEnd(Critter& crit, NpcPlane& plane, int reason, Critter@ someCr, Item@ someItem)
- {
- StartWalkRandom(crit); // Возобновляем движение
- return PLANE_RUN_GLOBAL;
- }
- void _InitWalk(Critter& crit)
- {
- uint8 run=0;
- /*if(crit.ModeBase[MODE_RUN_RANDOM]==1)
- {
- run=1;
- }*/
- InitWalkRandom(crit, run); // Возобновляем движение
- }
- void _OnDead(Critter& crit, Critter@ killer)
- {
- EraseTE(crit);
- }
- void EraseTE(Critter& crit)
- {
- uint[] rates,durations,indexes;
- uint count=crit.GetTimeEvents(CTE_WALK_RANDOM,indexes,durations, rates);
- if(count!=0)
- {
- crit.EraseTimeEvents(CTE_WALK_RANDOM);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement