#include #include #include #include #include #include #define MAX_SPAWN 255 #define MAX_WAYPOINT 500 #define MAX_WAY 20 // Custom Pointer Entity Value new pev_iAlive = pev_iuser1 new pev_iMoveIncrease = pev_iuser2 new pev_MoveToWayPoint = pev_iuser3 new pev_iCurrentWay = pev_iuser4 new pev_fThinkTime = pev_fuser1 new pev_fPreviousAttack = pev_fuser2 new pev_fIsNpc = pev_fuser3 new pev_fDuckState = pev_fuser4 new pev_LastPosition = pev_vuser1 // Size new Float:VEC_HUMAN_HULL_MIN[3] = { -16.0, -16.0, 0.0 } new Float:VEC_HUMAN_HULL_MAX[3] = { 16.0, 16.0, 72.0} // For Spawning NPC new Float:g_SpawnPoint[MAX_SPAWN][3], Float:g_Angles[MAX_SPAWN][3], Float:g_vAngles[MAX_SPAWN][3] new g_SpawnCount // NPC Custom Value new iNpcModelIndex new iNpcHam // Waypoints new iWaypointCount[MAX_WAY] new Float:g_WaypointOrigin[MAX_WAY][MAX_WAYPOINT][3] new iCurrentWay // NPC's Info new NPC_iSPEED = 150 new Float:NPC_fHEALTH = 100.0 new Float:NPC_fGRAVITY = 1.0 new NPC_CLASSNAME[] = "npc_" new NPC_MODEL[] = "models/bot_light.mdl" new NPC_MOVE_ANIMATION = 6 new NPC_ATTACK_ANIMATION = 2 new NPC_IDLE_ANIMATION = 1 new NPC_CROUCH_IDLE = 3 new NPC_CROUCH_ATTACK = 4 new Float:NPC_ATTACK_TIME = 1.84 new Float:NPC_EYE = 60.0 new Float:NPC_DAMAGE_MIN = 40.0 new Float:NPC_DAMAGE_MAX = 70.0 new NPC_ACCURACY = 40 new bool:bIsConnected[64] public plugin_init() { register_plugin("NPC Plugin", "1.0", "Nguyen Duy Linh") register_concmd("CreateNpc", "clcmd_npc"); register_concmd("NpcSetSpawnPoint", "_NpcSetSpawnPointCmd") register_concmd("NpcSetWayPoint", "_NpcSetWayPointCmd") register_concmd("NpcSelectWay", "_CmdSelectAWay") iNpcModelIndex = engfunc(EngFunc_PrecacheModel, NPC_MODEL) } public client_putinserver(id) bIsConnected[id] = true public client_disconnect(id) bIsConnected[id] = false public _NpcSetWayPointCmd(id) { if (iWaypointCount[iCurrentWay] > MAX_WAYPOINT - 1) return pev(id, pev_origin, g_WaypointOrigin[iCurrentWay][iWaypointCount[iCurrentWay]]) iWaypointCount[iCurrentWay]++ } public _NpcSetSpawnPointCmd(id) { if (g_SpawnCount >= MAX_SPAWN) return pev(id, pev_origin, g_SpawnPoint[g_SpawnCount]) pev(id, pev_angles, g_Angles[g_SpawnCount]) g_Angles[g_SpawnCount][2] = 0.0 pev(id, pev_v_angle, g_vAngles[g_SpawnCount]) g_vAngles[g_SpawnCount][2] = 0.0 g_SpawnCount++ } public _CmdSelectAWay(id, level, cid) { if (!cmd_access(id, level, cid, 2)) return new fArg[3] read_argv(1, fArg, 3) new iWay = str_to_num(fArg) if (iWay < 0 || iWay > MAX_WAY - 1) return iCurrentWay = iWay client_print(id, print_center, "Selected way %d", iWay) } public clcmd_npc(id) { for (new i = 0; i < g_SpawnCount; i++) { new ent = create_entity("info_target"); entity_set_origin(ent, g_SpawnPoint[i]) set_pev(ent, pev_angles, g_Angles[i]) set_pev(ent, pev_v_angle, g_vAngles[i]) set_pev(ent, pev_classname, NPC_CLASSNAME) entity_set_float(ent, EV_FL_takedamage, 1.0); entity_set_float(ent, EV_FL_health, NPC_fHEALTH); entity_set_model(ent, NPC_MODEL) entity_set_int(ent, EV_INT_movetype, MOVETYPE_STEP); entity_set_int(ent, EV_INT_solid, SOLID_SLIDEBOX); entity_set_size(ent, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX) set_pev(ent, pev_gravity, 1.0) set_pev(ent, pev_enemy, -1) set_pev(ent, pev_iAlive, 1) set_pev(ent, pev_MoveToWayPoint, -1) set_pev(ent, pev_iMoveIncrease, 1) set_pev(ent, pev_iCurrentWay, -1) set_pev(ent, pev_modelindex, iNpcModelIndex) new Float:fCurrentTime = get_gametime() set_pev(ent, pev_animtime, fCurrentTime); set_pev(ent, pev_framerate, 1.0); set_pev(ent, pev_frame, 0.0) set_pev(ent, pev_fPreviousAttack, fCurrentTime) set_pev(ent, pev_fIsNpc, 1.0) set_pev(ent, pev_gravity, NPC_fGRAVITY) set_pev(ent, pev_LastPosition, g_SpawnPoint[i]) set_pev(ent, pev_fThinkTime, fCurrentTime) if (!iNpcHam) { RegisterHamFromEntity(Ham_TakeDamage, ent, "npc_TakeDamage"); RegisterHamFromEntity(Ham_Killed, ent, "npc_Killed", 1); RegisterHamFromEntity(Ham_Think, ent, "npc_Think"); RegisterHamFromEntity(Ham_TraceAttack, ent, "npc_TraceAttack"); iNpcHam = 1 } drop_to_floor(ent); entity_set_float(ent, EV_FL_nextthink, get_gametime() + 0.1) } } public npc_TakeDamage(iEnt, inflictor, attacker, Float:damage, bits) { } public npc_Killed(iEnt) { set_pev(iEnt, pev_nextthink, get_gametime() + 4.0) set_pev(iEnt, pev_iAlive, 0) } public npc_TraceAttack(iEnt, attacker, Float: damage, Float: direction[3], trace, damageBits) { } public npc_Think(iEnt) { new Float:fCurrentTime = get_gametime() if (!pev_valid(iEnt)) return if (!(pev(iEnt, pev_flags) & FL_ONGROUND)) { set_pev(iEnt, pev_nextthink, fCurrentTime + 0.1) return } new iAlive = pev(iEnt, pev_iAlive) if (!iAlive) { remove_entity(iEnt) return } // Get current position new Float:fOrigin[3] pev(iEnt, pev_origin, fOrigin) new iMoveToWayPoint = pev(iEnt, pev_MoveToWayPoint) new iMoveIncreased = pev(iEnt, pev_iMoveIncrease) new iMyCurrentWay = pev(iEnt, pev_iCurrentWay) new iTarget = pev(iEnt, pev_enemy) if (!IsValidTarget(iTarget)) // Not a valid Target or NPC cant see it's target .... { // Try to find iTarget = NpcFindClosestEnemy(iEnt) if (!IsValidTarget(iTarget)) // Not valid target again????? { new Float:fThinkTime pev(iEnt, pev_fThinkTime, fThinkTime) if (fCurrentTime - fThinkTime >= 0.75) { new Float:fLastPosition[3] pev(iEnt, pev_LastPosition, fLastPosition) if (vector_distance(fLastPosition, fOrigin) <= 50.0) { NpcStop(iEnt) NpcFindWay(iEnt, fOrigin, NPC_iSPEED) } set_pev(iEnt, pev_fThinkTime, fCurrentTime) set_pev(iEnt, pev_LastPosition, fOrigin) set_pev(iEnt, pev_nextthink, fCurrentTime + 0.1) return } // If the NPC doesn't have anywhere to go, it HAS TO take a random point to move set_pev(iEnt, pev_enemy, -1) // Set the Target to -1 if (iMoveToWayPoint < 0 || iMyCurrentWay < 0) // Nowhere to go - Take Random Point Npc_TakeRandomPoint(iEnt) else { new bool:bCompleted = NPC_CompleteMove(iEnt, iMyCurrentWay, iMoveToWayPoint) if (!bCompleted) // I've not been there yet ! - Keep moving ! { if (!NpcCanSee(fOrigin, g_WaypointOrigin[iMyCurrentWay][iMoveToWayPoint]) || NPC_BlockedWay(iEnt)) { NpcStop(iEnt) NpcFindWay(iEnt, fOrigin, NPC_iSPEED) set_pev(iEnt, pev_MoveToWayPoint, -1) set_pev(iEnt, pev_nextthink, fCurrentTime + 0.1) return } else NpcMove(iEnt, fOrigin, g_WaypointOrigin[iMyCurrentWay][iMoveToWayPoint], NPC_iSPEED) } else { NpcStop(iEnt) if (iMoveIncreased) { iMoveToWayPoint += 1 if (iMoveToWayPoint > iWaypointCount[iMyCurrentWay] - 1) // Reach the last WayPoint? { new iComeToAnotherWayPoint = random_num(1, 10) if (iComeToAnotherWayPoint == 5) // NPC can change the way? { new iPoint, iReturnWay new iResult = GetNearestPointEx(fOrigin, iMyCurrentWay, iPoint, iReturnWay) if (iResult) { NpcMove(iEnt, fOrigin, g_WaypointOrigin[iReturnWay][iPoint], NPC_iSPEED) set_pev(iEnt, pev_nextthink, fCurrentTime + 0.1) return } } if (!NpcCanSee(fOrigin, g_WaypointOrigin[iMyCurrentWay][0])) { iMoveToWayPoint -= 2 iMoveIncreased = 0 } else iMoveToWayPoint = 0 set_pev(iEnt, pev_iMoveIncrease, iMoveIncreased) set_pev(iEnt, pev_MoveToWayPoint, iMoveToWayPoint) set_pev(iEnt, pev_nextthink, fCurrentTime + 0.1) return } else set_pev(iEnt, pev_MoveToWayPoint, iMoveToWayPoint) } else { iMoveToWayPoint -= 1 if (iMoveToWayPoint < 0) { new iNewWayPoint = iWaypointCount[iWaypointCount[iMyCurrentWay]] if (!NpcCanSee(fOrigin, g_WaypointOrigin[iMyCurrentWay][iNewWayPoint])) { iMoveToWayPoint += 2 iMoveIncreased = 1 } else iMoveToWayPoint = iNewWayPoint set_pev(iEnt, pev_iMoveIncrease, iMoveIncreased) set_pev(iEnt, pev_MoveToWayPoint, iMoveToWayPoint) set_pev(iEnt, pev_nextthink, fCurrentTime + 0.1) return } else set_pev(iEnt, pev_MoveToWayPoint, iMoveToWayPoint) } } } set_pev(iEnt, pev_nextthink, fCurrentTime + 0.1) return } else // Oh, NPC can see it's enemy now ! - What should it do ? { new Float:TargetOrigin[3] pev(iTarget, pev_origin, TargetOrigin) if (!NpcAlreadyStop(iEnt)) { set_pev(iEnt, pev_MoveToWayPoint, -1) NpcStop(iEnt) } if (!IsNpcCrouching(iEnt)) { if (NpcCrouchCanSee(iEnt, TargetOrigin)) { set_pev(iEnt, pev_fDuckState, 1.0) set_pev(iEnt, pev_sequence, NPC_CROUCH_IDLE) } } NPC_TurnToTarget(iEnt, iTarget) new iAttackResult = NPC_Attack(iEnt) if (iAttackResult) NPC_ShootAccurate(iEnt, iTarget) set_pev(iEnt, pev_nextthink, fCurrentTime + 0.1) return } } else { if (!NpcAlreadyStop(iEnt)) { set_pev(iEnt, pev_MoveToWayPoint, -1) NpcStop(iEnt) } new Float:TargetOrigin[3] pev(iEnt, pev_origin, TargetOrigin) if (!IsNpcCrouching(iEnt)) { if (NpcCrouchCanSee(iEnt, TargetOrigin)) { set_pev(iEnt, pev_fDuckState, 1.0) set_pev(iEnt, pev_sequence, NPC_CROUCH_IDLE) } } NPC_TurnToTarget(iEnt, iTarget) new iAttackResult = NPC_Attack(iEnt) if (iAttackResult) NPC_ShootAccurate(iEnt, iTarget) set_pev(iEnt, pev_nextthink, fCurrentTime + 0.1) return } set_pev(iEnt, pev_nextthink, fCurrentTime + 0.1) return } bool:can_see_fm(entindex1, entindex2) { if (!entindex1 || !entindex2) return false if (pev_valid(entindex1) && pev_valid(entindex1)) { new flags = pev(entindex1, pev_flags) if (flags & EF_NODRAW || flags & FL_NOTARGET) { return false } new Float:lookerOrig[3] new Float:targetBaseOrig[3] new Float:targetOrig[3] new Float:temp[3] pev(entindex1, pev_origin, lookerOrig) pev(entindex1, pev_view_ofs, temp) lookerOrig[0] += temp[0] lookerOrig[1] += temp[1] //if (IsEntNPC(entindex1)) //lookerOrig[2] += temp[2] + NPC_EYE lookerOrig[2] += temp[2] pev(entindex2, pev_origin, targetBaseOrig) pev(entindex2, pev_view_ofs, temp) targetOrig[0] = targetBaseOrig [0] + temp[0] targetOrig[1] = targetBaseOrig [1] + temp[1] targetOrig[2] = targetBaseOrig [2] + temp[2] engfunc(EngFunc_TraceLine, lookerOrig, targetOrig, 0, entindex1, 0) // checks the had of seen player if (get_tr2(0, TraceResult:TR_InOpen) && get_tr2(0, TraceResult:TR_InWater)) { return false } else { new Float:flFraction get_tr2(0, TraceResult:TR_flFraction, flFraction) if (flFraction == 1.0 || (get_tr2(0, TraceResult:TR_pHit) == entindex2)) { return true } else { targetOrig[0] = targetBaseOrig [0] targetOrig[1] = targetBaseOrig [1] targetOrig[2] = targetBaseOrig [2] engfunc(EngFunc_TraceLine, lookerOrig, targetOrig, 0, entindex1, 0) // checks the body of seen player get_tr2(0, TraceResult:TR_flFraction, flFraction) if (flFraction == 1.0 || (get_tr2(0, TraceResult:TR_pHit) == entindex2)) { return true } else { targetOrig[0] = targetBaseOrig [0] targetOrig[1] = targetBaseOrig [1] targetOrig[2] = targetBaseOrig [2] - 17.0 engfunc(EngFunc_TraceLine, lookerOrig, targetOrig, 0, entindex1, 0) // checks the legs of seen player get_tr2(0, TraceResult:TR_flFraction, flFraction) if (flFraction == 1.0 || (get_tr2(0, TraceResult:TR_pHit) == entindex2)) { return true } } } } } return false } stock make_dot(vec[3]) { message_begin( MSG_BROADCAST,SVC_TEMPENTITY) write_byte( 17 ) write_coord(vec[0]) write_coord(vec[1]) write_coord(vec[2]) write_short( dot ) write_byte( 10 ) write_byte( 255 ) message_end() } stock NpcFindWay(entid,Float:fOri[3], iSpeed) { new Float:vTrace[3],Float:vTraceEnd[3],Float:hitOri[3],Float:Vel[3],Float:angle[3] // set a entPos to trace a line velocity_by_aim(entid, 64, vTrace) vTraceEnd[0] = vTrace[0] + fOri[0] vTraceEnd[1] = vTrace[1] + fOri[1] vTraceEnd[2] = vTrace[2] + fOri[2]+25 new hitent=trace_line(entid, fOri, vTraceEnd, hitOri) new Float:gdis=vector_distance(fOri,hitOri) //set another entPos to trace another line velocity_by_aim(entid, 45, vTrace) vTraceEnd[0] = vTrace[0] + fOri[0] vTraceEnd[1] = vTrace[1] + fOri[1] vTraceEnd[2] = vTrace[2] + fOri[2]-45// lower than first dot trace_line(entid, fOri, vTraceEnd, hitOri) new Float:gdis2=vector_distance(fOri,hitOri) /*if( gdis2<43 ){ entity_get_vector(entid,EV_VEC_origin,fOri) fOri[2]+=5 entity_set_vector(entid,EV_VEC_origin,fOri) }*/ entity_get_vector(entid,EV_VEC_velocity,Vel) if( hitent || gdis<60 ){ //stop NpcStop(entid) //turn random angle entity_get_vector(entid,EV_VEC_v_angle,angle) new Float:fnum=random_float(-90.0,90.0) angle[1]+=fnum //angle[1]+=90.0 entity_set_vector(entid,EV_VEC_v_angle,angle) return } if( Vel[0]==0.0 || Vel[1]==0.0 ){ VelocityByAim(entid,iSpeed,Vel) Vel[2]=0.0 vector_to_angle(Vel,angle) entity_set_vector(entid,EV_VEC_angles,angle) entity_set_vector(entid,EV_VEC_velocity,Vel) entity_set_int(entid,EV_INT_sequence, NPC_MOVE_ANIMATION) } } stock DirectedVec(Float:start[3],Float:end[3],Float:reOri[3]) { //-------code from Hydralisk's 'Admin Advantage'-------// new Float:v3[3] v3[0]=start[0]-end[0] v3[1]=start[1]-end[1] v3[2]=start[2]-end[2] new Float:vl = vector_length(v3) reOri[0] = v3[0] / vl reOri[1] = v3[1] / vl reOri[2] = v3[2] / vl } stock NpcCanSee(Float:ent_origin[3], Float:target_origin[3]) { new Float:hit_origin[3] trace_line(-1, ent_origin, target_origin, hit_origin) if (!vector_distance(hit_origin, target_origin)) return 1; return 0; } stock NpcMove(iEnt, Float:fOrigin[3], Float:fDestination[3], iSpeed) { new Float:fFixOrigin[3], Float:fAngles[3] DirectedVec(fDestination, fOrigin, fFixOrigin) fFixOrigin[2] = 0.0 vector_to_angle(fFixOrigin, fAngles) set_pev(iEnt, pev_angles, fAngles) set_pev(iEnt, pev_v_angle, fAngles) VelocityByAim(iEnt, iSpeed, fFixOrigin) fFixOrigin[2] = 0.0 set_pev(iEnt, pev_velocity, fFixOrigin) set_pev(iEnt, pev_sequence, NPC_MOVE_ANIMATION) set_pev(iEnt, pev_fDuckState, 0.0) } stock NpcFindClosestEnemy(entid) { new Float:Dist new Float:maxdistance=4000.0 new indexid=0 //new Float:fEntOrigin[3] //pev(entid, pev_origin, fEntOrigin) for(new i=1;i<=get_maxplayers();i++) { if(is_user_alive(i) && is_valid_ent(i)) { new Float:fOrigin[3] pev(i, pev_origin, fOrigin) if (!can_see_fm(entid, i)) continue Dist = entity_range(entid,i) if(Dist <= maxdistance) { maxdistance=Dist indexid=i } } } return indexid } stock NpcStop(entid) { new Float:Vel[3] Vel[0]=0.0 Vel[1]=0.0 Vel[2]=0.0 entity_set_vector(entid,EV_VEC_velocity,Vel) set_pev(entid, pev_sequence, NPC_IDLE_ANIMATION) } stock bool:NpcAlreadyStop(iEnt) { new Float:fVel[3] pev(iEnt, pev_velocity, fVel) if (fVel[0] == 0.0 && fVel[1] == 0.0 && fVel[2] == 0.0) return true return false } stock NPCGetNearestWaypoint(iEnt, &iWay, &iPoint) { new Float:fOrigin[3] pev(iEnt, pev_origin, fOrigin) new Float:fDistanceMin = vector_distance(fOrigin, g_WaypointOrigin[0][0]) new iReturn = 0 for (new i = 0; i < MAX_WAY; i++) { if (!iWaypointCount[i]) continue for (new j = 0; j < iWaypointCount[i]; j++) { if (!NpcCanSee(fOrigin, g_WaypointOrigin[i][j])) continue new Float:fDistance = vector_distance(fOrigin, g_WaypointOrigin[i][j]) if (fDistance < fDistanceMin) { iWay = i iPoint = j iReturn++ } } } return iReturn } stock bool:NPC_CompleteMove(iEnt, iWay, iPoint) { new Float:fDistanceToStop = 50.0 new Float:fOrigin[3] pev(iEnt, pev_origin, fOrigin) new tr_result new Float:fVecEndPos[3] engfunc(EngFunc_TraceLine, fOrigin, g_WaypointOrigin[iWay][iPoint], DONT_IGNORE_MONSTERS, iEnt, tr_result) get_tr2(tr_result, TR_vecEndPos, fVecEndPos) new Float:fDistance, Float:sDistance fDistance = vector_distance(fOrigin, g_WaypointOrigin[iWay][iPoint]) sDistance = vector_distance(fOrigin, fVecEndPos) if (fDistance <= fDistanceToStop || sDistance <= fDistanceToStop) return true return false } stock Npc_TakeRandomPoint(iEnt) { new iWay, iPoint NPCGetNearestWaypoint(iEnt, iWay, iPoint) set_pev(iEnt, pev_MoveToWayPoint, iPoint) set_pev(iEnt, pev_iCurrentWay, iWay) } stock bool:IsValidTarget(iTarget) { if (!iTarget || !(1<= iTarget <= get_maxplayers()) || !bIsConnected[iTarget] || !is_user_alive(iTarget)) return false return true } stock GetNearestPoint(Float:fOrigin[3], iWay, iPoint) { new Float:fMinDistance = vector_distance(fOrigin, g_WaypointOrigin[iWay][0]) new iReturn = 0 for (new i = 1 ; i < iWaypointCount[iWay]; i++) { if (i == iPoint) continue if (!NpcCanSee(fOrigin, g_WaypointOrigin[iWay][i])) continue new Float:fDistance = vector_distance(fOrigin, g_WaypointOrigin[iWay][i]) if (fDistance < fMinDistance) iReturn = i } return iReturn } stock GetNearestPointEx(Float:fOrigin[3], iWay, &iPoint, &iReturnWay) { new iReturn = 0 new iWayGetValue = 0 new Float:fMinDistance new iPrePoint, iPreWay for (new i = 0 ; i < MAX_WAY; i++) { if (i == iWay) continue for (new j = 0; j < iWaypointCount[i]; j++) { if (!NpcCanSee(fOrigin, g_WaypointOrigin[i][j])) continue if (!iWayGetValue) { fMinDistance = vector_distance(fOrigin, g_WaypointOrigin[i][j]) iWayGetValue = 1 } new Float:fDistance = vector_distance(fOrigin, g_WaypointOrigin[iWay][i]) if (fDistance < fMinDistance) { iReturn++ iPrePoint = j iPreWay = i } } } iPoint = iPrePoint iReturnWay = iPreWay return iReturn } stock bool:fm_is_in_viewcone(index, const Float:point[3]) { new Float:angles[3]; pev(index, pev_angles, angles); engfunc(EngFunc_MakeVectors, angles); global_get(glb_v_forward, angles); angles[2] = 0.0; new Float:origin[3], Float:diff[3], Float:norm[3]; pev(index, pev_origin, origin); xs_vec_sub(point, origin, diff); diff[2] = 0.0; xs_vec_normalize(diff, norm); new Float:dot, Float:fov; dot = xs_vec_dot(norm, angles); pev(index, pev_fov, fov); if (dot >= floatcos(fov * M_PI / 360)) return true; return false; } stock NPC_Attack(iEnt) { new Float:fPreviousAttack pev(iEnt, pev_fPreviousAttack, fPreviousAttack) new Float:fCurrentTime = get_gametime() if (fCurrentTime - fPreviousAttack >= NPC_ATTACK_TIME) { if (!IsNpcCrouching(iEnt)) set_pev(iEnt, pev_sequence, NPC_ATTACK_ANIMATION) else set_pev(iEnt, pev_sequence, NPC_CROUCH_ATTACK) set_pev(iEnt, pev_fPreviousAttack, fCurrentTime) return 1 } return 0 } stock NPC_ShootAccurate(iEnt, iTarget) { new iRandom = random(100) if (0 < iRandom < NPC_ACCURACY) { new Float:fTmpDmg = random_float(NPC_DAMAGE_MIN, NPC_DAMAGE_MAX) ExecuteHamB(Ham_TakeDamage, iTarget, iEnt, iEnt, fTmpDmg, DMG_BULLET) } } stock IsEntNPC(iEnt) { if (!pev_valid(iEnt)) return 0 new Float:fState pev(iEnt, pev_fIsNpc, fState) if (fState) return 1 return 0 } stock bool:NpcCrouchCanSee(iEnt, Float:TargetOrigin[3]) { new Float:fOrigin[3] pev(iEnt, pev_origin, fOrigin) fOrigin[2] += NPC_EYE fOrigin[2] *= 0.75 if (NpcCanSee(fOrigin, TargetOrigin)) return true return false } stock bool:IsNpcCrouching(iEnt) { if (!IsEntNPC(iEnt)) return false new Float:fState pev(iEnt, pev_fDuckState, fState) if (fState) return true return false } stock NPC_TurnToTarget(iEnt, iTarget) { new Float:fFixedOrigin[3], Float:fOrigin[3], Float:TargetOrigin[3], Float:fAngles[3] pev(iEnt, pev_origin, fOrigin) pev(iTarget, pev_origin, TargetOrigin) DirectedVec(TargetOrigin,fOrigin,fFixedOrigin) fFixedOrigin[2]=0.0 vector_to_angle(fFixedOrigin,fAngles) set_pev(iEnt,pev_angles,fAngles) } stock NPC_BlockedWay(iEnt) { new Float:fOrigin[3] pev(iEnt, pev_origin, fOrigin) for (new i = 0; i < entity_count(); i++) { if (!pev_valid(i)) continue if (IsEntNPC(i) && i != iEnt) { new Float:fTargetDistance[3] pev(i, pev_origin, fTargetDistance) if (vector_distance(fOrigin, fTargetDistance) <= 80.0) // The checking NPC is being blocked by another return 1 } } return 0 } /* AMXX-Studio Notes - DO NOT MODIFY BELOW HERE *{\\ rtf1\\ ansi\\ deff0{\\ fonttbl{\\ f0\\ fnil Tahoma;}}\n\\ viewkind4\\ uc1\\ pard\\ lang1034\\ f0\\ fs16 \n\\ par } */