搜索
查看: 18557|回复: 35

【实战教程】导弹插件的制作

[复制链接]
发表于 2005-7-13 22:06:35 | 显示全部楼层 |阅读模式 来自 中国–辽宁–沈阳
实战教程(一)导弹插件制作   ――   浅谈实体关系
您是否想过自己编写导弹插件?是否看到导弹插件的源代码就感到恐怖?――完全没有必要!今天Hydralisk就为大家简单讲述一下如何自己动手制作自己的导弹插件!如果您有学习的兴趣――请镇定下来,其实这是个很简单的插件。

仅仅支持Amx Mod,不支持 AMXX
第一阶段 普通导弹插件制作
技术难度系数:★★★☆
理解难度系数:★★★★


首先介绍一下导弹插件制作流程,以便大家理清思路
1-简单初始化程序,监视控制台中的导弹发射命令(本教程的命令为missile_launch)
2-如果玩家在控制台中输入missile_launch则创建实体,给实体命名为“hy_missile”(这个名字大家可以自己起),给实体“穿上”导弹的“衣服”,给实体一个初速度,给实体一个拉线效果。
3-监视实体碰撞,如果发生碰撞的两个实体其中一个名字为“hy_missile”,则这个叫“hy_missile”的实体的位置创建爆炸的视觉效果,然后按距离平方的比例给玩家减血,创建“疼痛罗盘”效果(就是玩家被攻击的时候屏幕上的红色的指示敌人方向的东西),删除实体

主要就这么3步,简单吧?
下面按流程具体解释实现方法。
第一步,简单初始化程序
  1. #include <amxmod>
  2. #include <amxmisc>
  3. #include <vexd_utilities>
  4. #include <vexdum_stock>

  5. new beam, boom

  6. public plugin_precache(){
  7.   precache_model("models/rpgrocket.mdl")
  8.   beam = precache_model("sprites/laserbeam.spr")
  9.   boom = precache_model("sprites/zerogxplode.spr")
  10. }

  11. public plugin_init(){
  12.   register_plugin("Rocket example","0.1","Hydralisk")
  13.   register_clcmd("missile_launch","ms_launch",0,"Launch a missile")
  14.   return PLUGIN_CONTINUE
  15. }

  16. public ms_launch(id){
  17.   
  18. }

  19. public entity_touch(entity1,entity2){
  20.   
  21. }
复制代码

其中
  1. #include <amxmod>
  2. #include <amxmisc>
复制代码

是所有AMX插件必须的




  1. #include <vexd_utilities>
  2. #include <vexdum_stock>
复制代码

是AMX Mod里控制实体的必要模块。


  1. new beam, boom

  2. public plugin_precache(){
  3.   precache_model("models/rpgrocket.mdl")
  4.   beam = precache_model("sprites/laserbeam.spr")
  5.   boom = precache_model("sprites/zerogxplode.spr")
  6. }
复制代码

其中,new beam, boom 是插件申请的两个全局变量,所谓全局变量,就是这两个变量的值是整个插件公用的,而不是某个过程里面的值。
plugin_precache 是AMX自带的事件,这个事件在CS执行预存储的时候(CS1.6里显示precaching resources时)被调用,这里,precache_model("models/rpgrocket.mdl")是让CS预存储火箭炮炮弹的皮肤,beam = precache_model("sprites/laserbeam.spr")这个是让CS预存储火箭炮弹发射后,后面的白烟的spr文件,并将存储索引号码存入全局变量beam中,boom = precache_model("sprites/zeroxplode.spr")和 beam的那个差不多,只不过预存储的是爆炸效果的spr文件。



  1. public plugin_init(){
  2.   register_plugin("Rocket example","0.1","Hydralisk")
  3.   register_clcmd("missile_launch","ms_launch",0,"Launch a missile")
  4.   return PLUGIN_CONTINUE
  5. }
复制代码

