我以后玩游戏的时间越来越少了..分享下这个游戏mod制作方法., 没有编程基础也能做, 如果有编程基础的话,可以做出很多高级的mod来.

工具

1,Alien Swarm: Reactive Drop-sdk  [steam - 库 - 工具 ]  (官方开发套件 约90M ,先装游戏,再装SDK,已经安装了游戏,直接安装SDK)

2,GCFScape  [下载]  (mod解包工具 , 约500KB )

 

下文简称 SDK解包工具.

 

3,任意记事本编辑工具,推荐用notepad++ ,否者可能中文显示有问题.

 

 

官方开发文档网页版

1,  控制台参数/控制台命令 --> 链接

2,  mod函数  --> 链接

 

路径

我的游戏路径是:

D:\Program Files (x86)\Steam\steamapps\common\Alien Swarm Reactive Drop\

但是对于mod文件,真正的根目录应该是

D:\Program Files (x86)\Steam\steamapps\common\Alien Swarm Reactive Drop\reactivedrop\     <--下文简称根目录.

 

已安装的mod文件所在目录

创意工坊mod文件下载所在目录

D:\Program Files (x86)\Steam\steamapps\workshop\content\563560\

 

 

自己测试,本地安装mod目录

D:\Program Files (x86)\Steam\steamapps\common\Alien Swarm Reactive Drop\reactivedrop\addons\

 

下文我都将本地测试mod目录 简称为 MOD目录 .

 

 

从山寨开始了解MOD

 

我用4fun (创意工坊链接) 为例子.订阅后.steam自动下载后.

可以在创意工坊mod目录可以找到1112385907/addon.vpk

用解包工具打开.

 

 

解包

解包方式有两种,

1,鼠标按住root 拖动到一个本地文件夹

2,在root 上右键 Extract 导出到一个指定目录

 

解包后你会发现它的目录和游戏目录是一一对应的. (ROOT目录对应游戏根目录)

而里面多数都是文本文件,甚至记事本都能编辑.

 

 

 

现在做个简单实验

1,取消订阅4fun mod (游戏关闭状态) ,并在创意工坊下载mod目录里面确认这个mod被删除了.没被删就手动删.

2,运行游戏,单人开房,确认挑战里面已经没有 4fun 模式了.

2,游戏无需关闭, 直接将解包的mod文件复制游戏根目录,注意一一对应

3,退到游戏主菜单,你也可以重启游戏, 单人开房,看看挑战里面是不是又有4fun了.

 

创意工坊mod vpk文件工作模式,感觉就像解压后放游戏目录. (实际它的工作方式更像linux系统的挂载/软链接方式;window系统的快捷方式)

 

到这里,你只要了解,在游戏根目录放入特殊的文件,mod就能跑起来.

挑战: resource\challenges

挑战导演系统: resource

脚本:scripts , scripts\vscripts

地图:maps  ,  maps\graphs  , materials\vgui\swarm\

地图选择:  resource , resource\campaigns, resource\overviews

模型:models  , materials\models

 

 

多拆两个包.多看看别人怎么做的.

 

 

制作一个山寨挑战mod

现在拿我山寨的4fun挑战mod拿出来讲解.

 

创建一个挑战文件

新建一个文本文件,名字随意,建议小写英文或者追加数字的组合.

游戏根目录\resource\challenges\tl2.txt    (注意这里用的是tl2 ,尽量不要和官方文件重名,原因后面我说补充说下. )

 

文件内容如下

"CHALLENGE" {
	"name"	"屠杀场/跳跃版"
	"description"	"山寨版本的4FUN,基于4FUN改进中,尽可能地支持MOD地图"

	"convars" {
		rd_ready_mark_override 1   //自动准备
		rd_weapons_regular_allowed "7 27"  //7弹药箱 27灭火器
		rd_weapons_regular_allowed_inverted 1
		rd_weapons_extra_allowed "1 2 5 12 19 18 20 8 15"
		rd_weapons_extra_allowed_inverted 1
		rd_weapon_requirement_override 1
		rd_weapons_regular_class_unrestricted "1 2 3 15"
		rd_weapons_extra_class_unrestricted 11
		rd_techreq 0
		rd_hackall 1  
		rd_weapons_show_hidden 1      //显示隐藏武器.
		rd_player_bots_allowed 0     //禁止选机器人
		asw_wanderer_override   1   //锁定猛攻
		asw_marine_ff_absorption 0 //锁定友伤方式
	}
}

 

name  就是挑战名,支持中文.

description  挑战描述,支持中文

convars 就是参数设置.  自己参考前面我提供的官方文档链接.

 

ps:

这里参数主要作用于大厅.主要作用 用来限制/或解锁武器,  游戏地图限制必须要技术的, 这里也可以取消限制.

这些参数实际会作用到游戏里.这里可以把所有变量写这里,不过不建议.

 

 

