【教程】【NPC】【AI-Walker】配合aiwalker创建一个NPC 新手教程
例子在此#include <amxmodx>
#include <amxmisc>
#include <aiwalker>
#include <fakemeta_util>
#include <fakemeta>
#include <engine>
#include <hamsandwich>
#define PLUGIN_NAME"LB‘s NPC"
#define PLUGIN_VERSION"1.0"
#define PLUGIN_AUTHOR"LB"
new g_szmodel[] = { "models/ai/normal_zombie.mdl" }//模型路径
new g_modelid
new g_fTime
public plugin_init()
{
register_plugin(PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_AUTHOR)
register_forward(FM_StartFrame, "fw_StartFrame_Post", 1)//fakemeta
register_clcmd("say /t","te")//创建NPC的命令
}
public plugin_precache()
{
g_modelid = precache_model(g_szmodel)
}
public te(id)
{
new Float<img src="static/image/smiley/default/shocked.gif" border="0" smilieid="6" alt=":o">rigin
new Float:g_fTime = 0.0
pev(id, pev_origin, origin)
origin += 40.0
for(new i=1;i<=40;i++)
{
new ientity = CreateAi(origin, "sb", g_modelid, { -16.0, -10.0, -36.0 }, { 16.0, 10.0, 36.0 }, 200.0, 200.0, 0.1, 5.0, 75.0, 6.0, 0.01, 2.0, 3)//NPC属性(例:生命,速度,详情见下面INC)
SetAiAnim(ientity, 0, 2, 3, 4, { 5, 6, 7 })//NPC模型动作(不懂就用小飞本来的僵尸模型,然后这个直接复制)
}
}
public fw_StartFrame_Post()
{
if (get_gametime() - g_fTime > 2.0)
{
g_fTime = get_gametime()
}
}
源码完
以下节选自AI-Walker.inc
{
/*
以下是自定义pev,只是为了用起来方便,用原来的pev值也无所谓
AI静止动作:pev_idle
AI移动动作:pev_move
AI跳跃动作:pev_jump
AI攻击动作:pev_attack
AI死亡动作:pev_die
AI名字:pev_ainame
AI最大生命:pev_max_health
AI最大速度:pev_maxspeed
AI重力:pev_gravity
AI队伍:pev_team
AI攻击伤害:pev_damage
AI攻击范围:pev_distance
AI攻击速度:pev_attackrate
AI反应时间:pev_thinkrate
AI播放死亡动作的时间:pev_dyingtime
*/
/*以下是数据接口---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
//获取该实体是否是AI
native bool:IsAi(iEntity)
//创建一个AI(创建坐标,AI名字,AI模型缓存索引,AI体型Max,AI体型Min,AI最大生命,AI最大速度,AI重力,AI伤害,AI伤害距离,AI攻击速度,AI反应时间,AI播放死亡动作的时间,AI队伍),返回AI的实体索引
native CreateAi(Float<img src="static/image/smiley/default/shocked.gif" border="0" smilieid="6" alt=":o">rigin, AiName[], modelindex, Float:maxhull, Float:minhull, Float:maxhealth, Float:maxspeed, Float:gravity, Float:damage, Float:distance, Float:attackrate, Float:thinkrate, Float:dyingtime, team)
//设置该AI实体的动作(ID索引, 静止动作, 移动动作, 跳跃动作, 攻击动作, 死亡动作)
native SetAiAnim(iEntity, idle, move, jump, attack, die)
/*
在创建AI的时候设置动作就可以了
new modelindex
public plugin_precache() modelindex = engfunc(EngFunc_PrecacheModel, "models/zombie.mdl")
makezombie()
{
new Float:MAX_HULL, Float:MIN_HULL
MAX_HULL = -16.0
MAX_HULL = -10.0
MAX_HULL = -36.0
MIN_HULL = 16.0
MIN_HULL = 10.0
MIN_HULL = 36.0
new iEntity = CreateAi(origin, "SB僵尸", modelindex, MAX_HULL, MIN_HULL, 100.0, 240.0, 1.0, 5.0, 70.0, 1.0, 0.5, 2.0, 1)
SetAiAnim(iEntity, 1, 2, 3, 4, {5, 6, 7})
}
*/
//移除该名字的所有AI
native RemoveAi(const ainame[])
//移除所有AI
native RemoveAllAi()
//获取该名字的所有AI数量
native GetAIAmount(const ainame[])
//获取所有AI的数量
native GetAllAIAmount()
//播放AI的动作
native SendAiAnim(iEntity, anim)
}
在此感谢
@我是那鸡
@小飞CS
大神别吐槽,此帖给新手看。
顶
[表情]
!
吧主给个精呗!
@MS一B
[表情]
AI-Walker源码在此
#include <amxmodx>
#include <fakemeta>
#include <hamsandwich>
#include <xs>
#define PLUGIN "AI Walker"
#define VERSION "1.0"
#define AUTHOR "DSHGFHDS"
#define AI "ai_walker"
#define pev_idle pev_iuser1
#define pev_move pev_iuser2
#define pev_jump pev_iuser3
#define pev_attack pev_iuser4
#define pev_die pev_vuser4
#define pev_damage pev_speed
#define pev_distance pev_fuser1
#define pev_attackrate pev_fuser2
#define pev_thinkrate pev_fuser3
#define pev_dyingtime pev_fuser4
#define ISJUMPING 1312
new g_fwDummyResult, g_fwPreThink, g_fwPostThink, g_fwPreKilled, g_fwPostKilled, g_fwPreHurted, g_fwPostHurted
new cvar_bodytime
new spr_blood_spray, spr_blood_drop
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
RegisterHam(Ham_Think, "info_target", "HAM_AiThink")
RegisterHam(Ham_TraceAttack, "info_target", "HAM_AiTraceAttack")
RegisterHam(Ham_Killed, "info_target", "HAM_AiKilled")
g_fwPreThink = CreateMultiForward("AI_PreThink", ET_CONTINUE, FP_CELL)
g_fwPostThink = CreateMultiForward("AI_PostThink", ET_IGNORE, FP_CELL)
g_fwPreHurted = CreateMultiForward("AI_PreHurted", ET_CONTINUE, FP_CELL, FP_CELL, FP_FLOAT, FP_CELL, FP_CELL)
g_fwPostHurted = CreateMultiForward("AI_PostHurted", ET_IGNORE, FP_CELL, FP_CELL, FP_FLOAT, FP_CELL, FP_CELL)
g_fwPreKilled = CreateMultiForward("AI_PreKilled", ET_CONTINUE, FP_CELL, FP_CELL)
g_fwPostKilled = CreateMultiForward("AI_PostKilled", ET_IGNORE, FP_CELL, FP_CELL)
cvar_bodytime = register_cvar("ai_body_time", "5.0") //灏镐綋瀛桦湪镄勬椂闂?
}
public plugin_natives()
{
register_native("IsAi", "NativeIsAi", 1)
register_native("CreateAi", "NativeCreateAi")
register_native("SetAiAnim", "NativeSetAiAnim")
register_native("RemoveAi", "NativeRemoveAi", 1)
register_native("RemoveAllAi", "NativeRemoveAllAi", 1)
register_native("GetAIAmount", "NativeGetAIAmount", 1)
register_native("GetAllAIAmount", "NativeGetAllAIAmount", 1)
register_native("SendAiAnim", "NativeSendAiAnim", 1)
}
public plugin_precache()
{
spr_blood_spray = engfunc(EngFunc_PrecacheModel, "sprites/bloodspray.spr")
spr_blood_drop = engfunc(EngFunc_PrecacheModel, "sprites/blood.spr")
}
public HAM_AiThink(iEntity)
{
new classname
pev(iEntity, pev_classname, classname, charsmax(classname))
if(strcmp(classname, AI))
return HAM_IGNORED
ExecuteForward(g_fwPreThink, g_fwDummyResult, iEntity)
if(g_fwDummyResult == 1)
return HAM_SUPERCEDE
new deadflag = pev(iEntity, pev_deadflag)
if(deadflag == DEAD_DEAD)
{
engfunc(EngFunc_RemoveEntity, iEntity)
return HAM_SUPERCEDE
}
new Float:fCurTime
global_get(glb_time, fCurTime)
if(deadflag == DEAD_DYING)
{
set_pev(iEntity, pev_deadflag, DEAD_DEAD)
set_pev(iEntity, pev_nextthink, fCurTime+get_pcvar_float(cvar_bodytime))
return HAM_SUPERCEDE
}
new Float:szThinkRate
pev(iEntity, pev_thinkrate, szThinkRate)
set_pev(iEntity, pev_nextthink, fCurTime+szThinkRate)
new iPlayer = pev(iEntity, pev_enemy)
if(!iPlayer)
{
iPlayer = engfunc(EngFunc_FindClientInPVS, iEntity)
set_pev(iEntity, pev_enemy, iPlayer)
}
if(iPlayer && get_pdata_int(iPlayer, 114, 5) != pev(iEntity, pev_team))
{
new Float:start, Float:end
pev(iEntity, pev_origin, start)
pev(iPlayer, pev_origin, end)
engfunc(EngFunc_TraceLine, start, end, DONT_IGNORE_MONSTERS, iEntity, 0)
new blocker = get_tr2(0, TR_pHit)
if(0 < blocker < 33 && blocker != iPlayer)
{
iPlayer = blocker
set_pev(iEntity, pev_enemy, iPlayer)
pev(iPlayer, pev_origin, end)
}
if(blocker == iPlayer)
{
SetEntityTurn(iEntity, end)
new Float:distance, Float:velocity, Float:velocity2
pev(iEntity, pev_distance, distance)
pev(iEntity, pev_velocity, velocity)
if(get_distance_f(start, end) <= distance)
{
velocity2 = velocity
set_pev(iEntity, pev_velocity, velocity2)
new Float:damage, Float:attackrate
pev(iEntity, pev_damage, damage)
ExecuteHamB(Ham_TakeDamage, iPlayer, iEntity, iEntity, damage, DMG_CLUB)
pev(iEntity, pev_attackrate, attackrate)
set_pev(iEntity, pev_nextthink, fCurTime+attackrate)
NativeSendAiAnim(iEntity, pev(iEntity, pev_attack))
}
else
if(pev(iEntity, pev_playerclass) == ISJUMPING)
{
get_speed_vector(start, end, 50.0, velocity2)
velocity2 += velocity
velocity2 += velocity
velocity2 = velocity
set_pev(iEntity, pev_velocity, velocity2)
set_pev(iEntity, pev_playerclass, 0)
}
else
if(pev(iEntity, pev_flags) & FL_ONGROUND)
{
new Float:dest, Float:size
pev(iEntity, pev_origin, start)
pev(iEntity, pev_v_angle, dest)
engfunc(EngFunc_MakeVectors, dest)
global_get(glb_v_forward, dest)
pev(iEntity, pev_size, size)
xs_vec_mul_scalar(dest, 1.5*size, dest)
xs_vec_add(start, dest, dest)
engfunc(EngFunc_TraceHull, dest, dest, IGNORE_MONSTERS, HULL_HUMAN, iEntity, 0)
new Float:maxspeed
pev(iEntity, pev_maxspeed, maxspeed)
get_speed_vector(start, end, maxspeed, velocity2)
if(get_tr2(0, TR_StartSolid) && get_tr2(0, TR_AllSolid) && !get_tr2(0, TR_InOpen) && FootPlaneNormal(iEntity) == 1.0)
{
velocity2 *= 0.5
velocity2 *= 0.5
velocity2 = 300.0
NativeSendAiAnim(iEntity, pev(iEntity, pev_jump))
set_pev(iEntity, pev_nextthink, fCurTime+0.2)
set_pev(iEntity, pev_playerclass, ISJUMPING)
}
else
{
velocity2 = velocity
NativeSendAiAnim(iEntity, pev(iEntity, pev_move))
}
set_pev(iEntity, pev_velocity, velocity2)
if(pev(iEntity, pev_playerclass) != ISJUMPING)
{
pev(iEntity, pev_angles, dest)
engfunc(EngFunc_WalkMove, iEntity, dest, 0.5, WALKMOVE_NORMAL)
}
}
ExecuteForward(g_fwPostThink, g_fwDummyResult, iEntity)
return HAM_SUPERCEDE
}
}
if(pev(iEntity, pev_flags) & FL_ONGROUND)
{
new Float:start, Float:dest, Float:hullend
pev(iEntity, pev_origin, start)
pev(iEntity, pev_v_angle, dest)
engfunc(EngFunc_MakeVectors, dest)
global_get(glb_v_forward, dest)
new Float:size
pev(iEntity, pev_size, size)
xs_vec_mul_scalar(dest, 1.5*size, hullend)
xs_vec_add(start, hullend, hullend)
engfunc(EngFunc_TraceHull, hullend, hullend, DONT_IGNORE_MONSTERS, HULL_HUMAN, 0, 0)
new Float:velocity
pev(iEntity, pev_velocity, velocity)
if((!get_tr2(0, TR_StartSolid) && !get_tr2(0, TR_AllSolid) && get_tr2(0, TR_InOpen)) || FootPlaneNormal(iEntity) != 1.0)
{
new Float:maxspeed, Float:velocity2
pev(iEntity, pev_maxspeed, maxspeed)
get_speed_vector(start, hullend, maxspeed, velocity2)
velocity2 = velocity
set_pev(iEntity, pev_velocity, velocity2)
pev(iEntity, pev_angles, dest)
engfunc(EngFunc_WalkMove, iEntity, dest, 0.5, WALKMOVE_NORMAL)
SetEntityTurn(iEntity, hullend)
NativeSendAiAnim(iEntity, pev(iEntity, pev_move))
}
else
{
new Float:v_angle
pev(iEntity, pev_v_angle, v_angle)
v_angle += random_float(-90.0, 90.0)
set_pev(iEntity, pev_v_angle, v_angle)
velocity = 0.0
velocity = 0.0
set_pev(iEntity, pev_velocity, velocity)
NativeSendAiAnim(iEntity, pev(iEntity, pev_idle))
}
}
set_pev(iEntity, pev_enemy, 0)
ExecuteForward(g_fwPostThink, g_fwDummyResult, iEntity)
return HAM_SUPERCEDE
}
public HAM_AiTraceAttack(iEntity, attacker, Float:damage, Float:direction, tracehandle, damagetype)
{
new classname
pev(iEntity, pev_classname, classname, charsmax(classname))
if(strcmp(classname, AI))
return HAM_IGNORED
new HitGroup = get_tr2(tracehandle, TR_iHitgroup)
new Float:Ndamage = damage
if(HitGroup == HIT_HEAD) Ndamage *= random_float(1.5, 2.0)
else if(HIT_CHEST <= HitGroup <= HIT_RIGHTARM) Ndamage *= random_float(0.8, 1.0)
else if(HitGroup != HIT_GENERIC) Ndamage *= random_float(0.6, 0.8)
ExecuteForward(g_fwPreHurted, g_fwDummyResult, iEntity, attacker, Ndamage, tracehandle, damagetype)
if(g_fwDummyResult == 1)
return HAM_SUPERCEDE
new Float:origin_end
get_tr2(tracehandle, TR_vecEndPos, origin_end)
new Float:velocity
pev(iEntity, pev_velocity, velocity)
velocity *= 0.3
velocity *= 0.3
set_pev(iEntity, pev_velocity, velocity)
set_pev(iEntity, pev_nextthink, get_gametime()+0.1)
NativeSendAiAnim(iEntity, pev(iEntity, pev_idle))
SpawnBlood(origin_end, 247, floatround(Ndamage))
SetHamParamFloat(3, damage)
ExecuteForward(g_fwPostHurted, g_fwDummyResult, iEntity, attacker, Ndamage, tracehandle, damagetype)
return HAM_IGNORED
}
public HAM_AiKilled(iEntity, attacker, gib)
{
new classname
pev(iEntity, pev_classname, classname, charsmax(classname))
if(strcmp(classname, AI))
return HAM_IGNORED
ExecuteForward(g_fwPreKilled, g_fwDummyResult, iEntity, attacker)
if(g_fwDummyResult == 1)
return HAM_SUPERCEDE
set_pev(iEntity, pev_deadflag, DEAD_DYING)
new Float:fdie, die
pev(iEntity, pev_die, fdie)
FVecIVec(fdie, die)
NativeSendAiAnim(iEntity, die)
set_pev(iEntity, pev_velocity, {0.0, 0.0, 0.01})
set_pev(iEntity, pev_takedamage, DAMAGE_NO)
set_pev(iEntity, pev_solid, SOLID_NOT)
new Float:dyingtime
pev(iEntity, pev_dyingtime, dyingtime)
set_pev(iEntity, pev_nextthink, get_gametime()+dyingtime)
ExecuteForward(g_fwPostKilled, g_fwDummyResult, iEntity, attacker)
return HAM_SUPERCEDE
}
public NativeCreateAi(plugin, param)
{
static AiName
get_string(2, AiName, charsmax(AiName))
new iEntity = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "info_target"))
set_pev(iEntity, pev_solid, SOLID_BBOX)
set_pev(iEntity, pev_movetype, MOVETYPE_PUSHSTEP)
set_pev(iEntity, pev_takedamage, DAMAGE_YES)
set_pev(iEntity, pev_classname, AI)
set_pev(iEntity, pev_deadflag, DEAD_NO)
set_pev(iEntity, pev_targetname, AiName)
set_pev(iEntity, pev_team, get_param(14))
set_pev(iEntity, pev_max_health, get_param_f(6))
set_pev(iEntity, pev_health, get_param_f(6))
set_pev(iEntity, pev_maxspeed, get_param_f(7))
set_pev(iEntity, pev_gravity, get_param_f(8))
set_pev(iEntity, pev_damage, get_param_f(9))
set_pev(iEntity, pev_distance, get_param_f(10))
set_pev(iEntity, pev_attackrate, get_param_f(11))
set_pev(iEntity, pev_thinkrate, get_param_f(12))
set_pev(iEntity, pev_dyingtime, get_param_f(13))
set_pev(iEntity, pev_nextthink, get_gametime()+get_param_f(12))
set_pev(iEntity, pev_modelindex, get_param(3))
set_pev(iEntity, pev_gamestate, 1)
new Float:origin, Float:maxhull, Float:minhull
get_array_f(1, origin, 3)
get_array_f(4, maxhull, 3)
get_array_f(5, minhull, 3)
engfunc(EngFunc_SetSize, iEntity, maxhull, minhull)
engfunc(EngFunc_SetOrigin, iEntity, origin)
return iEntity
}
public NativeSetAiAnim(plugin, param)
{
new iEntity = get_param(1)
set_pev(iEntity, pev_idle, get_param(2))
set_pev(iEntity, pev_move, get_param(3))
set_pev(iEntity, pev_jump, get_param(4))
set_pev(iEntity, pev_attack, get_param(5))
new die, Float:fdie
get_array(6, die, 3)
IVecFVec(die, fdie)
set_pev(iEntity, pev_die, fdie)
}
public NativeRemoveAi(const AiName[])
{
new targetname, iEntity = -1
while((iEntity = engfunc(EngFunc_FindEntityByString, iEntity, "classname", AI)))
{
if(!pev_valid(iEntity))
continue
pev(iEntity, pev_targetname, targetname, charsmax(targetname))
if(strcmp(targetname, AiName))
continue
engfunc(EngFunc_RemoveEntity, iEntity)
}
}
public NativeRemoveAllAi()
{
new iEntity = -1
while((iEntity = engfunc(EngFunc_FindEntityByString, iEntity, "classname", AI)))
{
if(!pev_valid(iEntity))
continue
engfunc(EngFunc_RemoveEntity, iEntity)
}
}
public NativeGetAIAmount(const AiName[])
{
new targetname, iEntity = -1, Amount
while((iEntity = engfunc(EngFunc_FindEntityByString, iEntity, "classname", AI)))
{
if(!pev_valid(iEntity))
continue
pev(iEntity, pev_targetname, targetname, charsmax(targetname))
if(strcmp(targetname, AiName))
continue
Amount ++
}
return Amount
}
public NativeGetAllAIAmount()
{
new iEntity = -1, Amount
while((iEntity = engfunc(EngFunc_FindEntityByString, iEntity, "classname", AI)))
{
if(!pev_valid(iEntity))
continue
Amount ++
}
return Amount
}
public NativeSendAiAnim(iEntity, anim)
{
if(pev(iEntity, pev_sequence) == anim)
return
set_pev(iEntity, pev_sequence, anim)
set_pev(iEntity, pev_animtime, get_gametime())
set_pev(iEntity, pev_frame, 0.0)
set_pev(iEntity, pev_framerate, 1.0)
}
public bool:NativeIsAi(iEntity)
{
if(!pev_valid(iEntity))
return false
new classname
pev(iEntity, pev_classname, classname, charsmax(classname))
if(strcmp(classname, AI))
return false
return true
}
stock SetEntityTurn(iEntity, Float:target)
{
new Float:angle, Float:origin
pev(iEntity, pev_angles, angle)
pev(iEntity, pev_origin, origin)
new Float:x = origin - target
new Float:z = origin - target
new Float:radians = floatatan(z/x, radian)
angle = radians * 180.0/3.141592654
if(target < origin) angle -= 180.0
set_pev(iEntity, pev_angles, angle)
set_pev(iEntity, pev_v_angle, angle)
}
stock get_speed_vector(const Float:origin1,const Float:origin2,Float:speed, Float:new_velocity)
{
new_velocity = origin2 - origin1
new_velocity = origin2 - origin1
new_velocity = origin2 - origin1
new Float:num = floatsqroot(speed*speed / (new_velocity*new_velocity + new_velocity*new_velocity + new_velocity*new_velocity))
new_velocity *= num
new_velocity *= num
new_velocity *= num
return 1
}
stock Float:FootPlaneNormal(iEntity)
{
new Float:start, Float:end
pev(iEntity, pev_origin, start)
xs_vec_sub(start, Float:{0.0, 0.0, 9999.0}, end)
engfunc(EngFunc_TraceLine, start, end, DONT_IGNORE_MONSTERS, iEntity, 0)
get_tr2(0, TR_vecPlaneNormal, end)
return end
}
stock SpawnBlood(const Float:vecOrigin, iColor, iAmount)
{
if(iAmount == 0)
return
iAmount *= 2
if(iAmount > 255) iAmount = 255
engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, vecOrigin)
write_byte(TE_BLOODSPRITE)
engfunc(EngFunc_WriteCoord, vecOrigin)
engfunc(EngFunc_WriteCoord, vecOrigin)
engfunc(EngFunc_WriteCoord, vecOrigin)
write_short(spr_blood_spray)
write_short(spr_blood_drop)
write_byte(iColor)
write_byte(min(max(3, iAmount / 10), 16))
message_end()
}
不对,新手请把NPC源码里的那句for(new i=1;i<=40;i++)删掉,不然会有40只僵尸卡在一起 这不就是DS的ZR吗?
早期版本是在一起的,后来里面的NPC插件独立出来了可以提取出来用于其它地方。
如果是想用NPC的话,个人觉得csoldjb老大的不错,毕竟DS这个专门为Zombie准备的… 没有没有,当初是独立写出来的AI核心,跟ZR没关,只是没事附加上去的而已
页:
[1]