plugin_init()将在每次插件被初始化的时候调用,例如刚刚建立主机,每次更换地图,这个都会被调用。
register_plugin("Rocket example","0.1","Hydralisk")这个是注册插件,比如,我将插件注册为,插件名Rocket example, 版本号 0.1, 插件作者 Hydralisk 就是上面的那行
register_clcmd("missile_launch","ms_launch",0,"Launch a missile") 这个是注册控制台命令missile_launch,命令一旦被注册,AMX将会监视这个控制台命令,一旦有玩家输入这个命令,AMX会将其拦截并运行这个插件里名为 ms_launch (第二个参数)的函数。第三个参数0代表所有人都有权利执行这个命令,第四个参数"Launch a missile"是玩家输入amx_help时,能够在amx帮助中看到的解释。
return PLUGIN_HANDLED 这个,请您在plugin_init() 过程的最后一行加入他,记住就可以了。



  1. public ms_launch(id){
  2.   
  3. }
复制代码

这个,就是前面所说的ms_launch 函数了。



  1. public entity_touch(entity1,entity2){
  2.   
  3. }
复制代码

entity_touch(entity1,entity2)这个是Vexd_utilities里面预定义的事件,每当两个实体发生碰撞的时候,这个事件就会被触发,entity1, entity2 分别是两个实体的索引号码,如果一个实体碰撞了墙壁只类的东西,墙壁的索引号码是0。

第二步,创建导弹实体,并设置实体的属性
当玩家在控制台输入missile_launch之后,ms_launch过程将被调用,所以,创建导弹和设置导弹属性就要在这个过程中完成。

我们便拓展ms_launch的内容:
  1. public ms_launch(id){
  2.   if (!is_user_alive(id)) return PLUGIN_HANDLED
  3.   new Float:Ori[3],Float:Vel[3],Float:angle[3]
  4.   entity_get_vector(id,EV_VEC_origin,Ori)
  5.   new Ent = create_entity("info_target")
  6.   entity_set_model(Ent,"models/rpgrocket.mdl")
  7.   entity_set_string(Ent,EV_SZ_classname,"hy_missile")
  8.   entity_set_edict(Ent,EV_ENT_owner,id)
  9.   entity_set_origin(Ent,Ori)
  10.   entity_set_int(Ent,EV_INT_solid,SOLID_BBOX)
  11.   entity_set_int(Ent,EV_INT_movetype,MOVETYPE_FLY)
  12.   entity_set_size(Ent,Float:{-1.0,-1.0,-1.0},Float:{1.0,1.0,1.0})
  13.   VelocityByAim(id,1500,Vel)
  14.   entity_set_vector(Ent,EV_VEC_velocity,Vel)
  15.   vector_to_angle(Vel,angle)
  16.   entity_set_vector(Ent,EV_VEC_angles,angle)
  17.   
  18.   message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
  19.   write_byte(22)
  20.   write_short(Ent)
  21.   write_short(beam)
  22.   write_byte(45)
  23.   write_byte(4)
  24.   write_byte(255)
  25.   write_byte(0)
  26.   write_byte(0)
  27.   write_byte(128)
  28.   message_end()

  29.   return PLUGIN_HANDLED
  30. }
复制代码

ms_launch过程里的第一行
  1. if (!is_user_alive(id)) return PLUGIN_HANDLED
复制代码
是用来防止死人发射火箭炮的。 is_user_alive 函数的第一个参数为玩家索引,如果玩家活着,则返回“真”否则返回“假”,在这里,意义为 如果is_user_alive(id)为假,则执行 return PLUGIN_HANDLED 凡是带有return 字样的都会中止整个过程。于是,如果玩家死了,这个过程就会被终止,于是玩家就发射不了火箭了。


  1.   new Float:Ori[3],Float:Vel[3],Float:angle[3]
复制代码

这里,我们申请了名为Ori, Vel, angle三个浮点型局部3位数组变量。所谓浮点,就是小数的一种(您如果希望申请带有小数点变量,就用new Float:变量名 就可以了,不过注意大小写哦!),所谓数组,就是一个变量里面可以存储多个数据,例如Ori这个变量,可以存储三个数据,分别位于Ori[0] Ori[1] Ori[2] 虽然是一个变量,但也可以当作三个变量使用了。


  1.   entity_get_vector(id,EV_VEC_origin,Ori)
复制代码