测试:

 你重新开单人房间,你就发现里面有这个 屠杀场/跳跃版 挑战了.

 

这是最基本的挑战mod文件.光这个文件就能跑起来.

 

 

 

创建挑战MOD脚本

 

光参数并不能完美实现你要的功能,那么就需要用到脚本文件了.

脚本文件是自动载入制度.

前面我的挑战名字 tl2.txt

 

那么

我们新建一个后缀为nut的文件. 名为 challenge_挑战文件名.nut

游戏根目录\scripts\vscripts\challenge_tl2.nut

 

这个脚本文件会在游戏开始后自动加载.你可以把你所有需要的功能写这个文件里..

 

我更喜欢challenge_tl2.nut用IncludeScript包含脚本文件的方式引入其他脚本.

 

//为行注释符.

//基本参数
IncludeScript("tl_cvar.nut");
//难度控制
IncludeScript("tl_skill_level.nut");
//函数
IncludeScript("tl_fun.nut");
//恢复弹药逻辑脚本
IncludeScript("tl_regen_ammo.nut");
//武器伤害/反伤逻辑脚本
IncludeScript("tl_damage.nut");
//钩子
IncludeScript("tl_even.nut");	


//地图fix
IncludeScript("tl_map_fix.nut");	

另外在 游戏根目录\scripts\vscripts\ 新建一个tl_cvar.nut 放我的参数变量. (和challenge_tl2.nut 同目录)

另外在 游戏根目录\scripts\vscripts\  新建一个tl_skill_level.nut 放我的难度控制脚本.

另外在 游戏根目录\scripts\vscripts\ 新建一个tl_fun.nut 放我的函数脚本.

...类推

 

我感觉这样逻辑比较清晰.

 

设置参数方式得用命令

Convars.SetValue( "rd_sentry_invincible", 1 );  //炮台无敌

 

放上我tl_cvar.nut文件部分代码.

//~~~~~~~~~子弹设置部分~~~~~~~~

//炮台无限子弹
Convars.SetValue( "asw_sentry_infinite_ammo", 1 );
//医疗步枪 无限医疗
Convars.SetValue( "rd_medgun_infinite_ammo", 1 );
//不删除空装备
Convars.SetValue( "rm_destroy_empty_weapon", 0 );
//隐藏备用弹夹数量(无限子弹模式好看点)
Convars.SetValue( "rd_hud_hide_clips", 1 );
//没有弹药的时候不提示
Convars.SetValue( "rd_notify_about_out_of_ammo", 0 );


//~~~~~~~~~技能部分~~~~~~~~

//技术工程能力--快速放炮台
Convars.SetValue( "asw_skill_engineering_sentry_base", 99 );



//~~~~~~~~~武器部分~~~~~~~~

//缩小沙漠之鹰对特殊怪的伤害
Convars.SetValue( "rd_deagle_bigalien_dmg_scale", 1 );
//电甲持续时间
Convars.SetValue( "asw_electrified_armor_duration", 30 );
//灭火器冰冻量(默认为0不可冰冻怪物)
Convars.SetValue( "rd_extinguisher_freeze_amount", 0.2 );
//灭火器伤害  4fun为0.1
Convars.SetValue( "rd_extinguisher_dmg_amount", 0.2 );

//手雷导火索长度 (疑似引燃时间)
Convars.SetValue( "asw_cluster_grenade_child_fuse_max", 2 );
//手雷分裂数量
Convars.SetValue( "asw_skill_grenades_clusters_base", 5 );

 

这样,参数分类,加上注释, 以后要修改也比较方便.

官方文档也不太完美,我英文能力又差,很多变量理解上有点问题..官方文档解释不清楚的,一半靠蒙,一半靠游戏测试参数去理解.

 

 

脚本基本用法

变量定义

属于弱类型语法,可以不定义直接使用

 

定义有两种方式,一种是反向箭头

ent <- null;

 

另外可以用等号表示

hNearEnt = null;

 

默认为全局变量.

 

想要定义局部变量 加 local 前缀

local hNearEnt = null;

 

类型转换也有自动转换.

 

 

逻辑语法

看官方文档只看到这四种语法 ,用法和C/C++一样. 跳出循环,跳过循环的用法一样.

if ,for , while,switch/case

 

 

 

 

 

钩子函数

游戏脚本自带几个钩子函数,在满足特定条件下触发

 

 

OnTakeDamage_Alive_Any

触发伤害函数,无论是怪打你,还是你打怪,还是你自己炸到你自己.都会被触发

 

 

UserConsoleCommand

用户使用控制台命令触发此函数.

 

OnGameEvent_x

响应游戏某个事件,这里x是代替值,实际应用有很多,玩家加入,玩家离开,角色死亡,捡取弹药...

举例

OnGameEvent_sentry_complete  //炮台搭建完成

