求生之路2rpg插件下载rpg插件里面的菜单文字怎么修改?

后使用快捷导航没有帐号?
合作站点账号登陆
只需一步,快速开始
查看: 350|回复: 1
求生之路2 菜单背景动画替换
阅读权限255
自制求生之路2&&菜单页面动画替换
分别为海王星OVA& &&&海王星U& & 重生1 2 3& &&&新次元V2
重生1 2 3 新次元V2 U 原视频为720P(找不到1080P_(:з」∠)_) 海王星OVA画质略微差点(1080P无字幕资源下载不动_(:з」∠)_)
下载链接食用方法随后评论区放出~
PS.视频前面的卡顿是因为加载创意工坊的mod
效果预览:
下载链接:海王星OVA:链接:
密码: 3ibc
& && && & 海王星U:链接:
密码: z8tn
& && && & 重生1:链接:
密码: 2vsy
& && && & 重生2:链接:
密码: 6wtc
& && && & 重生3:链接:
& && && & 新次元V2:链接:
食用方法:找到游戏目录left4dead2-media里面有5个文件分别为l4d2_background01.bik-l4d2_background05.bik 将解压得到的文件复制4份共5份分别命名为l4d2_background01.bik-l4d2_background05.bik替换原文件。然后将left4dead2-sound-music-l4d2里面的原BGM新建一个文件夹放进去这样就不会出现原BGM
星缘天空游戏社区—求生之路—GMod—破解技术—插件制作— - 论坛版权1、本主题所有言论和图片纯属会员个人意见,与本论坛立场无关
2、本站所有主题由该帖子作者发表,该帖子作者与享有帖子相关版权
3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和的同意
4、帖子作者须承担一切因本文发表而直接或间接导致的民事或刑事法律责任
5、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
6、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意
7、管理员和版主有权不事先通知发贴者而删除本文
阅读权限10
二楼?,评论
Copyright (C) 2015
Powered by求生之路2游戏内海报 图片修改_求生之路吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0可签7级以上的吧50个
本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:322,536贴子:
求生之路2游戏内海报 图片修改
有没有人知道游戏内墙上海报 或者广告牌之类的上面的图片该怎么修改呢?还有演唱会那个关卡海报和舞台背景该怎么换?有人知道吗?或者给个教程链接
盘点娱乐圈孝子明星。
你是写手or读者?你怎么...
2月28日,乐天集团与韩...
今天分享给大家一道非常...
梧桐妹深情告白修杰楷。
胆小勿入!别晚上一个人...
真是涨姿势了!
一人我饮酒醉。。。
快来安利出自己心中的佳...
三生收官,收视不错,可...
看到了扎眼的古力娜扎,...
颖儿和付辛博甜蜜秀。
缺牙要及时修复,揭秘种植牙如何做到几十年不掉?
都快搜烂了。。。就是没找到 还有置顶的帖子里的那些MOD链接也都翻了 基本都是以模型皮肤之类为主的
玩游戏从来不用MOD的我也不懂
音乐会舞台背景,R姐会弄
我也不会MOD。。。求教~
其实只想知道一下原理怎么改。。。图片什么的自己都有素材,主要想改都不知道从哪里下手 下载的MOD整合包里一般又不带海报这些的
路过以前做过萌化包啊你要改先要去拆包,工具GCFScape.exeJ:\Left_4_dead_2_xs_77\left4dead2\pak01_000.vpk应该在这个包里 祝楼主好运
\root\materials\vgui\root\materials\signs附2个包里的路径
这玩意儿怎么用。。。解开以后就一个ROOT目录 然后点什么都没反应。。下面英文提示倒是读取成功 可是什么也没有
米诺电子专注于拉绳位移传感器,电子尺和角度传感器的研发生产
pak01_dir.vpk 搞错了 这个
各种。。。.VMT和VTF文件 这是什么。。。好吧 我败了 这又该怎么下手
本以为只是换换图片什么的。。。这个难度有点大
VTFEdit.exe vtf只是图片格式而已,用这个软件打开导入导出就行了.
THANKS 不过你那有现成的东西能给借鉴一下嘛?或者说 弄好的东西放在哪里 该怎么弄?想看看效果
你把人家的mod拆包 你就明白了然后去找一个原版vpn.exe封包具体办法百度知道
灰常感谢。。。真是好淫呐。。。我先学习一下了 有什么问题再M你
贴吧热议榜
使用签名档&&
保存至快速回贴sourcemod教程
个人理解的东西分享下_sourcemod吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0可签7级以上的吧50个
本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:196贴子:
sourcemod教程
个人理解的东西分享下
我只写过求生之路2的插件。而最近也已经不打算写了,然后看了下论坛,决定写点什么东西。我最开始对写插件一窍不通,不过呢自学了一年,最后基本上简单的插件可以写了。现在呢!觉得sourcemod的插件其实很简单。所以总结下,然后举例说明。等待求生之路3.
缺牙要及时修复,揭秘种植牙如何做到几十年不掉?
1.插件需要一点点c语音基础。非常基础。只需要看到函数章节即可。当然外网上面也有souremod开发网页上有,不过基本上看中文c语音基本视频是最省事的。2.需要一个开发工具,notepad++ 这个我推荐,虽然PawnStudio也可以,不过对中文支持不好。两个工具,PawnStudio有点是函数提示更强大。notepad对于中文支持。并且界面美观。3.对于开发插件来说需要了解游戏。建议看一些hammer教程。熟悉实体和各种参数。4.需要更深的学习一门语言。c。c++。这是为了更深入的写代码。
默认插件平台addons\sourcemod\scripting\include中包含所有inc头文件。其中一半前期的时候不需要认识。当然平台文件中addons\sourcemod\scripting中有些代码是可以学习的。其实人人都说写程序没有捷径,这句话是真理。我现在插件有5个G吧。都是源代码。其实玩得多,看得多,然后想想,就会懂得更多。
首先是强制分号使用。不许太在意,当然如果喜欢追根问底的可以自己查一下。#pragma semicolon 1
引入头文件,这里如果学过编程语言的都应该知道,这些文件中包含了你要使用函数的原型。#include &sourcemod&#include &sdktools&#include &geoip& define 插件作者自己定义的值。固定的。1 2 3 对应不同的团队。 求生之路里面 1为空闲 2为生还者 3为感染者。cs和tf好像有所改变。#define L4D_TEAM_INFECTED 3
//该定义方式语法
其中&index&
为getclientteam函数所返回的值。当接触到该函数的时候也就懂了#define L4D_TEAM_SURVIVOR 2#define L4D_TEAM_SPECTATOR 1标题部分
其实可有可无。只是呢,当你在游戏控制台输入sm plugins list的时候会显示 name 和 author 的信息public Plugin:myinfo =
name = &上面代码输入后 中文在游戏无法显示&,
author = &名字也是&,
description = &Left 4 Dead 1 & 2&,
version = &1.0&,
url = &http://&
插件中最多使用的是hook和函数。其实就是函数hook其实初学的时候感觉理解起来有点奇怪。说下hook 当玩家进入游戏后给玩家点个赞。进入游戏这个是一个游戏本身的函数。然而我只是想给玩家点个赞。所以需要在进入游戏这个事件上,添加我们自己的东西。(Source) 游戏中所有事件。当然获取事件文件也可以在游戏本体中寻找到。这里我就不多说题外话了,这属于mod范畴。喜欢做插件和mod可以多解剖下游戏本体。例如有一个事件叫做“player_team”我们想要hook它。也就是在这件事情发生的时候进行一些处理。做我们想做的事情。可以使用HookEvent();函数。
可以使用该网站快速查询HookEvent。可以看到原型native HookEvent(const String:name[], EventHook:callback, EventHookMode:mode=EventHookMode_Post)其中网站上查询有些函数会有人写一些例子。而如果没有例子需要自己学会使用一些东西。native 标签说明该函数是内部函数。意思就是必须放在public大函数体内。其中用法中很清楚Usage: nameName of event. 这代表事件名称 callbackAn EventHook function pointer.
一个回调函数,其实就是一个大函数体的函数名。 modeOptional EventHookMode determining the type of hook. 模式控制这里对于事件有3种模式控制。在HookEvent查询页面中file 页面 其实就是包含Hookevent事件inc文件的网页,制作者也可以自己打开平台中event。inc文件自己查看。其中英文其实说的也很明显enum EventHookMode {
EventHookMode_Pre,/**& Hook callback fired before event is fired */事件发生前 EventHookMode_Post,/**& Hook callback fired after event is fired */ 事件发生后 EventHookMode_PostNoCopy/**& Hook callback fired after event is fired, but event data won't be copied */事件发生后但是不复制事件数据。该mode是用于优化。比如你只需要在玩家死亡后给所有玩家显示一条文字,你可以使用改mode,因为不需要知道谁死了,也不需要知道谁杀的,我只想用该事件传达一个消息};其中对于非EventHookMode_Pre模式。默认是EventHookMode_Post模式HookEvent(&player_team&,Event_PlayerChangeTeam); public Event_PlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast){}如果是EventHookMode_Pre模式需要写成HookEvent(&player_team&,Event_PlayerChangeTeam,EventHookMode_Pre); public
Action:Event_PlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast){该三个返回值对应 Action: 这个符号。其中时间createtime 函数多用于该符号和返回值 return Plugin_H
表示交给插件,插件中如果修改了一些值会使用 return Plugin_C 表示继续执行,继续执行下去。 return Plugin_S 表示停止执行。一般时间函数使用最多。其他函数使用不明显这三个返回值,在一般函数带有Action的时候一般会使用Plugin_Handled。因为要让游戏引擎知道我做了什么改动,另外两个在某些情况下会影响插件正常效果的运行。因为source引擎不知道我们做了什么}其实以上内容在inc文件中都可以很好的找到一些归纳性的注释。新人多看看简单代码,多在游戏体验代码实际意义,看的时候带着翻译器,慢慢就明白了。提醒:对于事件来说 &player_team&。玩家加入某team的时候。而在某些时候也可以使用别的事件做到同样的事情。比如“player_first_spawn” 之后检测其team。或者调用函数public OnClientPostAdminCheck(Client)其实呢达到某一个事情,有多总方法
下面,摘用rpg插件来分享下经验 整理下发出来
这里借用下原始rpg代码。坐下说明同时推荐下 Silvers
的插件 。建议有一定基础的可以看这位大神写的插件。调理清晰并且其对游戏了解程度很高。引用#include &sourcemod&#include &sdktools&作者自定义的版本号。#define Version &1.0.7&//这里之前已经说过,定义不同组。实际游戏是分了组的,不同阵营不同组#define TEAM_SURVIVORS 2#define TEAM_INFECTED 3//这里是tank的index,每个特干一个固定index类。除了witch #define ZOMBIECLASS_TANK 8//标签。这里标签只要是控制生成的config文件的一些行为。//在console.inc中可以看到详细说明。实际上呢。没看到有多大的效果。至于有些可以隐藏是否生成该条cvar的config,那个可以自己配置试下#define CVAR_FLAGS FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_NOTIFY|FCVAR_DONTRECORD//这里也不用多说,结构函数的实例化。public Plugin:myinfo={name = &RPG 모드, RPG Mode&,author = &Rayne&,description = &RPG 모드&,version = Version, //这里使用了上面的define 的Version值。文件在编译的时候,编译器会自动翻译这些define的标识符为实际的值。url = &&};//这里我删除了99%的参数定义//插件中都是以new来定义一个变量//其中数组lv
中[MAXPLAYERS+1]
表示在数组lv[]中有MAXPLAYERS+1个元素。//MAXPLAYERS 是一个inc中定义了的值。64. 这里说下求生之路2中最大容纳玩家数量就是64,其他source游戏未知,可以手动测试。//
当然一共是64 其中两个团队分下来就是32,当然有人会说闲置组不算吗?闲置组是在整体容量下相对闲置空间。比如 64- 12【组1】-12【组2】=闲置组new Lv[MAXPLAYERS+1]
//默认handle的定义。句柄的定义吧。插件中一些函数会返回,或者参数是handle类型的。这里需要定义相同类型的参数。new Handle:LvUpExp30//boolen类型的参数。定义方式如下。这里当然是数组new bool:HealingBool[MAXPLAYERS+1]
new bool:xx_//浮点数定义,单精度。这里用的二维数组。new Float:NowLocation[MAXPLAYERS+1][3]
new Float:xx_//这里说下这个%1
其实一直没找到出处。其实应该是占位符,表示这里出入一个值。//这个有点像C#中的东西,但是也有点像别的语言的。我查询中也可以使用%0,%2.当我我没试过。#define IsValidClient(%1)(1 &= %1 &= MaxClients && IsClientInGame(%1))//一维数组初始化。这里看不懂就应该补习一下c语言基础。new JD[MAXPLAYERS+1] = {0, ...};//这里枚举类型。而括号中位运算,很少见,不过大概意思是里面的参数一次改变,&&=1。实话Silvers的插件很少完整的看。基本上没这么看过。//如果有人知道这个可以回复给我说下,互相学习下。enum (&&=1){ENUM_BLOCKED = 1,ENUM_POUNCED,ENUM_ONLEDGE,ENUM_INREVIVE,ENUM_BLOCK}//最常见的是这种方式。从1开始。一次加1enum (){TYPE_PISTOL = 1,TYPE_SMG,
2TYPE_MP5,
补充下上一楼说声明的参数为全局静态参数。。全局可见,并且一旦插件执行,就永久生存直到游戏退出window。至于还是不懂全局和静态的可以补习下c语音基础
// 这里调用一个函数OnPluginStart。其实这也类似与hook,当插件运行的时候执行一些东西//这里说下,该公共函数并非必须函数。因为每个公共函数 public 你可以看作是全文本可见的可直接调用的hookpublic OnPluginStart(){//内部函数CreateConVar 不需要返回值//使用编写软件noteapp或者查看函数网页或者看inc文件 可以看到原型native Handle:CreateConVar(const String:name[], const String:defaultValue[], const String:description[]=&&, flags=0, bool:hasMin=false, Float:min=0.0, bool:hasMax=false, Float:max=0.0);//其中包括用法。每个参数的具体意思。//不带返回值,并且我们也用不到返回值。因为只是想在config文件中产生一条说明。CreateConVar(&l4d2_RPG_Mode_Version&, Version, &RPG 모드 버전&, CVAR_FLAGS)// RPG 모드 버전
// -// Default: &1.0.7&l4d2_RPG_Mode_Version &1.0.7&//需要返回值//JocExp是一个handle类型值用于存放CreateConVar返回的值。其实应该说是指针一样的东西。当我们处理JocExp的时候就可以找到CreateConVar里面的值。//因为sourcemod平台的更新 多了后【,true,0.0,true,100.0);】这四个参数。所以我们更直观的控制convar值得取值范围。不用像以前控制HookConVarChangeJocExp = CreateConVar(&sm_JocExp&,&80&,&EXP that Jockey gives&, FCVAR_PLUGIN,true,0.0,true,100.0);// EXP that Jockey gives// -// Default: &80&// Minimum: &0.000000&// Maximum: &1.000000&//新建一个控制台命令。实际呢输入y可以调用的命令
至于原型呢!有兴趣可以自己查看下RegConsoleCmd(&statusconfirm&, ConfirmChooseMenu)
//新建一个管理员可以用的指令。同时呢设置权限。至于ADMFLAG_KICK可以自己看下inc文件中有明确的说明RegAdminCmd(&sm_giveexp&,Command_GiveExp,ADMFLAG_KICK,&sm_giveexp [#userid|name] [number of points]&)RegAdminCmd(&sm_givelv&,Command_GiveLevel,ADMFLAG_KICK,&sm_givelv [#userid|name] [number of points]&)//hook事件HookEvent(&witch_killed&, WK)//找到某个类里面某个变量的偏移值 CTerrorPlayer代表的是玩家这个类//当然对于这个我也不是十分了解,因为一接触这个东西就要开始使用c++了。//当然这只是游戏代码中某个类,其某个子类里面有个参数为m_zombieClass//玩家可以自己导出游戏mapdata或者prop数据进行查找某个类有哪些参数,当然有些参数是特定模式才能用。//这里初学者只需要记住这个东西就行了。就像公式一样记住。ZC = FindSendPropInfo(&CTerrorPlayer&, &m_zombieClass&);//顺便说下配对的函数为如下。new ZClass = GetEntData(deadbody, ZC);//同时也可以写为。当然官方是建议用GetEntProp,因为更安全。至于为什么更安全,有兴趣可以自己查询下该函数的说明GetEntProp(deadbody,Prop_Send,&m_zombieClass&,4,0);//生成congfig参数AutoExecConfig(true, &随便娶个名字&)}
首先这个是一个固定公式 ,statusconfirm和ConfirmChooseMenu是随意可改写的名字RegConsoleCmd(&statusconfirm&, ConfirmChooseMenu)
//这些固定格式可以在函数查询和inc文件中看到原始格式。public Action:ConfirmChooseMenu(client, args){//这里GetClientTeam(client)返回client的组的index,一个整数,标记其实感染者或者是生还者,是警察还是恐怖分子。//TEAM_SURVIVORS在之前已经被define为一个值。比较这两个值是否一样。其中求生之路游戏规定2为生还者。//所以如果返回2那么等于成立2==2返回true。if(GetClientTeam(client) == TEAM_SURVIVORS) {//执行想要执行的代码。可以是任何函数。}//这里返回handle是告诉游戏引擎我这里三方定制了一个新的规则,不然大部分情况下游戏输入指令后会提示没有这个指令return Plugin_Handled }//再说下事件HookEvent(&witch_killed&, eventkill)//固定格式不用多说public eventkill(Handle:event, String:event_name[], bool:dontBroadcast){//得到实际的id。//游戏每个关卡开始,也就是地图完成后玩家进入游戏会随机给予一个id。而每个关卡玩家id都在变化。//这里就得提到游戏的一些机制。地图章节结束进入下一个章节会调用dicconnect将所有玩家放到地图外面,或者说临时的一个地方。//至于哪儿?也许是大厅也许仅仅凌驾于游戏地图之外。其实也就一个数组参数值上吧。这事玩家处于连接上状态但是在游戏中的状态并未激活。//之后进入地图后重新给予id。所以求生之路2玩家的一些参数必须在地图结束前保存在地图开始后读取。这是rpg保存的底线。//首先获得事件中userid的事件index 然后通过该id找到玩家实际的id//其他事件参数就不一一做解释。看起类型分别调用GetEventInt GetEventBool GetEventString等等。//使用编辑软件的函数提示能更快的入门编写插件这是真相,你可以很快的知道自己可以用哪些函数。new killer = GetClientOfUserId(GetEventInt(event, &userid&))
//对于过滤语句这里要说下1.玩家index是在1-64.当然有人会说1-32,一般会使用
0& x &=MaxClients来限定玩家index2.游戏中最大实体容量为2048,3.实体分为两大类
玩家和其他 【当然这比cs和tf要复杂些】
其中其他代表witch和普通感染者,还有物理实体,某些临时实体,总而言之除了玩家可以直接操控的实体外都是临时实体4.所以这里就会比较复杂,特别是在理解伤害关系的时候需要仔细梳理不同类型之间的伤害为什么这么麻烦呢?因为GetClientTeam()等函数要求传入的值必须是有效的。否则会报告某某index无效。并且影响游戏流畅度。//这里很简单的过滤是否为生还者和是否为机器人bot//同时说下有些时间是只有玩家才能出发的所以可以不用限定index是否在0-64之间//这里击杀witch的只有玩家才能做到。当然如果不放心可以加上0-64的判定条件。if(GetClientTeam(killer) == TEAM_SURVIVORS && !IsFakeClient(killer)) {//下面是如果击杀了witch给予击杀者一个值得变化//EXP[killer]。某个玩家的值。获得之前CreateConVar 创建的handled:convar
WitExp的值//这句话是获取handle WitExp中的值,然后返回给EXP[killer]接受。EXP[killer] = EXP[killer] +
GetConVarInt(WitExp)//当然如果这句都不理解应该要好好看下基础语法了。c语音EXP[killer] += GetConVarInt(WitExp);//调用PrintToChat 给该玩家说一句话。//\x03 为颜色格式
其中包括\x01 \x02 \x04 \x05 当然自己也可以自己试试,也可以去查询该函数的说明PrintToChat(killer, &\\x03You got EXP as much as \x04%d \x03from \x05Witch&, GetConVarInt(WitExp))}}
米诺电子专注于拉绳位移传感器,电子尺和角度传感器的研发生产
这里提下sourcemod开发网页中基础部分是比较简单的AutoConfigs 就一个函数,用于产生config文件。Commands
用于创建新指令。或者AddCommandListener进行监听某个指令ConVars 类似于KeyValues,可以手动存档一个值在一个键中,可以通过handle直接调用,并且修改。Events
事件,当事件发生时做一些动作KeyValues 这个和hash表有点像,一键一值。最开始的rpg用于存档。目前大部分服务器用sql存档Menus //菜单。sourcemod有两种菜单一个panel一个是menu。panel不能分页,menu可以。而menu其实更加强大,可以传递参数并且可以任意调配。SQL //一般是拥有网站论坛的才会使用,需要配置平台的configs/databases.cfg文件。也很简单。但是需要安装一个sql,所以在玩家插件中不适合,一般用于有服务器的开发者。并且目前主要用于rpg和一些具有排行插件的服务器,用于数据共享与多服务器之间。Timers
//最常用的函数。通过一些hook或者函数触发createtime。不过由于平台更新,目前该函数在执行某些功能的时候出现卡顿。DataPacks
//类似于timer,只是集成了数据包的功能。Translations
//不太习惯用,外国人很喜欢用,因为可以通过文本进行插件汉化或者翻译为其他语言。而不用修改源码Entity References
//不太常用,类似于一种检测机制,就好想每次传递的值要检测其是否有效,这里是比较难的Administration API - Using the Admin Cache.//这个用得最多,主要使用在某些管理员插件上Admin Menu API - Attaching to the Admin Menu.//这个也属于扩展发布类Creating Natives - Exposing API to other plugins.//这个没怎么看。现阶段还用不上Function Calling API - Calling external functions.//这个目前写插件基本还用不到,除非你要写dll文件并且发布扩展incOptional Requirements - Managing dependencies.//这个已经涉及到汇编和c++到目前我还不能完全掌握。SDKTools - Using the powerful SDK abstraction layer.//这个其实算很简单的,就一个函数配置好参数就可以使用Temporary Entities - Using temporary entities. 这些内容所知道的慢慢更新。
在一些函数体中执行new entity = -1;因为FindEntityByClassname原型参数中提到entity需要一起起始点,所以初始化entity为-1并且INVALID_ENT_REFERENCE的定义也是-1;while ((entity = FindEntityByClassname(entity, &trigger_transition&)) != INVALID_ENT_REFERENCE){
new Float:Pos[3];获取有效entity的m_vecOrigin,也就是该实体在游戏中的坐标。
GetEntPropVector(entity, Prop_Send, &m_vecOrigin&, Pos);//这里使用CreateEntityByName函数创建一个env_sprite类的实体。new sprite = CreateEntityByName(&env_sprite&);//以下的配置。有条件的查看hammer参数配置或者相应的.fgd文件其中有详细说明。这里就不多说了毕竟好几百个实体一一说明我也没有那么大的本事和时间其中直接用英文理解或者翻译都可以知道其本身的意义DispatchKeyValueVector(sprite, &origin&, Pos);DispatchKeyValue(sprite, &spawnflags&, &0&);DispatchKeyValue(sprite, &scale&, &1.5&);DispatchKeyValue(sprite, &rendermode&, &5&);DispatchKeyValue(sprite, &rendercolor&, &0 255 0&);DispatchKeyValue(sprite, &renderamt&, &255&);DispatchKeyValue(sprite, &model&, &sprites/light_glow03.spr&);//产生该实体。大部分实体如果只有这个DispatchSpawn,它会出现在地图0.0.0坐标点上DispatchSpawn(sprite);//并且对于某些特定实体,例如粒子实体,需要进行激活处理。或者触发其启动。AcceptEntityInput(sprite, &ShowSprite&);}说到游戏实体这里说明下游戏实体中分3大类。物理实体,静态实体,动态实体物理实体,可以主动的运行【你给它一个方向的力量它可以自己惯性运行】,带有刚体效果,可以碰撞,例如游戏中手榴弹,火瓶,药瓶静态实体,基本上算是场景实体,不能运动,但是可以被碰撞。动态实体,可以跟随运行。可以有碰撞,一般具有自己的动画动作。例如玩家模型,某些粒子效果例如制作一个可以运动的物体,可以直接使用物理实体。而如果我要使用的模型没有物理特性那就必须使用父子关系。对于父子关系可以自己找下hammer父子关系设定。这里提醒下 只有动态实体能够跟随父物体运动。父子关系1.命名类型的父子关系decl String:Buffer[64];Format(Buffer, sizeof(Buffer), &Client%d&, client);首先要建立父子关系,必须知道父亲是谁。这里面hammer中很清晰的必须给父类一个名字其中给父类的targetname 赋予一个名字DispatchKeyValue(client, &targetname&, Buffer);//将其名字丢入全局可见的空间中。我是这么理解这个函数的。SetVariantString(Buffer);//设置该名字为父亲。谁的父亲呢? Body的父亲。AcceptEntityInput(Body, &SetParent&);
//下面这句一样的意思,只是上一句为默认。因为是孩子自动认识父亲//AcceptEntityInput(Body, &SetParent&,Body,Body,0);
2.仅用于玩家【其中包括bot】该方法hammer中也可以使用,让物体被动于玩家进行父子关系。由玩家触发。直接告诉body【body是动态实体】要跟着触碰你的玩家SetVariantString( &!activator& ); 跟着谁?触发者。这里!activator表示触发者当然还有别的值,这里就一一介绍,因为基本上很少用到别的。下面这句中client必备,因为AcceptEntityInput原型中client的参数的原型是触发者。当然其他触发者很少见,比如自爆,自己触发自己,或者是多实体之间互相触发的调用者。AcceptEntityInput( Body, &SetParent&, client );下面设置附件,可以省略但是必须使用TeleportEntity( Body, b_Org, b_Ang, NULL_VECTOR);因为你只是建立了A和B的父子关系,但是并没有说B应该在什么相对位置跟着A运行告诉body要依附在spine附件上。对于附件,这个需要modelview来查看。SetVariantString( &spine& );设置附件建立成功 AcceptEntityInput( Body, &SetParentAttachment& );//当然也可以这么写。这就是完全的hammer思想。SetParentAttachmentMaintainOffset 这个可以保持相对附件的位置偏移运动。这句话的意思是,建立一个类似时间函数的东西,当该物体出现在游戏中后执行指令OnUser1为事件名字,该事件是让body自己依附在已经建立父子关系的附件上,并且是偏移依附,执行时间间隔为0.1秒,当然这里-1说明是无限执行,实际应该使用1,但是实际效果并没有多大变化。但是建议根据需要设置次数,除非需要无限次执行。否则可能会对游戏性能造成一定影响SetVariantString(&OnUser1 !self,SetParentAttachmentMaintainOffset,spine,0.1,-1&);//固定格式也不多说,对于一些迭达需要修改一些部分,当然自己还用不要这些。AcceptEntityInput(Body, &AddOutput&);AcceptEntityInput(Body, &FireUser1&);如果说的有问题可以大家一起交流
应该 是编译预处理
(css插件我不懂)在编译时
将下面定义好的
全部替换成后面的值
这个应该说明白
是编译是做的事
在下面参数直接写成
随便说一下
我是新来的
楼主你好, 可以看看我在吧里发的那个帖子吗?我实在是不知道要怎么写了. 谢谢.
非常好哇!教程教材太难找了!多来点儿吧!。。。。。。。。。。。。。。。
好评and支持顺便一提在css本次更新后,GetEntityCount()函数作废,取得的值居然是负值,我还以为v社突破了css的实体数量限制。然而并不是
AutoConfigs 部分或者用notepad++ 和 sourcemod语法高亮插件(高亮插件部分高级api不支持,可以自己添加)AutoConfigs 就一个函数,用于产生config文件。AutoExecConfig语法原型:native AutoExecConfig(bool:autoCreate=true, const String:name[]=&&, const String:folder[]=&sourcemod&);用法: autoCreateIf true, 如果文件不存在将会自己添加。 name文件的名字 foldercfg/文件夹下
默认是 &sourcemod.&文件中/一般不用填写使用默认值。注意:Specifies that the given config file should be executed after plugin load.OnConfigsExecuted() will not be called until the config file has executed, but it will be called if the execution fails.因为英语不好所以保留注意的原文。意思是在插件加载后必须先执行config file(cfg文件)也就是先运行配置文件。因为OnConfigsExecuted()函数会等待cfg文件被执行。但是如果cfg文件运行失败OnConfigsExecuted也会被调用。这个函数一般使用在OnPluginStart(){AutoExecConfig(true,&我是一个配置文件&)}值得注意的是AutoExecConfig函数制作的的配置文件是什么CreateConVar(&ConvarName&,&2&,&我希望插件默认使用该值&,FCVAR_DONTRECORD,true,0,true,10);Syntax:native Handle:CreateConVar(const String:name[], const String:defaultValue[], const String:description[]=&&, flags=0, bool:hasMin=false, Float:min=0.0, bool:hasMax=false, Float:max=0.0);这个函数一般使用在OnPluginStart(){CreateConVar(&ConvarName&,&2&,&我希望插件默认使用该值&,FCVAR_DONTRECORD,true,0,true,10);AutoExecConfig(true,&我是一个配置文件&);}这样一个配置文件就完成了。CreateConVar中FCVAR_DONTRECORD这个flags文件在该api的文件console中有枚举。而FCVAR_DONTRECORD表示不再cfg文件中写出该ConVar的配置文件部分。当然至于配置文件什么样,这里就不多说了,玩过插件应该都知道。顺便再提下HookConVarChangeSyntax:native HookConVarChange(Handle:convar, ConVarChanged:callback);该函数实际用处不大,因为是一个很老的api当时CreateConVar还没有bool:hasMin=false, Float:min=0.0, bool:hasMax=false, Float:max=0.0这一个限定部分。Syntax:native Handle:CreateConVar(const String:name[], const String:defaultValue[], const String:description[]=&&, flags=0);当然现在CreateConVar已经完备了,所以可以忽略HookConVarChange,除非你需要一些特别的功能,但是实际使用确实意义不大。
Commands部分提示:在使用某个Api的时候必须include &APi所在ini文件的文件名字&RegAdminCmd //注册自己的管理员指令RegConsoleCmd //注册自己的控制台指令RegServerCmd //注册自己的服务器指令常用三个api具体用法可以自己查询下对于RegAdminCmd最容易出问题的应该是管理员权限flags的设定下面是flags的网页(复制的上面链接中的)当然你可以在admin.ini文件中直接查询#define ADMFLAG_RESERVATION(1&&0)/**& Convenience macro for Admin_Reservation as a FlagBit */#define ADMFLAG_GENERIC(1&&1)/**& Convenience macro for Admin_Generic as a FlagBit */#define ADMFLAG_KICK(1&&2)/**& Convenience macro for Admin_Kick as a FlagBit */#define ADMFLAG_BAN(1&&3)/**& Convenience macro for Admin_Ban as a FlagBit */#define ADMFLAG_UNBAN(1&&4)/**& Convenience macro for Admin_Unban as a FlagBit */#define ADMFLAG_SLAY(1&&5)/**& Convenience macro for Admin_Slay as a FlagBit */#define ADMFLAG_CHANGEMAP(1&&6)/**& Convenience macro for Admin_Changemap as a FlagBit */#define ADMFLAG_CONVARS(1&&7)/**& Convenience macro for Admin_Convars as a FlagBit */#define ADMFLAG_CONFIG(1&&8)/**& Convenience macro for Admin_Config as a FlagBit */#define ADMFLAG_CHAT(1&&9)/**& Convenience macro for Admin_Chat as a FlagBit */#define ADMFLAG_VOTE(1&&10)/**& Convenience macro for Admin_Vote as a FlagBit */#define ADMFLAG_PASSWORD(1&&11)/**& Convenience macro for Admin_Password as a FlagBit */#define ADMFLAG_RCON(1&&12)/**& Convenience macro for Admin_RCON as a FlagBit */#define ADMFLAG_CHEATS(1&&13)/**& Convenience macro for Admin_Cheats as a FlagBit */#define ADMFLAG_ROOT(1&&14)/**& Convenience macro for Admin_Root as a FlagBit */#define ADMFLAG_CUSTOM1(1&&15)/**& Convenience macro for Admin_Custom1 as a FlagBit */#define ADMFLAG_CUSTOM2(1&&16)/**& Convenience macro for Admin_Custom2 as a FlagBit */#define ADMFLAG_CUSTOM3(1&&17)/**& Convenience macro for Admin_Custom3 as a FlagBit */#define ADMFLAG_CUSTOM4(1&&18)/**& Convenience macro for Admin_Custom4 as a FlagBit */#define ADMFLAG_CUSTOM5(1&&19)/**& Convenience macro for Admin_Custom5 as a FlagBit */#define ADMFLAG_CUSTOM6(1&&20)/**& Convenience macro for Admin_Custom6 as a FlagBit */RegConsoleCmd是一个最最常用的api【虽然看上去是控制台输入。其实也可以完全在游戏中按Y输入!xx指令】比如在游戏你想输入!rpg弹出输入一句话一个菜单都要用到它而你在默认游戏中输入!admin弹出一个管理员菜单则是RegAdminCmd的功劳RegServerCmd则可以让你在服务器端输入一些指令。当然本地运行的话可以在控制台中输入【如果没记错】如果经常玩插件理解很简单。这三个api使用大同小异RegConsoleCmd(&sm_haha&,callback,&我只是注册一个haha的指令&,flags)至于最后一个flags一般是忽略的,很少用也没怎么去研究具体有多大的功能。RegConsoleCmd(&sm_haha&,callback,&我只是注册一个haha的指令&)对于callback回调函数都是下面这个【不明白可以看看console.ini】functag public Action:ConCmd(client, args);一个完整的例子//你可以放在任何public默认api中。默认放在onpluginstart()中//其他函数基本一样RegServerCmd因为不需要client这个参数,所以回调函数不需要client.//可以自己去console.ini中看看functag public Action:SrvCmd(args);RegConsoleCmd(&sm_haha&,MyCallBack,&我只是注册一个haha的指令&)//对于Api中的形参可以被修改//并且返回Plugin_Handled 对于一些新的自定义指令强烈建议这么返回。//Plugin_Handled让游戏引擎知道这个是我们自定义的指令。//否则你会发现在游戏中输入指令后提示指令不存在.public Action:MyCallBack(Client,Args){PrintToChat(Client,&我的索引是%d&,Client);//你的任何代码return Plugin_H}
ConVars 和 KeyValues 篇 附带说下服务器指令CreateConVarSyntax:native Handle:CreateConVar(const String:name[], const String:defaultValue[], const String:description[]=&&, flags=0, bool:hasMin=false, Float:min=0.0, bool:hasMax=false, Float:max=0.0);使用方法全局new Handle:MyH //默认会被设置为INVALID_HANDLEnew Handle:MyHandle = INVALID_HANDLE; //某些时候也可以显示的设置public OnMapStart(){MyHandle =CreateConVar(&sm_rpgmoney&,&100&,&金钱&,FCVAR_PLUGIN,true,1,true,10000);RegConsoleCmd(&ha&,callback);}public Action:callback(Client,Args){new x = GetConVarInt(MyHandle);PrintToChatAll(&我所设置的金币数目为%d&,x);return Plugin_H}一个小例子。很简单。大神不要喷我。如果有问题也请见谅。这里要补充一下上一楼的东西。贴吧帖子不能像论坛那么修改确实很遗憾。AddCommandListener//其中native代表该Api是必须在函数体内部使用。bool代表返回值类型Syntax:native bool:AddCommandListener(CommandListener:callback, const String:command[]=&&);Notes:Adds a callback that will fire when a command is sent to the server. Registering commands is designed to create a new command as part of the UI, whereas this is a lightweight hook on a command string, existing or not. Using Reg*Cmd to intercept is in poor practice, as it physically creates a new command and can slow down dispatch in general. To see if this feature is available, use FeatureType_Capability and FEATURECAP_COMMANDLISTENER.这个函数可以监听游戏中已经存在的指令。并且重写其回调方法。AddCommandListener(LisCallback,&say&); //没记错按Y输入默认指令为say 其中对抗中还有say_team//它所对应的结束APinative RemoveCommandListener(CommandListener:callback, const String:command[]=&&);//毁掉函数functag public Action:CommandListener(client, const String:command[], argc);//例如你可以让某些人打出的文字带有颜色。比如某些服务器使用的VIP打字有颜色。管理员打字有颜色//当然你可以使用Reg*Cmd这个笨办法来截断玩家的输入。来重写。//当看到Action你就应该知道一定要返回三种类型中的一种。这个我楼上有说过这里就不再说了//代码为随手写的。如果有问题请见谅public Action:CommandListener(client, const String:command[], argc){decl String:arg[255];
GetCmdArg(1, arg, sizeof(arg));PrintToChatAll(&\x01%s&,arg); //其中\x01代表颜色.\x02\x03\x04---\x09[现在很多插件使用color.ini来代替这种16进制颜色代码]return Plugin_C}//防止改名[复制别处的]//主要是讲解argspublic OnPluginStart(){
AddCommandListener(Command_Setinfo, &setinfo&);//setinfo是游戏者一个默认指令}设置游戏名字的全部指令为 setinfo name xxx012public Action:Command_Setinfo(client, const String:command[], args){
decl String:arg[32];
GetCmdArg(1, arg, sizeof(arg));//在上面的例子也可以看到arg 为什么是1呢?【GetCmdArg】
if (StrEqual(arg, &name&, false))
return Plugin_H
return Plugin_C}
[在求生之路2中]当我在游戏按Y输入!rpg A1 A2 A3GetCmdArgs()来测试下args的个数。args 应该是为3个.不算本身!rpg指令。不同游戏不同,所以需要自己测试下。!rpg = 0A1 = 1A2 = 2A3 = 3这里只需要知道指令后面跟着的东西是第几个参数就行了。
现在回到conver中ConVars 和 KeyValues很像都是键值对每个convar都有一个Handle来接受其对应的convar值每个keyvalue都有对应的key来读取对应的valuenew Handle:MyHandle =CreateConVar(&rpgmoney&,&100&,&金钱&,FCVAR_PLUGIN,true,1,true,10000);new x = GetConVarInt(MyHandle);new Handle:MykvKvSetNum(Mykv,&rpgmoney&,100);new x = KvGetNum(Mykv,&rpgmoney&,0);convar就不多说了.对于kv来说最难的是初学的时候理解结构用sql这个kv来说下&Databases& //root根节点{&default&//第一节点[第一层]{&driver&&default&&host&&localhost&&database&&sourcemod&&user&&root&&pass&&&//&timeout&&0&//&port&&0&&storage-local&//第一节点[第二层] 当然内部还可以继续嵌套{&driver&&sqlite&&database&&sourcemod-local&}}&storage-local&//第二节点[第一层]{&driver&&sqlite&&database&&sourcemod-local&}&clientprefs&//第三节点[第一层]{&driver&&sqlite&&host&&localhost&&database&&clientprefs-sqlite&&user&&root&&pass&&&//&timeout&&0&//&port&&0&}}最开始rpg使用的就是kv存档new Handle:YSSave = INVALID_HANDLE;new String:SavePath[128];/*enum PathType{Path_SM, SourceMod root folder }*///这个代码可以完全死记硬背{//默认是SourceMod【Path_SM】根目录中data文件夹中的RPGSave.txt文件BuildPath(Path_SM, SavePath, sizeof(SavePath), &data/RPGSave.txt&);//判断是否有文件if (FileExists(SavePath)) //如果有{//读取数据FileToKeyValues(YSSave, SavePath);}else //否则创建文件并存档[空档案]{//在控制台输出。游戏中看不到PrintToServer(&[SY] 文档建立失败: %s, 将重新建立!&, SavePath);KeyValuesToFile(YSSave, SavePath);}}//意思是将上面文件中的内容读取到内存中方便使用FileToKeyValues这个APi原型自己可以看看//意思是将内存中kv数据写入上面文件中KeyValuesToFile(YSSave, SavePath);kv值读取时一次性全部读取.比如一个rpg或者别的什么存档插件.一般只会在游戏开始和结束的时候使用这两个api。为了优化,因为反复读取会影响性能.//实际作用函数你可以在任何时候调用。一般食杂游戏开始和结束。roundstart或者roundend因为为了支持盗版所以使用名字和密码来限制//在存档总并写kvgetnum来获取密码/因为这个实在玩家进游戏输入密码后获取这些只是一种思考方式,可以照着做就行了。ClientDataLoad(Client){/* 读取玩家姓名 */decl String:user_name[MAX_NAME_LENGTH]=&&;GetClientName(Client, user_name, sizeof(user_name));/* 读取玩家资料 */KvJumpToKey(YSSave, user_name, true);//当前玩家参数存档ClientLv[Client] = KvGetNum(YSSave,
&Lv&,0);ClientExp[Client] = KvGetNum(YSSave,
&exp&,0);ClientGlod[Client] = KvGetNum(YSSave,
&glod&,0);KvGoBack(YSSave); //跳到上一层,和KvJumpToKey对应PrintToServer(&[Shaiya]%N的档案数据已读取!&, Client);}// 存储存档 存储密码和其他参数ClientDataSave(Client){decl String:user_name[MAX_NAME_LENGTH]=&&;GetClientName(Client, user_name, sizeof(user_name));KvJumpToKey(YSSave, user_name, true);KvSetNum(YSSave,
&Lv&,ClientLv[Client] );KvSetNum(YSSave,
&exp&,ClientExp[Client]);KvSetNum(YSSave,
&glod&,ClientGlod[Client]);KvSetString(YSSave, &密码&, Password[Client]);decl String:DisconnectDate[128];if(IsAdmin[Client])FormatTime(DisconnectDate, sizeof(DisconnectDate), &%j:1-%Y/%m/%d %H:%M:%S&); //&251:0- 00:40:42&elseFormatTime(DisconnectDate, sizeof(DisconnectDate), &%j:0-%Y/%m/%d %H:%M:%S&);KvSetString(YSSave,&DATE&, DisconnectDate);KvRewind(YSSave);KeyValuesToFile(YSSave, SavePath);PrintToServer(&[Shaiya]%N的档案数据已储存!&, Client);}这里只需要理解当YSSave在上面代码中正常获取到数据后就可以全局使用了。你可以在任何时候ClientGlod[Client] = KvGetNum(YSSave,
&glod&,0);而KvGetNum等kvget** Api会给你一个默认值。你可以自己设置。我设置为0.[这个是非常有用的一个东西]比如要获得某人的glod你只需要跳到某人的数据下获取内存中数据即可{......&倒霉鬼&{&gold&&12345&&host&&localhost&&database&&clientprefs-sqlite&&user&&root&&pass&&&//&timeout&&0&//&port&&0&}}因为在游戏开始的时候玩家输入密码就已经正确读取了数据了。也许还是不理解怎么读取了.首先:我们在内存中存放了一个档案包含所有人的数据然后:一个玩家加入后输入!mm 123 遍历了整个内存数据后正确读取数据我使用ClientDataLoad(Client)函数来读取对应数据new ClientGlod[MAXPLAYERS+1];为每个玩家单独创建一个量来存档自己对应的值 玩家自己的单独数据
内存数据ClientGlod[Client] = KvGetNum(YSSave,
&glod&,0);这下回顾下xxx(Client){/* 读取玩家姓名 */decl String:user_name[MAX_NAME_LENGTH]=&&;GetClientName(Client, user_name, sizeof(user_name));/* 读取玩家资料 */跳到第一个与玩家名字相同的节点因为之前已经判断玩家密码是否正确。所以可以正常读取KvJumpToKey(YSSave, user_name, true);//当前玩家参数存档ClientLv[Client] = KvGetNum(YSSave,
&Lv&,0);ClientExp[Client] = KvGetNum(YSSave,
&exp&,0);ClientGlod[Client] = KvGetNum(YSSave,
&glod&,0);KvGoBack(YSSave); //跳到上一层,和KvJumpToKey对应PrintToServer(&[Shaiya]%N的档案数据已读取!&, Client);}也许有人会很多疑问.为什么会正常读取{......&倒霉鬼& 1{&gold&&12345&&密码&&12345&...........}&倒霉鬼& 2{&gold&&23141&&密码&&22311&...........}}注意:如果存档中有两个档。那么KvJumpToKey只会读取到第一个【1】并且正常情况下。在游戏中如果有两个同名玩家。第一个为xxx 第二位xxx(1)被重命名还有一种情况就是在&倒霉鬼&下线后另外一个人在其他电脑上用同样的名字进入游戏当然就算知道密码也不行。进入游戏后并没有档。需要重新注册.这样就会发生两个同名这也许和ip有关系也或者是系统有关系。这里不深讨论.正版玩家就很简单.直接验证steamid即可。所以当内存读取到所有数据后。并不知道谁是谁的。数据就像一坨屎一样。玩家&倒霉鬼&加入游戏后。输入mm指令密码进行验证。首先:获取到该玩家名字GetClientName(Client, user_name, sizeof(user_name));直接跳到第一个相同玩家名字处。//该api会在没有该玩家名字情况下自动创建玩家名字节点.如果第三个参数设置为true//并且其拥有一个默认遍历功能。所以会找到默认第一个匹配的名字或者key值/你可以理解为一串鞭炮。从头到尾。比如第5个上面的鞭炮是倒霉鬼。那么KvJumpToKey就锁定到它。然后你又可以把倒霉鬼看作独立的一串鞭炮。它里面的值又是一个一个的键值。这样依次下去。&倒霉鬼& {KvJumpToKey(YSSave, user_name, true); //跳进&倒霉鬼& 这个名字下面&gold&&12345& &-&密码&&12345&...........}这时候我们就可以读取&倒霉鬼&中的密码。来比较是否和输入的一样。如果一样就说明是对的。那么就读取&倒霉鬼& 下面的所有数据ClientLv[Client]= KvGetNum(YSSave,
&Lv&,0);ClientExp[Client]= KvGetNum(YSSave,
&exp&,0);ClientGlod[Client]= KvGetNum(YSSave,
&glod&,0);因为YSSave这个handle是全时间都有效的。而且我们也不需要去关闭结束他。为了下次读取或者存档的时候正常需要使用KvRewind(YSSave); //直接跳到root顶节点。这里就是跳到&root& 的位置&root& &-{KvGoBack(YSSave); //跳到上一层,和KvJumpToKey对应 这里就是跳到&倒霉鬼& 的位置&倒霉鬼& &-{&gold&&12345&&密码&&12345&...........}}好了kv基本的东西大概就这些
这个只是适合个人使用。目前rpg大多使用sql来存档了.对于个人来说过于复杂了点.你需要一个数据库。并且在left4dead2\addons\sourcemod\configs的databases.cfg中配置参数.数据库这个对于一些论坛来说比较有意义.并且可以数据共享。也就是多个服务器数据通用。并且经行互通提示等等。如果要用数据库的那就只能看数据库知识了。其实也不难这里说下服务器切换.z这个本事半条命中的代码halflife.ini //这个需要在autoexec.cfg中写入下面这个因为DisplayAskConnectBox会提示让你确认。bind &f3&
&askconnect_accept&//stock DisplayAskConnectBox(client, Float:time, const String:ip[], const String:password[] = &&)DisplayAskConnectBox(Client, 30.0, &192.168.1.1&, &&);//你其他服务器的ip:这里我乱写的192.168.1.1//当然这里还有一些其他的stock函数块.自己可以尝试下 ShowMOTDPanel(Client, &汉化&,&这是个很奇怪的事情&, MOTDPANEL_TYPE_FILE);SendDialogToAll(&%N: %s&, Client, &去死&);SendDialogToAll(String:text[], any:...){new String:message[100];VFormat(message, sizeof(message), text, 3);new MaxClients = GetMaxClients();for(new i = 1; i & MaxC i++){if(IsClientInGame(i)){new Handle:kv = CreateKeyValues(&Stuff&, &title&, message);KvSetColor(kv, &color&, 255,0, 0, 255);KvSetNum(kv, &level&, 1);KvSetNum(kv, &time&, 10);CreateDialog(i, kv, DialogType_Msg);CloseHandle(kv);}}}
数据库SQL 简单介绍 【我很少接触这个.不过自己也有试过,并且成功连接和读写数据】提示:如果有兴趣好好的学习下数据库知识也不错。对于一般玩家如果只是想玩玩数据库,可以试试ESSamp.这个工具。是一个集成傻瓜式的数据库好吧上传图片居然一直失败。放弃了。真怀疑度 娘的锅吧能活这么久简直是一个奇迹。ESSamp在win7以上的系统需要管理员运行才可以。这个工具很傻瓜,网上也有简单教程就不多说了建议玩玩ESSamp再看,不然可能会有点抽象。首先在\addons\sourcemod\configs\databases.cfg复制&default&{&driver&&default&&host&&localhost&&database&&sourcemod&&user&&root&&pass&&&//&timeout&&0&//&port&&0&}修改为&anyname& //你可以任意修改{&driver&&default& //一般默认 这个默认应该就是指mysql 还有个是sqlite&host&&localhost&//服务器ip 也就是mysql 数据库的ip.自己电脑上就是默认就行了。除非用了虚拟机什么的。&database&&l4d2data&//phpmyadmin数据库名字【自定义】&user&&root& //默认ESSamp 的phpmyadmin用户名【自定义】&pass&&& //默认phpmyadmin的密码为空//&timeout&&0& //这个没测试过,超时&port&&3309& //默认端口。这个必须修改正确,复制无法连接}端口:可以在ESSamp的设置页面中查看修改。自己下载组件组装的另当别论。这里说下我对数据库的理解。大神勿喷,只是给插件初识者理解下建议先玩玩ESSamp或者自己组装的数据库php页面之后理解起来就简单了数据库&--& 表 之间的关系一个包裹&--&包里的一个小本而如果每个玩家都在表中有自己的数据就像小本子的每一页就是每个玩家一样。&database&&l4d2data& 这个代表的是建立的l4d2data这个数据库全部然后在插件中使用 【原型自己看api】new Handled:DatabaseDatabase = SQL_Connect(&anyname&, true, sqlError, sizeof(sqlError));来连接数据库。看需求选择函数。因为只要database.cfg配置正确后面基本上都属于数据库知识了.这里名字指的是根节点的名字。因为数据库连接,需要上面那么多参数,并非一个名字而已。这个你也可以在ESSamp的MYSQL连接测试的时候看到需要的参数和上面kv节点中的参数一样。在l4d2data数据库的表playerdata中写入数据new String:QueryString[256];Format(QueryString,256,&INSERT INTO playerdata (name, steamid,kill,dead,money) VALUES('%s','%s','%n','%n','%n')&,Playername,Steamid,Enemykill,Playerkill,Money);new Handle:HBs = SQL_Query(Database,query);这里面其实是使用SQL_Query函数来执行&INSERT INTO playerdata (name, steamid,kill,dead,money) VALUES('%s','%s','%n','%n','%n')“这句数据库语言。至于读取也一样。这里就不多说了。有兴趣可以找一些使用数据库统计插件来自己看看读取写入方式和错误报告方法。mysql这部分难点我觉得在于数据库理解和database.cfg的设置
补充一下&anyname& //&-根节点名字。在数据库连接的时候需要这个作为引用名字//所以Database = SQL_Connect(&anyname&, true, sqlError, sizeof(sqlError));使用&anyname&名字引用来使用该节点中所有配置参数进行与数据区mysql的连接.{&driver&&default& //一般默认 这个默认应该就是指mysql 还有个是sqlite&host&&localhost&//服务器ip 也就是mysql 数据库的ip.自己电脑上就是默认就行了。除非用了虚拟机什么的。&database&&l4d2data&//phpmyadmin数据库名字【自定义】&user&&root& //默认ESSamp 的phpmyadmin用户名【自定义】&pass&&& //默认phpmyadmin的密码为空//&timeout&&0& //这个没测试过,超时&port&&3309& //默认端口。这个必须修改正确,复制无法连接}而读写数据库l4d2data【这是我自己在sql中随便创建的数据库,名叫l4d2data】是使用 new Handle:HBs = SQL_Query(Database,query);返回一个handle 来判断是非访问到 aql中的数据。这里创建一个数据库,叫l4d2data建立好了如何退出或者长时间没动静就会重新登录。默认用户名为root,如果自己设置就是自己的用户名和密码在数据库中创建一个表叫做playerdata可以看到l4d2data(1)中的数字1.说明数据库l4d2data中目前有一个表叫做 playerdata如果连接成功后进行读写数据后就会有在表playerdata中有一条数据 使用Format把数据库语言写入一个字符串中。也可以用其他方法创建一个字符串。这里的字符串是sql的语法。这里我也不多说了。可以自己看下数据库语法使用方法或者找一些使用了数据库的插件来看看。插件使用的是很基本的东西。很简单Format(QueryString,256,&INSERT INTO playerdata (name, steamid,kill,dead,money) VALUES('%s','%s','%n','%n','%n')&,Playername,Steamid,Enemykill,Playerkill,Money);最后使用
楼主多来一些教程嘛
收藏了,首先我得学到函数
挖个坟,hook时间回合开始,每次回合开始自动控制台输入buymenuHookEvent(&round_start&, Event_RoundStart);然后下面怎么写呢?
我一字不漏的看了3小时。真的很想学。希望可以叫声师傅。
良心楼主,向您问好
贴吧热议榜
使用签名档&&
保存至快速回贴

我要回帖

更多关于 求生之路2服务器插件 的文章

 

随机推荐