entity_get_vector 这个函数是VexdUM 中预定义的,他的作用是获取某个实体的向量型变量,所谓向量型变量,其实就是一个3位数组型的浮点变量,例如,我前面申请的Ori Vel angle 都是这样的。(这里的向量不是真正意义的向量。据我看,VexdUM在向量方面的设置只有EV_VEC_velocity是向量,其他的都是形式上和向量一致,内涵上根本不是向量的。)entity_get_vector有三个参数,形式为:entity_get_vector(Entid, iparm, vRetrun) 其中Entid代表实体的索引号码, iparm代表您要获取哪种向量格式的实体参数,然后将返回的参数存在vReturn里。例如在我这里,id是玩家实体的索引号码, EV_VEC_origin代表的是玩家的位置,所以Ori变量里面就存储了玩家的位置。


  1.   new Ent = create_entity("info_target")
复制代码

这个create_entity用来创建实体。建议没有经验的脚本编写者在create_entity后面都用"info_target",这样肯定不会出现错误。create_entity 创建实体如果成功,则返回实体的索引号码,这样new Ent = create_entity("info_target") 中,Ent就存储了实体的索引号码,以便下面对这个实体的相关参数作设置。



  1.   entity_set_model(Ent,"models/rpgrocket.mdl")
  2.   entity_set_string(Ent,EV_SZ_classname,"hy_missile")
  3.   entity_set_edict(Ent,EV_ENT_owner,id)
  4.   entity_set_origin(Ent,Ori)
  5.   entity_set_int(Ent,EV_INT_solid,SOLID_BBOX)
  6.   entity_set_int(Ent,EV_INT_movetype,MOVETYPE_FLY)
  7.   entity_set_size(Ent,Float:{-1.0,-1.0,-1.0},Float:{1.0,1.0,1.0})
  8.   VelocityByAim(id,1500,Vel)
  9.   entity_set_vector(Ent,EV_VEC_velocity,Vel)
  10.   vector_to_angle(Vel,angle)
  11.   entity_set_vector(Ent,EV_VEC_angles,angle)
复制代码

这一段都是对实体的参数做设置。entity_set_edict, entity_set_string, entity_set_int, entity_set_vector 这些都是VexdUM预定义的过程,分别用来设置实体的edict(实体索引),string(字符串), int(整数), vector(向量) 型变量,用法都是 entity_set_***(Entid, iparm, var)其中Entid就是实体索引啦,iparm表示设置实体的哪个参数,var表示将这个参数设置为多少。EV_SZ_classname就是设置实体的名字。多个实体可以有一个名字。这里设置为hy_missile,不过不要忘了加引号哦。 EV_ENT_owner 设置这个实体的主人是谁。实体不会和自己的“主人”发生碰撞,也就是说,不会触发entity_touch事件,当然,识别自己的主人是靠玩家索引来实现的。 EV_INT_solid 是设置实体固体类型,这里设置为SOLID_BBOX表示为可发生碰撞的实体。 EV_INT_movetype设置的是实体的运动类型,MOVETYPE_FLY表示实体可发生碰撞,可以移动,但不受重力影响;其他的还有MOVETYPE_TOSS (受重力影响)、MOVETYPE_BOUNCE(受重力影响,而且受弹力影响)、MOVETYPE_BOUNCEMISSILE(不受重力影响,但是受弹力影响)、MOVETYPE_NOCLIP(不受任何力的影响,而且能穿墙) 等等。EV_VEC_velocity这个是设置实体速度及其方向,也是为一真正的向量了。EV_VEC_angles,这个是设置实体的角度,您总部希望导弹尖冲着自己的脸往远方飞吧:)。entity_set_origin这个是设置实体的位置,这里引用了前面获取玩家的位置,所以实体就在玩家这里出现了。entity_set_model这个就是给实体穿衣服,让实体变成导弹的形状。entity_set_size这个是设置实体的大小。VelocityByAim这个是按照玩家视线的方向给向量一个固定长度的向量。例如这里,方向是id所对应的玩家的方向,向量长度为1500,并将这个向量存储在Vel变量里。这个Vel一旦被设置到实体的EV_VEC_velocity属性下,实体就有了速度,方向就是玩家的方向,速度就是1500 vector_to_angle这个是将向量转换为角度,这里是将 Vel 这个向量转换为角度存在angle变量里,以便设置火箭的角度,也就是EV_VEC_angles.



  1.   message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
  2.   write_byte(22)
  3.   write_short(Ent)
  4.   write_short(beam)
  5.   write_byte(45)
  6.   write_byte(4)
  7.   write_byte(255)
  8.   write_byte(0)
  9.   write_byte(0)
  10.   write_byte(128)
  11.   message_end()
