图名分离和属性填写遍历对象的属性宏

28447人阅读
数据结构与算法(28)
c/c++(22)
图的遍历是指从图中的任一顶点出发,对图中的所有顶点访问一次且只访问一次。图的遍历操作和树的遍历操作功能相似。图的遍历是图的一种基本操作,图的其它算法如求解图的连通性问题,拓扑排序,求关键路径等都是建立在遍历算法的基础之上。
由于图结构本身的复杂性,所以图的遍历操作也较复杂,主要表现在以下四个方面:
① 在图结构中,没有一个“自然”的首结点,图中任意一个顶点都可作为第一个被访问的结点。
② 在非连通图中,从一个顶点出发,只能够访问它所在的连通分量上的所有顶点,因此,还需考虑如何选取下一个出发点以访问图中其余的连通分量。
③ 在图结构中,如果有回路存在,那么一个顶点被访问之后,有可能沿回路又回到该顶点。④ 在图结构中,一个顶点可以和其它多个顶点相连,当这样的顶点访问过后,存在如何选取下一个要访问的顶点的问题。
图的遍历通常有深度优先搜索和广度优先搜索两种方式,他们对无向图和有向图都适用。
深度优先搜索(Depth_Fisrst Search)遍历类似于树的先根遍历,是树的先根遍历的推广。
假设初始状态是图中所有顶点未曾被访问,则深度优先搜索可从图中某个顶点发v 出发,访问此顶点,然后依次从v 的未被访问的邻接点出发深度优先遍历图,直至图中所有和v 有路径相通的顶点都被访问到;若此时图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。
以如下图的无向图G5为例,进行图的深度优先搜索:
搜索过程:
假设从顶点v1 出发进行搜索,在访问了顶点v1 之后,选择邻接点v2。因为v2 未曾访问,则从v2 出发进行搜索。依次类推,接着从v4 、v8 、v5 出发进行搜索。在访问了v5 之后,由于v5 的邻接点都已被访问,则搜索回到v8。由于同样的理由,搜索继续回到v4,v2 直至v1,此时由于v1 的另一个邻接点未被访问,则搜索又从v1 到v3,再继续进行下去由此,得到的顶点访问序列为:
显然,这是一个递归的过程。为了在遍历过程中便于区分顶点是否已被访问,需附设访问标志数组visited[0:n-1], ,其初值为FALSE ,一旦某个顶点被访问,则其相应的分量置为TRUE。1)邻接矩阵的存储方式实现:
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
#pragma once
#include "targetver.h"
#include &stdio.h&
#include "stdlib.h"
#include &iostream&
#define TRUE
#define FALSE
#define NULL 0
#define OK
#define ERROR
#define INFEASIBLE -1
#define OVERFLOW -2
#define INFINITY
#define MAX_VERTEX_NUM 30
typedef int S
typedef int ElemT
typedef int VrT
typedef char VertexT
/************************************************************************/
/* 数组表示:邻接矩阵数据结构
/************************************************************************/
typedef struct ArcCell{
//顶点关系类型,对无权图,0/1表示是否相邻,有权图表示权值
//弧相关信息的指针
}ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct{
VertexType vexs[MAX_VERTEX_NUM];
//顶点向量
//邻接矩阵
int vexnum,
//图的当前顶点数和弧数
// Test.cpp : Defines the entry point for the console application.
#include "stdafx.h"
bool visited[MAX_VERTEX_NUM];
//访问标识
Status (*VisitFunc) (int v);
//函数变量
/************************************************************************/
确定顶点v在图G的位置
/************************************************************************/
int LocateVex(MGraph G,VertexType v)
for(int i = 0; i&G. ++i) {
if(G.vexs[i] == v)//找到
return -1;//不存在
/************************************************************************/
/************************************************************************/
int FirstAdjVex(MGraph G,int v)
for(i = 0; i&G. i++)
if( G.arcs[v][i].adj )
if(i == (G.vexnum
-1)) return -1;
return -1;
int NextAdjVex(MGraph G,int v,int w)
for( i = w+1; i&G. i++)//+1
if(G.arcs[v][i].adj)
if(i == (G.vexnum
-1)) return -1;
return -1;
/************************************************************************/
邻接矩阵的无向图的创建:
注释的代码可以动态生成图。
/************************************************************************/
void CreatUDG(MGraph &G){
cout&&"创建邻接矩阵的无向图:"&&
int i,j,k,w;
//G5的存储:
G.arcnum = 8;
G.vexnum = 9;
for(i=0;i&G.++i)
for(j=0;j&G.++j) {
G.arcs[i][j].adj=0;
G.arcs[i][j].info=NULL;
G.vexs[0] = '1';
G.vexs[1] = '2';
G.vexs[2] = '3';
G.vexs[3] = '4';
G.vexs[4] = '5';
G.vexs[5] = '6';
G.vexs[6] = '7';
G.vexs[7] = '8';
G.arcs[0][1].adj = 1;
G.arcs[0][1].info = NULL;
G.arcs[1][0].adj = 1;
G.arcs[1][0].info = NULL;
G.arcs[1][3].adj = 1;
G.arcs[1][3].info = NULL;
G.arcs[3][1].adj = 1;
G.arcs[3][1].info = NULL;
G.arcs[3][7].adj = 1;
G.arcs[3][7].info = NULL;
G.arcs[7][3].adj = 1;
G.arcs[7][3].info = NULL;
G.arcs[7][4].adj = 1;
G.arcs[7][4].info = NULL;
G.arcs[4][7].adj = 1;
G.arcs[4][7].info = NULL;
G.arcs[4][1].adj = 1;
G.arcs[4][1].info = NULL;
G.arcs[1][4].adj = 1;
G.arcs[1][4].info = NULL;
G.arcs[0][2].adj = 1;
G.arcs[0][2].info = NULL;
G.arcs[2][0].adj = 1;
G.arcs[2][0].info = NULL;
G.arcs[2][5].adj = 1;
G.arcs[2][5].info = NULL;
G.arcs[5][2].adj = 1;
G.arcs[5][2].info = NULL;
G.arcs[5][6].adj = 1;
G.arcs[5][6].info = NULL;
G.arcs[6][5].adj = 1;
G.arcs[6][5].info = NULL;
G.arcs[6][2].adj = 1;
G.arcs[6][2].info = NULL;
G.arcs[2][6].adj = 1;
G.arcs[2][6].info = NULL;
char v1,v2;
cout&&"请输入无向图顶点个数和边数:"&&
cin&&G.vexnum&&G.
cout&&"请输入"&&G.vexnum&&"个顶点的值:"&&
for(i=0;i&G.++i) cin&&G.vexs[i];
for(i=0;i&G.++i)
for(j=0;j&G.++j) {
G.arcs[i][j].adj=0;
G.arcs[i][j].info=NULL;
for( k=1;k&=G.++k){
cout&&"请输入第"&&k&&"条边的两个顶点值和它们的权重:"&&
cin&&v1&&v2&&w;
i = LocateVex(G,v1);
j=LocateVex(G,v2);
G.arcs[i][j].adj=w;
G.arcs[j][i]=G.arcs[i][j];
/************************************************************************/
/* 有向图邻接矩阵的创建
/************************************************************************/
void CreatDG(MGraph &G){
int i,j,k,w;
char v1,v2;
G.arcnum = 8;
G.vexnum = 9;
cout&&"请输入有向图顶点个数和边数:";
cin&& G.vexnum&& G.
cout&&"请输入"&&G.vexnum&&"个顶点的值:"&&
for(i=0;i&G.++i) cin&&G.vexs[i];
for(i=0;i&G.++i)
for(j=0;j&G.++j) {
G.arcs[i][j].adj = 0;
G.arcs[i][j].info = NULL;
for( k=1;k&=G.++k){
cout&&"请输入第"&&k&&"条边的两个顶点值和它们的权重:"&&
cin&&v1&&v2&&w;
i= LocateVex(G,v1);
j = LocateVex(G,v2);
G.arcs[i][j].adj =
void visitVex(MGraph G, int v){
cout&&G.vexs[v]&&" ";
/************************************************************************/
以V为出发点对图G 进行递归地DFS 搜索
/************************************************************************/
void DFS(MGraph G,int v){
visited[v] =
visitVex( G,
v); //访问第v 个顶点
for(int w = FirstAdjVex(G,v); w&=0; w = NextAdjVex(G,v,w)){
if(!visited[w]) DFS(G,w); //w未访问过,递归DFS搜索
/************************************************************************/
无向图的深度遍历
/************************************************************************/
void DFSTraverse(MGraph G){//
for( v = 0; v & G. ++v) visited[v] =
for( v = 0; v & G. )
if(!visited[v]) DFS( G, v); //v未访问过,从vi开始DFS搜索
++v;//不要像书上写的那样,++v放到for语句,这样会导致多出一次访问
void printMGraph(MGraph G){
cout&&"邻接矩阵已经创建,邻接矩阵为:"&&
for(int i=0;i&G.i++){
for(int j=0;j&G.j++)
cout&&G.arcs[i][j].adj&&" ";
void main(){
CreatUDG(G);
printMGraph(G);
cout&&"无向图邻接矩阵的深度遍历结果:"&&
DFSTraverse(G);
2) 邻接表的表示实现方式
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
#pragma once
#include "targetver.h"
#include &stdio.h&
#include "stdlib.h"
#include &iostream&
#define TRUE
#define FALSE
#define NULL 0
#define OK
#define ERROR
#define INFEASIBLE -1
#define OVERFLOW -2
#define INFINITY
#define MAX_VERTEX_NUM 30
typedef int S
typedef int ElemT
typedef int VrT
typedef char VertexT
/************************************************************************/
邻接表示的图数据结构
/************************************************************************/
//定义边结点,即表节点
typedef struct ArcNode
//弧所指的顶点位置
//指向下一条弧的指针
//定义顶点节点,即头节点
typedef struct VNode
//顶点信息
//指向第一条依附该顶点的弧的指针
}VNode,AdjList[MAX_VERTEX_NUM];
//定义无向图
typedef struct
int vexnum,
//图的当前顶点数和弧数
// Test.cpp : Defines the entry point for the console application.
#include "stdafx.h"
bool visited[MAX_VERTEX_NUM];
//访问标识
Status (*VisitFunc) (int v);
//函数变量
/************************************************************************/
/* 在无向图中添加以m,n为顶点的边
/************************************************************************/
void ArcAdd(ALGraph &G,int m,int n){
ArcNode *p,*h,*q;
p = new ArcN
p-&adjvex =
p-&nextarc = NULL;
h = q = G.vertices[n].
if(q == NULL)
G.vertices[n].firstarc =
if((p-&adjvex)&(q-&adjvex)){
p-&nextarc =
G.vertices[n].firstarc =
while( G.vertices[n].firstarc != NULL && q-&nextarc != NULL && (p-&adjvex)&(q-&adjvex)){ //使邻接表中边的数据按大到小排列。
if(q-&nextarc == NULL&&(p-&adjvex)&(q-&adjvex)){
q-&nextarc =
p-&nextarc =
h-&nextarc =
/************************************************************************/
创建无向图
/************************************************************************/
void CreateDG(ALGraph &G){
cout&&"请输入顶点个数和边数:"&&
cin&& G.vexnum&& G.
cout&&"请输入顶点值:"&&
for(int i= 1; i&= G. i++) {
G.vertices[i].data =
G.vertices[i].firstarc = NULL;
for(int k = 1; k&=G. k++){
cout&&"请输入第"&&k&&"条边的两个顶点:"&&
cin&&m&&n;
if(m&= G.vexnum && n &= G.vexnum && m&0 && n&0){
ArcAdd(G, m, n);
ArcAdd(G, n, m);
cout&&"ERROR."&&
/************************************************************************/
/* 打印邻接表的无向图
/************************************************************************/
void PrintGraph(ALGraph G)
cout&&"无向图的创建完成,该图的邻接表表示为:"&&
ArcNode *p;
for(int i=1; i&=G. i++)
if(G.vertices[i].firstarc == NULL)
cout&&i&&G.vertices[i].data&&"--&NULL"&&
p = G.vertices[i].
cout&&i&&G.vertices[i].data&&"--&";
while(p-&nextarc!=NULL)
cout&&p-&adjvex&&"--&";
cout&&p-&adjvex&&"--&NULL"&&
/************************************************************************/
返回v的第一个邻接顶点。若顶点在G中没有邻接表顶点,则返回“空”。
/************************************************************************/
int FirstAdjVex(ALGraph G,int v)
if(G.vertices[v].firstarc)
return G.vertices[v].firstarc-&
return NULL;
/************************************************************************/
返回v的(相对于w的)下一个邻接顶点。若w是v的最后一个邻接点,则返回“回”。
/************************************************************************/
int NextAdjVex(ALGraph G,int v,int w)
ArcNode *p;
if(G.vertices[v].firstarc==NULL)
return NULL;
p = G.vertices[v].
while(p-&adjvex!=w) p = p-&
if(p-&nextarc == NULL) return NULL;
return p-&nextarc-&
void visitVex(ALGraph G, int v){
cout&&G.vertices[v].data&&" ";
/************************************************************************/
无向图的深度遍历
/************************************************************************/
//从第v个顶点出发递归地深度优先遍历图G
void DFS(ALGraph G,int v)
visited[v] =
visitVex(G, v);
for(int w = FirstAdjVex(G,v);w &= 1; w = NextAdjVex(G,v,w))
if(!visited[w]) DFS(G,w);
//对图G作深度优先遍历
void DFSTraverse(ALGraph G)
for(int v = 1; v &= G. v++) visited[v]=
for(int m = 1; m &= G. m++)
if(!visited[m]) DFS(G,m);
void main(){
ALGraph G;
CreateDG(G);
PrintGraph(G);
DFSTraverse(G);
分析上述算法,在遍历时,对图中每个顶点至多调用一次DFS 函数,因为一旦某个顶点被标志成已被访问,就不再从它出发进行搜索。因此,遍历图的过程实质上是对每个顶点查找其邻接点的过程。其耗费的时间则取决于所采用的存储结构。当用二维数组表示邻接矩阵图的存储结构时,查找每个顶点的邻接点所需时间为O(n2) ,其中n 为图中顶点数。而当以邻接表作图的存储结构时,找邻接点所需时间为O(e),其中e 为无向图中边的数或有向图中弧的数。由此,当以邻接表作存储结构时,深度优先搜索遍历图的时间复杂度为O(n+e) 。
广度优先搜索(Breadth_First Search) 遍历类似于树的按层次遍历的过程。
假设从图中某顶点v 出发,在访问了v 之后依次访问v 的各个未曾访问过和邻接点,然后分别从这些邻接点出发依次访问它们的邻接点,并使“先被访问的顶点的邻接点”先于“后被访问的顶点的邻接点”被访问,直至图中所有已被访问的顶点的邻接点都被访问到。若此时图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。换句话说,广度优先搜索遍历图的过程中以v 为起始点,由近至远,依次访问和v 有路径相通且路径长度为1,2,…的顶点。
对图如下图所示无向图G5 进行广度优先搜索遍历:
广度搜索过程:
首先访问v1 和v1 的邻接点v2 和v3,然后依次访问v2 的邻接点v4 和v5 及v3 的邻接点v6 和v7,最后访问v4 的邻接点v8。由于这些顶点的邻接点均已被访问,并且图中所有顶点都被访问,由些完成了图的遍历。得到的顶点访问序列为:
v1→v2 →v3 →v4→ v5→ v6→ v7 →v8
和深度优先搜索类似,在遍历的过程中也需要一个访问标志数组。并且,为了顺次访问路径长度为2、3、…的顶点,需附设队列以存储已被访问的路径长度为1、2、… 的顶点。实现:
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
#pragma once
#include &stdio.h&
#include "stdlib.h"
// func.h :
#pragma once
#include &iostream&
#define TRUE
#define FALSE
#define NULL 0
#define OK
#define ERROR
#define INFEASIBLE -1
#define OVERFLOW -2
#define INFINITY
#define MAX_VERTEX_NUM 30
typedef int S
typedef int ElemT
typedef int VrT
typedef char VertexT
/************************************************************************/
邻接表示的图数据结构
/************************************************************************/
//定义边结点
typedef struct ArcNode
//弧所指的顶点位置
//指向下一条弧的指针
//定义顶点结点
typedef struct VNode
//顶点信息
//指向第一条依附该顶点的弧的指针
}VNode,AdjList[MAX_VERTEX_NUM];
//定义无向图
typedef struct
int vexnum,
//图的当前顶点数和弧数
/************************************************************************/
/************************************************************************/
typedef struct node //定义结点
typedef struct //定义链表
Link head,
/************************************************************************/
/* 构造一个带头结点和尾结点的空的线性链表队列Q
/************************************************************************/
Status InitQueue(Queue &Q)
Q.head-&next = Q.tail =
Q.tail-&next = NULL;
Q.len = 0;
/************************************************************************/
//在线性链表的队列L的结尾添加一个结点
/************************************************************************/
void EnQueue(Queue &Q,int e)
Q.tail-&next =
Q.tail-&data =
Q.tail-&next = NULL;
/************************************************************************/
/* 出列,并将出列的元素值用e返回
/************************************************************************/
void DeleteQueue(Queue &Q,int &e)
if(Q.head-&next == Q.tail) {
cout&&"队列为空"&&
p = Q.head-&
Q.head-&next =
}// Test.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include "func.h"
bool visited[MAX_VERTEX_NUM];
//访问标识
Status (*VisitFunc) (int v);
//函数变量
/************************************************************************/
/* 在无向图中添加以m,n为顶点的边
/************************************************************************/
void ArcAdd(ALGraph &G,int m,int n){
ArcNode *p,*h,*q;
p = new ArcN
p-&adjvex =
p-&nextarc = NULL;
h = q = G.vertices[n].
if(q == NULL)
G.vertices[n].firstarc =
if((p-&adjvex)&(q-&adjvex)){
p-&nextarc =
G.vertices[n].firstarc =
while( G.vertices[n].firstarc != NULL && q-&nextarc != NULL && (p-&adjvex)&(q-&adjvex)){
//使邻接表中边的数据按大到小排列。
if(q-&nextarc == NULL&&(p-&adjvex)&(q-&adjvex)){
q-&nextarc =
p-&nextarc =
h-&nextarc =
/************************************************************************/
创建无向图
/************************************************************************/
void CreateDG(ALGraph &G){
cout&&"请输入顶点个数和边数:"&&
cin&& G.vexnum&& G.
cout&&"请输入顶点值:"&&
for(int i= 1; i&= G. i++) {
G.vertices[i].data =
G.vertices[i].firstarc = NULL;
for(int k = 1; k&=G. k++){
cout&&"请输入第"&&k&&"条边的两个顶点:"&&
cin&&m&&n;
if(m&= G.vexnum && n &= G.vexnum && m&0 && n&0){
ArcAdd(G, m, n);
ArcAdd(G, n, m);
cout&&"ERROR."&&
/************************************************************************/
/* 打印邻接表的无向图
/************************************************************************/
void PrintGraph(ALGraph G)
cout&&"无向图的创建完成,该图的邻接表表示为:"&&
ArcNode *p;
for(int i=1; i&=G. i++)
if(G.vertices[i].firstarc == NULL)
cout&&i&&G.vertices[i].data&&"--&NULL"&&
p = G.vertices[i].
cout&&i&&G.vertices[i].data&&"--&";
while(p-&nextarc!=NULL)
cout&&p-&adjvex&&"--&";
cout&&p-&adjvex&&"--&NULL"&&
/************************************************************************/
返回v的第一个邻接顶点。若顶点在G中没有邻接表顶点,则返回“空”。
/************************************************************************/
int FirstAdjVex(ALGraph G,int v)
if(G.vertices[v].firstarc)
return G.vertices[v].firstarc-&
return NULL;
/************************************************************************/
返回v的(相对于w的)下一个邻接顶点。若w是v的最后一个邻接点,则返回“回”。
/************************************************************************/
int NextAdjVex(ALGraph G,int v,int w)
ArcNode *p;
if(G.vertices[v].firstarc==NULL)
return NULL;
p = G.vertices[v].
while(p-&adjvex!=w) p = p-&
if(p-&nextarc == NULL) return NULL;
return p-&nextarc-&
void visitVex(ALGraph G, int v){
cout&&G.vertices[v].data&&" ";
/************************************************************************/
广度优先遍历图G
/************************************************************************/
void BFSTraverse(ALGraph G)
for(int m=1; m&= G. m++) visited[m] =
InitQueue(Q);//借助辅助队列。
for(int v=1;v&=G.v++)
if(!visited[v]) {
visited[v]=
visitVex(G,v);
EnQueue(Q,v);
while(Q.len!=0)
DeleteQueue(Q,u);
for(int w=FirstAdjVex(G,u);w&=1;w=NextAdjVex(G,u,w))
if(!visited[w])
visited[w]=
visitVex(G,v);
EnQueue(Q,w);
void main(){
ALGraph G;
CreateDG(G);
PrintGraph(G);
cout&&"广度优先搜索的结果为:"&&
BFSTraverse(G);
分析上述算法,每个顶点至多进一次队列。遍历图的过程实质是通过边或弧找邻接点的过程,因此广度优先搜索遍历图的时间复杂度和深度优先搜索遍历相同,两者不同之处仅仅在于对顶点访问的顺序不同。后使用快捷导航没有帐号?
合作网站账号登录
查看: 42858|回复: 139
UID3488760在线时间2414 小时帖子阅读权限150注册时间最后登录积分8708星光23 经验6408 人气161 钻石2828 金币21340
UID3488760星光23 经验6408 人气161 钻石2828
希望转载者注明出处和作者,特别是后者。
作者是178的JQKA5401和陈雨
6月7日更新后无效
独自摸索了宏将近2个来月,作为一个研究宏的应用但是却不用宏的人,我感觉鸭梨很大。好吧,我不是标题党,不很写很引人注目的标题。通常这类帖子沉得很快(详情请参考前面写的的两篇七秀攻略贴),我也不想弄什么回复可见。如果大家觉得好的话就回一个帖子,作为对我的一种支持,如果喷,请不要人身攻击,虽然我很淡定,但是不想口水。自从第一篇攻略帖子开始,就习惯写些有的没有的前言,主要介绍下为什么会写这篇攻略,嗯,其实我的志向是当作者。言归正传,很多朋友们都在论坛上发帖求宏,我都尽量去满足。我个人认为给你宏,不如给你方法,我想很多研究宏的,写宏的,钻研程序的都有这种感觉,就像他们说的受人之鱼不如受人之渔。很多人都喜欢不劳而获,这种现象是很不正确的,你有一个脑子不是用来控制你的口和手来索要,而是用来思考。好了,就说不说太多废话,以下文章中的实例大部分都在近期进行过实验,证明有效,没有实验过的请慎用(会特别标明)。如果有任何疑问,欢迎大家发帖询问,只要是我能力范围内能做到的,一定给你一个满意的答复。在此,感谢陈雨姐姐技术上的支持,回答我一些很傻得问题。同时感谢各位分享宏的先驱们,你们的例子,给了我一些新的想法,才有了我的研究和这篇帖子。如有错误请指正,核实后会进行修改,感谢肯花时间看帖的童鞋们。这篇帖子起到一个整合的作用,几乎包含了常用的宏,可以作为一个检索以及研究方向,欢迎广大研究人士参考学习指正,在此抛砖引玉。
什么是宏?
我相信很多朋友们都不知道什么是宏,老听别人说用宏用宏,自己却不知道是啥意思,特此在这里扫盲一下。在计算机科学里的宏是一种抽象,它根据一系列预定义的规则替换一定的文本模式。简单来说,可以把他想像成一个小程序,按照特定的指令来执行命令。
比如说气纯的爆发宏:两仪化形+韬光养晦+两仪化形+带脉光明+韬光养晦+两仪化形
按照平常时候,这样的一个组合操作需要3个键位。在不考虑心理因素,网络因素下,这一套爆发需要将近5秒的时间。然而,在理论上,宏可以将这一套爆发的时间缩短为3秒,而考虑到各种原因,也就4到5秒的时间。既然时间差不多那么为什么要用宏?首先,是结合了按键,再来是简化了操作,从而起到在紧张时候不容易按错,最后,起到了缓和网络延迟的作用。这个就是最常见的一种宏,人们口中常说的一键爆发。
首先写宏必须知道宏语言以及命令格式,API等等,没有这些东西,是写不出来宏的。API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件的以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。简单的说就是金山给我们写宏的基础语言,例如魔兽中的/cast。因为金山的宏没有通过封装,所以不宜推广,这也是为什么很多人觉得困难的原因。但是如果了解了这些未封装的语言(其实只需要懂一点点英文)是什么意思,那么就可以进行套用,这也是一个学习宏的方法。根据先驱者们所发的宏跟作用解释,来推断每一行的意思,在进行验证,那么可以说是懂得了这个宏。
下面介绍一些常用的API
GetClientPlayer()
字面上的意思为获取客户端玩家,实际效果也是如此,以下同理
GetTarget()
GetTargetHandle()
获取指定目标ID
GetKungfuMount()
获取当前装备内功
GetDistanceByTarget(target1, target2)
获取target1跟target2指间的距离
GetSkillPrepareState()
获取读条状态
GetSkillCDProgress()
获取技能冷却时间
PLAYER_TALK_CHANNEL
玩家说话频道
OnUseSkill()
GetSkillLevel()
获取技能等级
StopCurrentAction()
停止当前动作
nCurrentLife
最大MaxLife
nCurrentMana
bFightState
战斗状态,true为战斗状态,false为非战斗状态
是否在马上
nAccumulateValue
纯阳或和尚的气或豆的个数
纯阳为半个气为1,也就是0-10之间的数,比如7就是3个半气
和尚为0-3指间的数,一比一
nCurrentRage
藏剑剑气值判断项,最小为0,最大为100
基本上常用的就是这些了,光是知道这些也是写不出来宏的,只有知道如何运用他们才能写出一个可用的宏来。
写宏最先要知道的就是技能的ID,将鼠标移到技能上面按住CTRL,会出现一个调试用信息,如下图
19:11 上传
由于金山截图机制貌似有点改动,所以图片不是很清楚。
如图所示,有个ID的地方写着561,level 9
这就是技能的ID与等级,在写使用技能的宏时非常有用。
基本语句:
这是剑三宏里面最常用的语句,其他的语句类型由于不常用则不做另外介绍
if& &条件&&then
if就是如果的意思,如果&&“条件”& &则执行&&“语句”& &如果达不到条件,则直接结束 if 语句块。
————————————————————————————————————————————————————
扩展格式:
if 条件 then
else (if&&条件 then)
如果&&“条件”& &则执行&&“语句”& &如果达不到条件,则执行ELSE的语句,然后结束 if 语句块。
————————————————————————————————————————————————————
for 循环变量 = 初值, 终值 do
————————————————————————————————————————————————————
扩展格式:
for 循环变量 = 初值, 终值,每次的增量 do
————————————————————————————————————————————————————
函数封装:
function 函数名(参数列表)
这是比较高级的运用,目的是为了简化宏,在判断同一类型条件的时候会用到,后面会详细介绍。
判断条件以及数值的表达式。
最常用的表达式为and,用于判断多个条件。其次是一些数值的判断例如:
双等号是判断,单等号是赋值,最后一个是不等于(可能出现未知错误,尽量少用不等于这个符号),其他的,嗯,不多解释。
思考要做一个什么宏。
例如我想做一个减少键位的宏,将坐忘无我,回春妙手跟猛虎下山这三个技能合并为一个键上,属于装备猛虎下山秘籍后的PVP宏。
首先去寻找技能ID:
猛虎下山 58,1
回春妙手 52,2
坐忘无我 312,X
这里由于坐忘没有满级,可能在战斗中提升等级,而导致宏不能用,那么在下面将提出解决方法。
写一个宏。
写宏的时候尤其要注意大小写的问题以及括号的问题- -,本人多次因为有一个字母本该小写却打成大写后导致运行不成功。
看以下例子:
/script N=GetClientPlayer()
/script a,b,c=N.GetSkillCDProgress(312,N.GetSkillLevel(312))
/script d,e,f=N.GetSkillCDProgress(58,1)
/script g,h,i=N.GetSkillCDProgress(52,2)
/script&&if f==0 then OnUseSkill(58,1) end
/script&&if c==0 then OnUseSkill(312,N.GetSkillLevel(312)) end
/script if&&i==0 then OnUseSkill(52,2) end
第一行是宣告一个变量N作为GetClientPlayer()的代替,大致上就跟数学里的设X一样,属于一种简单的函数封装,为了简化下面的语句。
第二,三,四行为判断技能冷却的语句,由于这里并不是很多,所以不用通过FUNCTION来封装。
第二行有一个获取技能等级的是因为不确定技能等级为多少,如果错误的填一个数字进去,则整个宏作用失效。当然如果知道技能等级则可以像第三,四行一样简化。
这里每行设置的三个数,a到i,其中每行的第二个字母,为该技能的公共冷却,第三个字母为技能冷却。
则:a,d,g为空。b,e,h为技能当前冷却时间,c,f,i为技能总共冷却时间,所以说随便判断一个都是一样的。例如a,b,c是获取天地低昂的调息时间,那么a为空,b的值为剩余秒数乘以16,c的值为90秒乘以16(带秘籍)。
B,C在初始的时候为0,在有技能释放,例如江海凝光,B,C虽然是天地低昂的调息时间判断,却会改变自身的值,B为剩余公共冷却秒数乘以16,C为24。所以说公共调息时间为24除以16=1.5秒。如果使用不占用公共调息的技能时,则B,C值不变。
第五行,如果技能猛虎下山(58)冷却为零,则使用猛虎下山
第六行,如果技能坐忘无我(312)冷却为零,则使用坐忘无我
第七行,如果技能回春妙手(52)冷却为零,则使用回春妙手
检查宏的效果,如果达到预期效果,那么这个宏就算做好了。
如果出错则要看看错误是在哪里,比如说,回春妙手用不出来,那么就检查第四跟七行是否有语句上的基本错误,如果没有再从第一行开始检查。
宏的基本运用
一键多技能
如上面得例子,将所有的技能合并到一个键上,通过各种条件判断技能释放前后。
注意事项:所有有公共冷却以及冷却时间的技能,都需要加入冷却时间判断,才能整合在一起。例外:名动四方
这是判断公共CD跟技能CD,一般情况下只用判断技能CD,格式如下:
/script N=GetClientPlayer()
/script XX1,XX2,XX3=N.GetSkillCDProgress(XXX,X)
/script YY1,YY2,YY3=N.GetSkillCDProgress(YYY,Y)
/script ZZ1,ZZ2,ZZ3=N.GetSkillCDProgress(ZZZ,Z)
/script&&if XX2==0 and XX3==0 then OnUseSkill(XXX,X) end
/script&&if YY2==0 and YY3==0 then OnUseSkill(YYY,Y) end
/script if&&ZZ2==0 and ZZ3==0 then OnUseSkill(ZZZ,Z) end
这是一个简单的技能冷却一到就使用技能的宏,适合于练第二门派技能的时候。
如果技能多了,可以进行函数封装:
下面是技能冷却的封装,调用的时候作为一个条件来用,只用改变括号里的ID就行了。
/scrpit function cd(id) A,B,C=N.GetSkillCDProgress(id,N.GetSkillLevel(id)) return C end
如果是判断坐忘无我的话就这样
/script if cd(312)==0 then OnUseSkill(312,N.GetSkillLevel(312)) end
这个是一个判断技能冷却以及使用技能的封装,一般情况下只需要直接使用就好了。
/script function use(id) A,B,C=N.GetSkillCDProgress(id,N.GetSkillLevel(id)) if C==0 then OnUseSkill(id,N.GetSkillLevel(id)) end end
如果是判断坐忘无我的话就这样
/script use(312)
buff判断封装
/script function buff(mb,id,lvl) for _, D in pairs(mb.GetBuffList() or {}) do if D.dwID==id and (lvl==nil or D.dwLevel==lvl) then return true end end return false end
可以判断自己或者敌人的BUFF跟DEBUFF,以及BUFF跟DEBUFF的等级,作为一个条件,下面有实例。
省事很多。
关于七秀的一键整合
由于名动四方这个特殊的BUFF,需要加入一个判断BUFF的判断。
下面就以一键爆发来说明
满堂势+繁音急节+冲脉关门+剑气长江+剑主天地+剑心通明
剑舞BUFF(409)
名动四方(537,7)
满堂势(573,1)
繁音急节(568,4)
冲脉关门(168,1)
剑气长江(561,9)
剑主天地(562,10)
剑心通明(547,5)
有这么多技能就需要一些封装,不然写出来都是一大串。
/script N=GetClientPlayer()
/script function use(id) A,B,C=N.GetSkillCDProgress(id,N.GetSkillLevel(id)) if C==0 then OnUseSkill(id,N.GetSkillLevel(id)) end end
/script function buff(mb,id,lvl) for _, D in pairs(mb.GetBuffList() or {}) do if D.dwID==id and (lvl==nil or D.dwLevel==lvl) then return true end end return false end
/script use(547)
/script if not buff(N,409,35) then use(573) end
/script if not buff(N,409) then use(537) end
/script if not buff(N,568) then use(568) end
/script use(168)
/script if buff(N,409) then use(561) end
/script if buff(N,409) then use(562) end
第一行是一个小封装,详细见上面。
第二行一个使用技能的封装,use(id)括号里的ID替代为技能ID。宣告ABC为获取技能冷却,如果技能CD等于0,则使用该技能。
第三行是一个判断BUFF的封装,buff(mb,id,lvl)括号里前面一个代表目标,后面一个是buffID,最后一个是判断BUFF等级,如果不填就不判断。这是一个判断目标BUFF跟DEBUFF的封装,只要需要判断BUFF就可以用到这个函数,我们这里目标是我们自己所以为N,剑舞BUFF为 409。在这里是为了判断剑舞是不是达到满堂势剑舞的等级,满堂势剑舞等级为35,而满层剑舞等级为34。
第四行是使用剑心通明
第五行是如果没有剑舞则使用满堂势
第六行是如果没有剑舞则使用剑舞(怕有些时候满堂势被去掉)
第七行是如果没有繁音,则使用繁音
第八行是使用冲脉关门
第九行是如果有剑舞则使用剑气长江
第十行是如果有剑舞则使用剑主天地
喜欢研究的同学可以对照研究,喜欢照搬的同学可以直接搬走。其他的一键输出可以参考这一项,后面会给一些实际例子。
关于其他技能整合
除了一键输出,宏可以用来解决键位问题,主要用于辅助技能整理,两个门派技能键位整合。
/script N=GetClientPlayer()
/script P=N.nAccumulateValue
/script function use(id) A,B,C=N.GetSkillCDProgress(id,N.GetSkillLevel(id)) if C==0 then OnUseSkill(id,N.GetSkillLevel(id)) end end
/script K=N.GetKungfuMount().dwSkillID
/script if K==10080 or K==10081 then use(544) end
/script if K==10014 and P&0 then use(303) end
第一二三四行为封装,不多解释。
第五行,如果内功为冰心或者云裳,则使用技能帝骖龙翔
第六行,如果内功为紫霞功(俗称气纯)以及气大于半格,则使用三才化生。
嗯,这是一个比较简单的不同门派内功绑定同一个键位的,由于这两种都是同一类型的技能,所以归类在一起。
内功的ID如下:
10002 洗髓经
10003 易筋经
10014 紫霞功
10015 太虚剑意
10021 花间游
10026 傲血战意
10028 离经易道
10062 铁牢律
10080 云裳心经
10081 冰心诀
10144 问水决
10145 山居剑意
判断其他内功的将那个数字替换就可以了,例如剑纯跟气纯的气场其实可以整合在一起。例如碎星辰+冲阴阳为一组等等,请自行组合。
/script for i=1,1 do GetClientPlayer().Talk(PLAYER_TALK_CHANNEL.NEARBY, &密语对象&, {{type = &text&, text = &请输入内容&}})
简单明了,作用于循环喊话。
前面的for i=1,1 是喊话一次, for i=1,2 是喊话2次
另外一个比较简化的是一个封装,可以用作判断。
/script N=GetClientPlayer()
/script function say() N.Talk(PLAYER_TALK_CHANNEL.NEARBY,&密语对象&,{{type=&text&,text =&请输入内容&}})
其他频道喊话只需要把NEARBY更换掉就好了(全部为大写):
NEARBY 近聊
SENCE 地图
WORLD 世界
RAID&&团队
BATTLE&&战场
TONG&&帮会
SCHOOL&&门派
CAMP& &阵营
FRIENDS& &好友
附带一个上马下马不同喊话的喊话宏:
/script N=GetClientPlayer()
/script function say1() N.Talk(PLAYER_TALK_CHANNEL.NEARBY,&&,{{type=&text&,text =&我有一头小毛驴,但我从来也不骑&}}) end
/script function say2() N.Talk(PLAYER_TALK_CHANNEL.NEARBY,&&,{{type=&text&,text =&小毛驴累了&}})
/script function buff(mb,id,lvl) for _, D in pairs(mb.GetBuffList() or {}) do if D.dwID==id and (lvl==nil or D.dwLevel==lvl) then return true end end
return false end
/script OnUseSkill(605,1)
/script if buff(N,244) then say2() else say1() end
/script N=GetClientPlayer()
/script H=N.bOnHorse
/script function say1()N.Talk(PLAYER_TALK_CHANNEL.NEARBY,&&,{{type=&text&,text =&我有一头小毛驴,但我从来也不骑&}}) end
/script function say2() N.Talk(PLAYER_TALK_CHANNEL.NEARBY,&&,{{type=&text&,text =&小毛驴累了&}})
/script if H==true then say2() else say1() end
/script OnUseSkill(605,1)
前者与后者的不同之处在于前者是判断骑马时的增益状态,后者是判断是否在马上。
喊话附带当前目标名字
/script N=GetClientPlayer()
/script name=GetTargetName(N.GetTarget())
/script for i=1,3 do N.Talk(PLAYER_TALK_CHANNEL.NEARBY,&&,{{type=&text&,text =&我已经对&&&&..name..&&&&舍身!!!!!&}})
/script OnUseSkill(258,1)
施展舍生并且喊话3次。内容为:我已经对&&&目标&&&舍身!!!!!
其中第二行就是获取目标名字的命令
这中间的两个点很重要,起到了连接的作用。
关于智能判断
这里介绍下比较常用的几项判断:
1.增益与减益的判断(buff或者debuff,见上)
2.技能冷却判断(见上)
3.纯阳与和尚的集气判断(见上)
4.气血以及内力的值或者比的判断
5.读条状态
6.距离判断
前四项可以在上面找到解释,这里只是重复解释一下。
1.增益于减益判断
建议使用函数封装,以下为原始语句:
以下为自身增益的检测
/script for _, D in pairs(GetClientPlayer().GetBuffList()) do if D.dwID == 增益的ID then 执行语句
以下为自身减益的检测
/script for _, D in pairs(GetClientPlayer().GetBuffList() or {}) do if D.dwID == 减益的ID then 执行语句
那么进行一下封装,成一个比较灵活的检测目标增益减益以及等级的判断
/script function buff(mb,id,lvl) for _, D in pairs(mb.GetBuffList() or {}) do if D.dwID==id and (lvl==nil or D.dwLevel==lvl) then return true end end
return false end
如果前面加入了小封装,则N=自身,T等于敌对目标的话,在这里,MB=N就是判断自身状态,MB=T就是判断敌方状态。 ID就是增益减益的ID,等级对应BUFF等级,有些BUFF有
层数的,如剑舞。
2.技能冷却判断
同样建议使用函数封装,以下为原始语句
/script XX1,XX2,XX3=N.GetSkillCDProgress(技能ID,技能等级)
这XX1用不到,XX2是代表公共冷却,XX3则是代表技能冷却。
进行下简单的封装
/scrpit function cd(id) A,B,C=N.GetSkillCDProgress(id,N.GetSkillLevel(id)) return C end
如果要将技能冷却判断跟使用技能一起封装的话就这样
/script function use(id) A,B,C=N.GetSkillCDProgress(id,N.GetSkillLevel(id)) if C==0 then OnUseSkill(id,N.GetSkillLevel(id)) end end
3.纯阳与和尚的集气判断
判断集气的API是
nAccumulateValue
纯阳或和尚的气或豆的个数
纯阳为半个气为1,也就是0-10之间的数,比如7就是3个半气
和尚为0-3指间的数,一比一
只能判断自身集气数,没有强大到判断敌方集气数。
使用方法如下
/script if GetClientPlayer.nAccumulateValue==10 then OnUseSkill(301,X) end
进行下封装
/script P=GetClientPlayer.nAccumulateValue
/script if P==10 then OnUseSkill(301,X) end
4.气血以及内力值或者比的判断
关于这类的判断会用到以下几个API
nCurrentLife
nCurrentMana
判断自身当前生命值
/script HP=GetClientPlayer.nCurrentLife
/script if HP=&5000 then OnUseSkill(XXX,X) end
判断内力值就把nCurrentLife换成nCurrentMana
判断自身生命比
/script HPR=GetClientPlayer.nCurrentLife/GetCLientPlayer.nMaxLife
/script if HPR&=0.5 then OnUseSkill(XXX,X) end
判断自身当前内力比就将nCurrentLife以及nMaxLife,换成对应的nCurrentMana跟nMaxMana
判断敌方当前生命值
/script T=GetTargetHandle(GetClientPlayer.GetTarget())
/script tHP=T.nCurrentLife
/script if tHP&=5000 then OnUseSkill(XXX,X) end
判断内力值就把nCurrentLife换成nCurrentMana
判断敌方生命比
/script T=GetTargetHandle(GetClientPlayer.GetTarget())
/script tHPR=T.nCurrentLife/T.nMaxLife
/script if tHPR&=0.5 then OnUseSkill(XXX,X) end
判断自身当前内力比就将nCurrentLife以及nMaxLife,换成对应的nCurrentMana跟nMaxMana
5.读条状态
判断自身读条状态
/script N=GetClientPlayer()
/script bPrePare, dwID, dwLevel, fP = N.GetSkillPrepareState()
/script if bPrePare then N.StopCurrentAction() end
如果自身处于读条状态,则打断读条。
判断敌方读条状态
/script N=GetClientPlayer()
/script t=GetTargetHandle(N.GetTarget())
/script bPrePare, dwID, dwLevel, fP = t.GetSkillPrepareState()
/script if bPrePare then OnUseSkill(547,5) end
如果对方读条,则使用剑心通明打断。
判断敌方读条技能
/script N=GetClientPlayer()
/script t=GetTargetHandle(N.GetTarget())
/script bPrePare, dwID, dwLevel, fP = t.GetSkillPrepareState()
/script if bPrePare and dwID==367 then OnUseSkill(547,5) else OnUseSkill(553,10) end
如果对方读条技能为四象轮回,则使用剑心通明打断,反之使用江海凝光。
有心的同学们可以发现这里这个判断释放什么技能的很强力,嗯,确实很强力,例如BOSS使用读条技能,可以作为一个判断BOSS技能的,例如镇龙头。
问题:如何得知BOSS技能ID?
有一种笨办法就是自己去收集,嗯,如何收集见下:
/script N=GetClientPlayer()
/script t=GetTargetHandle(N.GetTarget())
/script bPrePare, dwID, dwLevel, fP = t.GetSkillPrepareState()
/script OutputMessage(&MSG_SYS&,dwID)
/script OutputMessage(&MSG_SYS&,&,&)
/script OutputMessage(&MSG_SYS&,dwLevel)
在BOSS读条的时候在聊天窗口返回两个数值,用逗号隔开,方便辨认,前一个数值就是BOSS技能的ID,后一个是技能等级。然后加入进判断条件里面就可以做到镇龙头开御,佛归西扶摇等。
另外一种方法:(由178的SQ圣力提供)
通过技能名字来写判断。
/script N=GetClientPlayer()
/script t=GetTargetHandle(N.GetTarget())
/script bPrePare, dwID, dwLevel, fP = t.GetSkillPrepareState()
/script if bPrePare and Table_GetSkillName(dwID, dwLevel)==&四象轮回& then OnUseSkill(547,5) else OnUseSkill(553,10) end
6.距离判断
嗯,关于距离判断的比较复杂,我尽量解释清楚。
第一种是:
/script N = GetClientPlayer()
/script t=GetTargetHandle(N.GetTarget())
/script function GetDistanceByTarget(target1, target2)
if not target1 or not target2 then return false end
if target1.nMapID ~= target2.nMapID then return false end
nX1= target1.nX
nX2 = target2.nX
nY1 = target1.nY
nY2 = target2.nY
strdis=(((nX1 - nX2) ^ 2 + (nY1 - nY2) ^ 2) ^ 0.5)/64
return strdis
/script d=GetDistanceByTarget(t,N)
中间那个函数就是计算距离的,通过人工的方式来计算。
如果没有目标则返回FALSE
如果两个目标不在一个地图,则返回FALSE
NX1是目标1的X坐标
NX2是目标2的X坐标
NY1是目标1的Y坐标
NY2是目标2的Y坐标
直线距离等于((X1-X2)的平方加上(Y1-Y2)的平方)的0.5次方除以64
返回直线距离
另外一种比较简单的
/script N = GetClientPlayer()
/script t=GetTargetHandle(N.GetTarget())
/script m=GetCharacterDistance(N.dwID,t.dwID)
这种判断在判断距离的时候要除以64,才是真正的距离
为了方便加入一个封装
/script d=m/64
调用距离的时候就使用d
附带一个例子:
判断距离如果目标距离小于6尺使用冲脉太乙加九转归一,如果目标距离大于6尺并且小于8尺则使用九转归一。
/script N = GetClientPlayer();
/script t=GetTargetHandle(N.GetTarget())
/script m=GetCharacterDistance(N.dwID,t.dwID)
/script d=m/64
/script if d&=6 then OnUseSkill(169,1) end
/script if d&=6 then OnUseSkill(305,1) end
/script if d&6 and d&8 then OnUseSkill(305,1) end
关于玩家的移动状态
剑三之中有各种状态判定,以下为一个列表。
MOVE_STATE.ON_STAND& && && && &= &站立&,& && && &
MOVE_STATE.ON_WALK& && &&&= &走路&,& && && &
MOVE_STATE.ON_RUN& && && && && & = &跑步&,& && && &
MOVE_STATE.ON_JUMP& && &&&= &跳跃&,& && && &
MOVE_STATE.ON_SWIM_JUMP& && &&&= &水中跳跃&,& &
MOVE_STATE.ON_SWIM& && &&&= &游泳&,& && && &
MOVE_STATE.ON_FLOAT& && && && &= &水中悬浮&,& && &
MOVE_STATE.ON_SIT& && && && && & = &坐下&,& && && &
MOVE_STATE.ON_KNOCKED_DOWN& & = &被击倒&,& &
MOVE_STATE.ON_KNOCKED_BACK& & = &被击退&,& &
MOVE_STATE.ON_KNOCKED_OFF& && &&&= &被击飞&,& &
MOVE_STATE.ON_HALT& && && && &= &眩晕&,& && && &
MOVE_STATE.ON_FREEZE& && && && &= &定身&,& && &&&
MOVE_STATE.ON_ENTRAP& && && && &= &锁足&,& && &&&
MOVE_STATE.ON_AUTO_FLY& && &&&= &乘坐交通工具&,
MOVE_STATE.ON_DEATH& && && && &= &重伤&,& && && &
MOVE_STATE.ON_DASH& && && && &= &冲刺&,& && && &
MOVE_STATE.ON_PULL& && && && &= &被抓&,& && && &
MOVE_STATE.ON_REPULSED& && &&&= &滑行&,& && &&&
MOVE_STATE.ON_RISE& && && && &= &爬起&,& && && &
MOVE_STATE.ON_SKID& && && && &= &滑行&,
一般常用的就只有站立,倒地,眩晕,定身,跟锁足
以下为格式
/script N=GetClientPlayer()
/script if N.nMoveState == MOVE_STATE.ON_KNOCKED_DOWN then 执行命令 end
/script N=GetClientPlayer()
/script t=GetTargetHandle(N.GetTarget())
/script if t.nMoveState == MOVE_STATE.ON_KNOCKED_DOWN then OnUseSkill(402,N.GetSkillLevel(402)) end
目标倒地则使用定军
关于目标类型判断
剑三里面的目标有三种类型,敌对,中立跟友善,其中敌对包括了黄名,但是鼠标移上去是剑符号那种,判断目标是否敌对对于藏剑来说是个不小的帮助,当然对于其他职业来说也有帮助。
判断的三个参数:
IsEnemy 敌对
IsAlly 友善
IsNeutrality 中立
以下为万花治疗判断宏:
/script N=GetClientPlayer()
/script t=GetTargetHandle(N.GetTarget())
/script tT,tID=N.GetTarget()
/script if IsEnemy(N.dwID,tID) then thp=N.nCurrentLife/N.nMaxLife elseif IsAlly(N.dwID,tID) or IsNeutrality(N.dwID,tID) then thp=t.nCurrentLife/t.nMaxLife end
/script function run(id) A,B,C=N.GetSkillCDProgress(id,N.GetSkillLevel(id)) if C==0 then OnUseSkill(id,N.GetSkillLevel(id)) end end
/script function buff(mb,id,lvl) for _, D in pairs(mb.GetBuffList() or {}) do if D.dwID==id and (lvl==nil or D.dwLevel==lvl) then return true end end return false end
/script if&&thp&=0.3 then run(136) end
/script if buff(N,722) or buff(N,412) then run(142) end
/script if buff(t,631) then run(137) end
/script run(101)
如果目标是敌对,则判断自身血量,血量少于30%进行水月长针急救措施
如果目标是友方或者中立,则判断目标血量,血量少于30%进行水月长针救急
自动补握针,出逐流效果后自动转为施放长针,其余时间无脑局针。
/script N=GetClientPlayer()
/script tT,tID=N.GetTarget()
/script kungfu=N.GetKungfuMount().dwSkillID
/script function run(id) A,B,C=N.GetSkillCDProgress(id,N.GetSkillLevel(id)) if C==0 then OnUseSkill(id,N.GetSkillLevel(id)) end end
/script if kungfu==10144 then if IsEnemy(N.dwID,tID) then run(1577) elseif IsAlly(N.dwID,tID) or IsNeutrality(N.dwID,tID) then run(1655) end elseif kungfu==10145 then if IsEnemy(N.dwID,tID) then run(1613) elseif IsAlly(N.dwID,tID) or IsNeutrality(N.dwID,tID)&&then run(1655) end end
轻剑下目标为友方就探梅,敌方就玉虹贯日
重剑下目标友方就探梅,敌方就放云景
/script tT,tID=N.GetTarget();
这一行其实是个简写,其中tT是target type,tID是target ID
为获取当前目标定义两个值,一个是目标的类型,一个是目标ID
而IsEnemy(N.dwID,tID),IsAlly(N.dwID,tID) ,IsNeutrality(N.dwID,tID)
是判断目标类型是否为敌人,(N.dwID,tID)这个就是说这项判断是在自身与自身目标两个之间进行,可以换成他人与他人之间的关系判定。这是用ID来判断,所以说,这个就是判断自身跟目标之间的关系。
关于范围内敌人数量判断(感谢呆瓜)
/script N=GetClientPlayer()
/script tT,tID=N.GetTarget()
/script EnemyNum=0
/script for _,dwNpcID in pairs(GetNpcList()) do hNpc = GetNpc(dwNpcID) if IsEnemy(hNpc.dwID, N.dwID) and GetCharacterDistance(N.dwID,hNpc.dwID)&=8*64 then EnemyNum=EnemyNum+1 end end
参考呆瓜的藏剑一键DPS,感谢作者
这个是一个判断8尺内敌人数目的宏
1,2行不解释,3行定义一个值EnemyNum为0,4行是获取周围NPC列表,然后定义一个hNpc的值为获取NPC的ID,如果该NPC与玩家为敌对,该NPC与玩家距离小于8尺,则在前面定义的值上+1。那么EnemyNum就成为了一个8尺内敌对目标的判断数据。
至于这里距离判断为什么是乘以64而不是除以64,这跟开始定义的值有关系
/script N = GetClientPlayer()
/script t=GetTargetHandle(N.GetTarget())
/script m=GetCharacterDistance(N.dwID,t.dwID)
这里判断的是当前目标的TargetHandle这个东西
/script tT,tID=N.GetTarget()
而这里是获取当前目标类型与ID
定义的东西不一样,所以一个是乘一个是除,很容易搞混乱
很早以前其实就研究了这个东西,不过纠结于不太明白原理而没有放出来,现在虽然还是不太懂,但我尽量解释,不懂的地方可以回帖或者PM我。
关于使用物品
使用物品其实就只有一个简单的命令
/script OnUseItem(X,Y)
在这里X代表要使用的物品处于第几个背包,Y则是代表物品处于背包的第几格。
注意,这里的Y值是从0开始算的,也就是说16格包包对应的格子号为0到15,不是1到16.
对于使用整合背包的同学们,还请调换成基础背包模式,就是一个一个背包分开那种。
通过物品名称来使用物品
先看下下面这个函数封装:
/script function Use(szName)
& & N=GetClientPlayer()
& &&&for i=1,5 do
& && &&&if N.GetBoxSize(i)&0 then
& && && && &for j=0,N.GetBoxSize(i)-1 do
& && && && && & item=N.GetItem(i,j)
& && && && && & bCool, nLeft, _, _=N.GetItemCDProgress(i,j)
& && && && && & if GetItemNameByItem(item)==szName and (not bCool or nLeft==0)&&then
& && && && && && && &&&OnUseItem(i,j,BigBagPanel_GetItemBox(i,j))
& && && && && & end
& && && && &end
& && &&&end
/script Use(&上品活络丸&)
1.建立一个为Use的函数
2.申请一个为N的变量,这个变量代表当前玩家
3.建立一个i的循环,这个循环从1开始,会重复执行5次(一共有5个包)
4.将i值当做玩家当前背包格子,如果i&0,则执行(注:i在这里是什么作用的问题,在这个循环里,i从1开始执行,那么第一次的N.GetBoxSize(1)就是获取第一个包的格子数量,那么第二次执行的时候就是N.GetBoxSize(2)就是获取第二个包的格子数量,以此类推直到第五个包。当返回格子为0的时候,代表没有装备包包栏上没有装备包包,那么这个循环就会终止。例如装备了2个包包,加上本来的那个一共3个包包,那么他就会在第4次执行的时候返回0,然后在这里停下来,因为第4个包包没有装备上去。)
5.建立一个为j的循环,这个循环从0开始,会重复执行i值-1次(i这个值是返回包包格子数量,但是从使用物品的原理上来看,Y也就是现在的j是从0开始的,那么在这里要从第一格开始循环就要减去1,因为是从0开始循环的。例如包包装备栏左起第二个是16格包,那么N.GetBoxSize(2)=16,j=15,范围从0到15,符合前面Y的要求。)
6.申请一个item的变量,这个变量作用是获取道具的i,j值
7.申请4个变量,这4个变量作为判断物品状态,后两个值为空,第一个值为冷却时间,第二个值为剩余数量
8.如果,获取item的名字等于我们所输入的名字,且物品不在冷却以及还有剩余的时候,则执行
9.获取i,j值,并使用位于i,j的物品
其实有些地方我依旧不是很明白,例如说关于语句为什么这么用,但是大体上设计方向是:
通过输入物品名字,达到使用该物品的效果。
问题:使用物品只能通过坐标使用(见上)
解决方案:通过对每一个格子的物品进行校对,来获取坐标值,当物品名字等于我们所输入的物品名字时候,这时返回i值跟j值,通过这个坐标值来使用相应物品。例如:当i循环到第4次,j循环到第8次的时候,发现名字吻合,那么这时的i值就等于4,j值等于8,也就是说使用第4个包包的第9格物品。
以上原理不喜欢研究的可以不用去弄懂,直接复制这个函数,并且修改物品名字就好了。
使用装备的道具
有些装备是能够使用的,例如:圣士腰坠,东海珠坠等,那么在一键爆发的时候可以将这些加入其中增强爆发能力。语句如下:
/script OnUseItem(CharacterPanel.m_nObjectType,9,CharacterPanel_GetItemBox(INVENTORY_INDEX.EQUIP,9,true))
如果要跟其他语句一起使用的话,最好加入一个判断物品冷却的句子:
/script bCool, nLeft, nTotal, bBroken=GetClientPlayer.GetItemCDProgress(INVENTORY_INDEX.EQUIP,9)
宣告4个变量,第一个是冷却,第二个是剩余,第三个是总量,第四个是是否损坏
进行判断:
/script if not bCool then OnUseItem(CharacterPanel.m_nObjectType,9,CharacterPanel_GetItemBox(INVENTORY_INDEX.EQUIP,9,true)) end
这是一个使用腰坠部位装备的宏命令,至于这个语句为什么是这样,我也不很明白,解释不清楚。列表如下
1=藏剑重剑
至于是如何得知的,其实是人工整理的
/script N=GetClientPlayer()
/script EquipPoslist={0,2,3,4,5,6,7,8,9,10,11,12,13,23,24}
/script for _,i in pairs(EquipPoslist) do item=GetPlayerItem(N,INVENTORY_INDEX.EQUIP,i) OutputMessage(&MSG_SYS&,GetItemNameByItem(item)) end
通过这个命令,返回名字来对比,这个判断的在某些情况下会用到,后面会介绍。
更换装备:
/script OnExchangeItem(i, j, INVENTORY_INDEX.EQUIP, nEquipPos)
这个原理跟上面使用物品的是一样的,就不再解释
通过装备名字来更换装备:
/script function Equip(szName)
& & N=GetClientPlayer()
& & for i=1,5 do
& && && &if N.GetBoxSize(i)&0 then
& && && && &&&for j=0,N.GetBoxSize(i)-1 do
& && && && &&&item=N.GetItem(i,j)
& && && && && && & if GetItemNameByItem(item)==szName&&then
& && && && && && & eRetCode, nEquipPos = N.GetEquipPos(i, j)
& && && && && && && && & if eRetCode == ITEM_RESULT_CODE.SUCCESS then
& && && && && && && && & OnExchangeItem(i, j, INVENTORY_INDEX.EQUIP, nEquipPos)
& && && && && && && && & end
& && && && && && & end
& && && && &&&end
& && && &end
基本上是差不多的,就是多了一个eRetCode, nEquipPos = N.GetEquipPos(i, j)的判断,eRetCode个人感觉应该是能否更换装备(战斗中无法更换武器外的装备),nEquipPos是装备位置。
判断当前装备:
/script N=GetClientPlayer()
/script item=GetPlayerItem(N,INVENTORY_INDEX.EQUIP,0)
/script if GetItemNameByItem(item)==&九霄双剑& then OutputMessage(&MSG_SYS&,&有&) else OutputMessage(&MSG_SYS&,&没有&) end
红色部分为执行语句,可以修改。
延伸思路:
使用回春妙手时换武器,然后使用其他技能时换回来
/script N=GetClientPlayer()
/script wq=GetPlayerItem(N,INVENTORY_INDEX.EQUIP,0)
/script a,b,c=N.GetSkillCDProgress(52,2)
/script function Equip(szName)
& &&&for i=1,5 do
& && && &if N.GetBoxSize(i)&0 then
& && && && &&&for j=0,N.GetBoxSize(i)-1 do
& && && && &&&item=N.GetItem(i,j)
& && && && && && & if GetItemNameByItem(item)==szName&&then
& && && && && && & eRetCode, nEquipPos = N.GetEquipPos(i, j)
& && && && && && && && & if eRetCode == ITEM_RESULT_CODE.SUCCESS then
& && && && && && && && & OnExchangeItem(i, j, INVENTORY_INDEX.EQUIP, nEquipPos)
& && && && && && && && & end
& && && && && && & end
& && && && &&&end
& && && &end
if c==0 then
& && && &if GetItemNameByItem(wq)==&长恨& then OnUseSkill(52,2)
& && && &else Equip(&长恨&)
& && && &end
& && && &Equip(&九霄双剑&)
如果回春妙手可用,然后如果武器不是长恨的话则切换武器为长恨,如果武器是长恨的话则使用回春妙手
如果回春妙手处于冷却,则切换武器为九霄双剑
关于减少宏的字数:
1.使用函数封装,最常用的就是N=GetClientPlayer()
比较复杂的如:
function use(id) A,B,C=N.GetSkillCDProgress(id,N.GetSkillLevel(id)) if C==0 then OnUseSkill(id,N.GetSkillLevel(id)) end end
再复杂的就是上面的那几个函数了
2.合理运用判断语句以简化语句,如上面的
if c==0 then
& && && &if GetItemNameByItem(wq)==&长恨& then OnUseSkill(52,2)
& && && &else Equip(&长恨&)
& && && &end
& && && &Equip(&九霄双剑&)
如果c==0,如果武器名字等于长恨然后使用回春妙手,这里的else是除了以上情况以外,也就是说如果不是长恨,就使用技能。
如果c不等于0,就装备九霄双剑。
if c==0 and GetItemNameByItem(wq)~=&长恨& then Equip(&长恨&) end
if c==0 and GetItemNameByItem(wq)==&长恨& then OnUseSkill(52,2) end
if c~=0 then Equip(&九霄双剑&) end
虽然都是达到一样的效果,但是后者比前者要多上50多个字符,金山宏限制1024字符,50个字符是很多的= =
3./script的省略
其实一个宏只需要在开头写上一个/script就可以了。
/script N=GetClientPlayer()
/script H=N.bOnHorse
/script function say1()N.Talk(PLAYER_TALK_CHANNEL.NEARBY,&&,{{type=&text&,text =&我有一头小毛驴,但我从来也不骑&}}) end
/script function say2() N.Talk(PLAYER_TALK_CHANNEL.NEARBY,&&,{{type=&text&,text =&小毛驴累了&}})
/script if H==true then say2() else say1() end
/script OnUseSkill(605,1)
/script N=GetClientPlayer()
H=N.bOnHorse
function say1()N.Talk(PLAYER_TALK_CHANNEL.NEARBY,&&,{{type=&text&,text =&我有一头小毛驴,但我从来也不骑&}}) end
function say2() N.Talk(PLAYER_TALK_CHANNEL.NEARBY,&&,{{type=&text&,text =&小毛驴累了&}})
if H==true then say2() else say1() end
OnUseSkill(605,1)
这两个效果是一样的,不过建议新手还是使用每行/script这样看起来比较有条理一些不像后者全部挤在一起。
以下这些宏都是这两个月来四处收集的,由于收集的时候并没有复制作者名字,在此向宏的作者们致歉。感谢那些无私贡献分享宏的先驱们(由于时间有限,以下宏部分未经
1.一键后跳
/script OnUseSkill(9007,1)
2.一键打断自身读条
/script GetClientPlayer().StopCurrentAction()
下一行命令延时1S执行
4.点奇穴宏(适合冲10的同胞们)
/script GetClientPlayer().OpenVenation(dwID)
/script GetClientPlayer().OpenVenation(dwID)
/script GetClientPlayer().OpenVenation(dwID)
奇穴·任脉·气端& & 40
奇穴·督脉·腰眼& & 41
奇穴·督脉·抬肩& & 42
奇穴·督脉·睛中& & 43
奇穴·带脉·曲泉& & 44
奇穴·带脉·龙玄& & 45
奇穴·冲脉·极泉& & 46
奇穴·冲脉·合阳& & 170
奇穴·任脉·下极俞&&9
奇穴·任脉·崇骨& & 1206
5.上下马,一键后跳
/script N = GetClientPlayer();
/script Fight=N.bFightS
/script Horse=N.bOnH
/script if Fight==false then OnUseSkill(605,N.GetSkillLevel(605))
/script if Horse==true and Fight==true then OnUseSkill(605,N.GetSkillLevel(605))
/script if Horse==false and Fight==true then OnUseSkill(9007,N.GetSkillLevel(9007))
不在战斗中,就是上下马的快捷键。
如果在战斗时,分两种情况,一种是在马上就是下马,一种是在马下,则为后跳。
备注:不在战斗中,是不会后跳的。
6.自动扶摇
/script N=GetClientPlayer()
/script N.StopCurrentAction()
/script OnUseSkill(9002,N.GetSkillLevel(9002))
/script Jump()
打断当前读条 延时2s,然后扶摇+起跳
--------------------------------------------------------------------------------------------------------------------------------------
1.天策一键MT宏(低智能版,小副本适用)
/script N = GetClientPlayer();
/script t=GetTargetHandle(N.GetTarget())
/script m=GetCharacterDistance(N.dwID,t.dwID);
/script d=m/64
/script HPR=N.nCurrentLife/N.nMaxLife
/script MPR=N.nCurrentMana/N.nMaxMana
/script function buff(mb,id)
for _, D in pairs(mb.GetBuffList() or {}) do if D.dwID==id then
return&&true end end return false end
/script function use(id) A,B,C=N.GetSkillCDProgress(id,N.GetSkillLevel(id)) if C==0 then OnUseSkill(id,N.GetSkillLevel(id)) end end
/script if d&=8 then use(418) end
/script if HPR&=0.3 then use(422) end
/script if MPR&=0.9 then use(405) end
/script use(58)
/script use(412)
/script use(482)
/script use(442)
/script use(441)
/script use(402)
/script use(411)
/script use(401)
如果目标大于8尺小于25尺,则使用突。
如果自身气血少于30%则使用虎。
如果自身内力少于90%则使用林
技能优先级别如下:
使用猛虎下山
使用疾如风
使用掠如火
2.天策宏OT后补救
/script N = GetClientPlayer()
/script t=GetTargetHandle(N.GetTarget())
/script d=GetCharacterDistance(N.dwID,t.dwID)
/script m=d/64
/script u=GetTargetHandle(t.GetTarget())
/script function buff(id)
for _, D in pairs(t.GetBuffList() or {}) do if D.dwID==id then
return&&true end end return false end
/script A,B,C=N.GetSkillCDProgress(402,6)
/script function ot(sw) if sw.dwSchoolID==2 or sw.dwSchoolID==3 or sw.dwSchoolID==4 then return true else return false end end
/script OnUseSkill(58,1)
/script if ot(u) and m=&4 then OnUseSkill(402,6) end
/script if not buff(512) and C&0 then OnUseSkill(411,N.GetSkillLevel(411)) end
/script if ot(u) and m=&4 and (not checkbuff(199)) and C&0 then OnUseSkill(411,6) end
/script if m&8 and m=&25 then OnUseSkill(418,6) end
/script if not ot(u) and m&4.5 then OnUseSkill(401,10) end
/script if not ot(u) and m&4.5 then OnUseSkill(12,1) end
释放猛虎下山
当前目标的目标是七秀或者万花或者纯阳,则释放定军。
当定军miss时,则释放火+定军。
当目标在8尺以外时 则释放突。
当目标的目标不是七秀或者万花或者纯阳时,在4尺以内,则释放破风,梅花枪
此宏做完FB有人OT时的抢怪……勿用为野外开怪第一个突来用,否则会悲剧的
3.天策输出宏
/script N = GetClientPlayer();
/script t=GetTargetHandle(N.GetTarget())
/script function buff(mb,id)
for _, D in pairs(mb.GetBuffList() or {}) do if D.dwID==id then
return&&true end end return false end
/script function use(id) A,B,C=N.GetSkillCDProgress(id,N.GetSkillLevel(id)) if C==0 then OnUseSkill(id,N.GetSkillLevel(id)) end end
/script use(58)
/script if buff(N,366) then use(403) end
/script if buff(t,540) then use(415) end
/script if not buff(N,366) and not buff(t,540) then use(423) end
/script use(400)
释放猛虎下山
当本身有克敌状态时,则释放龙吟
当目标有致残状态时,则释放龙牙
当目标无克敌或者致残时,则释放灭
当目标无克敌或者致残,且灭在CD时,则释放穿云
4.天策输出宏(带飞镖版)
/script N = GetClientPlayer();
/script t=GetTargetHandle(N.GetTarget())
/script m=GetCharacterDistance(N.dwID,t.dwID)
/script d=m/64
/script function buff(mb,id)
for _, D in pairs(mb.GetBuffList() or {}) do if D.dwID==id then
return&&true end end return false end
/script function use(id) A,B,C=N.GetSkillCDProgress(id,N.GetSkillLevel(id)) if C==0 then OnUseSkill(id,N.GetSkillLevel(id)) end end
/script use(58)
/script if d&=4 then use(34) end
/script if buff(t,540) then use(415) end
/script if buff(N,366) then use(403) end
/script if not buff(t,661) then use(401) end
/script use(400)
优先级别为
1.猛虎下山
2.判断是否飞镖,目标超过4尺则释放
3.判断是否龙牙,目标致残则释放
4.判断是否龙吟,获得克敌则释放
5.判断是否破风,目标无流血则释放
5.镇龙头自动御(由178的SQ圣力提供)
/script I=GetClientPlayer()
/script tar=GetTargetHandle(I.GetTarget())
/script tbP,dwID,dwLevel,fP=tar.GetSkillPrepareState()
/script function CDO(n)
CD,CDA,CDB=I.GetSkillCDProgress(n,I.GetSkillLevel(n)) if CDA==0 then OnUseSkill(n,I.GetSkillLevel(n)) end return end
/script if tbP and Table_GetSkillName(dwID, dwLevel)==&镇龙头& then CDO(442) end
--------------------------------------------------------------------------------------------------------------------------------------
/script N=GetClientPlayer();
/script Power=N.nAccumulateV
/script Fight=N.bFightS
/script MH1,MH2,MH3=N.GetSkillCDProgress(58,N.GetSkillLevel(58));
/script if MH2==0 and MH3==0 and Fight==true then OnUseSkill(58,N.GetSkillLevel(58))
/script TD1,TD2,TD3=N.GetSkillCDProgress(309,N.GetSkillLevel(309));
/script SH1,SH2,SH3=N.GetSkillCDProgress(364,N.GetSkillLevel(364));
/script if Power&7 then OnUseSkill(365,N.GetSkillLevel(365))
/script if Power&8 and TD2==0 and TD3==0 then OnUseSkill(309,N.GetSkillLevel(309))
/script if Power&8 and SH2==0 and SH3==0 then OnUseSkill(364,N.GetSkillLevel(364))
/script OnUseSkill(13,N.GetSkillLevel(13));
猛虎下山冷却好了就使用。
如果气大于3格半则使用无我无剑如果气小于4格,天地无极或者三环套月没有冷却,则释放天地无极跟三环套月,天地无极优先于三环套月释放。
其余时间释放三柴剑法。
2.气纯无脑输出
/script N=GetClientPlayer()
/script p=N.nAccumulateValue
/script function buff(mb,id,lvl) for _, D in pairs(mb.GetBuffList() or {}) do if D.dwID==id and (lvl==nil or D.dwLevel==lvl) then return true end end
return false end
/script sx1,sx2,sx3=N.GetSkillCDProgress(367,N.GetSkillLevel(367));
/script ly1,ly2,ly3=N.GetSkillCDProgress(301,N.GetSkillLevel(301));
/script if buff(N,999) then OnUseSkill(367,N.GetSkillLevel(367))
/script if sx2&=1&&then OnUseSkill(300,N.GetSkillLevel(300))
/script if p&=8& &then OnUseSkill(301,N.GetSkillLevel(301))
/script if p&=7&&then OnUseSkill(367,N.GetSkillLevel(367))
如果触发雨集效果,则优先释放四象轮回
如果公共冷却大于等于1,则释放凝神聚气。
如果气大于等于4格,则释放两仪化形。
如果气小于或等于3格半,则释放四象轮回。
按得时候请按慢一点,按太快容易导致凝神聚气刚使用出来就被取消掉。
3.气纯无脑输出(回蓝版)
/script N=GetClientPlayer()
/script p=N.nAccumulateValue
/script function buff(mb,id,lvl) for _, D in pairs(mb.GetBuffList() or {}) do if D.dwID==id and (lvl==nil or D.dwLevel==lvl) then return true end end
return false end
/script sx1,sx2,sx3=N.GetSkillCDProgress(367,N.GetSkillLevel(367));
/script ly1,ly2,ly3=N.GetSkillCDProgress(301,N.GetSkillLevel(301));
/script by1,by2,by3=N.GetSkillCDProgress(316,N.GetSkillLevel(316));
/script a=0
/script m=N.nCurrentMana
/script if sx2&=1&&then OnUseSkill(300,N.GetSkillLevel(300))
/script if m&=7500 and by2==0 then a=1
/script if buff(N,999) then OnUseSkill(367,N.GetSkillLevel(367))
/script if p&=9 and a==1 then OnUseSkill(367,N.GetSkillLevel(367))
/script if p==10 and a==1 then OnUseSkill(316,N.GetSkillLevel(316))
/script if p&=8&&and a==0 then OnUseSkill(301,N.GetSkillLevel(301))
/script if p&=7&&and a==0 then OnUseSkill(367,N.GetSkillLevel(367))
增加了一个判断是否需要回蓝的变量a,当蓝少于7500且抱元冷却时,判断a=1也就是进入需要回蓝状态,此时如果气不满则不停释放四象集气,一直到满气后释放抱元回蓝。
(7500是参考数,可以自行调节)
如果触发雨集效果,则优先释放四象轮回
4.剑纯爆发宏
/script N = GetClientPlayer();
/script P=N.nAccumulateV
/script F=N.bFightS
/script function use(id) A,B,C=N.GetSkillCDProgress(id,N.GetSkillLevel(id)) if C==0 then OnUseSkill(id,N.GetSkillLevel(id)) end end
/script TG1,TG2,TG3=N.GetSkillCDProgress(313,N.GetSkillLevel(313));
/script use(58)
/script if P&=4 then use(365) end
/script if P&4 then use(309) end
/script if P&4 then use(364) end
/script if P&3 and F==true then use(313) end
/script if P&9 and F==true then use(154) end
/script if TG3&1 and Fight==true then use(153) end
/script OnUseSkill(13,N.GetSkillLevel(13))
当气少于2格的时候释放天地无极以及三环套月集气,当气等于或者大于2格的时候释放无我当韬光养晦,或是带脉· 光明不处于冷却时,无我必须在1格气以上(不含1格气
)时方可释放,否则无效。
带脉·外丘只有满豆时,会自动释放。
考虑到剑纯叠刃BUFF是3秒一次刷新,所以将无我释放定为两格气。
5.气纯爆发宏
/script N=GetClientPlayer()
/script P=N.nAccumulateValue
/script F=N.bFightState
/script A,B,C=N.GetSkillCDProgress(301,N.GetSkillLevel(301));
/script A1,B1,C1=N.GetSkillCDProgress(313,1);
/script A2,B2,C2=N.GetSkillCDProgress(153,1);
/script A3,B3,C3=N.GetSkillCDProgress(168,1);
/script if (C==0 and P==10) then&&OnUseSkill(301,N.GetSkillLevel(301))
/script if (C1==0 and F==true) then&&OnUseSkill(313,N.GetSkillLevel(313))
/script if (C3==0 and F==true)&&then OnUseSkill(168,1) end
/script if (C==0 and P==10) then&&OnUseSkill(301,N.GetSkillLevel(301))
/script if (C1&0) then OnUseSkill(153,1) end
/script if (C1==0 and F==true) then&&OnUseSkill(313,N.GetSkillLevel(313))
/script if (C==0 and P==10) then&&OnUseSkill(301,N.GetSkillLevel(301))
2个两仪爆发,第二个两仪附带关门,避免不在战斗中不小心按到。
如果打开了光明则3两仪爆发,第二个附带关门。
不在战斗中光明,关门,韬光养晦是不会释放的。
6.气纯一键四气场
/script N = GetClientPlayer();
/script A,B,C=N.GetSkillCDProgress(360,1);
/script a1,b1,c1=N.GetSkillCDProgress(357,1);
/script a2,b2,c2=N.GetSkillCDProgress(358,1);
/script a3,b3,c3=N.GetSkillCDProgress(359,N.GetSkillLevel(359));
/script if (C==0) then OnUseSkill(360,1)
/script if (c1==0) then OnUseSkill(357,1)
/script if (c2==0) then OnUseSkill(358,1)
/script if (c3==0) then OnUseSkill(359,N.GetSkillLevel(359)) end
顺序是:冲阴阳,化三清,生太极,破苍穹。分别对应下面这个宏的最后四行,如果不需要气场请自行删除。删除的第 2,3,4,5行是判断冷却的,最后4行是释放气场。
7.自动生太极
/script N = GetClientPlayer();
/script SelectPlayer()
/script c1,c2,c3=N.GetSkillCDProgress(358,1)
/script function buff(mb,id,lvl) for _, D in pairs(mb.GetBuffList() or {}) do if D.dwID==id and (lvl==nil or D.dwLevel==lvl) then return true end end
return false end
/script if not buff(N,374) and c3==0 then OnUseSkill(358,N.GetSkillLevel(358))
8.自动无敌附加喊话
/script N = GetClientPlayer();
/script for i=1,3 do N.Talk(PLAYER_TALK_CHANNEL.NEARBY, &&, {{type = &text&, text = &马上释放无敌,迅速向我靠拢……& &马上释放无敌,迅速向我靠拢……& &&}})
/script SelectPlayer();
/script a1,a2,a3=N.GetSkillCDProgress(371,1);
/script if a3&1 then OnUseSkill(371,1)&&else&&OnUseSkill(167,1)&&
/Delay 2这句是在延迟2s后才可以释放无敌,大家可以删去,也可以更改2这个数字,2在这里代表2秒 请注意多按几次……避免喊话后,你没有再按,则无敌释放不出来……
9.气纯坐忘+吐纳故新
/script N = GetClientPlayer();
/script function checkbuff(id) for _, D in pairs(N.GetBuffList()) do if D.dwID==id then
return&&true end end return false end
/script if not checkbuff(136) then OnUseSkill(314,N.GetSkillLevel(314)) end
/script if not checkbuff(1376) then OnUseSkill(312,N.GetSkillLevel(312)) end
10.剑纯一键4BUFF
/script N=GetClientPlayer()
/script function buff(mb,id,lvl) for _, D in pairs(mb.GetBuffList() or {}) do if D.dwID==id and (lvl==nil or D.dwLevel==lvl) then return true end end return false end
/script function run(id) a,b,c=N.GetSkillCDProgress(id,N.GetSkillLevel(id)) if c==0 then OnUseSkill(id,N.GetSkillLevel(id)) end end
/script run(312)
/script if not buff(N,1241) or not buff(N,136) then run(314) end
/script if not buff(N,131) then run(307) end
/script if not buff(N,132) then run(308) end
坐忘CD好了就用,没有生阳或者吐故纳新补吐故纳新,玄一跟剑冲没有就补
--------------------------------------------------------------------------------------------------------------------------------------
1.万花春泥毫针宏:
/script N = GetClientPlayer()
/script t=GetTargetHandle(N.GetTarget())
/script if t==nil then SelectPlayer() end
/script function checkbuff(id) for _, D in pairs(t.GetBuffList() or {}) do if D.dwID==id then return true end end return false end
/script function sk(ss) OnUseSkill(ss,N.GetSkillLevel(ss)) end
/script A,B,C=N.GetSkillCDProgress(141,N.GetSkillLevel(141));
/script if C==0 then sk(141) end
/script if not checkbuff(1674) and not checkbuff(684)&&then sk(132) end
如果目标没有则选择自己 此时目标为自己
毫针冷却则放毫针
如果目标身上没有 春泥的负面buff以及没有天地低昂 时释放春泥
2.离经无脑治疗
/script N=GetClientPlayer()
/script t=GetTargetHandle(N.GetTarget())
/script tT,tID=N.GetTarget()
/script if IsEnemy(N.dwID,tID) then thp=N.nCurrentLife/N.nMaxLife elseif IsAlly(N.dwID,tID) or IsNeutrality(N.dwID,tID) then thp=t.nCurrentLife/t.nMaxLife end
/script function run(id) A,B,C=N.GetSkillCDProgress(id,N.GetSkillLevel(id)) if C==0 then OnUseSkill(id,N.GetSkillLevel(id)) end end
/script function buff(mb,id,lvl) for _, D in pairs(mb.GetBuffList() or {}) do if D.dwID==id and (lvl==nil or D.dwLevel==lvl) then return true end end return false end
/script if&&thp&=0.3 then run(136) end
/script if buff(N,722) or buff(N,412) then run(142) end
/script if buff(t,631) then run(137) end
/script run(101)
如果目标是敌对,则判断自身血量,血量少于30%进行水月长针急救措施
如果目标是友方或者中立,则判断目标血量,血量少于30%进行水月长针救急
自动补握针,出逐流效果后自动转为施放长针,其余时间无脑局针。
3.离经一键治疗宏(节蓝版)
/script p=GetClientPlayer();
/script t=GetTargetHandle(p.GetTarget());
/script tl=t.nCurrentLife/t.nMaxL
/script A,B,C=p.GetSkillCDProgress(136,1);
/script a,b,c=p.GetSkillCDProgress(167,1);
/script D,E,F=p.GetSkillCDProgress(141,5);
/script for _,v in pairs(p.GetBuffList())do if (v.dwID==722 or v.dwID==412 and tl&0.7) then OnUseSkill(137,7)
/script for _,v in pairs(p.GetBuffList())do if (v.dwID==722 or v.dwID==412 and tl &=0.7 and tl&0.5) then OnUseSkill(138,8)
/script for _,v in pairs(p.GetBuffList())do if (v.dwID==722 or v.dwID==412 and tl &=0.5) then OnUseSkill(142,6)
/script if (tl&=0.3 and C==0) then OnUseSkill(136,1)
/script if (tl&=0.3 and C&0 and c==0) then OnUseSkill(167,1)
/script for _, v in pairs(t.GetBuffList()) do if (v.dwID==631 and F==0) then OnUseSkill(141,5)
/script for _, v in pairs(t.GetBuffList()) do if (v.dwID==631 and F&0) then OnUseSkill(137,7)
/script OnUseSkill(101,9);
本宏作用:
普通情况下没握针就补握针,毫针CD一到就用。其它时间无脑局针。不喜欢这么用毫针的同学可以去掉橙色部分
特殊情况1:触发逐流BUFF。
目标血量大于70%局针
目标血量小于70%大于50%提针
目标血量小于50%长针
特殊情况2:目标血量低于30%,且没有逐流BUFF
水月不在CD中开水月+长针
水月CD了且冲脉幽门不在CD中,放幽门+水月+长针。没有点出冲脉幽门的请去掉宏命令中红色部分。
由于字符数的限制没有把冲脉关门做进去,同样是字符限制,只能在写宏的时候把详细的技能等级加上去,而不能用GetSkillLevel()函数,这样技能没有练满的童鞋需要根
据自己实际情况改宏。
修改处1:p.GetSkillCDProgress(141,5)&&改成 p.GetSkillCDProgress(141,x) x为你的毫针等级。
修改处2:OnUseSkill(137,7) 改成 OnUseSkill(137,x) x为你的局针等级。
修改处3:OnUseSkill(138,8) 改成 OnUseSkill(138,x) x为你的提针等级。
修改处4:OnUseSkill(142,6) 改成 OnUseSkill(142,x) x为你的长针等级。
修改处5:OnUseSkill(141,5) 改成 OnUseSkill(141,x) x为你的毫针等级。
修改处6:OnUseSkill(101,9) 改成 OnUseSkill(101,x) x为你的握针等级。
4.离经水月长针
/script N = GetClientPlayer();
/script A,B,C=N.GetSkillCDProgress(136,1);
/script a,b,c=N.GetSkillCDProgress(167,1);
/script for _, D in pairs(N.GetBuffList()) do if (D.dwID==722 or D.dwID==412) then OnUseSkill(142,6)&&
/script if (C==0) then OnUseSkill(136,1)
/script if (C&0 and c==0) then OnUseSkill(167,1)
首先判断是否有逐流BUFF,有就放长针没有就放水月+长针。
如果水月在CD中放“冲脉.幽门”+ 水月+长针
如果没有幽门,去掉第三行跟最后一行。
5.花间无限定身宏
/script N = GetClientPlayer();
/script t=GetTargetHandle(N.GetTarget());
/script A,B,C=N.GetSkillCDProgress(186,N.GetSkillLevel(186));
/script for _, v in pairs(t.GetBuffList()) do if (v.dwID==675) then OnUseSkill(179,N.GetSkillLevel(179))
/script if (C==0) then OnUseSkill(186,N.GetSkillLevel(186))
/script if (C&0) then OnUseSkill(181,N.GetSkillLevel(181))
/script if (C&0) then OnUseSkill(228,N.GetSkillLevel(228))
本宏作用:芙蓉并蒂=&阳明指=&芙蓉并蒂=&阳明指。。。。。。。。。偏离了循环中断,就放少阳指减速,或者放太阴指拉开距离。重要:红色部分和橙色部分只能二选一。
像我上面写的那样,橙色部分是不会起任何作用的。
目前缺陷:1、进入战斗状态后才}

我要回帖

更多关于 js 遍历属性 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信