OnGameEvent_weapon_reload_finish //弹药装填完毕

具体完整列表在这两个文件,事件名和参数都有说明.

文件1  -> 链接

文件2  -> 链接

 

OnMissionStart

当任务开始,或者理解为游戏开始触发.

 

Update

定时执行钩子函数,这个函数最终返回一个浮点型,这个数值就是下次执行该函数的间隔.

 

 

 

脚本实例讲解

4fun mod中有个,所有人死亡自动重启任务效果,这个就是钩子用法.

我将他代码做了一些改进.

 

//钩子 死亡(异形和玩家死亡都会触发)
function OnGameEvent_entity_killed(params)
{

	//读取死亡者
	local victim = EntIndexToHScript(params["entindex_killed"]);

	//如果死掉的是海军陆战队成员
	if (victim != null && victim.GetClassname() == "asw_marine"){

		if (marinesTable.rawin(victim)){

			//当海军陆战队死亡后在存活表中移除
			marinesTable.rawdelete(victim);
			
			
			
			//当全部死亡,重启任务
			if (marinesTable.len() == 0){
			
				//4fun 这里是直接重启任务,这里如果直接重启的话,所有玩家都无法获得经验.
				//正常游戏失败了是有经验的,虽然比较少.
				
				//创建一次性定时器
				//通过延时1秒所有人都能获得经验.
				
				
				
				//创建计时器
				local timer = Entities.CreateByClassname("logic_timer"); 
				
				//应该是循环间隔
				timer.__KeyValueFromFloat("RefireTime", 1);
				
				//先停止定时器(因为定时器脚本还没挂载)
				DoEntFire("!self", "Disable", "", 0, null, timer);
				
				//验证脚本作用域??
				timer.ValidateScriptScope();
				
				//用另外一个函数来接管,类似回调函数
				local timerScope = timer.GetScriptScope();
				

				//回调函数
				timerScope.Delay <- function()
				{
					//重启任务
					Director.RestartMission();
					self.DisconnectOutput("OnTimer", "Delay");
					//计时器销毁
					self.Destroy();	

				}
				//链接计时器作用域脚本				
				timer.ConnectOutput("OnTimer", "Delay");
				
				//激活计时器
				DoEntFire("!self", "Enable", "", 0, null, timer);			
			
			}
			
				
				
		}
	}else {
		//死的不是玩家的时候,这里4fun有
		
		//当火蚊子死亡的时候,停止蚊子声音(预保留)
		if (victim.GetName() == "asw_tl_buzzer"){	
				victim.StopSound("d1_town.LargeFireLoop");
				victim.StopSound("d1_town.LargeFireLoop");	
		}
	}
}

 

 

导演文件

导演文件乃是文档最少的,官方wiki甚至没提这个万一.

 

导演文件是控制生成的特殊脚本.

相对于挑战文件

游戏根目录\scripts\vscripts\challenge_tl2.nut

那么自动执行的导演文件有两种.

alien_selection_tl2.txt

alien_selection_对应地图名_tl2.txt

 

标有地图名字的脚本应该优先级会更高.

 

这个文件自己研究.

 

 

打包

1,游戏外面,比如你桌面或者C盘新建一个root文件夹.

2,然后根据前面 挑战文件,导演文件,脚本  对应的文件放root目录,注意它们和游戏根目录对应规则.

 

用命令

D:\Program Files (x86)\Steam\steamapps\common\Alien Swarm Reactive Drop\bin\vpk.exe    "C:\root\"

会在root目录生成一个vpk文件.

 

发布

在游戏中,创意工坊新建一个mod,打个名字,和描述(目前只能打英文或者数字  后面上传后可以改中文),

然后设置一个封面图片.

然后选择你的VPK文件,点发布即可.上传完毕后,会自动打开浏览器,就是你这个mod创意工坊链接.

 

这时这个mod只能你自己访问. 你把mod设置公共访问就可以其他人订阅了.

 

 

更新

有更新的话,只要在游戏中重新上传新的VPK包即可.

 

 

 

注意事项

1,不要和官方文件重名. 覆盖官方文件会导致你进不去公共服务器.  (比如你修改武器模型)

游戏会检验本地和服务器核心文件是否相同.

 

2,不要和其他mod文件名字相同.

如果你也叫个挑战也用4fun.txt ,如果你服务器同时开启4fun和你这个同名4fun,那么在挑战列表里面只会出现一个挑战.

回到前文看下MOD工作方式你就知道为啥了.

 

ps : 你可以叫个8fun.txt (只要文件不冲突) ,文件内描述可以和4fun一样.  这样服务器同时启用两个mod,就能在挑战列表看到两个4fun.

 

3,版权问题

山寨的mod不要上传到创意工坊,除非取得作者同意.

或者代码用抄袭别人的.都不要上传创意工坊.

 

国外版权意识很强.