复制代码

这个有关message的东西非常复杂,以后我有时间给大家详细的讲述。您只需理解,这里这个东西是让Ent这个实体,也就是火箭这个实体带上拉白线的效果。



  1. return PLUGIN_HANDLED
复制代码

这个,请在拦截的命令说触发的过程的最后一行将他加上,避免在控制台中出现 unknown command: …..

第三步,监视实体碰撞
如果实体一旦发生碰撞,entity_touch 就会被触发,所以,我们需要扩充entity_touch的内容。
  1. public entity_touch(entity1,entity2){
  2.   new sz[33]
  3.   if (is_entity(entity1)){
  4.     entity_get_string(entity1,EV_SZ_classname,sz,32)
  5.     if (equal(sz,"hy_missile")){
  6.       new Float:Ori[3],Iori[3]
  7.       entity_get_vector(entity1,EV_VEC_origin,Ori)
  8.       FVecIVec(Ori,Iori)
  9.       message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
  10.       write_byte(3)
  11.       write_coord(Iori[0])
  12.       write_coord(Iori[1])
  13.       write_coord(Iori[2])
  14.       write_short(boom)
  15.       write_byte(50)
  16.       write_byte(15)
  17.       write_byte(0)
  18.       message_end()
  19.       radius_damage2(entity1,200.0,800.0)
  20.       remove_entity(entity1)
  21.     }
  22.   }
  23.   if (is_entity(entity2)){
  24.     entity_get_string(entity2,EV_SZ_classname,sz,32)
  25.     if (equal(sz,"hy_missile")){
  26.       new Float:Ori[3],Iori[3]
  27.       entity_get_vector(entity2,EV_VEC_origin,Ori)
  28.       FVecIVec(Ori,Iori)
  29.       message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
  30.       write_byte(3)
  31.       write_coord(Iori[0])
  32.       write_coord(Iori[1])
  33.       write_coord(Iori[2])
  34.       write_short(boom)
  35.       write_byte(50)
  36.       write_byte(15)
  37.       write_byte(0)
  38.       message_end()
  39.       radius_damage2(entity2,200.0,800.0)
  40.       remove_entity(entity2)
  41.           }
  42.         }
  43. }
复制代码


内容似乎很多,但是不要怕。我慢慢讲述。
entity_touch被触发后,entity1和entity2两个变量存储了发生碰撞的实体的索引号码。如果其中一个不是实体,而是墙壁、天棚之类的东西,那么对应的entity1 或者 entity2将会是0。为了检验发生碰撞的两个实体中其中有一个是我们前面命名的hy_missile,我们需要在entity_touch里检验。首先,我们申请了名为sz的33位数组,充当储存字符串的空间,所谓字符串就是字符组成的一个串,例如"abc" "Hydralisk" ".fjfkei" 这些都是字符串。我们用entity_get_string可以获取相关实体的字符串类型的参数,准备将其储存在sz里,然后对其进行判断。因为我们不知道火箭实体的索引号码是存储在entity1变量里还是entity2变量里,所以我们需要判断两次。首先我们来看第一次判断:
  1.   if (is_entity(entity1)){
  2.     entity_get_string(entity1,EV_SZ_classname,sz,32)
  3.     if (equal(sz,"hy_missile")){
  4.       new Float:Ori[3],Iori[3]
  5.       entity_get_vector(entity1,EV_VEC_origin,Ori)
  6.       FVecIVec(Ori,Iori)
  7.       message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
  8.       write_byte(3)
  9.       write_coord(Iori[0])
  10.       write_coord(Iori[1])
  11.       write_coord(Iori[2])
  12.       write_short(boom)
  13.       write_byte(50)
  14.       write_byte(15)
  15.       write_byte(0)
  16.       message_end()
  17.       radius_damage2(entity1,200.0,800.0)
  18.       remove_entity(entity1)
  19.     }
  20.   }
复制代码

is_entity 是用来判断它后面第一个参数是不是一个有效实体的索引号码。如果是,if条件成立,将进入if所对应的花括号"{ }"里。如果不成立,那么将不能进入if 所对应的花括号里,相当于放弃。我们不妨假设entity1是实体。于是我们可以放心的使用entity_get_string来获得实体的字符串型变量。前面说过EV_SZ_classname是实体的名字。于是我们用entity_get_string(entity1,EV_SZ_classname,sz,32) 作用是获得entity1的EV_SZ_classname也就是他的名字,截取前32位(第4个参数)储存在sz里。这里提一下,所有获取字符串型的变量都有一个特点,就是您需要告诉计算机获取多少为字符串,比如,我申请的是33位的数组,最多能截获32位的字符串,所以我告诉电脑,截取32位,写在sz后面。以后有机会我详细讲一下。下面,我们判断这个实体的名字是不是hy_missile:
  1. if (equal(sz,"hy_missile"))
复制代码

equal(字符串1,字符串2) 这个使用来检验字符串1的内容是否和字符串2的内容一致。如果一致,这返回真。这里就是判断字符串sz的内容是不是我们所要的hy_missile。如果是,则if 条件通过,可以进入这个if所对应的花括号里,如果不成立,则执行if对应的花括号里的内容。现在,我们假设sz 就是 "hy_missile" ,这就说明是我们创建的导弹和其他实体或墙壁发生碰撞。于是:
  1.       new Float:Ori[3],Iori[3]
  2.       entity_get_vector(entity1,EV_VEC_origin,Ori)
  3.       FVecIVec(Ori,Iori)
  4.       message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
  5.       write_byte(3)
  6.       write_coord(Iori[0])
  7.       write_coord(Iori[1])
  8.       write_coord(Iori[2])
  9.       write_short(boom)
  10.       write_byte(50)
  11.       write_byte(15)
  12.       write_byte(0)
  13.       message_end()
  14.       radius_damage2(entity1,200.0,800.0)
  15.       remove_entity(entity1)
复制代码

申请Ori, Iori变量,Ori是浮点型,Iori是整数型,他们都是3位数组(前面讲过)。entity_get_vector也讲过,这个FVecIVec是一个转换格式的过程,能将浮点向量型变量转换为整数向量型变量。这里讲Ori(浮点向量型变量)转换为整数向量型存储在Iori里面了,因为创建爆炸效果的时候要用整数来表示位置。



  1.       message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
  2.       write_byte(3)
  3.       write_coord(Iori[0])
  4.       write_coord(Iori[1])
  5.       write_coord(Iori[2])
  6.       write_short(boom)
  7.       write_byte(50)
  8.       write_byte(15)
  9.       write_byte(0)
  10.       message_end()
复制代码

这个就是创建爆炸效果的了。又涉及到一个message的问题,以后详细讲啦,您只需知道,有关message的一般涉及到效果。



  1. radius_damage2(entity1,200.0,800.0)
复制代码

这个是我自己编写的创造范围性爆炸减血和杀得过程。具体内容如下(您只需将这个放在脚本最下端):
  1. stock radius_damage2(inf,Float:dmg,Float:rad){
  2.   new players[32],pnum,Float:rng,Float:cd,Float:ori[3],owner,cdi,health,vec[3]
  3.   new Float:pori[3]
  4.   new sz[33]
  5.   entity_get_string(inf,EV_SZ_classname,sz,32)
  6.   new team2,team1,ff = get_cvar_num("mp_friendlyfire")
  7.   entity_get_vector(inf,EV_VEC_origin,ori)
  8.   FVecIVec(ori,vec)
  9.   owner = entity_get_edict(inf,EV_ENT_owner)
  10.   team1 = get_user_team(owner)
  11.   get_players(players,pnum,"a")
  12.   for (new i=0;i<pnum;i++){
  13.     team2 = get_user_team(players[i])
  14.     if (team2 == team1 && !ff) continue
  15.     entity_get_vector(players[i],EV_VEC_origin,pori)
  16.     rng = VecDist(ori,pori)
  17.     if (rng > rad) continue
  18.     rng = rad - rng
  19.     cd = dmg / (rad*rad) * (rng * rng)
  20.     cdi = floatround(cd)
  21.     health = get_user_health(players[i])
  22.     health -= cdi
  23.     if (health <=0){
  24.       MessageBlock(get_user_msgid("DeathMsg"),BLOCK_ONCE)
  25.       user_kill(players[i],1)
  26.       entity_set_int(players[i],EV_INT_iuser3,owner)
  27.       message_begin(MSG_ALL,get_user_msgid("DeathMsg"))
  28.       write_byte(owner)
  29.       write_byte(players[i])
  30.       write_byte(0)
  31.       write_string(sz)
  32.       message_end();
  33.       message_begin(MSG_ALL,get_user_msgid("ScoreInfo"))
  34.       write_byte(players[i])
  35.       write_short(get_user_frags(players[i]))
  36.       write_short(get_user_frags(players[i])+1)
  37.       write_short(0)
  38.       write_short(get_user_team(players[i]))
  39.       message_end();
  40.       message_begin(MSG_ALL,get_user_msgid("ScoreInfo"))
  41.       write_byte(owner)
  42.       write_short((team1 != team2)?(get_user_frags(owner)+1):(get_user_frags(owner)-1))
  43.       write_short(get_user_frags(owner))
  44.       write_short(0)
  45.       write_short(get_user_team(owner))
  46.       message_end();
  47.       set_user_frags(owner,(team1 != team2)?(get_user_frags(owner)+1):(get_user_frags(owner)-1))
  48.     } else {
  49.       set_user_health(players[i],health)
  50.       message_begin(MSG_ONE,get_user_msgid("Damage"),{0,0,0},players[i])
  51.       write_byte( 0 );
  52.       write_byte( cdi );
  53.       write_long( DMG_BLAST );
  54.       write_coord( vec[0] );
  55.       write_coord( vec[1] );
  56.       write_coord( vec[2] );
  57.       message_end();
  58.     }
  59.   }
  60. }
复制代码


用法是radius_damage2(实体索引,中心爆炸威力(小数),爆炸半径(小数))
功能是在实体索引对应的实体已给定的中心爆炸威力和爆炸半径创造减血的效果,酷似手雷爆炸。这里实体索引对应的就是导弹实体,您明白了吧?至于这个radius_damage2例内容的详细含义,今后需要您慢慢理解,我会更多的写一写教程帮助您的理解。




  1. remove_entity(entity1)
复制代码

导弹的使命结束了(他都爆炸了!)我们不能让导弹留在墙上,所以,remove_entity就是删除索引号码为entity1的实体,也就是导弹实体。

第二次判断,就是判断entity2了,方法和对entity1的判断完全相同。只消把entity1改称entity2,应该明白吧?

这样,一个简单的导弹插件就编写完了。全部过程如下:
  1. #include <amxmod>
  2. #include <amxmisc>
  3. #include <vexd_utilities>
  4. #include <vexdum_stock>
  5. new beam, boom

  6. public plugin_init(){
  7.   register_plugin("Rocket example","0.1","Hydralisk")
  8.   register_clcmd("missile_launch","ms_launch",0,"Launch a missile")
  9.   return PLUGIN_CONTINUE
  10. }

  11. public plugin_precache(){
  12.   precache_model("models/rpgrocket.mdl")
  13.   beam = precache_model("sprites/laserbeam.spr")
  14.   boom = precache_model("sprites/zerogxplode.spr")
  15. }

  16. public ms_launch(id){
  17.   if (!is_user_alive(id)) return PLUGIN_HANDLED
  18.   new Float:Ori[3],Float:Vel[3],Float:angle[3]
  19.   entity_get_vector(id,EV_VEC_origin,Ori)
  20.   new Ent = create_entity("info_target")
  21.   entity_set_model(Ent,"models/rpgrocket.mdl")
  22.   entity_set_string(Ent,EV_SZ_classname,"hy_missile")
  23.   entity_set_edict(Ent,EV_ENT_owner,id)
  24.   entity_set_origin(Ent,Ori)
  25.   entity_set_int(Ent,EV_INT_solid,SOLID_BBOX)
  26.   entity_set_int(Ent,EV_INT_movetype,MOVETYPE_FLY)
  27.   entity_set_size(Ent,Float:{-1.0,-1.0,-1.0},Float:{1.0,1.0,1.0})
  28.   VelocityByAim(id,1500,Vel)
  29.   entity_set_vector(Ent,EV_VEC_velocity,Vel)
  30.   vector_to_angle(Vel,angle)
  31.   entity_set_vector(Ent,EV_VEC_angles,angle)
  32.   
  33.   message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
  34.   write_byte(22)
  35.   write_short(Ent)
  36.   write_short(beam)
  37.   write_byte(45)
  38.   write_byte(4)
  39.   write_byte(255)
  40.   write_byte(0)
  41.   write_byte(0)
  42.   write_byte(128)
  43.   message_end()

  44.   return PLUGIN_HANDLED
  45. }

  46. public entity_touch(entity1,entity2){
  47.   new sz[33]
  48.   if (is_entity(entity1)){
  49.     entity_get_string(entity1,EV_SZ_classname,sz,32)
  50.     if (equal(sz,"hy_missile")){
  51.       new Float:Ori[3],Iori[3]
  52.       entity_get_vector(entity1,EV_VEC_origin,Ori)
  53.       FVecIVec(Ori,Iori)
  54.       message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
  55.       write_byte(3)
  56.       write_coord(Iori[0])
  57.       write_coord(Iori[1])
  58.       write_coord(Iori[2])
  59.       write_short(boom)
  60.       write_byte(50)
  61.       write_byte(15)
  62.       write_byte(0)
  63.       message_end()
  64.       radius_damage2(entity1,200.0,800.0)
  65.       remove_entity(entity1)
  66.     }
  67.   }
  68.   if (is_entity(entity2)){
  69.     entity_get_string(entity2,EV_SZ_classname,sz,32)
  70.     if (equal(sz,"hy_missile")){
  71.       new Float:Ori[3],Iori[3]
  72.       entity_get_vector(entity2,EV_VEC_origin,Ori)
  73.       FVecIVec(Ori,Iori)
  74.       message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
  75.       write_byte(3)
  76.       write_coord(Iori[0])
  77.       write_coord(Iori[1])
  78.       write_coord(Iori[2])
  79.       write_short(boom)
  80.       write_byte(50)
  81.       write_byte(15)
  82.       write_byte(0)
  83.       message_end()
  84.       radius_damage2(entity2,200.0,800.0)
  85.       remove_entity(entity2)
  86.           }
  87.         }
  88. }

  89. stock radius_damage2(inf,Float:dmg,Float:rad){
  90.   new players[32],pnum,Float:rng,Float:cd,Float:ori[3],owner,cdi,health,vec[3]
  91.   new Float:pori[3]
  92.   new sz[33]
  93.   entity_get_string(inf,EV_SZ_classname,sz,32)
  94.   new team2,team1,ff = get_cvar_num("mp_friendlyfire")
  95.   entity_get_vector(inf,EV_VEC_origin,ori)
  96.   FVecIVec(ori,vec)
  97.   owner = entity_get_edict(inf,EV_ENT_owner)
  98.   team1 = get_user_team(owner)
  99.   get_players(players,pnum,"a")
  100.   for (new i=0;i<pnum;i++){
  101.     team2 = get_user_team(players[i])
  102.     if (team2 == team1 && !ff) continue
  103.     entity_get_vector(players[i],EV_VEC_origin,pori)
  104.     rng = VecDist(ori,pori)
  105.     if (rng > rad) continue
  106.     rng = rad - rng
  107.     cd = dmg / (rad*rad) * (rng * rng)
  108.     cdi = floatround(cd)
  109.     health = get_user_health(players[i])
  110.     health -= cdi
  111.     if (health <=0){
  112.       MessageBlock(get_user_msgid("DeathMsg"),BLOCK_ONCE)
  113.       user_kill(players[i],1)
  114.       entity_set_int(players[i],EV_INT_iuser3,owner)
  115.       message_begin(MSG_ALL,get_user_msgid("DeathMsg"))
  116.       write_byte(owner)
  117.       write_byte(players[i])
  118.       write_byte(0)
  119.       write_string(sz)
  120.       message_end();
  121.       message_begin(MSG_ALL,get_user_msgid("ScoreInfo"))
  122.       write_byte(players[i])
  123.       write_short(get_user_frags(players[i]))
  124.       write_short(get_user_frags(players[i])+1)
  125.       write_short(0)
  126.       write_short(get_user_team(players[i]))
  127.       message_end();
  128.       message_begin(MSG_ALL,get_user_msgid("ScoreInfo"))
  129.       write_byte(owner)
  130.       write_short((team1 != team2)?(get_user_frags(owner)+1):(get_user_frags(owner)-1))
  131.       write_short(get_user_frags(owner))
  132.       write_short(0)
  133.       write_short(get_user_team(owner))
  134.       message_end();
  135.       set_user_frags(owner,(team1 != team2)?(get_user_frags(owner)+1):(get_user_frags(owner)-1))
  136.     } else {
  137.       set_user_health(players[i],health)
  138.       message_begin(MSG_ONE,get_user_msgid("Damage"),{0,0,0},players[i])
  139.       write_byte( 0 );
  140.       write_byte( cdi );
  141.       write_long( DMG_BLAST );
  142.       write_coord( vec[0] );
  143.       write_coord( vec[1] );
  144.       write_coord( vec[2] );
  145.       message_end();
  146.     }
  147.   }
  148. }
复制代码


熟悉编写插件的路并不太漫长,只要您上心,其实一且都很简单:)
如果您又不明白的地方,请回帖,如果文章有语病,有错别字,请回帖,谢谢!
发表于 2005-7-14 00:19:25 | 显示全部楼层 来自 中国–广西–玉林
顶~!!!! :super:

虽然我是用AMXX :thefinger
回复

使用道具 举报

发表于 2005-7-14 05:37:23 | 显示全部楼层 来自 中国–北京–北京–海淀区
开课啦
哇哈哈
:mad:
技术难度系数:★★★☆
理解难度系数:★★★★

:sweat:
回复

使用道具 举报

 楼主| 发表于 2005-7-14 08:40:51 | 显示全部楼层 来自 中国–辽宁–沈阳
谢谢支持。我继续写。。。
回复

使用道具 举报

发表于 2005-7-14 12:35:55 | 显示全部楼层 来自 中国–陕西–西安
:D 很详细,加精
回复

使用道具 举报

 楼主| 发表于 2005-7-14 12:41:39 | 显示全部楼层 来自 中国–辽宁–沈阳
谢谢! :d:
回复

使用道具 举报

发表于 2005-7-15 10:21:39 | 显示全部楼层 来自 中国–河北–石家庄
好东西呀  :super:
回复

使用道具 举报

 楼主| 发表于 2005-7-15 10:48:19 | 显示全部楼层 来自 中国–辽宁–沈阳
谢谢夸奖 :go:
回复

使用道具 举报

发表于 2005-7-19 09:34:50 | 显示全部楼层 来自 中国–天津–天津–河西区
真是个高手!!!我也想学制作AMXX插件,我要先学那些东西??? :em06:
回复

使用道具 举报

 楼主| 发表于 2005-7-22 13:12:57 | 显示全部楼层 来自 中国–辽宁–沈阳
Post by RonyDick
真是个高手!!!我也想学制作AMXX插件,我要先学那些东西??? :em06:


这个是AMX的教程。
想学制作插件,建议您看看C语言入门的相关书籍,但是不要看得太深,只消把顺序、选择、循环、变量、数组、过程、函数看看就行了,然后,我以后会尽量写一些AMX/AMXX入门的教程,帮助大家。我非常希望大家都会制作插件。
回复

使用道具 举报

游客
回复
您需要登录后才可以回帖 登录 | 注个册吧

快速回复 返回顶部 返回列表