地图触发

地图可以像剧情编辑器那样添加触发程序,不过非常复杂,特别是台海战争那幅1V1地图,用触发设定AI刷兵、占领超级大炮我用了7天时间写上20个触发,地图触发的语句已经占了三分之二。下面会介绍三种触发程序的写法、以及一些注意事项。

1:旧版本触发程序(官方设定)

实际上为官方在地图定义的触发程序创建方式就只有这种,但因为其使用比较繁琐,不方便,依赖xml文件,多人联机时没办法自定义触发程序等,被注入式触发程序取代,因此将其称为旧版本触发程序。
.
..
...
....
.....
......
太久没有使用这种旧版本触发了,忘记怎样语句是怎样写的了。
	幸好孙百里是用旧版本触发程序的,所以台海战争有他设定的旧版本触发程序:
	rmCreateTrigger("string triggerName");	//设定触发程序名称
	rmSwitchToTrigger(rmTriggerID("string triggerName"));		//可以不设定,若设定,则切换到某触发程序,后续调用rmAddTriggerCondition与rmAddTriggerEffect将会添加在该触发中。
	rmSetTriggerPriority(3); 		//优先级
	rmSetTriggerActive(true);		//设定是否作用中,false为关闭状态
	rmSetTriggerRunImmediately(true);	//设定是否立即运行,false为开局5秒后才允许
	rmSetTriggerLoop(false);		//设定是否无限循环本触发,false为只执行一次

	rmAddTriggerCondition("string conditionType");	//设定条件,必须与游戏目录的trigger3文件夹里面的typetest.xml文件中的Condition name=""对应
	//设定条件内容,paramName必须与条件名称在同一个触发,与typetest.xml的Param name=""对应,typetest.xml那个条件有多少个选项你就添加多少句
	rmSetTriggerConditionParam("string paramName", "string value", false);		//rmSetTriggerEffectParam 为string参数 ,第二个值要加英文双引号
	rmSetTriggerConditionParamInt("string paramName", int value, false);			//假如rmSetTriggerConditionParam加上Int则变为整数,第二个值只能填数字。
	rmSetTriggerConditionParamFloat("string paramName", float value, false);		//假如rmSetTriggerConditionParam加上Float则变为浮点数,第二个值只能填数字。
	rmSetTriggerConditionParamArmy("string paramName", int playerID, int armyID, false);		//假如rmSetTriggerConditionParam加上Army则变成军队专用参数 ,其第二个玩家ID,第三个值为军队ID



	rmAddTriggerEffect("string effectType");		//设定触发程序的效果,必须与游戏目录的 trigger3 文件夹里面的 typetest.xml 文件中的 Effect name="" 对应
	//设定效果参数, paramName 必须与条件名称在同一个触发,与 typetest.xml 的 Param name="" 对应, typetest.xml 那个效果有多少个选项你就添加多少句
	rmSetTriggerEffectParam("string paramName", "string value", false);			//rmSetTriggerEffectParam 为string参数 ,第二个值要加英文双引号
	rmSetTriggerEffectParamInt("string paramName", int value, false);		//假如 rmSetTriggerEffectParam 加上 Int则变为整数,第二个值只能填数字
	rmSetTriggerEffectParamFloat("string paramName", float value, false);		//假如 rmSetTriggerEffectParam 加上 Float 则变为浮点数,第二个值只能填数字
	rmSetTriggerEffectParamArmy("string paramName",int playerID, int armyID, false);		//rmSetTriggerEffectParam 加上 Army则变成军队专用参数 ,其第二个玩家ID,第三个值为军队ID


模板:
	rmCreateTrigger("string triggerName");
	rmSwitchToTrigger(rmTriggerID("string triggerName"));
	rmSetTriggerPriority(3);
	rmSetTriggerActive(true);
	rmSetTriggerRunImmediately(true);
	rmSetTriggerLoop(false);

	rmAddTriggerCondition("string conditionType");
	rmSetTriggerConditionParam("string paramName", "string value", false);
	rmSetTriggerConditionParamInt("string paramName", int value, false);
	rmSetTriggerConditionParamFloat("string paramName", float value, false);
	rmSetTriggerConditionParamArmy("string paramName", int playerID, int ArmyID, false);

	rmAddTriggerEffect("string effectType");
	rmSetTriggerEffectParam("string paramName", "string value", false);
	rmSetTriggerEffectParamInt("string paramName", int value, false);
	rmSetTriggerEffectParamFloat("string paramName", float value, false);
	rmSetTriggerEffectParamArmy("string paramName", int playerID, int ArmyID, false);

	

优点:官方设定的触发程序,除此之外没有优点。
缺点:
  1. 体积庞大。
  2. 受typetest.xml限制,所有string conditionType、string effectType、string paramName必须与typetest.xml的设定对应。存在中文路径无法运行。
  3. 存在中文路径的帝国3目录将无法运行,联机会与非中文路径的不同步。
  4. 大部分涉及玩家ID的触发无法输出0,即为不能设定为对大自然起作用。大概原因是0被识别为空(假),此处只有程序员才能看懂。
  5. 自定义触发需要自己修改trigger3文件夹里面的xml文件,不能与没有修改过的玩家联机,(其实可以算是不能自定义触发程序了)。

样板:在TaiwanStrait(台湾海峡)地图能找到类似触发程序

2:注入式触发程序(天书

顾名思义,注入式触发程序就是通过注入代码,绕过原有的调用方式,运行了不应该运行的代码。注入式触发程序原理是,xs地图的rm函数创建触发程序后,rm函数会转换成触发的专用代码,全部转换完成后会再重新编译输出一次代码;但官方没有过滤/**/,当开发者在rm函数中的引号中调用/**/时,被/**/包围的内容会被当成注释,跳过不执行,导致可以注入代码的可能性;这绝对是判断不严谨导致的严重注入漏洞(该漏洞让我们实现了可以在xs地图中使用自定义触发,不再需要依赖trigger3/typetest.xml,带来了无限的可能性,百利无一害。但如果你的网站出现这样一个漏洞,你的服务器+网站没了。
由于注入代码是相当复杂的,为了方便、简化注入代码,你需要在void main(void)前面添加以下语句,用于声明函数:
// 踢出中文路径玩家,避免触发程序不正常运行以及联机不同步 void forceExitIfNonAnsiPath() { /* It can't running in Chinese path .*/ rmCreateTrigger("CheckANSI"); rmSetTriggerActive(true); rmSetTriggerRunImmediately(true); rmSetTriggerPriority(5); rmAddTriggerEffect("SetIdleProcessing"); rmSetTriggerEffectParam("IdleProc","true);trQuestVarSet(\"Path\",1);xsDisableSelf();}}/*"); rmAddTriggerEffect("SetIdleProcessing"); rmSetTriggerEffectParam("IdleProc", "true); */rule _aoebbs_net inactive { if(true){ xsDisableSelf("); /*The next trigger will immediately kick out any player whose game path contains non-ANSI characters (Chinese, Japanese, etc.)*/ rmCreateTrigger("ForceExitIfNonAnsiPath active runImmediately{if(trQuestVarGet(\"Path\")!=1){"+"showSPCNote(\"Error!\",\"<color=0,1,0>Use-an-English-path-to-install-the-Age-of-Empires-III,Please.\");"+"uiMessageBox2(20948);trEndGame();trYouWin(true);xsDisableSelf();}}/*"); rmSetTriggerActive(false); rmSetTriggerPriority(5); rmCreateTrigger("*/rule _ForceExitIfNonAnsiPathEnd"); rmSetTriggerActive(false); } // rmSetTriggerEffectParam代码注入:起始设定 void aoebbsParamInjectStart(string xs="") { rmCreateTrigger("aoebbsInject"); rmSwitchToTrigger(rmTriggerID("aoebbsInject")); rmSetTriggerRunImmediately(true); rmSetTriggerActive(false); rmAddTriggerEffect("SetIdleProcessing"); rmSetTriggerEffectParam("IdleProc", "true);"+xs+"}}/*"); } // rmSetTriggerEffectParam代码注入:结束设定 void aoebbsParamInjectFinish(string xs="") { rmAddTriggerEffect("Chat Status"); rmSetTriggerEffectParam("Active", "true); */rule _aoebbsInjectEnd active { trQuestVarSet(\"Path\",1);if(true){ "+xs+"xsDisableSelf("); rmCreateTrigger("ForceExitGame active runImmediately{if(trQuestVarGet(\"Path\")!=1){"+"showSPCNote(\"Error!\",\"<color=0,1,0>Use-an-English-path-to-install-the-Age-of-Empires-III,Please.\");"+"uiMessageBox2(20948);trEndGame();trYouWin(true);xsDisableSelf();}}/*"); rmSetTriggerPriority(5); rmCreateTrigger("*/rule _IfNonAnsiPath"); rmSetTriggerActive(false); } // rmSetTriggerEffectParam代码注入:局部代码 void aoebbs(string xs="") { rmAddTriggerEffect("Chat Status"); rmSetTriggerEffectParam("Active", "true); */ "+xs+"/*"); } //rmSetTriggerEffectParam代码注入:单个rule结尾,已弃用,实际与aoebbs函数相同,并不需要使用。但也可以用作多个rule快速区分。//因为历史遗留问题,仅作保留。 void aoebbsE(string xs="") { rmAddTriggerEffect("Chat Status"); rmSetTriggerEffectParam("Active", "true); */ "+xs+"/*"); } //rmSetTriggerEffectParam代码注入:单个rule结尾,不带花括号,自带xsDisableSelf() void aoebbsF(string xs="") { rmAddTriggerEffect("Chat Status"); rmSetTriggerEffectParam("Active", "true); */ xsDisableSelf();"+xs+"/*"); } // rmSetTriggerEffectParam代码注入:已弃用,因旧函数滥用,仅作保留 void aoebbsZ(string xs="") { rmAddTriggerEffect("Chat Status"); rmSetTriggerEffectParam("Active", "true); */ "+xs+"trSetUnitIdleProcessing(true"); } //单个rmCreateTrigger代码注入:可在中文路径上运行,限制256字符;ruleName触发程序名称 void aoebbsR(string ruleName="",string xs="") { rmCreateTrigger(ruleName+" "+xs+"/*"); rmCreateTrigger("*/rule _"+ruleName+"End"); rmSetTriggerActive(false); } //rmCreateTrigger代码注入:可在中文路径上运行,无字符串限制,必须用aoebbsD结尾。ruleName触发程序名称 void aoebbsA(string ruleName="",string xs1="",string xs2="") { rmCreateTrigger(ruleName+" "+xs1+"{int C=1;"+xs2+"/*"); } //rmCreateTrigger代码注入:局部代码区域,必须插入在aoebbsA与aoebbsD之间。该函数的注入会产生3行相同代码。该函数是如何解决三行代码的问题?定义了一个在aoebbsA函数中先定义一个变量C(Counter的首字母),根据C的值限制代码只执行一次。 void aoebbsB(string xs1="") { rmCreateTrigger("*/if(C<2){"+xs1+"}C++;if(C>3)C=1;/*"); } //rmCreateTrigger代码注入:用于跨行调用if,不能使用else格式。不要用于执行if以外的代码,不然会运行三次。 void aoebbsC(string xs="") { rmCreateTrigger("*/"+xs+"/*"); rmSetTriggerActive(false); } //rmCreateTrigger代码注入:ruleName触发程序名称,其名称可与aoebbsA的ruleName相同。 void aoebbsD(string ruleName="",string xs="") { rmCreateTrigger("*/"+xs+"}rule _"+ruleName+"End"); rmSetTriggerActive(false); }

rmAddTriggerEffect注入代码

以下红色字体为必要设定,只需要添加一次,添加一次后,你就可以在aoebbsParamInjectStart()与aoebbsParamInjectFinish()之间任意插入xs触发。

	aoebbsParamInjectStart();
	
	//---------在下面输入rule(触发程序),旧版本触发程序会输出类似下面的rule,输出的名称叫rule _触发程序名--------
	//----可以无限添加rule----------


	//这个是示例:
	aoebbs("rule _1start inactive runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) >= 300.00000000){");
	aoebbs("trSetLighting(\"New England Start\", 130.00000000);");
	aoebbs("xsDisableRule(\"_1start\");");
	aoebbs("xsEnableRule(\"_2start\");");
	aoebbsE("}}");

	//如果你使用的是aoebbsZ结束函数,那么必须要以aoebbsZ("/*");结尾
	aoebbs("rule _1startZ inactive runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) >= 300.00000000){");
	aoebbs("trSetLighting(\"New England Start\", 130.00000000);");
	aoebbs("xsDisableRule(\"_1startZ\");");
	aoebbs("xsEnableRule(\"_2start\");");
	aoebbsZ("}} /*");

	//RM与XS混用,根据RM的设定,生成不同的触发
	int PlayerType = rmRandInt(1,2);
	aoebbs("rule _2start inactive runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) >= 130.00000000){");
	if ( PlayerType == 1 )
	{
		aoebbs("trSetLighting(\"yellow_river\", 140.00000000);");
	}
	if ( PlayerType == 2 )
	{
		aoebbs("trSetLighting(\"yukon\", 140.00000000);");
	}
	aoebbs("xsDisableRule(\"_2start\");");
	aoebbs("xsEnableRule(\"_3patagonia\");");
	aoebbsE("}}");

	if (rmGetNomadStart()!=true)
	{
		aoebbs("rule _start active runImmediately { ");
		aoebbs("if((trTime()-cActivationTime) >= 1.00000000){");
			for(p=1;<=cNumberNonGaiaPlayers)
			{
				if (rmGetPlayerCiv(p) >= 14 && rmGetPlayerCiv(p) <= 18 )
				{
					aoebbs("trChatSendToPlayer(0,"+p+",\"{63974}\");");
				}
				else if (rmGetPlayerCiv(p) >= 19 && rmGetPlayerCiv(p) <= 26 )
				{
					aoebbs("trChatSendToPlayer(0,"+p+",\"{63973}\");");
				}
				else
				{
					aoebbs("trChatSendToPlayer(0,"+p+",\"{31536}\");");
				}
			}
		aoebbs("xsDisableRule(\"_start\");");
		aoebbsE("}}");
	}


	aoebbs("rule _Debug1 active runImmediately { ");		//rule _后面的文字相当于旧版本触发程序的触发名称
	aoebbs("if((trTime()-cActivationTime) >= 1.00000000){");
	aoebbs("trChatSendSpoofed(0,\"<color=0,1,1>Forum : https://www.aoebbs.net\");");
	aoebbs("xsDisableRule(\"_Debug1\");");
	aoebbsE("}}");

	aoebbs("rule _Debug2 active runImmediately { ");		//runImmediately为立刻运行,理论上跟剧情编辑器一样,如果不设定立刻运行,开局后会有延迟。
	aoebbs("if((trTime()-cActivationTime) >= 1.00000000){");
	aoebbs("trChatSendSpoofed(0,\"<color=0,1,1>Forum : https://www.aoebbs.net\");");
	aoebbs("xsDisableRule(\"_Debug2\");");
	aoebbsE("}}");

	aoebbs("rule _Debug3 active runImmediately { ");		//active代表作用中,改成inactive就变成关闭状态
	aoebbs("if((trTime()-cActivationTime) >= 1.00000000){");
	aoebbs("trChatSendSpoofed(0,\"<color=0,1,1>Forum : https://www.aoebbs.net\");");
	aoebbs("xsDisableRule(\"_Debug3\");");
	aoebbsE("}}");


	aoebbs("rule _Debug4 active runImmediately { ");		
	aoebbs("if((trTime()-cActivationTime) >= 1.00000000){");
	aoebbs("trChatSendSpoofed(0,\"<color=0,1,1>Forum : https://www.aoebbs.net\");");
	aoebbs("xsDisableRule(\"_Debug3\");");
	aoebbs("}}");															//实际上末尾的aoebbsE并不是必须的,可以直接用aoebbs代替,aoebbsE的作用仅为快速区分各触发程序。

	//-------------------rule必须在上面添加------------

	//触发程序结尾,所有rule的必须在上面添加,超出此处将导致整体触发失效。
	aoebbsParamInjectFinish();
	
优点:
  1. 极大简化了触发程序的语句。
  2. 可以自定义触发程序。
  3. 最高可输出2万+个字符。
  4. 所有触发将以函数形式显示,有不懂看函数表就行了。
  5. 可以联合RM函数使用,例如在同一个触发内根据国家不同生成不同效果。
  6. 可以联合XS数组使用。
  7. 制作方便,查看方便,修改方便。
  8. 涉及玩家ID的触发可以输出0,即为设定对象为大自然。
缺点:
  1. 所有rule都必须放在开头aoebbsParamInjectStart()与末尾aoebbsParamInjectFinish()之间。
  2. 一个引号里面的内容最多只能输入127个字符,超出将会导致无法打开地图,如果超出127个字符可以使用加号使两个引号连接起来。例如:"127"+"xxxxxxx"。
  3. 所有语句都是在英文双引号""下使用,触发中的string值的双引号""必须用c++转移字符\"\"代替,例如aoebbs("xsDisableRule(\"_Debug3\");");。(2026-02-15注:你不可以用单引号' '来取代\"\",实测单引号没办法被触发程序的编译器识别。)
  4. 因为注入代码是通过rmSetTriggerEffectParam来完成的,因此需要读取typetest.xml,假如帝国3的安装目录存在中文路径则无法运行,联机会与非中文路径的不同步。

样板:在China Map(中国)地图、TaiwanStrait(台湾海峡)地图、Lake of the Moon(月之湖)等地图能找到类似触发程序。


注入代码原理:
首先来看一个正常的RM触发程序(顶部的“1.旧版本触发程序”):
	int randomplayer = rmRandInt(1, 2);
	rmCreateTrigger("BuildLimit");
	rmSwitchToTrigger(rmTriggerID("BuildLimit"));
	rmSetTriggerPriority(3); 
	rmSetTriggerActive(true);
	rmSetTriggerRunImmediately(false);
	rmSetTriggerLoop(false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", 1, false);
	rmSetTriggerEffectParam("ProtoUnit", "ypCastle", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "20", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", 1, false);
	rmSetTriggerEffectParam("ProtoUnit", "Outpost", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "20", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", 1, false);
	rmSetTriggerEffectParam("ProtoUnit", "Blockhouse", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "20", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", 1, false);
	rmSetTriggerEffectParam("ProtoUnit", "WarHut", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "20", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", 1, false);
	rmSetTriggerEffectParam("ProtoUnit", "YPOutpostAsian", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "20", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", 2, false);
	rmSetTriggerEffectParam("ProtoUnit", "ypCastle", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "20", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", 2, false);
	rmSetTriggerEffectParam("ProtoUnit", "Outpost", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "20", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", 2, false);
	rmSetTriggerEffectParam("ProtoUnit", "Blockhouse", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "20", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", 2, false);
	rmSetTriggerEffectParam("ProtoUnit", "WarHut", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "20", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", 2, false);
	rmSetTriggerEffectParam("ProtoUnit", "YPOutpostAsian", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "20", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", 1, false);
	rmSetTriggerEffectParam("ProtoUnit", "Caravel", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "30", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", 1, false);
	rmSetTriggerEffectParam("ProtoUnit", "Galley", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "30", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", 1, false);
	rmSetTriggerEffectParam("ProtoUnit", "Canoe", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "60", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", 1, false);
	rmSetTriggerEffectParam("ProtoUnit", "ypFune", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "30", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", 1, false);
	rmSetTriggerEffectParam("ProtoUnit", "ypWarJunk", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "30", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", 2, false);
	rmSetTriggerEffectParam("ProtoUnit", "Caravel", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "30", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", 2, false);
	rmSetTriggerEffectParam("ProtoUnit", "Galley", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "30", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", 2, false);
	rmSetTriggerEffectParam("ProtoUnit", "Canoe", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "60", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", 2, false);
	rmSetTriggerEffectParam("ProtoUnit", "ypFune", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "30", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", 2, false);
	rmSetTriggerEffectParam("ProtoUnit", "ypWarJunk", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "30", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", randomplayer, false);
	rmSetTriggerEffectParam("ProtoUnit", "Monitor", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "5", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", randomplayer, false);
	rmSetTriggerEffectParam("ProtoUnit", "Galleon", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "5", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", randomplayer, false);
	rmSetTriggerEffectParam("ProtoUnit", "Fluyt", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "5", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", randomplayer, false);
	rmSetTriggerEffectParam("ProtoUnit", "Frigate", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "5", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", randomplayer, false);
	rmSetTriggerEffectParam("ProtoUnit", "ypFuchuan", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "5", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", randomplayer, false);
	rmSetTriggerEffectParam("ProtoUnit", "ypAtakabune", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "5", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", randomplayer, false);
	rmSetTriggerEffectParam("ProtoUnit", "ypTekkousen", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "5", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", 3-randomplayer, false);
	rmSetTriggerEffectParam("ProtoUnit", "Fluyt", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "20", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", 3-randomplayer, false);
	rmSetTriggerEffectParam("ProtoUnit", "Monitor", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "20", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", 3-randomplayer, false);
	rmSetTriggerEffectParam("ProtoUnit", "Galleon", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "20", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", 3-randomplayer, false);
	rmSetTriggerEffectParam("ProtoUnit", "Frigate", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "20", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", 3-randomplayer, false);
	rmSetTriggerEffectParam("ProtoUnit", "ypFuchuan", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "20", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", 3-randomplayer, false);
	rmSetTriggerEffectParam("ProtoUnit", "ypAtakabune", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "20", false);
 
	rmAddTriggerEffect("Modify Protounit");
	rmSetTriggerEffectParamInt("PlayerID", 3-randomplayer, false);
	rmSetTriggerEffectParam("ProtoUnit", "ypTekkousen", false);
	rmSetTriggerEffectParam("Field", "10", false);
	rmSetTriggerEffectParam("Delta", "20", false);

游戏中进入地图后,我们打开“文档(Documents)\My Games\Age of Empires 3\Trigger3\trigtemp.xs”可以得知上面的触发被转换成了以下代码:
rule _BuildLimit
minInterval 2
active
{
   bool bVar0 = (true);

   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      trModifyProtounit("ypCastle", 1, 10, 20);
      trModifyProtounit("Outpost", 1, 10, 20);
      trModifyProtounit("Blockhouse", 1, 10, 20);
      trModifyProtounit("WarHut", 1, 10, 20);
      trModifyProtounit("YPOutpostAsian", 1, 10, 20);
      trModifyProtounit("ypCastle", 2, 10, 20);
      trModifyProtounit("Outpost", 2, 10, 20);
      trModifyProtounit("Blockhouse", 2, 10, 20);
      trModifyProtounit("WarHut", 2, 10, 20);
      trModifyProtounit("YPOutpostAsian", 2, 10, 20);
      trModifyProtounit("Caravel", 1, 10, 30);
      trModifyProtounit("Galley", 1, 10, 30);
      trModifyProtounit("Canoe", 1, 10, 60);
      trModifyProtounit("ypFune", 1, 10, 30);
      trModifyProtounit("ypWarJunk", 1, 10, 30);
      trModifyProtounit("Caravel", 2, 10, 30);
      trModifyProtounit("Galley", 2, 10, 30);
      trModifyProtounit("Canoe", 2, 10, 60);
      trModifyProtounit("ypFune", 2, 10, 30);
      trModifyProtounit("ypWarJunk", 2, 10, 30);
      trModifyProtounit("Monitor", 1, 10, 5);
      trModifyProtounit("Galleon", 1, 10, 5);
      trModifyProtounit("Fluyt", 1, 10, 5);
      trModifyProtounit("Frigate", 1, 10, 5);
      trModifyProtounit("ypFuchuan", 1, 10, 5);
      trModifyProtounit("ypAtakabune", 1, 10, 5);
      trModifyProtounit("ypTekkousen", 1, 10, 5);
      trModifyProtounit("Fluyt", 2, 10, 20);
      trModifyProtounit("Monitor", 2, 10, 20);
      trModifyProtounit("Galleon", 2, 10, 20);
      trModifyProtounit("Frigate", 2, 10, 20);
      trModifyProtounit("ypFuchuan", 2, 10, 20);
      trModifyProtounit("ypAtakabune", 2, 10, 20);
      trModifyProtounit("ypTekkousen", 2, 10, 20);
      xsDisableRule("_BuildLimit");
      trEcho("Trigger disabling rule BuildLimit");
   }
}
		


我们再把关键部分提取出来,
rule _BuildLimit minInterval 2 active
{
      trModifyProtounit("ypCastle", 1, 10, 20);
      trModifyProtounit("Outpost", 1, 10, 20);
      trModifyProtounit("Blockhouse", 1, 10, 20);
      trModifyProtounit("WarHut", 1, 10, 20);
      trModifyProtounit("YPOutpostAsian", 1, 10, 20);
      trModifyProtounit("ypCastle", 2, 10, 20);
      trModifyProtounit("Outpost", 2, 10, 20);
      trModifyProtounit("Blockhouse", 2, 10, 20);
      trModifyProtounit("WarHut", 2, 10, 20);
      trModifyProtounit("YPOutpostAsian", 2, 10, 20);
      trModifyProtounit("Caravel", 1, 10, 30);
      trModifyProtounit("Galley", 1, 10, 30);
      trModifyProtounit("Canoe", 1, 10, 60);
      trModifyProtounit("ypFune", 1, 10, 30);
      trModifyProtounit("ypWarJunk", 1, 10, 30);
      trModifyProtounit("Caravel", 2, 10, 30);
      trModifyProtounit("Galley", 2, 10, 30);
      trModifyProtounit("Canoe", 2, 10, 60);
      trModifyProtounit("ypFune", 2, 10, 30);
      trModifyProtounit("ypWarJunk", 2, 10, 30);
      trModifyProtounit("Monitor", 1, 10, 5);
      trModifyProtounit("Galleon", 1, 10, 5);
      trModifyProtounit("Fluyt", 1, 10, 5);
      trModifyProtounit("Frigate", 1, 10, 5);
      trModifyProtounit("ypFuchuan", 1, 10, 5);
      trModifyProtounit("ypAtakabune", 1, 10, 5);
      trModifyProtounit("ypTekkousen", 1, 10, 5);
      trModifyProtounit("Fluyt", 2, 10, 20);
      trModifyProtounit("Monitor", 2, 10, 20);
      trModifyProtounit("Galleon", 2, 10, 20);
      trModifyProtounit("Frigate", 2, 10, 20);
      trModifyProtounit("ypFuchuan", 2, 10, 20);
      trModifyProtounit("ypAtakabune", 2, 10, 20);
      trModifyProtounit("ypTekkousen", 2, 10, 20);
      xsDisableRule("_BuildLimit");
   }

转换器转换后获得以下代码:
aoebbs("rule _BuildLimit minInterval 2 active");
aoebbs("{");
aoebbs("trModifyProtounit(\"ypCastle\", 1, 10, 20);");
aoebbs("trModifyProtounit(\"Outpost\", 1, 10, 20);");
aoebbs("trModifyProtounit(\"Blockhouse\", 1, 10, 20);");
aoebbs("trModifyProtounit(\"WarHut\", 1, 10, 20);");
aoebbs("trModifyProtounit(\"YPOutpostAsian\", 1, 10, 20);");
aoebbs("trModifyProtounit(\"ypCastle\", 2, 10, 20);");
aoebbs("trModifyProtounit(\"Outpost\", 2, 10, 20);");
aoebbs("trModifyProtounit(\"Blockhouse\", 2, 10, 20);");
aoebbs("trModifyProtounit(\"WarHut\", 2, 10, 20);");
aoebbs("trModifyProtounit(\"YPOutpostAsian\", 2, 10, 20);");
aoebbs("trModifyProtounit(\"Caravel\", 1, 10, 30);");
aoebbs("trModifyProtounit(\"Galley\", 1, 10, 30);");
aoebbs("trModifyProtounit(\"Canoe\", 1, 10, 60);");
aoebbs("trModifyProtounit(\"ypFune\", 1, 10, 30);");
aoebbs("trModifyProtounit(\"ypWarJunk\", 1, 10, 30);");
aoebbs("trModifyProtounit(\"Caravel\", 2, 10, 30);");
aoebbs("trModifyProtounit(\"Galley\", 2, 10, 30);");
aoebbs("trModifyProtounit(\"Canoe\", 2, 10, 60);");
aoebbs("trModifyProtounit(\"ypFune\", 2, 10, 30);");
aoebbs("trModifyProtounit(\"ypWarJunk\", 2, 10, 30);");
aoebbs("trModifyProtounit(\"Monitor\", 1, 10, 5);");
aoebbs("trModifyProtounit(\"Galleon\", 1, 10, 5);");
aoebbs("trModifyProtounit(\"Fluyt\", 1, 10, 5);");
aoebbs("trModifyProtounit(\"Frigate\", 1, 10, 5);");
aoebbs("trModifyProtounit(\"ypFuchuan\", 1, 10, 5);");
aoebbs("trModifyProtounit(\"ypAtakabune\", 1, 10, 5);");
aoebbs("trModifyProtounit(\"ypTekkousen\", 1, 10, 5);");
aoebbs("trModifyProtounit(\"Fluyt\", 2, 10, 20);");
aoebbs("trModifyProtounit(\"Monitor\", 2, 10, 20);");
aoebbs("trModifyProtounit(\"Galleon\", 2, 10, 20);");
aoebbs("trModifyProtounit(\"Frigate\", 2, 10, 20);");
aoebbs("trModifyProtounit(\"ypFuchuan\", 2, 10, 20);");
aoebbs("trModifyProtounit(\"ypAtakabune\", 2, 10, 20);");
aoebbs("trModifyProtounit(\"ypTekkousen\", 2, 10, 20);");
aoebbs("xsDisableRule(\"_BuildLimit\");");
aoebbs("}");
aoebbsE("");
然后游戏中实测(如果你想复现这个过程,需要在上述转换后的代码前面添加rmCreateTrigger("test");不然aoebbs函数内自带的rmSetTriggerEffectParam是不会生效的),游戏加载地图后,打开trigtemp.xs可以见到输出了以下代码:
      trChatSetStatus(true); */ rule _BuildLimit minInterval 2 active/*);
      trChatSetStatus(true); */ {/*);
      trChatSetStatus(true); */ trModifyProtounit("ypCastle", 1, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("Outpost", 1, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("Blockhouse", 1, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("WarHut", 1, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("YPOutpostAsian", 1, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("ypCastle", 2, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("Outpost", 2, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("Blockhouse", 2, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("WarHut", 2, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("YPOutpostAsian", 2, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("Caravel", 1, 10, 30);/*);
      trChatSetStatus(true); */ trModifyProtounit("Galley", 1, 10, 30);/*);
      trChatSetStatus(true); */ trModifyProtounit("Canoe", 1, 10, 60);/*);
      trChatSetStatus(true); */ trModifyProtounit("ypFune", 1, 10, 30);/*);
      trChatSetStatus(true); */ trModifyProtounit("ypWarJunk", 1, 10, 30);/*);
      trChatSetStatus(true); */ trModifyProtounit("Caravel", 2, 10, 30);/*);
      trChatSetStatus(true); */ trModifyProtounit("Galley", 2, 10, 30);/*);
      trChatSetStatus(true); */ trModifyProtounit("Canoe", 2, 10, 60);/*);
      trChatSetStatus(true); */ trModifyProtounit("ypFune", 2, 10, 30);/*);
      trChatSetStatus(true); */ trModifyProtounit("ypWarJunk", 2, 10, 30);/*);
      trChatSetStatus(true); */ trModifyProtounit("Monitor", 1, 10, 5);/*);
      trChatSetStatus(true); */ trModifyProtounit("Galleon", 1, 10, 5);/*);
      trChatSetStatus(true); */ trModifyProtounit("Fluyt", 1, 10, 5);/*);
      trChatSetStatus(true); */ trModifyProtounit("Frigate", 1, 10, 5);/*);
      trChatSetStatus(true); */ trModifyProtounit("ypFuchuan", 1, 10, 5);/*);
      trChatSetStatus(true); */ trModifyProtounit("ypAtakabune", 1, 10, 5);/*);
      trChatSetStatus(true); */ trModifyProtounit("ypTekkousen", 1, 10, 5);/*);
      trChatSetStatus(true); */ trModifyProtounit("Fluyt", 2, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("Monitor", 2, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("Galleon", 2, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("Frigate", 2, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("ypFuchuan", 2, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("ypAtakabune", 2, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("ypTekkousen", 2, 10, 20);/*);
      trChatSetStatus(true); */ xsDisableRule("_BuildLimit");/*);
      trChatSetStatus(true); */ }/*);
      trChatSetStatus(true); */ /*);

为什么运行后会获得这样的代码?我拿其中一句来解释,aoebbs("trModifyProtounit(\"ypCastle\", 1, 10, 20);");这个aoebbs函数调用了以下代码:
rmAddTriggerEffect("Chat Status");
rmSetTriggerEffectParam("Active", "true); */ trModifyProtounit(\"ypCastle\", 1, 10, 20);/*");
实际上就是不停用游戏自带的触发程序,利用*/与/*把原有代码给注释掉。


为什么一定要插入在aoebbsParamInjectStart与aoebbsParamInjectFinish的中间内?因为上面的注释符号是不合规的,会导致整个触发程序失效。只有补齐注释符,使代码符合伪·c++语法,才能保证触发程序正常运行,这时候需要用上aoebbsParamInjectStart与aoebbsParamInjectFinish。 aoebbsParamInjectStart()原理是创建了这样一个触发程序,然后插入Effect先用两个true);}}把原有代码给闭合了,再利用注释符号/*把后面的内容注释掉:
//aoebbsParamInjectStart()的函数定义:
	rmCreateTrigger("aoebbsInject");
	rmSwitchToTrigger(rmTriggerID("aoebbsInject"));
	rmSetTriggerRunImmediately(true);
	rmSetTriggerActive(false);
	rmAddTriggerEffect("SetIdleProcessing");
	rmSetTriggerEffectParam("IdleProc", "true);"+xs+"}}/*");

末尾需要添加aoebbsParamInjectFinish()原因为:上面的aoebbsInject触发程序把原有的结构破坏了,需要自己手动补上一个rule,然后再利用if(true){xsDisableSelf(补齐缺漏,使原因代码正确闭合并且符合帝国时代3的内置函数以及语法。
//aoebbsParamInjectFinish()的函数定义:
	rmAddTriggerEffect("Chat Status");
	rmSetTriggerEffectParam("Active", "true); */rule _aoebbsInjectEnd inactive { if(true){ "+xs+"xsDisableSelf(");

当你将自定义rule插入在aoebbsParamInjectStart()与aoebbsParamInjectFinish()之间后,
      aoebbsParamInjectStart();
      aoebbs("rule _BuildLimit minInterval 2 active");
      aoebbs("{");
      aoebbs("trModifyProtounit(\"ypCastle\", 1, 10, 20);");
      aoebbs("trModifyProtounit(\"Outpost\", 1, 10, 20);");
      aoebbs("trModifyProtounit(\"Blockhouse\", 1, 10, 20);");
      aoebbs("trModifyProtounit(\"WarHut\", 1, 10, 20);");
      aoebbs("trModifyProtounit(\"YPOutpostAsian\", 1, 10, 20);");
      aoebbs("trModifyProtounit(\"ypCastle\", 2, 10, 20);");
      aoebbs("trModifyProtounit(\"Outpost\", 2, 10, 20);");
      aoebbs("trModifyProtounit(\"Blockhouse\", 2, 10, 20);");
      aoebbs("trModifyProtounit(\"WarHut\", 2, 10, 20);");
      aoebbs("trModifyProtounit(\"YPOutpostAsian\", 2, 10, 20);");
      aoebbs("trModifyProtounit(\"Caravel\", 1, 10, 30);");
      aoebbs("trModifyProtounit(\"Galley\", 1, 10, 30);");
      aoebbs("trModifyProtounit(\"Canoe\", 1, 10, 60);");
      aoebbs("trModifyProtounit(\"ypFune\", 1, 10, 30);");
      aoebbs("trModifyProtounit(\"ypWarJunk\", 1, 10, 30);");
      aoebbs("trModifyProtounit(\"Caravel\", 2, 10, 30);");
      aoebbs("trModifyProtounit(\"Galley\", 2, 10, 30);");
      aoebbs("trModifyProtounit(\"Canoe\", 2, 10, 60);");
      aoebbs("trModifyProtounit(\"ypFune\", 2, 10, 30);");
      aoebbs("trModifyProtounit(\"ypWarJunk\", 2, 10, 30);");
      aoebbs("trModifyProtounit(\"Monitor\", 1, 10, 5);");
      aoebbs("trModifyProtounit(\"Galleon\", 1, 10, 5);");
      aoebbs("trModifyProtounit(\"Fluyt\", 1, 10, 5);");
      aoebbs("trModifyProtounit(\"Frigate\", 1, 10, 5);");
      aoebbs("trModifyProtounit(\"ypFuchuan\", 1, 10, 5);");
      aoebbs("trModifyProtounit(\"ypAtakabune\", 1, 10, 5);");
      aoebbs("trModifyProtounit(\"ypTekkousen\", 1, 10, 5);");
      aoebbs("trModifyProtounit(\"Fluyt\", 2, 10, 20);");
      aoebbs("trModifyProtounit(\"Monitor\", 2, 10, 20);");
      aoebbs("trModifyProtounit(\"Galleon\", 2, 10, 20);");
      aoebbs("trModifyProtounit(\"Frigate\", 2, 10, 20);");
      aoebbs("trModifyProtounit(\"ypFuchuan\", 2, 10, 20);");
      aoebbs("trModifyProtounit(\"ypAtakabune\", 2, 10, 20);");
      aoebbs("trModifyProtounit(\"ypTekkousen\", 2, 10, 20);");
      aoebbs("xsDisableRule(\"_BuildLimit\");");
      aoebbs("}");
      aoebbsE("");
      aoebbsParamInjectFinish();
	

再次载入地图,trigtemp.xs将输出以下代码:

rule _aoebbsInject
minInterval 4
inactive
runImmediately
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      trSetUnitIdleProcessing(true);}}/*);
      trChatSetStatus(true); */ rule _BuildLimit minInterval 2 active/*);
      trChatSetStatus(true); */ {/*);
      trChatSetStatus(true); */ trModifyProtounit("ypCastle", 1, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("Outpost", 1, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("Blockhouse", 1, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("WarHut", 1, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("YPOutpostAsian", 1, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("ypCastle", 2, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("Outpost", 2, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("Blockhouse", 2, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("WarHut", 2, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("YPOutpostAsian", 2, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("Caravel", 1, 10, 30);/*);
      trChatSetStatus(true); */ trModifyProtounit("Galley", 1, 10, 30);/*);
      trChatSetStatus(true); */ trModifyProtounit("Canoe", 1, 10, 60);/*);
      trChatSetStatus(true); */ trModifyProtounit("ypFune", 1, 10, 30);/*);
      trChatSetStatus(true); */ trModifyProtounit("ypWarJunk", 1, 10, 30);/*);
      trChatSetStatus(true); */ trModifyProtounit("Caravel", 2, 10, 30);/*);
      trChatSetStatus(true); */ trModifyProtounit("Galley", 2, 10, 30);/*);
      trChatSetStatus(true); */ trModifyProtounit("Canoe", 2, 10, 60);/*);
      trChatSetStatus(true); */ trModifyProtounit("ypFune", 2, 10, 30);/*);
      trChatSetStatus(true); */ trModifyProtounit("ypWarJunk", 2, 10, 30);/*);
      trChatSetStatus(true); */ trModifyProtounit("Monitor", 1, 10, 5);/*);
      trChatSetStatus(true); */ trModifyProtounit("Galleon", 1, 10, 5);/*);
      trChatSetStatus(true); */ trModifyProtounit("Fluyt", 1, 10, 5);/*);
      trChatSetStatus(true); */ trModifyProtounit("Frigate", 1, 10, 5);/*);
      trChatSetStatus(true); */ trModifyProtounit("ypFuchuan", 1, 10, 5);/*);
      trChatSetStatus(true); */ trModifyProtounit("ypAtakabune", 1, 10, 5);/*);
      trChatSetStatus(true); */ trModifyProtounit("ypTekkousen", 1, 10, 5);/*);
      trChatSetStatus(true); */ trModifyProtounit("Fluyt", 2, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("Monitor", 2, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("Galleon", 2, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("Frigate", 2, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("ypFuchuan", 2, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("ypAtakabune", 2, 10, 20);/*);
      trChatSetStatus(true); */ trModifyProtounit("ypTekkousen", 2, 10, 20);/*);
      trChatSetStatus(true); */ xsDisableRule("_BuildLimit");/*);
      trChatSetStatus(true); */ }/*);
      trChatSetStatus(true); */ /*);
      trChatSetStatus(true); */rule _aoebbsInjectEnd inactive { if(true){ xsDisableSelf();
      xsDisableRule("_aoebbsInject");
      trEcho("Trigger disabling rule aoebbsInject");
   }
}

暗绿色代码不会生效,实际上生效的就只有以下代码(已作格式化处理):

rule _aoebbsInject
minInterval 4
inactive
runImmediately
{
  bool bVar0 = (true);
  bool tempExp = (bVar0);
  if (tempExp)
  {
    trSetUnitIdleProcessing(true);
    trSetUnitIdleProcessing(true);
  }
}
rule _BuildLimit minInterval 2 active
{
 trModifyProtounit("ypCastle", 1, 10, 20);
 trModifyProtounit("Outpost", 1, 10, 20);
 trModifyProtounit("Blockhouse", 1, 10, 20); 
 trModifyProtounit("WarHut", 1, 10, 20); 
 trModifyProtounit("YPOutpostAsian", 1, 10, 20);
 trModifyProtounit("ypCastle", 2, 10, 20);
 trModifyProtounit("Outpost", 2, 10, 20);
 trModifyProtounit("Blockhouse", 2, 10, 20);
 trModifyProtounit("WarHut", 2, 10, 20)
 trModifyProtounit("YPOutpostAsian", 2, 10, 20);
 trModifyProtounit("Caravel", 1, 10, 30);
 trModifyProtounit("Galley", 1, 10, 30);
 trModifyProtounit("Canoe", 1, 10, 60); 
 trModifyProtounit("ypFune", 1, 10, 30); 
 trModifyProtounit("ypWarJunk", 1, 10, 30);
 trModifyProtounit("Caravel", 2, 10, 30);
 trModifyProtounit("Galley", 2, 10, 30);
 trModifyProtounit("Canoe", 2, 10, 60);
 trModifyProtounit("ypFune", 2, 10, 30);
 trModifyProtounit("ypWarJunk", 2, 10, 30);
 trModifyProtounit("Monitor", 1, 10, 5);
 trModifyProtounit("Galleon", 1, 10, 5);
 trModifyProtounit("Fluyt", 1, 10, 5);
 trModifyProtounit("Frigate", 1, 10, 5);
 trModifyProtounit("ypFuchuan", 1, 10, 5);
 trModifyProtounit("ypAtakabune", 1, 10, 5);
 trModifyProtounit("ypTekkousen", 1, 10, 5);
 trModifyProtounit("Fluyt", 2, 10, 20);
 trModifyProtounit("Monitor", 2, 10, 20);
 trModifyProtounit("Galleon", 2, 10, 20);
 trModifyProtounit("Frigate", 2, 10, 20);
 trModifyProtounit("ypFuchuan", 2, 10, 20);
 trModifyProtounit("ypAtakabune", 2, 10, 20);
 trModifyProtounit("ypTekkousen", 2, 10, 20);
 xsDisableRule("_BuildLimit");
}
rule _aoebbsInjectEnd
inactive
{ 
  if(true)
  {
    xsDisableSelf();
    xsDisableRule("_aoebbsInject");
    trEcho("Trigger disabling rule aoebbsInject");
  }
}

就这样,利用/**/成功注入代码,使原有的触发程序运行了不应该运行的代码。原本地图的触发程序仅限于trigger3/typetest.xml,超出这个范围便无法自定义触发。虽然你也可以新建一个 XML 文件,但由于文件不一致,无法与他人联机,会导致不同步现象。而这个代码注入,使自定义触发成为可能;我们可以使用的代码函数有TR、XS、KB,甚至UI函数也可以使用。
所有函数:https://www.aoebbs.net/tutorial-15-1.html
UI函数:https://www.aoebbs.net/tutorial-15-4.html
KB函数:https://www.aoebbs.net/tutorial-15-2.html
XS函数:https://www.aoebbs.net/tutorial-15-6.html

(因为地图本身就是RM函数,所以RM函数在触发程序需要使用需要使用"+RMcode+"方式调用)
RM函数:https://www.aoebbs.net/tutorial-15-14.html
因为能通过注入代码直接运行我们想要的触发程序,所以无需再使用下面这种繁琐的触发程序
   rmCreateTrigger("BuildLimit");
   rmSwitchToTrigger(rmTriggerID("BuildLimit"));
   rmSetTriggerPriority(3); 
   rmSetTriggerActive(true);
   rmSetTriggerRunImmediately(false);
   rmSetTriggerLoop(false);

   rmAddTriggerEffect("Modify Protounit");
   rmSetTriggerEffectParamInt("PlayerID", 1, false);
   rmSetTriggerEffectParam("ProtoUnit", "ypCastle", false);
   rmSetTriggerEffectParam("Field", "10", false);
   rmSetTriggerEffectParam("Delta", "20", false);

   rmAddTriggerEffect("Modify Protounit");
   rmSetTriggerEffectParamInt("PlayerID", 1, false);
   rmSetTriggerEffectParam("ProtoUnit", "Outpost", false);
   rmSetTriggerEffectParam("Field", "10", false);
   rmSetTriggerEffectParam("Delta", "20", false);
取而代之的是下面这种简化写法,6行代码等同于上面16行:
      aoebbs("rule _BuildLimit minInterval 2 active");
      aoebbs("{");
      aoebbs("trModifyProtounit(\"ypCastle\", 1, 10, 20);");
      aoebbs("trModifyProtounit(\"Outpost\", 1, 10, 20);");
      aoebbs("xsDisableSelf();");
      aoebbs("}");



rmCreateTrigger注入代码

以下为标准示例:

aoebbsR("TriggerName","active runImmediately{trChatSendSpoofed(0,\"<color=0,1,1>Forum : https://www.aoebbs.net\");xsDisableSelf();}");

实际上aoebbsR调用了以下这段代码
	rmCreateTrigger("TriggerName	active	runImmediately{trChatSendSpoofed(0,\"<color=0,1,1>Forum	:	https://www.aoebbs.net\");xsDisableSelf();}/*");
	rmCreateTrigger("*/rule	_TriggerNameEnd");

//TriggerName为触发名称,等于rule _TriggerName,这里是不需要自己增加rule _,因为rmCreateTrigger输出的代码自带rule _。

优点:
  1. 极大简化了触发程序的语句。
  2. 可以自定义触发程序。
  3. 所有触发将以函数形式显示,有不懂看函数表就行了。
  4. 即时存在中文路径的帝国3目录也能运行,联机不会出现由中文路径导致的不同步现象。
  5. 涉及玩家ID的触发可以输出0,即为设定对象为大自然。

缺点:
  1. 不能输入任何空格,因为输入空格会自动转换成_,你只能用tab制表符代替空格。(不知道什么是tab制表符?你的键盘的Q建左边有个tab建,那个就是制表符)
  2. 最高只能输出257个字符,超出257字符会导致所有触发程序失效。(不小心超出了怎么办?去打开我的文档/My Game/Age of Empires 3/Trigger3/trigtemp.xs这个文件,找到你的触发,会发现某个地方少了一截,那里就是上限了)
  3. 不能换行,所有判断、循环必须写在同一行。
  4. 一个引号里面的内容最多只能输入127个字符,超出将会导致无法打开游戏,可以使用加号使两个引号连接起来。例如:"127"+"xxxxxxx"
  5. 所有语句都是在英文双引号""下使用,触发中的string值的双引号""必须用c++转移字符\"\"代替,例如aoebbsR("Debug","active {xsDisableRule(\"_Debug3\");}");。(2026-02-15注:你不可以用单引号' '来取代\"\",实测单引号没办法被触发程序的编译器识别。)
  6. 因为这种触发使用作用在语句双引号""里面的/*、*/注释,所以每创建一个触发就要用一个空触发把注释关掉,否则再任何添加触发都会无效。(2026-01-19,注:这里是针对直接使用rmCreateTrigger。对于aoebbsR函数会生成两个触发程序,自动补全/**/,无需手动创建空触发。)

样板:在我修改过的Christmas(冬季奇境)地图底部能找到类似触发程序。你可能会看不懂SC0~SC6有什么作用,SC0是判断有多少个贸易站(创建贸易站之后的第一个单位ID-第一个贸易站单位ID=贸易站数量),SC1~SC6就是分别第一个贸易站单位ID加上0~5(因为rmGetUnitPlaced在一组只能获取第一个创建的单位ID)。



注入代码原理:
以下面的触发程序,作为例子,
	rmCreateTrigger("TriggerName	active	runImmediately{trChatSendSpoofed(0,\"<color=0,1,1>Forum	:	https://www.aoebbs.net\");xsDisableSelf();}/*");
	rmCreateTrigger("*/rule	_TriggerNameEnd");
运行后得到以下代码:
rule _TriggerName	active	runImmediately{trChatSendSpoofed(0,"<color=0,1,1>Forum	:	https://www.aoebbs.net");xsDisableSelf();}/*
minInterval 4
active
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      xsDisableRule("_TriggerName	active	runImmediately{trChatSendSpoofed(0,"<color=0,1,1>Forum	:	https://www.aoebbs.net");xsDisableSelf();}/*");
      trEcho("Trigger disabling rule TriggerName	active	runImmediately{trChatSendSpoofed(0,"<color=0,1,1>Forum	:	https://www.aoebbs.net");xsDisableSelf();}/*");
   }
}

rule _*/rule	_TriggerNameEnd
minInterval 4
active
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      xsDisableRule("_*/rule	_TriggerEnd");
      trEcho("Trigger disabling rule */rule	_TriggerEnd");
   }
}

又一次利用了/**/将原有的触发程序注释掉,成功注入代码。

比起上面使用两个rmCreateTrigger,我建议使用aoebbsR函数。其中aoebbsR函数与上面两个rmCreateTrigger是完全一样的,只是封装了两行rmCreateTrigger代码以及再增加一行rmSetTriggerActive(false);,作用为让用于闭合/**/的空触发程序处于inactive状态。


aoebbsR("TriggerName","active runImmediately{trChatSendSpoofed(0,\"<color=0,1,1>Forum : https://www.aoebbs.net\");xsDisableSelf();}");

上述代码运行后,输出如下:
rule _TriggerName	active	runImmediately{trChatSendSpoofed(0,"<color=0,1,1>Forum	:	https://www.aoebbs.net");xsDisableSelf();}/*
minInterval 4
active
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      xsDisableRule("_TriggerName	active	runImmediately{trChatSendSpoofed(0,"<color=0,1,1>Forum	:	https://www.aoebbs.net");xsDisableSelf();}/*");
      trEcho("Trigger disabling rule TriggerName	active	runImmediately{trChatSendSpoofed(0,"<color=0,1,1>Forum	:	https://www.aoebbs.net");xsDisableSelf();}/*");
   }
}

rule _*/rule	_TriggerNameEnd
minInterval 4
inactive
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      xsDisableRule("_*/rule	_TriggerNameEnd");
      trEcho("Trigger disabling rule */rule	_TriggerNameEnd");
   }
}
去除暗绿色的注释后,剩余以下代码(已作格式化处理):
rule _TriggerName
active
runImmediately
{
   trChatSendSpoofed(0,"<color=0,1,1>Forum	:	https://www.aoebbs.net");xsDisableSelf();
}

rule	_TriggerNameEnd
minInterval 4
inactive
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      xsDisableRule("_*/rule	_TriggerNameEnd");
      trEcho("Trigger disabling rule */rule	_TriggerNameEnd");
   }
}
	

为什么这个触发程序能在中文路径运行? 因为没有使用rmAddTriggerEffect等函数,不再需要调用trigger3文件夹里面的typetest.xml文件,所以该触发程序是可以在中文路径运行的。





rmCreateTrigger突破256字符:
下述是一个示例,使用多个rmCreateTrigger拼接,然后得到三重代码。
rmCreateTrigger("T1	active	runImmediately{for(p=1;<cNumberPlayers){trModifyProtounit(\"TownCenter\",p,0,1000);}xsDisableSelf();/*");
rmCreateTrigger("*/trChatSendSpoofed(0,\"<color=0,1,1>Forum : https://www.aoebbs.net\");/*");
rmCreateTrigger("*/}	rule	TriggerName123");
上述代码运行后,输出如下:
rule _T1	active	runImmediately{for(p=1;<cNumberPlayers){trModifyProtounit("TownCenter",p,0,1000);}xsDisableSelf();/*
minInterval 4
active
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      xsDisableRule("_T1	active	runImmediately{for(p=1;<cNumberPlayers){trModifyProtounit("TownCenter",p,0,1000);}xsDisableSelf();/*");
      trEcho("Trigger disabling rule T1	active	runImmediately{for(p=1;<cNumberPlayers){trModifyProtounit("TownCenter",p,0,1000);}xsDisableSelf();/*");
   }
}

rule _*/trChatSendSpoofed(0,"<color=0,1,1>Forum_:_https://www.aoebbs.net");/*
minInterval 4
active
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      xsDisableRule("_*/trChatSendSpoofed(0,"<color=0,1,1>Forum_:_https://www.aoebbs.net");/*");
      trEcho("Trigger disabling rule */trChatSendSpoofed(0,"<color=0,1,1>Forum_:_https://www.aoebbs.net");/*");
   }
}

rule _*/}	rule	TriggerName123
minInterval 4
active
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      xsDisableRule("_*/}	rule	TriggerName123");
      trEcho("Trigger disabling rule */}	rule	TriggerName123");
   }
}
	
上述代码重点在于第二句rmCreateTrigger("*/trChatSendSpoofed(0,\"<color=0,1,1>Forum : https://www.aoebbs.net\");/*");中两端使用了*/与/*将整个触发程序注释掉,仅残留单独一句触发程序,但因为xsDisableRule与trEcho是不可避免输出*/与/*的,所以会变成了运行三句trChatSendSpoofed代码。


为了解决三重代码问题,可以先设定一个int值用于计数,例如1;然后判断是否少于2(这里不用==1,因为==1比<2还要多占用一个字符),每次运行代码时,计数器都+1;当计数器大于3时,计数器变回1。(注意int后面用制表符,不然空格会变成下划线_这个符号。)
rmCreateTrigger("T1	active	runImmediately{for(p=1;<cNumberPlayers){trModifyProtounit(\"TownCenter\",p,0,1000);}xsDisableSelf();int	Counter=1;/*");
rmCreateTrigger("*/if(Counter<2){trChatSendSpoofed(0,\"<color=0,1,1>Forum : https://www.aoebbs.net\");}Counter=Counter+1;if(Counter>3){Counter=1;}/*");
rmCreateTrigger("*/if(Counter<2){trChatSendSpoofed(0,\"<color=0,1,1>Forum : https://mod.aoebbs.net\");}Counter=Counter+1;if(Counter>3){Counter=1;}/*");
rmCreateTrigger("*/}	rule	TriggerName123");


这是代码运行后的输出结果:
rule _T1	active	runImmediately{for(p=1;<cNumberPlayers){trModifyProtounit("TownCenter",p,0,1000);}xsDisableSelf();int	Counter=1;/*
minInterval 4
active
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      xsDisableRule("_T1	active	runImmediately{for(p=1;<cNumberPlayers){trModifyProtounit("TownCenter",p,0,1000);}xsDisableSelf();int	Counter=1;/*");
      trEcho("Trigger disabling rule T1	active	runImmediately{for(p=1;<cNumberPlayers){trModifyProtounit("TownCenter",p,0,1000);}xsDisableSelf();int	Counter=1;/*");
   }
}

rule _*/if(Counter<2){trChatSendSpoofed(0,"<color=0,1,1>Forum_:_https://www.aoebbs.net");}Counter=Counter+1;if(Counter>3){Counter=1;}/*
minInterval 4
active
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      xsDisableRule("_*/if(Counter<2){trChatSendSpoofed(0,"<color=0,1,1>Forum_:_https://www.aoebbs.net");}Counter=Counter+1;if(Counter>3){Counter=1;}/*");
      trEcho("Trigger disabling rule */if(Counter<2){trChatSendSpoofed(0,"<color=0,1,1>Forum_:_https://www.aoebbs.net");}Counter=Counter+1;if(Counter>3){Counter=1;}/*");
   }
}

rule _*/if(Counter<2){trChatSendSpoofed(0,"<color=0,1,1>Forum_:_https://mod.aoebbs.net");}Counter=Counter+1;if(Counter>3){Counter=1;}/*
minInterval 4
active
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      xsDisableRule("_*/if(Counter<2){trChatSendSpoofed(0,"<color=0,1,1>Forum_:_https://mod.aoebbs.net");}Counter=Counter+1;if(Counter>3){Counter=1;}/*");
      trEcho("Trigger disabling rule */if(Counter<2){trChatSendSpoofed(0,"<color=0,1,1>Forum_:_https://mod.aoebbs.net");}Counter=Counter+1;if(Counter>3){Counter=1;}/*");
   }
}

rule _*/}	rule	TriggerName123
minInterval 4
active
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      xsDisableRule("_*/}	rule	TriggerName123");
      trEcho("Trigger disabling rule */}	rule	TriggerName123");
   }
}

当前的代码可以处理if(xxxx){}的边界不在同一行的问题,但输出三次仍然是不可避免的。
rmCreateTrigger("*/if(1==1){/*");
rmCreateTrigger("*/if(Counter<2){trChatSendSpoofed(0,\"<color=0,1,1>Forum : https://www.aoebbs.net\");}"+"Counter=Counter+1;if(Counter>3){Counter=1;}/*");
rmCreateTrigger("*/if(Counter<2){trChatSendSpoofed(0,\"<color=0,1,1>Forum : https://mod.aoebbs.net\");}"+"Counter=Counter+1;if(Counter>3){Counter=1;}/*");
rmCreateTrigger("*/}/*");
rmCreateTrigger("*/}	rule	TriggerName123");
上述代码运行后,输出如下,可以看到if(1==1)被运行了三次,但只是多了两次重复判断,没有其他影响:
rule _T1	active	runImmediately{for(p=1;<cNumberPlayers){trModifyProtounit("TownCenter",p,0,1000);}xsDisableSelf();int	Counter=1;/*
minInterval 4
active
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      xsDisableRule("_T1	active	runImmediately{for(p=1;<cNumberPlayers){trModifyProtounit("TownCenter",p,0,1000);}xsDisableSelf();int	Counter=1;/*");
      trEcho("Trigger disabling rule T1	active	runImmediately{for(p=1;<cNumberPlayers){trModifyProtounit("TownCenter",p,0,1000);}xsDisableSelf();int	Counter=1;/*");
   }
}

rule _*/if(1==1){/*
minInterval 4
active
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      xsDisableRule("_*/if(1==1){/*");
      trEcho("Trigger disabling rule */if(1==1){/*");
   }
}

rule _*/if(Counter<2){trChatSendSpoofed(0,"<color=0,1,1>Forum_:_https://www.aoebbs.net");}Counter=Counter+1;if(Counter>3){Counter=1;}/*
minInterval 4
active
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      xsDisableRule("_*/if(Counter<2){trChatSendSpoofed(0,"<color=0,1,1>Forum_:_https://www.aoebbs.net");}Counter=Counter+1;if(Counter>3){Counter=1;}/*");
      trEcho("Trigger disabling rule */if(Counter<2){trChatSendSpoofed(0,"<color=0,1,1>Forum_:_https://www.aoebbs.net");}Counter=Counter+1;if(Counter>3){Counter=1;}/*");
   }
}

rule _*/if(Counter<2){trChatSendSpoofed(0,"<color=0,1,1>Forum_:_https://mod.aoebbs.net");}Counter=Counter+1;if(Counter>3){Counter=1;}/*
minInterval 4
active
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      xsDisableRule("_*/if(Counter<2){trChatSendSpoofed(0,"<color=0,1,1>Forum_:_https://mod.aoebbs.net");}Counter=Counter+1;if(Counter>3){Counter=1;}/*");
      trEcho("Trigger disabling rule */if(Counter<2){trChatSendSpoofed(0,"<color=0,1,1>Forum_:_https://mod.aoebbs.net");}Counter=Counter+1;if(Counter>3){Counter=1;}/*");
   }
}

rule _*/}/*
minInterval 4
active
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      xsDisableRule("_*/}/*");
      trEcho("Trigger disabling rule */}/*");
   }
}

rule _*/}	rule	TriggerName123
minInterval 4
active
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      xsDisableRule("_*/}	rule	TriggerName123");
      trEcho("Trigger disabling rule */}	rule	TriggerName123");
   }
}


为了方便使用,我特意设定封装了四个函数,分别为aoebbsA、aoebbsB、aoebbsD、aoebbsC。

void aoebbsA(string ruleName="",string xs1="",string xs2="") {
rmCreateTrigger(ruleName+"	"+xs1+"{int	C=1;"+xs2+"/*");
}

void aoebbsB(string xs1="") {
rmCreateTrigger("*/if(C<2){"+xs1+"}C++;if(C>3)C=1;/*");
}

void aoebbsC(string xs="") {
rmCreateTrigger("*/"+xs+"/*");
rmSetTriggerActive(false);
}

void aoebbsD(string ruleName="",string xs="") {
rmCreateTrigger("*/"+xs+"}rule	_"+ruleName+"End");
rmSetTriggerActive(false);
}
其中aoebbsA用于单个rule的开头,aoebbsD用于结尾。aoebbsB、aoebbsC这两个函数必须插入在aoebbsA与aoebbsD之间。
aoebbsB不能用于跨多行的判断式,一般用于非判断式代码,aoebbsB的注入会产生3行相同代码,aoebbsB在跨多行的情况下使用if(){}会导致花括号不正确闭合,所有触发程序失效。具体原因为使用了if(C<2){"+xs1+"}C++;if(C>3)C=1;来限制代码只执行一次,跨行使用if的情况下,花括号会不正确闭合。
aoebbsC一般情况下只用于if判断式以及花括号的封闭,aoebbsC的注入也会产生3行相同代码,因此if判断式不能跨行使用else格式,不过单一if可以跨行使用(但注意只能用aoebbsC跨行,不能与aoebbsA、aoebbsB、aoebbsD混合跨行使用。

aoebbsA(string ruleName="",string xs1="",string xs2="")限制:自带int C=1;不能使用变量C,最多能输入247字符(包含触发程序名称的字符长度)
aoebbsB(string xs1="")限制:不能使用变量C,最多能输入230字符。
aoebbsD(string ruleName="",string xs="")限制:最多能输入247字符。



以下是一个示例:
aoebbsA("test_trigger","active	runImmediately","trChatSendSpoofed(0,\"test1\");");
aoebbsC("if((trTime()-cActivationTime)>=1.00000000){");
aoebbsB("trChatSendSpoofed(0,\"<color=0,1,1>Forum : https://www.aoebbs.net\");");
aoebbsB("trChatSendSpoofed(0,\"<color=0,1,1>Forum : https://mod.aoebbs.net\");");
aoebbsC("}");
aoebbsB("trChatSendSpoofed(0,\"<color=0,1,1>test2\");");
aoebbsD("test_trigger","if((trTime()-cActivationTime)>=1.00000000){xsDisableSelf();}");
下面为输出后的代码:
rule _test_trigger	active	runImmediately{int	C=1;trChatSendSpoofed(0,"test1");/*
minInterval 4
active
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      xsDisableRule("_test_trigger	active	runImmediately{int	C=1;trChatSendSpoofed(0,"test1");/*");
      trEcho("Trigger disabling rule test_trigger	active	runImmediately{int	C=1;trChatSendSpoofed(0,"test1");/*");
   }
}

rule _*/if((trTime()-cActivationTime)>=1.00000000){/*
minInterval 4
inactive
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      xsDisableRule("_*/if((trTime()-cActivationTime)>=1.00000000){/*");
      trEcho("Trigger disabling rule */if((trTime()-cActivationTime)>=1.00000000){/*");
   }
}

rule _*/if(C<2){trChatSendSpoofed(0,"<color=0,1,1>Forum_:_https://www.aoebbs.net");}C++;if(C>3)C=1;/*
minInterval 4
active
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      xsDisableRule("_*/if(C<2){trChatSendSpoofed(0,"<color=0,1,1>Forum_:_https://www.aoebbs.net");}C++;if(C>3)C=1;/*");
      trEcho("Trigger disabling rule */if(C<2){trChatSendSpoofed(0,"<color=0,1,1>Forum_:_https://www.aoebbs.net");}C++;if(C>3)C=1;/*");
   }
}

rule _*/if(C<2){trChatSendSpoofed(0,"<color=0,1,1>Forum_:_https://mod.aoebbs.net");}C++;if(C>3)C=1;/*
minInterval 4
active
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      xsDisableRule("_*/if(C<2){trChatSendSpoofed(0,"<color=0,1,1>Forum_:_https://mod.aoebbs.net");}C++;if(C>3)C=1;/*");
      trEcho("Trigger disabling rule */if(C<2){trChatSendSpoofed(0,"<color=0,1,1>Forum_:_https://mod.aoebbs.net");}C++;if(C>3)C=1;/*");
   }
}

rule _*/}/*
minInterval 4
inactive
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      xsDisableRule("_*/}/*");
      trEcho("Trigger disabling rule */}/*");
   }
}

rule _*/if(C<2){trChatSendSpoofed(0,"<color=0,1,1>test2");}C++;if(C>3)C=1;/*
minInterval 4
active
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      xsDisableRule("_*/if(C<2){trChatSendSpoofed(0,"<color=0,1,1>test2");}C++;if(C>3)C=1;/*");
      trEcho("Trigger disabling rule */if(C<2){trChatSendSpoofed(0,"<color=0,1,1>test2");}C++;if(C>3)C=1;/*");
   }
}

rule _*/if((trTime()-cActivationTime)>=1.00000000){xsDisableSelf();}}rule	_test_triggerEnd
minInterval 4
inactive
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      xsDisableRule("_*/if((trTime()-cActivationTime)>=1.00000000){xsDisableSelf();}}rule	_test_triggerEnd");
      trEcho("Trigger disabling rule */if((trTime()-cActivationTime)>=1.00000000){xsDisableSelf();}}rule	_test_triggerEnd");
   }
}



/*将上面的代码的注释去除,并格式化处理:*/
rule _test_trigger	active	runImmediately 
{
   int	C=1;trChatSendSpoofed(0,"test1");
   if((trTime()-cActivationTime)>=1.00000000)
   {
      if((trTime()-cActivationTime)>=1.00000000)
      {
         if((trTime()-cActivationTime)>=1.00000000)
         {
            if(C<2){trChatSendSpoofed(0,"<color=0,1,1>Forum_:_https://www.aoebbs.net");}C++;if(C>3)C=1;
            if(C<2){trChatSendSpoofed(0,"<color=0,1,1>Forum_:_https://www.aoebbs.net");}C++;if(C>3)C=1;
            if(C<2){trChatSendSpoofed(0,"<color=0,1,1>Forum_:_https://www.aoebbs.net");}C++;if(C>3)C=1;
            if(C<2){trChatSendSpoofed(0,"<color=0,1,1>Forum_:_https://mod.aoebbs.net");}C++;if(C>3)C=1;
            if(C<2){trChatSendSpoofed(0,"<color=0,1,1>Forum_:_https://mod.aoebbs.net");}C++;if(C>3)C=1;
            if(C<2){trChatSendSpoofed(0,"<color=0,1,1>Forum_:_https://mod.aoebbs.net");}C++;if(C>3)C=1;
         }
      }
   }
   if(C<2){trChatSendSpoofed(0,"<color=0,1,1>test2");}C++;if(C>3)C=1;
   if(C<2){trChatSendSpoofed(0,"<color=0,1,1>test2");}C++;if(C>3)C=1;
   if(C<2){trChatSendSpoofed(0,"<color=0,1,1>test2");}C++;if(C>3)C=1;
   if((trTime()-cActivationTime)>=1.00000000)
   {
      xsDisableSelf();
   }
}
rule	_test_triggerEnd
minInterval 4
inactive
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      xsDisableRule("_*/if((trTime()-cActivationTime)>=1.00000000){xsDisableSelf();}}rule	_test_triggerEnd");
      trEcho("Trigger disabling rule */if((trTime()-cActivationTime)>=1.00000000){xsDisableSelf();}}rule	_test_triggerEnd");
   }
}

值得注意的是:aoebbsA、aoebbsD与前面讲到的aoebbsR是有区别的,aoebbsA、aoebbsD外层自带花括号,不用手动添加,而aoebbsR是需要手动添加的。
下面是两个版本代码,你可以自行对比:
aoebbsA("test_trigger","active	runImmediately","trChatSendSpoofed(0,\"test1\");");
aoebbsC("if((trTime()-cActivationTime)>=1.00000000){");
aoebbsB("trChatSendSpoofed(0,\"<color=0,1,1>Forum : https://www.aoebbs.net\");");
aoebbsB("trChatSendSpoofed(0,\"<color=0,1,1>Forum : https://mod.aoebbs.net\");");
aoebbsC("}");
aoebbsB("trChatSendSpoofed(0,\"<color=0,1,1>test2\");");
aoebbsD("test_trigger","if((trTime()-cActivationTime)>=1.00000000){xsDisableSelf();}");

aoebbsR("test_trigger","active	runImmediately{trChatSendSpoofed(0,\"test1\");if((trTime()-cActivationTime)>=1.00000000){trChatSendSpoofed(0,\"<color=0,1,1>Forum : https://www.aoebbs.net\");trChatSendSpoofed(0,\"<color=0,1,1>Forum : https://mod.aoebbs.net\");}trChatSendSpoofed(0,\"<color=0,1,1>test2\");if((trTime()-cActivationTime)>=1.00000000){xsDisableSelf();}}");






注意事项

若不遵从以下多项事项,均会导致所有触发程序失效: 关于kb函数:

触发程序示例

我会用多种种方式给玩家1创建一个开局10秒后增加资源的触发



旧版本触发是需要用上trigger3\typetest.xml的,(至于决定版,请用Resource Manager在Data\Data.bar打开trigger\triggerData.xml)。 如果你用过剧情编辑器应该知道给玩家增加资源的触发有Grant Resources,计算秒数的条件是Timer,发送消息用Send Chat。不好意思,我还真的不知道(lll¬ω¬),就算用剧情编辑器,触发程序也是自己写的,根本不需要用上typetest.xml原有的定义。
这是亚洲王朝游戏目录的trigger3文件夹里面的typetest.xml的内容:
    <Condition name="Timer">
      <Param name="Param1" dispName="$$22291$" VarType="long">0</Param>
      <Expression>(trTime()-cActivationTime) >= %Param1%</Expression>
    </Condition>
    <Effect name="Grant Resources">
      <Param name="PlayerID" dispName="$$22301$" varType="player">1</Param>
      <Param name="ResName" dispName="$$22455$" varType="resource">food</Param>
      <Param name="Amount" dispName="$$22456$" varType="long">100</Param>
      <Command>trPlayerGrantResources(%PlayerID%, "%ResName%", %Amount%);</Command>
    </Effect>

方法1.旧版本触发:
	rmCreateTrigger("Gold");
	rmSwitchToTrigger(rmTriggerID("Gold"));
	rmSetTriggerPriority(3);
	rmSetTriggerActive(true);
	rmSetTriggerRunImmediately(true);
	rmSetTriggerLoop(false);
	rmAddTriggerCondition("Timer");
	rmSetTriggerConditionParamInt("Param1", 10, false);
	rmAddTriggerEffect("Grant Resources");
	rmSetTriggerEffectParamInt("PlayerID", 1, false);
	rmSetTriggerEffectParam("ResName", "Gold", false);
	rmSetTriggerEffectParamInt("Amount", 100, false);


方法2.注入式触发程序-rmAddTriggerEffect注入代码:
	aoebbs("rule _Resources active runImmediately { ");	
	aoebbs("if((trTime()-cActivationTime) >= 10.00000000){");	//意思是(游戏总时间-这个触发作用时长)>=10
	aoebbs("trPlayerGrantResources(1,\"Gold\",100);");			//玩家1获得100黄金
	aoebbs("xsDisableRule(\"_Resources\");");							//关闭自身触发,相当于旧版触发的rmSetTriggerLoop(false)。
	aoebbsE("}}");

	//再写一个加100食物、500木材的触发作为示例,注意以下两个rule名称不要重复,不然后面的触发程序都会失效
	aoebbs("rule _ResourcesFW active runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) >= 10.00000000){");
	aoebbs("trPlayerGrantResources(1,\"Food\",100);");
	aoebbs("trPlayerGrantResources(1,\"Wood\",500);");
	aoebbs("xsDisableSelf();");				//xsDisableSelf();是通用关闭自身触发的函数,无需手动设定触发程序名称。
	aoebbsE("}}");

方法3.注入式触发程序-rmCreateTrigger注入代码:

	//原型代码注入(不推荐使用),增加100金:
	rmCreateTrigger("AddGold2	active	runImmediately{if((trTime()-cActivationTime)>=10){trPlayerGrantResources(1,\"Gold\",100);xsDisableSelf();}}/*");
	rmCreateTrigger("*/rule	_AddGold2End");	
	rmSetTriggerActive(false);

	//绿色背景是tab制表符(你只能用制表符代替空格,因为空格会被转义成下划线);xsDisableSelf()是关闭触发本身,因为整个触发只能输入255字符,所以语句字数越少越好。


	//aoebbsR函数(推荐使用),增加100金:
	aoebbsR("AddGold","active	runImmediately{if((trTime()-cActivationTime)>=10){trPlayerGrantResources(1,\"Gold\",100);xsDisableSelf();}}");



	//aoebbsABCD函数(一般在触发程序超出257字符时才使用),增加300食物+200木+100金+400茶叶:
	//aoebbsA用于开头、aoebbsB用于执行效果,aoebbsC用于判断,aoebbsD用于结尾
	aoebbsA("AddResourceFWG","active	runImmediately","");
	aoebbsC("if((trTime()-cActivationTime)>=10){");
	aoebbsB("trPlayerGrantResources(1,\"Food\",300);");
	aoebbsB("trPlayerGrantResources(1,\"Wood\",200);");
	aoebbsB("trPlayerGrantResources(1,\"Gold\",100);");
	aoebbsB("trPlayerGrantResources(1,\"Trade\",100);");
	aoebbsB("xsDisableSelf();");
	aoebbsC("}");
	aoebbsD("AddResourceFWG","");


顶部定义函数
旧版本触发程序
rmAddTriggerEffect注入代码
rmCreateTrigger(原型)注入代码
rmCreateTrigger(aoebbsR函数)注入代码
rmCreateTrigger(aoebbsA、aoebbsB、aoebbsC、aoebbsD、函数)注入代码
Debug.xs - 记事本
	include "mercenaries.xs";
	include "ypAsianInclude.xs";
	include "ypKOTHInclude.xs";
	//顶部定义函数
	void aoebbsParamInjectStart(string xs="")
	{
		rmCreateTrigger("aoebbsInject");
		rmSwitchToTrigger(rmTriggerID("aoebbsInject"));
		rmSetTriggerRunImmediately(true);
		rmSetTriggerActive(false);
		rmAddTriggerEffect("SetIdleProcessing");
		rmSetTriggerEffectParam("IdleProc", "true);"+xs+"}}/*");
	}
	
	void aoebbsParamInjectFinish(string xs="")
	{
		rmAddTriggerEffect("Chat Status");
		rmSetTriggerEffectParam("Active", "true); */rule _aoebbsInjectEnd inactive { if(true){ "+xs+"xsDisableSelf(");
	}
	
	void aoebbs(string xs="")
	{
		rmAddTriggerEffect("Chat Status");
		rmSetTriggerEffectParam("Active", "true); */ "+xs+"/*");
	}
	
	void aoebbsE(string xs="")
	{
		rmAddTriggerEffect("Chat Status");
		rmSetTriggerEffectParam("Active", "true); */ "+xs+"/*");
	}
	
	void aoebbsF(string xs="")
	{
		rmAddTriggerEffect("Chat Status");
		rmSetTriggerEffectParam("Active", "true); */ xsDisableSelf();"+xs+"/*");
	}
	
	void aoebbsZ(string xs="")
	{
		rmAddTriggerEffect("Chat Status");
		rmSetTriggerEffectParam("Active", "true); */ "+xs+"trSetUnitIdleProcessing(true");
	}
	
	void aoebbsR(string ruleName="",string xs="")
	{
		rmCreateTrigger(ruleName+"	"+xs+"/*");
		rmCreateTrigger("*/rule	_"+ruleName+"End");
		rmSetTriggerActive(false);
	}
	
	void aoebbsA(string ruleName="",string xs1="",string xs2="")
	{
		rmCreateTrigger(ruleName+"	"+xs1+"{int	C=1;"+xs2+"/*");
	}
	
	void aoebbsB(string xs1="")
	{
		rmCreateTrigger("*/if(C<2){"+xs1+"}C++;if(C>3)C=1;/*");
	}
	
	void aoebbsC(string xs="")
	{
		rmCreateTrigger("*/"+xs+"/*");
		rmSetTriggerActive(false);
	}
	
	void aoebbsD(string ruleName="",string xs="")
	{
		rmCreateTrigger("*/"+xs+"}rule	_"+ruleName+"End");
		rmSetTriggerActive(false);
	}

	void main(void)
	{
		// ---------------------------------------- Map Info -------------------------------------------
		int playerTilesX=13200;			//设定地图X大小
		int playerTilesZ=13200;			//设定地图Z大小(帝国3的Y是高度,Z才是我们平常所用到的Y)


		//如果玩家大于4将playerTilesX与playerTilesZ改为11500(同一个值的int只能出现1次,当你需要修改数值的时候,不能再加入int)
		if (cNumberNonGaiaPlayers >4){	playerTilesX=11500;	playerTilesZ=11500;}



		if (cNumberNonGaiaPlayers >6){	playerTilesX=10500;	playerTilesZ=10500;}		//Modify Map X&Z Size of 6,7,8 Player



		int SizeX = 2*sqrt(cNumberNonGaiaPlayers*playerTilesX);
		int SizeZ = 2*sqrt(cNumberNonGaiaPlayers*playerTilesZ);



		string MapTerrain ="Carolinas\ground_marsh3_car";	//<-------- 地图地形,自己参照剧情编辑器 <--------

		string MapLighting ="319a_Snow";			//<-------- 照明,自己参照剧情编辑器 <--------

		string PlayerTerrain ="Carolinas\ground_marsh1_car";	//<--------- 玩家范围地形 <---------




		//设定地图XZ大小,分别调用上面用int定义的SizeX与SizeZ,即为rmSetMapSize(13200,13200);如果玩家大于4将改为11500
		rmSetMapSize(SizeX, SizeZ);



		rmSetMapElevationParameters(cElevTurbulence, 0.15, 2.5, 0.35, 3.0); // type, frequency, octaves, persistence, variation 

		rmSetMapElevationHeightBlend(1.0);


		//地形初始化,设定地图初始地形,调用上面用string定义MapTerrain,即为"Carolinas\ground_marsh3_car";
		rmTerrainInitialize(MapTerrain,6);



		//设定照明,调用上面用string定义MapLighting,即为"319a_Snow"
		rmSetLightingSet(MapLighting);



		rmSetGlobalRain(0.9);		//设定下雨
		chooseMercs();
		rmSetMapType("yucatan");
		rmSetMapType("water");
		rmSetMapType("default");	//设定地图类型,地图类型影响到宝藏
		rmSetMapType("land");
		rmSetMapType("bayou");
		rmSetSeaLevel(0); // this is height of river surface compared to surrounding land. River depth is in the river XML.

		rmSetStatusText("",0.01);//读取地图进度条



		rmSetPlacementSection(0.6, 0.00);
		rmPlacePlayersCircular(0.40, 0.40, 0.0);


	//	rmSetPlayerResource(1, "Food", 200);

		//玩家范围
		float AreaSizePlayer = rmAreaTilesToFraction(700);
		for(i=1; <=cNumberNonGaiaPlayers)
		{
			int id=rmCreateArea("Player"+i);
			rmSetPlayerArea(i, id);
			rmSetAreaWarnFailure(id, false);
			rmSetAreaSize(id, AreaSizePlayer, AreaSizePlayer);
			rmSetAreaLocPlayer(id, i);
			rmSetAreaCoherence(id, 0.85);
			rmSetAreaSmoothDistance(id, 2);
			rmSetAreaMinBlobs(id, 1);
			rmSetAreaMaxBlobs(id, 1);
			rmSetAreaTerrainType(id,PlayerTerrain);
			rmBuildArea(id);
		}


		//定义城镇中心
		int TownCenterID = rmCreateObjectDef("player TC");
		if (rmGetNomadStart())
		{
			rmAddObjectDefItem(TownCenterID, "CoveredWagon", 1, 0.0);
		}
		else
		{
			rmAddObjectDefItem(TownCenterID, "TownCenter", 1, 0);
		}
		rmSetObjectDefMinDistance(TownCenterID, 0.0);
		rmSetObjectDefMaxDistance(TownCenterID, 20.0);

		for(i=1; <=cNumberNonGaiaPlayers)
		{	//放置城镇中心,rmPlaceObjectDefAtLoc第二个值为被放置玩家对象,这里使用了for循环,循环值=1,<=玩家人数,所以会放置所有玩家的城镇中心。
			rmPlaceObjectDefAtLoc(TownCenterID, i, rmPlayerLocXFraction(i), rmPlayerLocZFraction(i));
		}


		//定义起始单位(civs.xml定义那些开局单位)
		int startingUnits = rmCreateStartingUnitsObjectDef(5.0);
		rmSetObjectDefMinDistance(startingUnits, 6.0);
		rmSetObjectDefMaxDistance(startingUnits, 10.0);

		for(i=1; <=cNumberNonGaiaPlayers)
		{
			//我暂时只能告诉你这个是调用城镇中心坐标,不解释太多,解释太多你听不懂。另外留意下for(i=1;<=xx){},这是c++的一种循环格式。
			vector TCLocation = rmGetUnitPosition(rmGetUnitPlacedOfPlayer(TownCenterID, i));

			//放置起始单位
			rmPlaceObjectDefAtLoc(startingUnits, i, rmXMetersToFraction(xsVectorGetX(TCLocation)), rmZMetersToFraction(xsVectorGetZ(TCLocation)));
		}

  int TestID=rmCreateArea("Test ID Area");
  rmSetAreaSize(TestID, rmAreaTilesToFraction(500), rmAreaTilesToFraction(500));
  rmSetAreaWaterType(TestID, "Cinematic Ship Ocean");
  rmSetAreaWarnFailure(TestID, true);
  rmSetAreaSmoothDistance(TestID, 0);
  rmSetAreaCoherence(TestID, 0.0);
  //rmSetAreaMix(TestID, "himalayas_a");将设定地形类型语句删除,就算是保留也不会再起任何作用了。
  rmSetAreaBaseHeight(TestID, 4.0);//地形高度可加,也可以不加,看你自己想怎样设定。
  rmSetAreaElevationOctaves(TestID, 3);
  rmSetAreaObeyWorldCircleConstraint(TestID, false);
  rmSetAreaLocation(TestID, 0.5, 0.5);
  rmBuildArea(TestID);

rmSetOceanReveal(true);



		rmSetStatusText("",0.50);//读取地图进度条

	rmCreateTrigger("Gold");
	rmSwitchToTrigger(rmTriggerID("Gold"));
	rmSetTriggerPriority(3);
	rmSetTriggerActive(true);
	rmSetTriggerRunImmediately(true);
	rmSetTriggerLoop(false);
	rmAddTriggerCondition("Timer");
	rmSetTriggerConditionParamInt("Param1", 10, false);
	rmAddTriggerEffect("Grant Resources");
	rmSetTriggerEffectParamInt("PlayerID", 1, false);
	rmSetTriggerEffectParam("ResName", "Gold", false);
	rmSetTriggerEffectParamInt("Amount", 100, false);

	//下面就是rmSetTriggerEffect注入代码了;(上面是旧版本触发,上面的触发最后会输出成下面蓝色文字那种形式,相当于我们绕过了编译工具,直接用原代码编写程序)
	aoebbsParamInjectStart();				//rmAddTriggerEffect注入代码必要开头

	aoebbs("rule _Resources active runImmediately { ");	
	aoebbs("if((trTime()-cActivationTime) >= 10.00000000){");	//意思是(游戏总时间-这个触发作用时长)>=10
	aoebbs("trPlayerGrantResources(1,\"Gold\",100);");			//玩家1获得100黄金
	aoebbs("xsDisableRule(\"_Resources\");");							//关闭自身触发,相当于旧版触发的rmSetTriggerLoop(false)。
	aoebbsE("}}");

	//再写一个加100食物、500木材的触发,注意以下两个rule名称不要重复,不然后面的触发程序都会失效
	aoebbs("rule _ResourcesFW active runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) >= 10.00000000){");
	aoebbs("trPlayerGrantResources(1,\"Food\",100);");
	aoebbs("trPlayerGrantResources(1,\"Wood\",500);");
	aoebbs("xsDisableSelf();");				//xsDisableSelf();是通用关闭自身触发的函数,无需手动设定触发程序名称。
	aoebbsE("}}");

	aoebbsParamInjectFinish();				//rmAddTriggerEffect注入代码必要结尾


	//以下为三种rmCreateTrigger注入代码示例。
	//原型代码注入(不推荐使用),增加100金:
	rmCreateTrigger("AddGold2	active	runImmediately{if((trTime()-cActivationTime)>=10){trPlayerGrantResources(1,\"Gold\",100);xsDisableSelf();}}/*");
	rmCreateTrigger("*/rule	_AddGold2End");	

	//绿色背景是tab制表符(你只能用制表符代替空格,因为空格会被转义成下划线);xsDisableSelf()是关闭触发本身,因为整个触发只能输入255字符,所以语句字数越少越好。


	//aoebbsR函数(推荐使用),增加100金:
	aoebbsR("AddGold","active	runImmediately{if((trTime()-cActivationTime)>=10){trPlayerGrantResources(1,\"Gold\",100);xsDisableSelf();}}");



	//aoebbsABCD函数(一般在触发程序超出257字符时才使用),增加300食物+200木+100金+400茶叶:
	//aoebbsA用于开头、aoebbsB用于执行效果,aoebbsC用于判断,aoebbsD用于结尾
	aoebbsA("AddResourceFWG","active	runImmediately","");
	aoebbsC("if((trTime()-cActivationTime)>=10){");
	aoebbsB("trPlayerGrantResources(1,\"Food\",300);");
	aoebbsB("trPlayerGrantResources(1,\"Wood\",200);");
	aoebbsB("trPlayerGrantResources(1,\"Gold\",100);");
	aoebbsB("trPlayerGrantResources(1,\"Trade\",100);");
	aoebbsB("xsDisableSelf();");
	aoebbsC("}");
	aoebbsD("AddResourceFWG","");





	aoebbsR("aoebbs","active	runImmediately{trChatSendSpoofed(0,\"<color=0,1,1>Forum	:	https://www.aoebbs.net\");xsDisableSelf();}");

	rmSetStatusText("",1.00);//读取地图进度条

	} //END

算一下我们刚才加了多少资源?
旧版本触发+100金,
rmAddTriggerEffect注入代码①+100金币
rmAddTriggerEffect注入代码②+100食物+500木材
rmCreateTrigger(原型)注入代码+100金币
rmCreateTrigger(aoebbsR)注入代码+100金币,
rmCreateTrigger(aoebbsABCD)注入代码+300食物+200木材+100金币+100茶叶
共6种触发程序,开局10秒后玩家①将获得100茶叶、400食物、700木材、500金币。






上面是单独给玩家1创建的,如果要给所有玩家创建要怎样做呢? 用for循环就行
Debug.xs - 记事本
	include "mercenaries.xs";
	include "ypAsianInclude.xs";
	include "ypKOTHInclude.xs";
	//顶部定义函数
	void aoebbsParamInjectStart(string xs="")
	{
		rmCreateTrigger("aoebbsInject");
		rmSwitchToTrigger(rmTriggerID("aoebbsInject"));
		rmSetTriggerRunImmediately(true);
		rmSetTriggerActive(false);
		rmAddTriggerEffect("SetIdleProcessing");
		rmSetTriggerEffectParam("IdleProc", "true);"+xs+"}}/*");
	}
	
	void aoebbsParamInjectFinish(string xs="")
	{
		rmAddTriggerEffect("Chat Status");
		rmSetTriggerEffectParam("Active", "true); */rule _aoebbsInjectEnd inactive { if(true){ "+xs+"xsDisableSelf(");
	}
	
	void aoebbs(string xs="")
	{
		rmAddTriggerEffect("Chat Status");
		rmSetTriggerEffectParam("Active", "true); */ "+xs+"/*");
	}
	
	void aoebbsE(string xs="")
	{
		rmAddTriggerEffect("Chat Status");
		rmSetTriggerEffectParam("Active", "true); */ "+xs+"/*");
	}
	
	void aoebbsF(string xs="")
	{
		rmAddTriggerEffect("Chat Status");
		rmSetTriggerEffectParam("Active", "true); */ xsDisableSelf();"+xs+"/*");
	}
	
	void aoebbsZ(string xs="")
	{
		rmAddTriggerEffect("Chat Status");
		rmSetTriggerEffectParam("Active", "true); */ "+xs+"trSetUnitIdleProcessing(true");
	}
	
	void aoebbsR(string ruleName="",string xs="")
	{
		rmCreateTrigger(ruleName+"	"+xs+"/*");
		rmCreateTrigger("*/rule	_"+ruleName+"End");
		rmSetTriggerActive(false);
	}
	
	void aoebbsA(string ruleName="",string xs1="",string xs2="")
	{
		rmCreateTrigger(ruleName+"	"+xs1+"{int	C=1;"+xs2+"/*");
	}
	
	void aoebbsB(string xs1="")
	{
		rmCreateTrigger("*/if(C<2){"+xs1+"}C++;if(C>3)C=1;/*");
	}
	
	void aoebbsC(string xs="")
	{
		rmCreateTrigger("*/"+xs+"/*");
		rmSetTriggerActive(false);
	}
	
	void aoebbsD(string ruleName="",string xs="")
	{
		rmCreateTrigger("*/"+xs+"}rule	_"+ruleName+"End");
		rmSetTriggerActive(false);
	}

	void main(void)
	{
		// ---------------------------------------- Map Info -------------------------------------------
		int playerTilesX=13200;			//设定地图X大小
		int playerTilesZ=13200;			//设定地图Z大小(帝国3的Y是高度,Z才是我们平常所用到的Y)


		//如果玩家大于4将playerTilesX与playerTilesZ改为11500(同一个值的int只能出现1次,当你需要修改数值的时候,不能再加入int)
		if (cNumberNonGaiaPlayers >4){	playerTilesX=11500;	playerTilesZ=11500;}



		if (cNumberNonGaiaPlayers >6){	playerTilesX=10500;	playerTilesZ=10500;}		//Modify Map X&Z Size of 6,7,8 Player



		int SizeX = 2*sqrt(cNumberNonGaiaPlayers*playerTilesX);
		int SizeZ = 2*sqrt(cNumberNonGaiaPlayers*playerTilesZ);





		string MapTerrain ="Carolinas\ground_marsh3_car";	//<-------- 地图地形,自己参照剧情编辑器 <--------

		string MapLighting ="319a_Snow";			//<-------- 照明,自己参照剧情编辑器 <--------

		string PlayerTerrain ="Carolinas\ground_marsh1_car";	//<--------- 玩家范围地形 <---------




		//设定地图XZ大小,分别调用上面用int定义的SizeX与SizeZ,即为rmSetMapSize(13200,13200);如果玩家大于4将改为11500
		rmSetMapSize(SizeX, SizeZ);



		rmSetMapElevationParameters(cElevTurbulence, 0.15, 2.5, 0.35, 3.0); // type, frequency, octaves, persistence, variation 

		rmSetMapElevationHeightBlend(1.0);


		//地形初始化,设定地图初始地形,调用上面用string定义MapTerrain,即为"Carolinas\ground_marsh3_car";
		rmTerrainInitialize(MapTerrain,6);



		//设定照明,调用上面用string定义MapLighting,即为"319a_Snow"
		rmSetLightingSet(MapLighting);



		rmSetGlobalRain(0.9);		//设定下雨
		chooseMercs();
		rmSetMapType("yucatan");
		rmSetMapType("water");
		rmSetMapType("default");	//设定地图类型,地图类型影响到宝藏
		rmSetMapType("land");
		rmSetMapType("bayou");
		rmSetSeaLevel(0); // this is height of river surface compared to surrounding land. River depth is in the river XML.

		rmSetStatusText("",0.01);//读取地图进度条



		rmSetPlacementSection(0.6, 0.00);
		rmPlacePlayersCircular(0.40, 0.40, 0.0);


	//	rmSetPlayerResource(1, "Food", 200);

		//玩家范围
		float AreaSizePlayer = rmAreaTilesToFraction(700);
		for(i=1; <=cNumberNonGaiaPlayers)
		{
			int id=rmCreateArea("Player"+i);
			rmSetPlayerArea(i, id);
			rmSetAreaWarnFailure(id, false);
			rmSetAreaSize(id, AreaSizePlayer, AreaSizePlayer);
			rmSetAreaLocPlayer(id, i);
			rmSetAreaCoherence(id, 0.85);
			rmSetAreaSmoothDistance(id, 2);
			rmSetAreaMinBlobs(id, 1);
			rmSetAreaMaxBlobs(id, 1);
			rmSetAreaTerrainType(id,PlayerTerrain);
			rmBuildArea(id);
		}


		//定义城镇中心
		int TownCenterID = rmCreateObjectDef("player TC");
		if (rmGetNomadStart())
		{
			rmAddObjectDefItem(TownCenterID, "CoveredWagon", 1, 0.0);
		}
		else
		{
			rmAddObjectDefItem(TownCenterID, "TownCenter", 1, 0);
		}
		rmSetObjectDefMinDistance(TownCenterID, 0.0);
		rmSetObjectDefMaxDistance(TownCenterID, 20.0);

		for(i=1; <=cNumberNonGaiaPlayers)
		{	//放置城镇中心,rmPlaceObjectDefAtLoc第二个值为被放置玩家对象,这里使用了for循环,循环值=1,<=玩家人数,所以会放置所有玩家的城镇中心。
			rmPlaceObjectDefAtLoc(TownCenterID, i, rmPlayerLocXFraction(i), rmPlayerLocZFraction(i));
		}


		//定义起始单位(civs.xml定义那些开局单位)
		int startingUnits = rmCreateStartingUnitsObjectDef(5.0);
		rmSetObjectDefMinDistance(startingUnits, 6.0);
		rmSetObjectDefMaxDistance(startingUnits, 10.0);

		for(i=1; <=cNumberNonGaiaPlayers)
		{
			//我暂时只能告诉你这个是调用城镇中心坐标,不解释太多,解释太多你听不懂。另外留意下for(i=1;<=xx){},这是是c++的一种循环格式。
			vector TCLocation = rmGetUnitPosition(rmGetUnitPlacedOfPlayer(TownCenterID, i));

			//放置起始单位
			rmPlaceObjectDefAtLoc(startingUnits, i, rmXMetersToFraction(xsVectorGetX(TCLocation)), rmZMetersToFraction(xsVectorGetZ(TCLocation)));
		}

  int TestID=rmCreateArea("Test ID Area");
  rmSetAreaSize(TestID, rmAreaTilesToFraction(500), rmAreaTilesToFraction(500));
  rmSetAreaWaterType(TestID, "Cinematic Ship Ocean");
  rmSetAreaWarnFailure(TestID, true);
  rmSetAreaSmoothDistance(TestID, 0);
  rmSetAreaCoherence(TestID, 0.0);
  //rmSetAreaMix(TestID, "himalayas_a");将设定地形类型语句删除,就算是保留也不会再起任何作用了。
  rmSetAreaBaseHeight(TestID, 4.0);//地形高度可加,也可以不加,看你自己想怎样设定。
  rmSetAreaElevationOctaves(TestID, 3);
  rmSetAreaObeyWorldCircleConstraint(TestID, false);
  rmSetAreaLocation(TestID, 0.5, 0.5);
  rmBuildArea(TestID);

rmSetOceanReveal(true);



		rmSetStatusText("",0.50);//读取地图进度条


	//旧版本触发:

	//循环方法1,循环所有语句,创建cNumberNonGaiaPlayers个触发:
	for(i=1; <=cNumberNonGaiaPlayers)
	{
		rmCreateTrigger("Gold"+i);	//为什么要加循环值i呢?因为不能出现两个相同名称的触发,否则会全体触发失效。
		rmSwitchToTrigger(rmTriggerID("Gold"+i));
		rmSetTriggerPriority(3);
		rmSetTriggerActive(true);
		rmSetTriggerRunImmediately(true);
		rmSetTriggerLoop(false);
		rmAddTriggerCondition("Timer");
		rmSetTriggerConditionParamInt("Param1", 10, false);
		rmAddTriggerEffect("Grant Resources");
		rmSetTriggerEffectParamInt("PlayerID", i, false);
		rmSetTriggerEffectParam("ResName", "Gold", false);
		rmSetTriggerEffectParamInt("Amount", 100, false);
	}


	//循环方法2,仅循环效果语句:
	rmCreateTrigger("AllPlayerGold");
	rmSwitchToTrigger(rmTriggerID("AllPlayerGold"));
	rmSetTriggerPriority(3);
	rmSetTriggerActive(true);
	rmSetTriggerRunImmediately(true);
	rmSetTriggerLoop(false);
	rmAddTriggerCondition("Timer");
	rmSetTriggerConditionParamInt("Param1", 10, false);
	for(i=1; <=cNumberNonGaiaPlayers)
	{
		rmAddTriggerEffect("Grant Resources");
		rmSetTriggerEffectParamInt("PlayerID", i, false);
		rmSetTriggerEffectParam("ResName", "Gold", false);
		rmSetTriggerEffectParamInt("Amount", 100, false);
	}



	//rmAddTriggerEffect注入代码:

	aoebbsParamInjectStart();				//rmAddTriggerEffect注入代码必要开头


	//循环方法1,RM层循环所有语句,创建cNumberNonGaiaPlayers个触发(地图加载完成后,会生成多个触发程序):
	//为什么是"+i+"?因为我们是在地图语句循环的,属于RM层,不属于触发XS层;所以引号内的语句要用"+i+",意思是"左边的xxx"加上循环值i再加上"右边的xxxx"。
	//第一句双引号加了颜色,这样你应该看的懂是怎样一回事。
	for(i=1; <=cNumberNonGaiaPlayers)
	{
		aoebbs("rule _Resources"+i+" active runImmediately { ");
		aoebbs("if((trTime()-cActivationTime) >= 10.00000000){");
		aoebbs("trPlayerGrantResources("+i+",\"Gold\",100);");
		aoebbs("xsDisableRule(\"_Resources"+i+"\");");
		aoebbsE("}}");

		//加100食物、500木材的触发
		aoebbs("rule _ResourcesFW"+i+" active runImmediately { ");
		aoebbs("if((trTime()-cActivationTime) >= 10.00000000){");
		aoebbs("trPlayerGrantResources("+i+",\"Food\",100);");
		aoebbs("trPlayerGrantResources("+i+",\"Wood\",500);");
		aoebbs("xsDisableSelf();");				
		aoebbsE("}}");
	}
	
	//循环方法2,RM层循仅环函数语句(会在编译地图时输出cNumberNonGaiaPlayers个语句,再编译触发程序):
	aoebbs("rule _AllPlayerResources active runImmediately { ");	
	aoebbs("if((trTime()-cActivationTime) >= 10.00000000){");
	for(i=1; <=cNumberNonGaiaPlayers)
	{	
		aoebbs("trPlayerGrantResources("+i+",\"Gold\",100);");
	}	
	aoebbs("xsDisableSelf();");							
	aoebbsE("}}");

	aoebbs("rule _AllPlayerResourcesFW active runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) >= 10.00000000){");
	for(i=1; <=cNumberNonGaiaPlayers)
	{	
		aoebbs("trPlayerGrantResources("+i+",\"Food\",100);");
		aoebbs("trPlayerGrantResources("+i+",\"Wood\",500);");
	}	
	aoebbs("xsDisableSelf();");				
	aoebbsE("}}");

	//循环方法3,XS层循环语句(当地图加载完成,触发程序编译完成后,再执行):
	aoebbs("rule _ResourcesTest active runImmediately {");
	aoebbs("if((trTime()-cActivationTime) >= 10.00000000){");
	aoebbs("for(i=1; <="+cNumberNonGaiaPlayers+")");
	aoebbs("{");
	aoebbs("	trPlayerGrantResources(i,\"Gold\",100);");
	aoebbs("}");
	aoebbs("xsDisableSelf();");				
	aoebbsE("}}");

	aoebbs("rule _ResourcesFWTest active runImmediately {");
	aoebbs("if((trTime()-cActivationTime) >= 10.00000000){");
	aoebbs("for(i=1; <cNumberPlayers)");
	aoebbs("{");
	aoebbs("	trPlayerGrantResources(i,\"Food\",100);");
	aoebbs("	trPlayerGrantResources(i,\"Wood\",500);");
	aoebbs("}");
	aoebbs("xsDisableSelf();");				
	aoebbsE("}}");

	//注:cNumberNonGaiaPlayers为玩家数量(不包括大自然),无法在TR层使用,要使用"+cNumberNonGaiaPlayers+"使它变成RM层数据。另一个计算玩家数量的变量cNumberPlayers(包括大自然)可以在XS层使用。由于cNumberPlayers包含大自然的数量,所以for循环不使用<=,而是直接使用<。


	//再加一个将玩家资源信息发送到聊天的触发
	//发送聊天信息的是trChatSendSpoofed(fromID message): Changes the chat status, but does not append player.
	//trChatSendSpoofed(0,\"\");(0就是大自然)
	//返回玩家资源语句为trPlayerResourceCount(playerID, resource): returns the number of resources for the player.
	//trPlayerResourceCount(playerID, \"\")

	//发送聊天触发11秒后再执行(因为触发是按顺序执行的,如果是十秒就先执行这个,再执行下面的触发
	aoebbs("rule _SendChat active runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) >= 11.00000000){");
	for(i=1; <=cNumberNonGaiaPlayers)
	{
		aoebbs("trChatSendSpoofed(0,\"Player"+i+" <color=0,1,0>Food:\"+trPlayerResourceCount("+i+", \"Food\"));");
		aoebbs("trChatSendSpoofed(0,\"Player"+i+" <color=0,1,1>Wood:\"+trPlayerResourceCount("+i+", \"Wood\"));");
		aoebbs("trChatSendSpoofed(0,\"Player"+i+" <color=0.25,1,0.25>Gold:\"+trPlayerResourceCount("+i+", \"Gold\"));");
		aoebbs("trChatSendSpoofed(0,\"Player"+i+" <color=0,1,0>Trade:\"+trPlayerResourceCount("+i+", \"Trade\"));");
	}
	aoebbs("xsDisableRule(\"_SendChat\");");
	aoebbsE("}}");
	//有时候你设定随机数或者不明白RM函数设定的值(坐标、vector坐标那些)是什么,可以用这种触发返回那个值,用trChatSendSpoofed(0,\""+此处写上int定义之类的+"\");发送到聊天窗口。
	//怎么一会用"+ +",一会儿不用?已经说了RM层语句与TR层语句不通用,TR层调用RM层数值要用"+ +"。
	


	aoebbsParamInjectFinish();				//rmAddTriggerEffect注入代码必要结尾





	//rmCreateTrigger注入代码:
	//循环方法1,RM层循环所有语句,创建cNumberNonGaiaPlayers个触发(地图加载完成后,会生成多个触发程序):
	for(i=1; <=cNumberNonGaiaPlayers)
	{
	//原型代码注入(不推荐使用):
	rmCreateTrigger("AddGold2"+i+"	active	runImmediately{if((trTime()-cActivationTime)>=10){trPlayerGrantResources("+i+",\"Gold\",100);xsDisableSelf();}}/*");
	rmCreateTrigger("*/rule	_AddGold2End"+i);

	//aoebbsR函数(推荐使用):
	aoebbsR("AddGold"+i,"active	runImmediately{if((trTime()-cActivationTime)>=10){trPlayerGrantResources("+i+",\"Gold\",100);xsDisableSelf();}}");

	//aoebbsABCD函数(一般在触发程序超出257字符时才使用):
	aoebbsA("AddResourceFWG"+i,"active	runImmediately","");
	aoebbsC("if((trTime()-cActivationTime)>=10){");
	aoebbsB("trPlayerGrantResources("+i+",\"Food\",300);");
	aoebbsB("trPlayerGrantResources("+i+",\"Wood\",200);");
	aoebbsB("trPlayerGrantResources("+i+",\"Gold\",100);");
	aoebbsB("trPlayerGrantResources("+i+",\"Trade\",100);");
	aoebbsB("xsDisableSelf();");
	aoebbsC("}");
	aoebbsD("AddResourceFWG"+i,"");

	}

	
	//循环方法2,RM层循仅环函数语句(会在编译地图时输出cNumberNonGaiaPlayers个语句,再编译触发程序):
	//只能用于aoebbsABCD函数,其他两种因为只有一行并且不能断开的原因,不能用这个方法。
	aoebbsA("AddResourceFWGtest","active	runImmediately","");
	aoebbsC("if((trTime()-cActivationTime)>=10){");
	for(i=1; <=cNumberNonGaiaPlayers)
	{
		aoebbsB("trPlayerGrantResources("+i+",\"Food\",300);");
		aoebbsB("trPlayerGrantResources("+i+",\"Wood\",200);");
		aoebbsB("trPlayerGrantResources("+i+",\"Gold\",100);");
		aoebbsB("trPlayerGrantResources("+i+",\"Trade\",100);");
	}
	aoebbsB("xsDisableSelf();");
	aoebbsC("}");
	aoebbsD("AddResourceFWGtest","");





	//循环方法3,XS层循仅环函数语句(当地图加载完成,触发程序编译完成后,再执行):
	//原型代码注入(不推荐使用):
	rmCreateTrigger("AddGoldForAll	active	runImmediately{if((trTime()-cActivationTime)>=10){for(i=1;<cNumberPlayers){trPlayerGrantResources"+"(i,\"Gold\",100);}xsDisableSelf();}}/*");
	rmCreateTrigger("*/rule	_AddGoldEnd");

	//上面已经说过了cNumberNonGaiaPlayers不能在TR层使用,所以用cNumberPlayers代替,但是我还是推荐使用"+cNumberNonGaiaPlayers+",为什么呢?rmCreateTrigger注入代码只能输出257个字符,"+cNumberNonGaiaPlayers+"从RM转成数字后会变成只有一个字符(游戏最多能有8人),所以比cNumberPlayers节省了14个字符。

	
	//aoebbsR函数(推荐使用):
	aoebbsR("GrantGold","active	runImmediately{if((trTime()-cActivationTime)>=10){for(i=1;<="+cNumberNonGaiaPlayers+"){trPlayerGrantResources(i,\"Gold\",100);}xsDisableSelf();}}");

	//由于aoebbsB与aoebbsC都会生成三行相同代码的原因,跨行for循环会导致花括号不正确闭合又或者出现cNumberNonGaiaPlayers3次循环,所以必须将for循环拆分成多行。
	aoebbsA("AddResourceABCD","active	runImmediately","");
	aoebbsC("if((trTime()-cActivationTime)>=10){");
	aoebbsB("for(i=1;<cNumberPlayers){trPlayerGrantResources(i,\"Food\",300);}");
	aoebbsB("for(i=1;<="+cNumberNonGaiaPlayers+"){trPlayerGrantResources(i,\"Wood\",200);}");
	aoebbsB("for(i=1;<="+cNumberNonGaiaPlayers+"){trPlayerGrantResources(i,\"Gold\",100);trPlayerGrantResources(i,\"Trade\",100);}");
	aoebbsB("xsDisableSelf();");
	aoebbsC("}");
	aoebbsD("AddResourceABCD","");


		rmSetStatusText("",1.00);//读取地图进度条
	} //END
统计上面一共加了多少资源?
旧版本触发 :所有玩家+100金币 *2个;
rmSetTriggerEffect注入代码 :所有玩家+100金 *3个;所有玩家+[100食物、500木材] *3个
rmCreateTrigger(原型)注入代码 :所有玩家+100金 *2个;
rmCreateTrigger(aoebbsR)注入代码 :所有玩家+100金 *2个;
rmCreateTrigger(aoebbsABCD)注入代码 :所有玩家+[300食物、200木材、100金币、100茶叶]*3个
共6种触发程序,开局10秒后所有玩家将获得300茶叶、1200食物、2100木材、1200金币。

最后补充:有不懂语句是什么作用的,可以去查看XS、KB、TR函数表搜索函数 触发程序不仅可以使用TR函数,还可以使用XS、KB以及一小部分UI函数。 使用KB函数注意事项,使用KB函数必须加上xsSetContextPlayer来设定KB函数的对象玩家。 [(void )] xsSetContextPlayer( int playerID ): Sets the current context player ID (DO NOT DO THIS IF YOU DO NOT KNOW WHAT YOU ARE DOING). [(float )] kbTotalResourceGet( int resourceID ): Returns the total amount of the given resource gathered to this point in the game. 例如获取玩家1采集了多少食物(食物的resourceID为2):xsSetContextPlayer(1);kbTotalResourceGet(2); 获取所有玩家采集了多少食物for(i=1;<cNumberPlayers){xsSetContextPlayer(i);{kbTotalResourceGet(2);} 获取这些值有什么用呢?如下 用if判断玩家食物是否大于100 for(i=1;<cNumberPlayers) { xsSetContextPlayer(i); if(kbTotalResourceGet(2)>100) { } } 个人推荐使用第一种注入式触发程序`rmSetTriggerEffect`,因为这种触发方便,也能自定义,还能写出非常复杂的触发。 第二种可以在中文路径使用的注入式触发程序`rmCreateTrigger`适用小批量触发程序,你自己也懂的,在天朝每10个人就有7个人安装路径存在中文字符,小批量能用这种触发程序就用这种。 为了避免因为中文路径导致的不同步现象,可以这样设定: 以下语句为开局踢出中文路径玩家: /* It can't use in Chinese path .*/ rmCreateTrigger("GameStart"); rmSetTriggerRunImmediately(true); rmSetTriggerPriority(5); rmSetTriggerEffectParam("IdleProc","true);trQuestVarSet(\"Path\",1);xsDisableSelf();}}/*"); /*the next Trigger will kick "Chinese Path Player" out of the game.*/ rmCreateTrigger("Path active runImmediately{if(trQuestVarGet(\"Path\")!=1){"+"showSPCNote(\"Error!\",\"<color=0,1,0>Use-the-English-path-to-install-the-Age-of-Empires-III,please.\");"+"uiMessageBox2(20948);trEndGame();leaveGame();xsDisableRule(\"_Path\");}}/*"); rmSetTriggerActive(false); rmSetTriggerPriority(5); rmCreateTrigger("*/rule _PathEnd"); rmSetTriggerActive(false); 这效果是怎样达成的呢? 已知帝国3安装目录存在中文路径所有触发程序将会失效,那么我们就用官方版本的触发程序用Quest Var Set设定一个值,设定那个值为1。而中文路径的帝国3因为触发程序失效,那个值就不为1,然后我们可以利用rmCreateTrigger注入代码,由于rmCreateTrigger注入代码后不受中文路径影响,可以获取那个值,不等于1就执行效果trEndGame();结束游戏,然后使用trYouWin(true);或者leaveGame();使其自己离开游戏(出局)。有一点要说明的是不是用触发设定那个玩家出局,而是让那个玩家自己离开游戏才不会导致出现问题。 最终,中文路径玩家会显示:





你觉得单位ID是怎样导出的?


	aoebbs("rule _Debug29 active runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) == 1.00000000){");
	aoebbs("trChatSendSpoofed(0,\"<color=0,1,1>\"+kbGetUnitTypeName(0));");
	aoebbs("trChatSendSpoofed(0,\"<color=0,1,1>\"+kbGetUnitTypeName(1));");
	aoebbs("trChatSendSpoofed(0,\"<color=0,1,1>\"+kbGetUnitTypeName(2));");
	aoebbs("trChatSendSpoofed(0,\"<color=0,1,1>\"+kbGetUnitTypeName(1463));");
	aoebbs("trChatSendSpoofed(0,\"<color=0,1,1>\"+kbGetUnitTypeName(1464));");
	aoebbs("xsDisableRule(\"_Debug29\");");
	aoebbsE("}}");

	


	aoebbs("rule _Unittype active runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) >= 1.00000000){");
	for(u=1; <1800)
	{
	aoebbs("trChatSendSpoofed(0,\"<color=0,1,1>"+u+":\");");
	}
	aoebbs("xsDisableRule(\"_Unittype\");");
	aoebbsE("}}");




整合两个触发
	aoebbs("rule _Unittype2 active runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) >= 1.00000000){");
	for(u=1463; <1800)
	{
		aoebbs("trChatSend(0,\"<color=0,1,1>"+u+"     \"+kbGetUnitTypeName("+u+"));");
	}
	aoebbs("xsDisableRule(\"_Unittype2\");");
	aoebbsE("}}");




































































































































地图里面怎么用汉字
cms1314258 发表于 2022-5-8 16:50:10
比如汉字提示,我定义一个string赋汉字就加载不了
こはね 发表于 2022-5-8 18:03:38
只能调用srtingtabley的文字
比如我制作的某些地图的触发程序是需要使用酋长单位的,单一亚洲王朝是无法加载成功的,会卡住无法开局,然后我在开局聊天输出了下面的文字

<String _locID="68440" symbol="cStringRequiresXpackContent">%s -- 需要“帝国时代 III: 战争酋长”资料片</String>
	rmCreateTrigger("Message2	active	runImmediately{"+"trChatSendSpoofed(0,\"{68440}\");trChatSendSpoofed(0,\"<color=0,1,0>If you don't have the WarChiefs"+" Content, please press the Alt + F4 key.\");xsDisableSelf();}/*");

rmCreateTrigger("*/rule _Message2End");


%s -- 需要“帝国时代 III: 战争酋长”资料片
If you don't have the WarChiefs Content, please press the Alt + F4 key












































kbUnitQuery查询单位
kbUnitQuery系列函数可用于地图触发程序、剧情编辑器触发程序、AI文件

首先用kbUnitQueryCreate创建查询,然后kbUnitQueryResetResults清除之前的查询数据;kbUnitQuerySet系列函数 设定各种查询条件,但似乎必须含有kbUnitQuerySetPlayerID函数,否则查询失败。
除此之外,必须用xsSetContextPlayer指定对象玩家,不然连queryID都不存在;还有一点xsSetContextPlayer与kbUnitQuerySetPlayerID的对象玩家必须一致(意义不明,多此一举),否则查询结果为空。

以下是一个地图注入式触发程序查询例子

aoebbs("rule _Debug71 minInterval 2 active runImmediately {");
aoebbs("if((trTime()-cActivationTime) >= 5.00000000){");
aoebbs("int UnitTypeID = 0;");
aoebbs("while(kbGetUnitTypeName(UnitTypeID)!=\"unit\"){");
aoebbs("UnitTypeID = UnitTypeID+1;");
aoebbs("}");
aoebbs("xsSetContextPlayer(1);");
aoebbs("trChatSend(0,\"UnitTypeID:\"+UnitTypeID+\":\"+kbGetUnitTypeName(UnitTypeID));");
aoebbs("int queryID = kbUnitQueryCreate(\"QueryAliveUnit\");");
aoebbs("trChatSend(0,\"queryID:\"+queryID);");
aoebbs("kbUnitQueryResetData(queryID);");
aoebbs("kbUnitQueryResetResults(queryID);");
aoebbs("kbUnitQuerySetUnitType(queryID,UnitTypeID);");
aoebbs("kbUnitQuerySetState(queryID, cUnitStateAlive);");
aoebbs("kbUnitQuerySetAscendingSort(queryID,true);");
aoebbs("kbUnitQuerySetPlayerID(queryID, 1,false);");
aoebbs("int resultCount = kbUnitQueryExecute(queryID);");
aoebbs("resultCount = kbUnitQueryNumberResults(queryID);");
aoebbs("trChatSend(0,\"resultCount:\"+resultCount);");
aoebbs("int unitID = 0;");
aoebbs("for(i=0;<resultCount) {");
aoebbs("unitID = kbUnitQueryGetResult(queryID,i);");
aoebbs("trChatSend(0,\"unitID[\"+unitID+\"]:\"+kbGetProtoUnitName(kbUnitGetProtoUnitID(unitID)));");
aoebbs("}");
aoebbs("xsDisableSelf();");
aoebbs("}");
aoebbs("}");
aoebbsE("");











还原后的源代码(可以自行使用转换器转换地图触发程序转换器):

	rule _Debug71 minInterval 2 active runImmediately {
	if((trTime()-cActivationTime) >= 5.00000000){
		int UnitTypeID = 0;
		while(kbGetUnitTypeName(UnitTypeID)!="unit"){
			UnitTypeID = UnitTypeID+1;
		}
		xsSetContextPlayer(1);
		trChatSend(0,"UnitTypeID:"+UnitTypeID+":"+kbGetUnitTypeName(UnitTypeID));
		int queryID = kbUnitQueryCreate("QueryAliveUnit");
		trChatSend(0,"queryID:"+queryID);
		kbUnitQueryResetData(queryID);
		kbUnitQueryResetResults(queryID);
		kbUnitQuerySetUnitType(queryID,UnitTypeID);
		kbUnitQuerySetState(queryID, cUnitStateAlive);
		kbUnitQuerySetAscendingSort(queryID,true);
		kbUnitQuerySetPlayerID(queryID, 1,false);
		int resultCount = kbUnitQueryExecute(queryID);
		resultCount = kbUnitQueryNumberResults(queryID);
		trChatSend(0,"resultCount:"+resultCount);
		int unitID = 0;
		for(i=0;<resultCount) {
			unitID = kbUnitQueryGetResult(queryID,i);
			trChatSend(0,"unitID["+unitID+"]:"+kbGetProtoUnitName(kbUnitGetProtoUnitID(unitID)));
		}
		xsDisableSelf();
	}
}





















示例:所有玩家带有AbstractInfantry的步兵增加1000生命值

aoebbs("rule _Debug431 active runImmediately {");
aoebbs("float UnitTypeID = 0;");
aoebbs("while(kbGetUnitTypeName(UnitTypeID) != \"AbstractInfantry\") {");
aoebbs("UnitTypeID = UnitTypeID+1;");
aoebbs("}");
aoebbs("for(i=1;<=cNumberPlayers) {");
aoebbs("float UnitID = 0;");
aoebbs("xsSetContextPlayer(i);");
aoebbs("while(kbGetUnitTypeName(UnitID) !=\"Unit\") {");
aoebbs("if(kbProtoUnitIsType(i,UnitID,UnitTypeID)) {");
aoebbs("trModifyProtounit(kbGetProtoUnitName(UnitID), i, 0, 1000.0);");
aoebbs("}");
aoebbs("UnitID = UnitID +1;");
aoebbs("}");
aoebbs("}");
aoebbs("xsDisableSelf();");
aoebbs("}");
aoebbsE(""); 
原代码:
	
rule _Debug431 active runImmediately {
	float UnitTypeID = 0;
	while(kbGetUnitTypeName(UnitTypeID) != "AbstractInfantry") {
		UnitTypeID = UnitTypeID+1;
	}
	for(i=1;<=cNumberPlayers) {
		float UnitID = 0;
		xsSetContextPlayer(i);
		while(kbGetUnitTypeName(UnitID) !="Unit") {
			if(kbProtoUnitIsType(i,UnitID,UnitTypeID)) {
				trModifyProtounit(kbGetProtoUnitName(UnitID), i, 0, 1000.0);
			}
			UnitID = UnitID +1;
		}
	}
	xsDisableSelf();
}


//注释版:
rule _Debug431 active runImmediately {

	// 定义浮点数UnitTypeID初始值为0;
	float UnitTypeID = 0; 

	//循环查找某个单位类型,直到找到名字为 "AbstractInfantry"(kbGetUnitTypeName(UnitTypeID)返回UnitTypeName,若不为AbstractInfantry,UnitTypeID+1)
	while(kbGetUnitTypeName(UnitTypeID) != "AbstractInfantry") {
		UnitTypeID = UnitTypeID+1;
	}


	// 遍历所有玩家
	for(i=1;<=cNumberPlayers) {
		// 定义浮点数UnitID初始值为0;
		float UnitID = 0;
		//kb函数对象玩家,用于无对象的kb函数指定对象玩家,找bug找怕了,凡是kb函数,不管其是否有对象,一律使用xsSetContextPlayer
		xsSetContextPlayer(i);

		// 循环查找某个单位类型,直到找到名字为 "Unit",其作用为以第一个unittype作为断点遍历所有单位(已知protoy.xml最后一个单位ID+1的ID为Unit,因此Unit常用于作断点)
		while(kbGetUnitTypeName(UnitID) !="Unit") {

			// 判断当前玩家的当前的protoy单位是否拥有指定类型 (AbstractInfantry)
			if(kbProtoUnitIsType(i,UnitID,UnitTypeID)) {
				
				// 当前玩家,当前单位的生命值增加1000。
				trModifyProtounit(kbGetProtoUnitName(UnitID), i, 0, 1000.0);

			}
			UnitID = UnitID +1;
		}
	}
	xsDisableSelf();
}
	
	trModifyProtounit请参考Modify Protounit
这是我用来测试触发程序遗留下来的资料,里面的写法你可以自己参考一下
rmSwitchToTrigger实测: rm函数在转换时,将代码添加到指定触发ID中。
	rmCreateTrigger("Gold");
	rmSwitchToTrigger(rmTriggerID("Gold"));
	rmSetTriggerPriority(3);
	rmSetTriggerActive(true);
	rmSetTriggerRunImmediately(true);
	rmSetTriggerLoop(false);
	rmAddTriggerCondition("Timer");
	rmSetTriggerConditionParamInt("Param1", 10, false);
	rmAddTriggerEffect("Grant Resources");
	rmSetTriggerEffectParamInt("PlayerID", 1, false);
	rmSetTriggerEffectParam("ResName", "Fame", false);
	rmSetTriggerEffectParamInt("Amount", 5000, false);

	rmCreateTrigger("Gold2");
	rmSwitchToTrigger(rmTriggerID("Gold"));
	rmAddTriggerEffect("Grant Resources");
	rmSetTriggerEffectParamInt("PlayerID", 1, false);
	rmSetTriggerEffectParam("ResName", "Fame", false);
	rmSetTriggerEffectParamInt("Amount", 5000, false);

	rmCreateTrigger("Gold3");
	rmAddTriggerEffect("Grant Resources");
	rmSetTriggerEffectParamInt("PlayerID", 1, false);
	rmSetTriggerEffectParam("ResName", "Fame", false);
	rmSetTriggerEffectParamInt("Amount", 5000, false);
实测被转换成

rule _Gold
minInterval 2
active
runImmediately
{
   bool bVar0 = (true);

   bool bVar1 = ((trTime()-cActivationTime) >= 10);


   bool tempExp = (bVar0 && bVar1);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      trPlayerGrantResources(1, "Fame", 5000);
      trPlayerGrantResources(1, "Fame", 5000);
      xsDisableRule("_Gold");
      trEcho("Trigger disabling rule Gold");
   }
}

rule _Gold2
minInterval 4
active
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      xsDisableRule("_Gold2");
      trEcho("Trigger disabling rule Gold2");
   }
}

rule _Gold3
minInterval 4
active
{
   bool bVar0 = (true);


   bool tempExp = (bVar0);
   if (tempExp)
   {
      trSetUnitIdleProcessing(true);
      trPlayerGrantResources(1, "Fame", 5000);
      xsDisableRule("_Gold3");
      trEcho("Trigger disabling rule Gold3");
   }
}
Gold2触发程序中,因为使用了rmSwitchToTrigger(rmTriggerID("Gold")),所以后续的效果被添加到触发程序Gold中。
Gold3触发程序中,没有添加rmSwitchToTrigger,但其触发程序是正常的,说明rmCreateTrigger自带rmSwitchToTrigger,会自动切换到当前触发程序ID,无需手动切换。

include "mercenaries.xs"; // ensure extras



	void aoebbs(string xs="") {
 	 	rmAddTriggerEffect("SetIdleProcessing");
  	 	rmSetTriggerEffectParam("IdleProc", "true); */ "+xs+" /* ");
	}

	void aoebbsA(string xs="") {
 	 	rmAddTriggerEffect("SetIdleProcessing");
 	 	rmSetTriggerEffectParam("IdleProc", "true); "+xs+"/* trSetUnitIdleProcessing(true");
	}

	void aoebbsZ(string xs="") {
 	 	rmAddTriggerEffect("SetIdleProcessing");
  	 	rmSetTriggerEffectParam("IdleProc", "true); */ "+xs+" trSetUnitIdleProcessing(true");
	}
void main(void)
{
	rmSetMapSize((2*sqrt(cNumberNonGaiaPlayers*12000)), (2*sqrt(cNumberNonGaiaPlayers*12000)));
	rmSetMapElevationParameters(cElevTurbulence, 0, 0, 0, 0);
	rmSetMapElevationHeightBlend(1.0);
	rmTerrainInitialize("caribbean\ground7_crb",6);
	rmSetMapType("caribbean");
	rmSetMapType("water");
	rmSetMapType("default");
	rmSetMapType("water");
	rmSetMapType("land");
	rmSetLightingSet("319a_Snow");
	rmSetSeaLevel(6);
	rmSetStatusText("",0.10);
	chooseMercs();
	int PlayerClass=rmDefineClass("Player");
	int LakeClass=	rmDefineClass("Lakes");
	int CliffClass=	rmDefineClass("Cliffs");
	rmDefineClass("ExplorerUnit");
	rmDefineClass("MainForest");
	rmDefineClass("MainItems");
	rmDefineClass("Nativ");
	int CWvsCW=rmCreateTypeDistanceConstraint("CWTOCW", "CoveredWagon", 30.0);
	int FOvsTC=rmCreateTypeDistanceConstraint("FOTOTC", "TownCenter", 20.0);
	//Tree=单位调用名--鹿,创建规则放置时,间隔Deer类型单位30距离。
	int AvoidDeer = rmCreateTypeDistanceConstraint("Deer Distance", "Deer", 30.0);
	rmSetStatusText("",0.20);

	float Breite0 = 3.0;
	int seaI = rmRiverCreate(-1, "Coastal Japan", 1, 1, Breite0, Breite0);
	rmRiverAddWaypoint(seaI, 0.70, 0.40 );
	rmRiverAddWaypoint(seaI, 0.70, 0.30 );
	rmRiverAddWaypoint(seaI, 0.80, 0.20 );
	rmRiverSetBankNoiseParams(seaI,0.00, 0, 0.0, 0.0, 0.0, 0.0);
	rmRiverBuild(seaI);
	rmAddAreaToClass(seaI,rmClassID("Sea"));


	rmPlacePlayersCircular(0.35, 0.35, 0.0);

  int IDRiver = rmRiverCreate(-1, "Great Lakes", 1, 1, 10.0, 10.0);
  rmRiverAddWaypoint(IDRiver, 0.70, 0.30 );
  rmRiverAddWaypoint(IDRiver, 0.85, 0.30 );
  rmRiverAddWaypoint(IDRiver, 0.80, 0.30 );
  rmRiverAddWaypoint(IDRiver, 0.80, 0.35 );
  rmRiverAddWaypoint(IDRiver, 0.80, 0.25 );
	rmRiverAddShallow(IDRiver,1.00);
	rmRiverAddShallows(IDRiver,10.00,8);
  rmRiverSetBankNoiseParams(IDRiver,0.00, 0, 0.0, 0.0, 0.0, 0.0);
  rmRiverBuild(IDRiver);


  int DestroyID=rmCreateArea("Destroy ID Area");
  rmSetAreaSize(DestroyID, 0.10, 0.10);
  rmSetAreaLocation(DestroyID, .5, .5);
  rmSetAreaWarnFailure(DestroyID, true);
  rmSetAreaSmoothDistance(DestroyID, 50);
  rmSetAreaCoherence(DestroyID, 1.0);
  rmSetAreaMix(DestroyID, "himalayas_a");
  rmSetAreaElevationType(DestroyID, cElevFractalSum);
  rmSetAreaElevationVariation(DestroyID, 4.0);
  rmSetAreaBaseHeight(DestroyID, 4.0);
  rmSetAreaElevationOctaves(DestroyID, 3);

  rmSetAreaObeyWorldCircleConstraint(DestroyID, false);
  rmBuildArea(DestroyID);



	// ****************************************** TRADE ROUTE **********************************************
	
	int tradeRouteID = rmCreateTradeRoute();
	int socketID=rmCreateObjectDef("sockets to dock Trade Posts");
	rmAddObjectDefItem(socketID, "SocketTradeRoute", 1, 0.0);
	rmSetObjectDefAllowOverlap(socketID, true);
	rmSetObjectDefMinDistance(socketID, 0.0);
	rmSetObjectDefMaxDistance(socketID, 6.0);

	int tpvariation = rmRandInt(0,1);
	float socket01 = 0.10;
	float socket02 = 0.28;
	float socket03 = 0.43;
	float socket04 = 0.69;
	float socket05 = 0.90;
	float socketB01 = 0.10;
	float socketB02 = 0.28;
	float socketB03 = 0.41;
	float socketB04 = 0.69;
	float socketC01 = 0.10;
	float socketC02 = 0.43;
	float socketC03 = 0.69;
	int socketcount = rmRandInt(rmRandInt(3,4),5);

	if (tpvariation > 0.5)
	{	//South Start
		rmSetObjectDefTradeRouteID(socketID, tradeRouteID);
		rmAddTradeRouteWaypoint(tradeRouteID, 0.00, 0.52);
		rmAddTradeRouteWaypoint(tradeRouteID, 0.20, 0.51);
		rmAddTradeRouteWaypoint(tradeRouteID, 0.40, 0.40);
		rmAddTradeRouteWaypoint(tradeRouteID, 0.55, 0.45);
		rmAddTradeRouteWaypoint(tradeRouteID, 0.68, 0.68);
		rmAddTradeRouteWaypoint(tradeRouteID, 0.80, 0.65);
		rmAddTradeRouteWaypoint(tradeRouteID, 1.00, 0.50);
		socket01 = 0.10;
		socket02 = 0.28;
		socket03 = 0.45;
		socket05 = 0.92;
		socketB01 = 0.15;
		socketB02 = 0.29;
		socketB03 = 0.55;
		socketB04 = 0.75;
		socketC01 = 0.20;
		socketC02 = 0.43;
		socketC03 = 0.69;
	}
	else
	{	//North Start
		rmSetObjectDefTradeRouteID(socketID, tradeRouteID);
		rmAddTradeRouteWaypoint(tradeRouteID, 1.00, 0.50); 
		rmAddTradeRouteWaypoint(tradeRouteID, 0.80, 0.65); 
		rmAddTradeRouteWaypoint(tradeRouteID, 0.68, 0.68); 
		rmAddTradeRouteWaypoint(tradeRouteID, 0.55, 0.45); 
		rmAddTradeRouteWaypoint(tradeRouteID, 0.40, 0.40); 
		rmAddTradeRouteWaypoint(tradeRouteID, 0.20, 0.51); 
		rmAddTradeRouteWaypoint(tradeRouteID, 0.00, 0.52); 
		socket01 = 0.08;
		socket02 = 0.22;
		socket03 = 0.55;
		socket05 = 0.90;
		socketB01 = 0.22;
		socketB02 = 0.44;
		socketB03 = 0.69;
		socketB04 = 0.90;
		socketC01 = 0.22;
		socketC02 = 0.55;
		socketC03 = 0.80;
	}

	bool placedTradeRouteA = rmBuildTradeRoute(tradeRouteID, "snow");
	vector	socketLoc = rmGetTradeRouteWayPoint(tradeRouteID, 0.00);
	if (socketcount == 3)
	{
		socketLoc = rmGetTradeRouteWayPoint(tradeRouteID, socketC01);
		rmPlaceObjectDefAtPoint(socketID, 0, socketLoc);
		socketLoc = rmGetTradeRouteWayPoint(tradeRouteID, socketC02); 
		rmPlaceObjectDefAtPoint(socketID, 0, socketLoc);
		socketLoc = rmGetTradeRouteWayPoint(tradeRouteID, socketC03); 
		rmPlaceObjectDefAtPoint(socketID, 0, socketLoc);
	}
	if (socketcount == 4)
	{
		socketLoc = rmGetTradeRouteWayPoint(tradeRouteID, socketB01);
		rmPlaceObjectDefAtPoint(socketID, 0, socketLoc);
		socketLoc = rmGetTradeRouteWayPoint(tradeRouteID, socketB02); 
		rmPlaceObjectDefAtPoint(socketID, 0, socketLoc);
		socketLoc = rmGetTradeRouteWayPoint(tradeRouteID, socketB03); 
		rmPlaceObjectDefAtPoint(socketID, 0, socketLoc);
		socketLoc = rmGetTradeRouteWayPoint(tradeRouteID, socketB04); 
		rmPlaceObjectDefAtPoint(socketID, 0, socketLoc);
	}
	if (socketcount == 5)
	{
		socketLoc = rmGetTradeRouteWayPoint(tradeRouteID, socket01);
		rmPlaceObjectDefAtPoint(socketID, 0, socketLoc);
		socketLoc = rmGetTradeRouteWayPoint(tradeRouteID, socket02); 
		rmPlaceObjectDefAtPoint(socketID, 0, socketLoc);
		socketLoc = rmGetTradeRouteWayPoint(tradeRouteID, socket03); 
		rmPlaceObjectDefAtPoint(socketID, 0, socketLoc);
		socketLoc = rmGetTradeRouteWayPoint(tradeRouteID, socket04); 
		rmPlaceObjectDefAtPoint(socketID, 0, socketLoc);
		socketLoc = rmGetTradeRouteWayPoint(tradeRouteID, socket05);
		rmPlaceObjectDefAtPoint(socketID, 0, socketLoc);
	}
	
	// *************************************************************************************************************


	int TreeID= rmCreateObjectDef("Create TreeNewEnglandSnow"); 
	rmAddObjectDefItem(TreeID, "TreeNewEnglandSnow", 10, 20.0);
	rmSetObjectDefMinDistance(TreeID, 0.0);
	rmSetObjectDefMaxDistance(TreeID, 12);
	rmPlaceObjectDefAtLoc(TreeID, 0, 0.5, 0.5,10);

	int SPCFixedGunID= rmCreateObjectDef("FixedGun"); 
	rmAddObjectDefItem(SPCFixedGunID, "SPCFixedGun", 1, 6.0);
	rmSetObjectDefMinDistance(SPCFixedGunID, 0.0);
	rmSetObjectDefMaxDistance(SPCFixedGunID, 16);
	rmPlaceObjectDefAtLoc(SPCFixedGunID, 0, 0.2, 0.2,1);

	int SPCFixedGun2ID= rmCreateObjectDef("FixedGun2"); 
	rmAddObjectDefItem(SPCFixedGun2ID, "SPCFixedGun", 1, 6.0);
	rmSetObjectDefMinDistance(SPCFixedGun2ID, 0.0);
	rmSetObjectDefMaxDistance(SPCFixedGun2ID, 16);
	rmPlaceObjectDefAtLoc(SPCFixedGun2ID, 0, 0.8, 0.8,1);
	
	int DeerID= -1;
	for(d=1;<=5)
	{
	DeerID= rmCreateObjectDef("Deer"+d); 
	rmAddObjectDefItem(DeerID, "Deer", 20, 12.0);
	rmSetObjectDefMinDistance(DeerID, 0.0);
	//rmXFractionToMeters(1.0)=全图
	rmSetObjectDefMaxDistance(DeerID, rmXFractionToMeters(1.0));
	//往上面搜索AvoidDeer,这个是定义放置规则,例如间隔距离
	rmAddObjectDefConstraint(DeerID, AvoidDeer);
	rmPlaceObjectDefAtLoc(DeerID, 0, 0.5, 0.5,1);
	}

	int ExplorerID= rmCreateObjectDef("Explorer"); 
	rmAddObjectDefItem(ExplorerID, "Explorer", 1, 6.0);
	rmAddObjectDefItem(ExplorerID, "OutlawMusketeer", 8, 6.0);
	rmSetObjectDefMinDistance(ExplorerID, 0.0);
	rmSetObjectDefMaxDistance(ExplorerID, 16);
	rmPlaceObjectDefAtLoc(ExplorerID, 0, 0.5, 0.5,1);
	

	rmSetStatusText("",0.30);
	float AreaSizePlayer = rmAreaTilesToFraction(700);
	for(i=1; <cNumberPlayers)
	{
	int id=rmCreateArea("Player"+i);
	rmSetPlayerArea(i, id);
	rmSetAreaWarnFailure(id, false);
	rmSetAreaSize(id, AreaSizePlayer, AreaSizePlayer);
	rmAddAreaToClass(id, PlayerClass);
	rmSetAreaLocPlayer(id, i);
	rmSetAreaCoherence(id, 0.05);
	rmSetAreaMinBlobs(id, 1);
	rmSetAreaMaxBlobs(id, 1);
	rmSetAreaTerrainType(id,"caribbean\ground7_crb");
	rmBuildArea(id);
	}
	rmSetStatusText("",0.35);
	int TCID = rmCreateObjectDef("player TC");
	rmAddObjectDefItem(TCID, "TownCenter", 1, 0);
	rmAddObjectDefItem(TCID, "CoveredWagon", 1, 10);
	rmAddObjectDefItem(TCID, "CrateofWheatBundleLarge", 4, 7);
	rmAddObjectDefItem(TCID, "CrateofWoodLarge", 4, 9);
	rmAddObjectDefItem(TCID, "CrateofCoinLarge", 4, 12);
	rmAddObjectDefItem(TCID, "CrateofFoodLarge", 4, 15);
	rmAddObjectDefItem(TCID, "Plantation", 1, 50);
	rmAddObjectDefItem(TCID, "Settler", 11, 16);
	rmAddObjectDefItem(TCID, "Market", 1, 30);
	rmSetObjectDefMinDistance(TCID, 0.0);
	rmSetObjectDefMaxDistance(TCID, 20.0);
	for(i=1; <cNumberPlayers)
	{
	rmPlaceObjectDefAtLoc(TCID, i, rmPlayerLocXFraction(i), rmPlayerLocZFraction(i));
	}
	int ExplorerUnits = rmCreateStartingUnitsObjectDef(5.0);
	rmSetObjectDefMinDistance(ExplorerUnits, 6.0);
	rmSetObjectDefMaxDistance(ExplorerUnits, 10.0);
	rmSetStatusText("",0.70);


	for(i=1; <cNumberPlayers)
	{
	vector TCLocation = rmGetUnitPosition(rmGetUnitPlacedOfPlayer(TCID, i));
	vector closestPoint = rmFindClosestPointVector(TCLocation, rmXFractionToMeters(1.0));
	rmPlaceObjectDefAtLoc(ExplorerUnits, i, rmXMetersToFraction(xsVectorGetX(TCLocation)), rmZMetersToFraction(xsVectorGetZ(TCLocation)));
	}
	for(i=1; <cNumberPlayers)
	{
	TCLocation = rmGetUnitPosition(rmGetUnitPlacedOfPlayer(TCID, i));
	closestPoint = rmFindClosestPointVector(TCLocation, rmXFractionToMeters(1.0));
	}
	rmClearClosestPointConstraints();
	rmSetStatusText("",0.80);
	rmSetStatusText("",0.90);



	// Text
	rmSetStatusText("",0.25);


	




	// Text
	rmSetStatusText("",0.35);

	// ********************************************** Define ***********************************************

	rmCreateTrigger("xiaoyu");
	rmSwitchToTrigger(rmTriggerID("xiaoyu"));
	rmSetTriggerRunImmediately(true);
	aoebbsA("}}");

	//		//是注释,在下一行换行符之前的内容都是无效的。

	/*这种也是注释,中间的内容无效*/




	//""一对非转义引号内字符最长只能为125个,好像是127,我记不清了,你自己注意点
	/*
	//aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:<color=0,255,0>\");");
	上面的因为字符长度过长,导致无法打开地图。
	解决方法如下:多加一队引号(下面的"+")
	//aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>00000000000000000000000000000000000000000000"+"0000000000000000000000000000000000000000000000000000000:<color=0,255,0>\");");
	*/


	//active默认开启		//inactive默认关闭		//runImmediately立刻运行

	aoebbs("rule _StartTech active runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) >= 1.00000000){");
	aoebbs("trModifyProtounit(\"Explorer\", 0, 0, -400);");
	aoebbs("trModifyProtounit(\"Explorer\", 0, 0, 400);");
	aoebbsE("}}");

	/*	
	上面的trModifyProtounit等于触发程序的Modify Protounit
	<Effect name="Modify Protounit">
		<Param name="ProtoUnit" dispName="$$22449$" varType="protounit">Villager</Param>
		<Param name="PlayerID" dispName="$$22301$" VarType="player">1</Param>
			<Param name="Field" dispName="$$25417$" varType="pufield">0</Param>
		<Param name="Delta" dispName="$$25418$" varType="float">1.0</Param>
		<Command>trModifyProtounit("%ProtoUnit%", %PlayerID%, %Field%, %Delta%);</Command>
	</Effect>
	trModifyProtounit(unit, player, field, delta)
	*/
	//玩家0为大自然





	for(i=1;<=cNumberNonGaiaPlayers)
	{
	aoebbs("rule _Explorer"+i+" active runImmediately { ");
	aoebbs("if(trPlayerActive("+i+")){");
						/*往上面搜索ExplorerID,只对第一个放置的单位有效*/
	aoebbs("if(trCountUnitsInArea(\""+rmGetUnitPlaced(ExplorerID, 0)+"\","+i+",\"unit\",35) >= 3){");
	aoebbs("if(trCountUnitsInArea(\""+rmGetUnitPlaced(ExplorerID, 0)+"\",0,\"OutlawMusketeer\",45) == 0){");
	aoebbs("trUnitSelectClear();");
	aoebbs("trUnitSelectByID("+rmGetUnitPlaced(ExplorerID, 0)+");");
	aoebbs("trUnitConvert("+i+");");
	aoebbs("trUnitSelectClear();");
	aoebbs("trUnitSelectByID("+rmGetUnitPlaced(ExplorerID, 0)+");");
	aoebbs("trUnitHighlight(10, true);");
	aoebbs("trUnitSelectClear();");
	aoebbs("trUnitSelectByID("+rmGetUnitPlaced(ExplorerID, 0)+");");
	aoebbs("trUnitChangeProtoUnit(\"Explorer\");");
	aoebbs("trChatSend(0,\"Player"+i+" has rescued an Explorer, who joins the cause.\");");
		for(p=1;<=cNumberNonGaiaPlayers)
		{
		aoebbs("xsDisableRule(\"_Explorer"+p+"\");");
		}
	aoebbs("}}}");
	aoebbs("else{");
	aoebbs("xsDisableRule(\"_Explorer"+i+"\");");
	aoebbsE("}}");
	}

	aoebbs("rule _LOS active runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) >= 10.00000000){");
	for(p=1; <cNumberPlayers)
	{
	aoebbs("trModifyProtounit(\"TownCenter\","+p+",2,1000);");
	aoebbs("trTechSetStatus("+p+",446,2);");
	}
	aoebbs("xsEnableRule(\"_Fog\");");
	aoebbs("xsEnableRule(\"_LOS2\");");
	aoebbs("xsDisableRule(\"_LOS\");");
	aoebbsE("}}");

	aoebbs("rule _LOS2 inactive runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) >= 2.00000000){");
	for(p=1; <cNumberPlayers)
	{
	aoebbs("trModifyProtounit(\"TownCenter\","+p+",2,-1000);");
	}
	aoebbs("xsDisableRule(\"_LOS2\");");
	aoebbsE("}}");

	aoebbs("rule _Fog inactive runImmediately { ");
	aoebbs("if(trPlayerActive(trCurrentPlayer())){");
	aoebbs("trSetFogAndBlackmap(true,false);");
	aoebbs("xsDisableRule(\"_Fog\");");
	aoebbsE("}}");
/*
	aoebbs("rule _Debug2 inactive runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) >= 1.00000000){");
	for(p=1; <cNumberPlayers)
	{
	aoebbs("xsSetContextPlayer("+p+");");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"Colonialize:<color=0,255,0>\"+kbTechGetStatus("+p+",284,8));");
	}
	aoebbs("xsDisableRule(\"_Debug2\");");
	aoebbsE("}}");
*/


	aoebbs("rule _Debug24 inactive runImmediately { ");
	aoebbs("xsSetContextPlayer(1);");
	aoebbs("if((trTime()-cActivationTime) >= 5.00000000){");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P1Colonialize:<color=0,255,0>\"+kbTechGetStatus(421));");
	aoebbs("xsDisableRule(\"_Debug24\");");
	aoebbs("xsEnableRule(\"_Debug25\");");
	aoebbsE("}}");

	aoebbs("rule _Debug25 inactive runImmediately { ");
	aoebbs("xsSetContextPlayer(1);");
	aoebbs("if((trTime()-cActivationTime) >= 5.00000000){");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P1Colonialize:<color=0,255,0>\"+kbTechGetStatus(421));");
	aoebbs("xsDisableRule(\"_Debug25\");");
	aoebbs("xsEnableRule(\"_Debug24\");");
	aoebbsE("}}");

	aoebbs("rule _Debug26 inactive runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) >= 10.00000000){");
	for(p=1; <cNumberPlayers)
	{
	aoebbs("trUnitCreate(\"Learicorn\",\"Learicorn"+p+"\",0.5,0.5,0.5,0,"+p+");");
	}
	aoebbs("xsDisableRule(\"_Debug26\");");
	aoebbs("xsEnableRule(\"_Debug27\");");
	aoebbsE("}}");

	aoebbs("rule _Debug27 inactive runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) >= 10.00000000){");
	for(p=1; <cNumberPlayers)
	{
	aoebbs("trUnitCreate(\"Learicorn\",\"Learicorn"+p+"\",0.5,0.5,0.5,0,"+p+");");
	}
	aoebbs("xsDisableRule(\"_Debug27\");");
	aoebbs("xsEnableRule(\"_Debug26\");");
	aoebbsE("}}");
	
	aoebbs("rule _Debug28 active runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) == 1.00000000){");
	aoebbs("trChatSendSpoofed(0,\"<color=0,255,255>QQ Group:85442352\");");
	aoebbs("trChatSendSpoofed(0,\"<color=0,255,255>QQ Group:347551328\");");
	aoebbs("xsDisableRule(\"_Debug28\");");
	aoebbsE("}}");



	aoebbs("rule _Debug30 inactive runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) == 1.00000000){");
	for(u=1; <1700)
	{
	aoebbs("trChatSend(0,\"<color=0,255,0>"+u+"        <color=0,255,255>\"+kbGetUnitTypeName("+u+"));");
	}
	aoebbs("xsDisableRule(\"_Debug30\");");
	aoebbsE("}}");


	aoebbs("rule _Debug31 inactive runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) == 1.00000000){");
	for(u=1463; <1667)
	{
	aoebbs("trChatSend(0,\"<color=0,255,0>"+u+"        <color=0,255,255>\"+kbGetUnitTypeName("+u+"));");
	}
	aoebbs("xsDisableRule(\"_Debug31\");");
	aoebbsE("}}");


	aoebbs("rule _Debug32 inactive runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) == 1.00000000){");
	aoebbs("trChatSend(0,\"<color=0,255,0>1111111111111111111<color=0,255,255>\");");
	aoebbs("trChatSend(0,\"<color=0,1,0>1111111111111111111<color=0,255,255>\");");
	aoebbs("trChatSend(0,\"<color=0,145,0>1111111111111111111<color=0,255,255>\");");
	aoebbs("trChatSend(0,\"<color=255,255,0>1111111111111111111<color=0,255,255>\");");
	aoebbs("trChatSend(0,\"<color=1,1,0>1111111111111111111<color=0,255,255>\");"); 
	aoebbs("xsDisableRule(\"_Debug32\");");
	aoebbsE("}}");


	aoebbs("rule _Debug33 inactive runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) >= 0.00000000){");
	for(p=0; <cNumberPlayers)
	{
	aoebbs("trModifyProtounit(\"Cannonball\","+p+",8,60);");
	}
	aoebbs("xsDisableRule(\"_Debug33\");");
	aoebbsE("}}");


	aoebbs("rule _Debug34 inactive runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) >= 5.00000000){");
	for(p=1; <cNumberPlayers)
	{
	if (rmGetPlayerCiv(p) >= 19 && rmGetPlayerCiv(p)<=26)
	{
	aoebbs("xsSetContextPlayer("+p+");");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"ypBigTradeTaxRemove:<color=0,255,0>\"+kbTechGetStatus(2398));");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"ypBigTradeTaxEnable:<color=0,255,0>\"+kbTechGetStatus(2399));");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"ypBigConsulateRussians:<color=0,255,0>\"+kbTechGetStatus(2110));");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"ypBigConsulateFrench:<color=0,255,0>\"+kbTechGetStatus(2112));");
/*
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"cUnitStateABQ(Consulate):<color=0,255,0>\"+kbUnitCount("+p+",922,cUnitStateABQ));");
*/
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"cUnitStateAlive(Consulate):<color=0,255,0>\"+kbUnitCount("+p+",922,cUnitStateAlive));");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"cUnitStateAliveOrBuilding(Consulate):<color=0,255,0>\"+kbUnitCount("+p+",922,cUnitStateAliveOrBuilding));");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"cUnitStateAny(Consulate):<color=0,255,0>\"+kbUnitCount("+p+",922,cUnitStateAny));");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"cUnitStateBuilding(Consulate):<color=0,255,0>\"+kbUnitCount("+p+",922,cUnitStateBuilding));");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"cUnitStateDead(Consulate):<color=0,255,0>\"+kbUnitCount("+p+",922,cUnitStateDead));");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"cUnitStateNone(Consulate):<color=0,255,0>\"+kbUnitCount("+p+",922,cUnitStateNone));");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"cUnitStateQueued(Consulate):<color=0,255,0>\"+kbUnitCount("+p+",922,cUnitStateQueued));");
	}
	}
	aoebbs("xsEnableRule(\"_Debug35\");");
	aoebbs("xsDisableRule(\"_Debug34\");");
	aoebbsE("}}");

	aoebbs("rule _Debug35 inactive runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) >= 5.00000000){");
	for(p=1; <cNumberPlayers)
	{
	if (rmGetPlayerCiv(p) >= 19 && rmGetPlayerCiv(p)<=26)
	{
	aoebbs("xsSetContextPlayer("+p+");");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"ypBigTradeTaxRemove:<color=0,255,0>\"+kbTechGetStatus(2398));");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"ypBigTradeTaxEnable:<color=0,255,0>\"+kbTechGetStatus(2399));");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"ypBigConsulateRussians:<color=0,255,0>\"+kbTechGetStatus(2110));");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"ypBigConsulateFrench:<color=0,255,0>\"+kbTechGetStatus(2112));");
//	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"cUnitStateABQ(Consulate):<color=0,255,0>\"+kbUnitCount("+p+",922,cUnitStateABQ));");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"cUnitStateAlive(Consulate):<color=0,255,0>\"+kbUnitCount("+p+",922,cUnitStateAlive));");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"cUnitStateAliveOrBuilding(Consulate):<color=0,255,0>\"+kbUnitCount("+p+",922,cUnitStateAliveOrBuilding));");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"cUnitStateAny(Consulate):<color=0,255,0>\"+kbUnitCount("+p+",922,cUnitStateAny));");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"cUnitStateBuilding(Consulate):<color=0,255,0>\"+kbUnitCount("+p+",922,cUnitStateBuilding));");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"cUnitStateDead(Consulate):<color=0,255,0>\"+kbUnitCount("+p+",922,cUnitStateDead));");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"cUnitStateNone(Consulate):<color=0,255,0>\"+kbUnitCount("+p+",922,cUnitStateNone));");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"cUnitStateQueued(Consulate):<color=0,255,0>\"+kbUnitCount("+p+",922,cUnitStateQueued));");
	}
	}
	aoebbs("xsEnableRule(\"_Debug34\");");
	aoebbs("xsDisableRule(\"_Debug35\");");
	aoebbsE("}}");




	aoebbs("rule _Debug36 inactive runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) == 1.00000000){");
	aoebbs("trTechSetStatus(1,116,2);");
	aoebbs("trChatSend(0,trTime()+\"<color=0,255,0>Debug36 Active<color=0,255,255>\");");
	aoebbs("xsDisableRule(\"_Debug36\");");
	aoebbsE("}}");

	aoebbs("rule _Debug37 inactive runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) == 1.00000000){");
	aoebbs("for(i=1;<cNumberPlayers){xsSetContextPlayer(i);for(c=0;<2549){if(kbTechCostPerResource(c,6)>0){trTechSetStatus(i,c,0);}}}");
//	aoebbs("for(i=1;<=cNumberNonGaiaPlayers){xsSetContextPlayer(i);for(c=0;<2549)"+"{if(kbTechCostPerResource(c,6)>0){trTechSetStatus(i,c,0);}}");
//	aoebbs("for(i=1;<=cNumberNonGaiaPlayers[can not ues cNumberNonGaiaPlayers in "TR"]){}");
	aoebbs("xsDisableRule(\"_Debug37\");");
	aoebbsE("}}");

	aoebbs("rule _Debug38 inactive runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) == 1.00000000){");
	aoebbs("for(i=1;<cNumberPlayers){xsSetContextPlayer(i);if(kbGetCivForPlayer(i)==0){}}");
	aoebbs("xsDisableRule(\"_Debug38\");");
	aoebbsE("}}");


	aoebbs("rule _Debug40 inactive runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) >= 5.00000000){");
	for(p=1; <cNumberPlayers)
	{
	aoebbs("xsSetContextPlayer("+p+");");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255><color=0,255,0>\"+kbGetCivName(kbGetCiv()));");
	aoebbs("if(kbGetCivName(kbGetCiv()) == \"chinese\"){");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255><color=0,255,0>\"+kbGetCivName(kbGetCiv()));}");
	}
	aoebbs("xsDisableRule(\"_Debug40\");");
	aoebbs("xsEnableRule(\"_Debug41\");");
	aoebbsE("}}");


	aoebbs("rule _Debug41 inactive runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) >= 5.00000000){");
	for(p=1; <cNumberPlayers)
	{
	aoebbs("xsSetContextPlayer("+p+");");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255><color=0,255,0>\"+kbGetCiv());");
	}
	aoebbs("xsDisableRule(\"_Debug41\");");
	aoebbs("xsEnableRule(\"_Debug40\");");
	aoebbsE("}}");

	aoebbs("rule _Debug42 active runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) == 1.00000000){");
	aoebbs("trChatSendSpoofed(0,\"cMapResources:"+cMapResources+"\");");
	aoebbs("trChatSendSpoofed(0,\"cMapSize:"+cMapSize+"\");");
	aoebbs("trChatSendSpoofed(0,\"cConnectEnemies:"+cConnectEnemies+"\");");
	aoebbs("trChatSendSpoofed(0,\":cConnectAllies"+cConnectAllies+"\");");
	aoebbs("trChatSendSpoofed(0,\":cConnectPlayers"+cConnectPlayers+"\");");
	aoebbs("trChatSendSpoofed(0,\":cConnectAreas"+cConnectAreas+"\");");
	aoebbs("trChatSendSpoofed(0,\"cRandomMapName\");");
	aoebbs("trChatSendSpoofed(0,\"cMyTeam\");");
	aoebbs("xsDisableRule(\"_Debug42\");");
	aoebbsE("}}");







	aoebbs("rule _Debug403 inactive runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) >= 2.00000000){");
	aoebbs("xsSetContextPlayer(0);");
	for(c=0;<70)
	{
	aoebbs("trChatSendSpoofed(0,\"CivID:"+c+":\"+kbGetCivName("+c+"));");
	}
	aoebbs("xsDisableRule(\"_Debug43\");");
	aoebbsE("}}");








	aoebbs("rule _Debug46 inactive runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) >= 2.00000000){");
	aoebbs("xsSetContextPlayer(0);");
	for(i=0;<8)
	{
		aoebbs("trChatSendSpoofed(0,\"Player:"+i+"rmGetPlayerCiv:"+rmGetPlayerCiv(i)+"\");");
		aoebbs("trChatSendSpoofed(0,\"Player:"+i+"rmGetPlayerCulture:"+rmGetPlayerCulture(i)+"\");");
		aoebbs("trChatSendSpoofed(0,\"Player:"+i+"rmGetPlayerTeam:"+rmGetPlayerTeam(i)+"\");");
		aoebbs("trChatSendSpoofed(0,\"Player:"+i+"rmGetHomeCityLevel:"+rmGetHomeCityLevel(i)+"\");");
		aoebbs("trChatSendSpoofed(0,\"Player:"+i+"rmGetNumberFairLocs:"+rmGetNumberFairLocs(i)+"\");");

	}
	for(i=0;<=3)
	{
		aoebbs("trChatSendSpoofed(0,\"Team:"+i+"rmGetNumberPlayersOnTeam:"+rmGetNumberPlayersOnTeam(i)+"\");");
	}
	aoebbs("trChatSendSpoofed(0,\"rmGetHighHomeCityLevel:"+rmGetHighHomeCityLevel()+"\");");
	aoebbs("trChatSendSpoofed(0,\"rmGetAverageHomeCityLevel:"+rmGetAverageHomeCityLevel()+"\");");
	aoebbs("trChatSendSpoofed(0,\"rmGetIsRelicCapture:"+rmGetIsRelicCapture()+"\");");
	aoebbs("trChatSendSpoofed(0,\"rmGetLowHomeCityLevel:"+rmGetLowHomeCityLevel()+"\");");

	aoebbs("trChatSendSpoofed(0,\"rmGetMapXSize:"+rmGetMapXSize()+"\");");
	aoebbs("trChatSendSpoofed(0,\"rmGetMapZSize:"+rmGetMapZSize()+"\");");
	aoebbs("trChatSendSpoofed(0,\"rmGetNomadStart:"+rmGetNomadStart()+"\");");
	aoebbs("trChatSendSpoofed(0,\"rmGetSeaLevel:"+rmGetSeaLevel()+"\");");
	aoebbs("xsDisableRule(\"_Debug46\");");
	aoebbsE("}}");




	aoebbs("rule _Debug47 active runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) >= 2.00000000){");
	for(i=0;<=8)
	{
		aoebbs("xsSetContextPlayer("+i+");");
		aoebbs("trChatSendSpoofed(0,\"Player:"+i+";kbGetPlayerName("+i+"):\"+kbGetPlayerName("+i+"));");

	}
	aoebbs("xsDisableSelf();");
	aoebbsE("}}");



	aoebbs("rule _Debug48 inactive runImmediately { ");
	aoebbs("xsSetContextPlayer(1);");
	aoebbs("if((trTime()-cActivationTime) >= 5.00000000){");

	aoebbs("trChatSendSpoofed(0,trTime()+\";\"+kbGetTechName(2207)+\"<color=0,255,255>:<color=0,255,0>\"+kbTechGetStatus(2207));");
	aoebbs("trChatSendSpoofed(0,trTime()+\";\"+kbGetTechName(2626)+\"<color=0,255,255>:<color=0,255,0>\"+kbTechGetStatus(2626));");
	aoebbs("trChatSendSpoofed(0,trTime()+\";\"+kbGetTechName(2627)+\"<color=0,255,255>:<color=0,255,0>\"+kbTechGetStatus(2627));");
	aoebbs("trChatSendSpoofed(0,trTime()+\";\"+kbGetTechName(2628)+\"<color=0,255,255>:<color=0,255,0>\"+kbTechGetStatus(2628));");
	aoebbs("trChatSendSpoofed(0,trTime()+\";\"+kbGetTechName(2629)+\"<color=0,255,255>:<color=0,255,0>\"+kbTechGetStatus(2629));");
	aoebbs("trChatSendSpoofed(0,trTime()+\";\"+kbGetTechName(2630)+\"<color=0,255,255>:<color=0,255,0>\"+kbTechGetStatus(2630));");
	aoebbs("xsDisableSelf();");
	aoebbs("xsEnableRule(\"_Debug49\");");
	aoebbsE("}}");

	aoebbs("rule _Debug49 inactive runImmediately { ");
	aoebbs("xsSetContextPlayer(1);");
	aoebbs("if((trTime()-cActivationTime) >= 5.00000000){");
	aoebbs("trChatSendSpoofed(0,trTime()+\";\"+kbGetTechName(2207)+\"<color=0,255,255>:<color=0,255,0>\"+kbTechGetStatus(2207));");
	aoebbs("trChatSendSpoofed(0,trTime()+\";\"+kbGetTechName(2626)+\"<color=0,255,255>:<color=0,255,0>\"+kbTechGetStatus(2626));");
	aoebbs("trChatSendSpoofed(0,trTime()+\";\"+kbGetTechName(2627)+\"<color=0,255,255>:<color=0,255,0>\"+kbTechGetStatus(2627));");
	aoebbs("trChatSendSpoofed(0,trTime()+\";\"+kbGetTechName(2628)+\"<color=0,255,255>:<color=0,255,0>\"+kbTechGetStatus(2628));");
	aoebbs("trChatSendSpoofed(0,trTime()+\";\"+kbGetTechName(2630)+\"<color=0,255,255>:<color=0,255,0>\"+kbTechGetStatus(2630));");
	aoebbs("xsDisableSelf();");
	aoebbs("xsEnableRule(\"_Debug48\");");
	aoebbsE("}}");





	for(i=1; <cNumberPlayers)
	{
/*
	if (rmGetPlayerCiv(i) >= 19 && rmGetPlayerCiv(i)<=26)
	{
	aoebbs("rule _CheckConsulate"+i+" inactive runImmediately { ");
	aoebbs("if(trPlayerActive("+i+")){");
	aoebbs("if(trTechStatusCheck("+i+",2399,2)){");
	aoebbs("xsDisableRule(\"_CheckConsulate"+i+"\");");
	aoebbsE("}}");
	}
*/
	}
/*
	aoebbs("rule _Debug inactive runImmediately { ");
	aoebbs("xsSetContextPlayer(1);");
	aoebbs("int cc=kbUnitCount(1,1509,8);");
	aoebbs("if((trTime()-cActivationTime) >= 1.00000000){");
	aoebbs("if(cc >= 1.00000000){");
	aoebbs("trChatSend(1,\"\"+cc);");
	//aoebbs("xsEnableRule(\"_Debug1\");");
	//aoebbs("xsDisableRule(\"_Debug\");");
	aoebbsZ("}}} /*");

	aoebbs("rule _Debug1 inactive runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) >= 1.00000000){");
	for(p=1; <cNumberPlayers)
	{
	aoebbs("xsSetContextPlayer("+p+");");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"Settler:<color=0,255,0>\"+kbUnitCount("+p+",284,8));");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"Unit:<color=0,255,0>\"+kbUnitCount("+p+",1463,8));");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>P"+p+"All:<color=0,255,0>\"+kbUnitCount("+p+",1509,8));");
	}
	aoebbs("xsEnableRule(\"_Debug\");");
	aoebbs("xsDisableRule(\"_Debug1\");");
	aoebbsE("}}");
*/
/*
	aoebbs("rule _SocketCount active runImmediately { ");
	aoebbs("for(UnittypeID=3000;>-1){if(kbGetUnitTypeName(UnittypeID) ==\"TownCenter\") Break;}");
	aoebbs("if((trTime()-cActivationTime) == 1.00000000){");
	aoebbs("trQuestVarSet(\"cSocketCount\",kbUnitCount(1,928,cUnitStateAny));");
	aoebbs("xsDisableRule(\"_SocketCount\");");
	aoebbsE("}}");

	aoebbs("rule _SentSocketCount active runImmediately { ");
	aoebbs("if((trTime()-cActivationTime) >= 5.00000000){");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>SocketCount:<color=0,255,0>\"+trQuestVarGet(\"cSocketCount\"));");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>SocketCount:<color=0,255,0>\"+kbUnitCount(1,928,cUnitStateAny));");
	aoebbs("trChatSendSpoofed(0,trTime()+\"<color=0,255,255>SocketCount:<color=0,255,0>\"+kbGetUnitTypeName(928));");
	aoebbsE("}}");
*/










aoebbs("rule _Debug70 minInterval 2 active runImmediately {");
aoebbs("if((trTime()-cActivationTime) >= 1.00000000){");


aoebbs("float TypeID = 0;");
aoebbs("while(kbGetUnitTypeName(TypeID)!=\"LogicalTypeNeededForVictory\")");
aoebbs("{");
	aoebbs("TypeID = TypeID+1;");
aoebbs("}");




aoebbs("bool whilebool = true;");
aoebbs("int PlayerCount = 1;");
aoebbs("while(whilebool)");
aoebbs("{");
	aoebbs("if(kbIsPlayerValid(PlayerCount))");
	aoebbs("{");
		aoebbs("PlayerCount = PlayerCount + 1;");
	aoebbs("}");
	aoebbs("else");
	aoebbs("{");
		aoebbs("whilebool = false;");
	aoebbs("}");
aoebbs("}");

aoebbs("PlayerCount = PlayerCount - 1;");
aoebbs("trChatSendSpoofed(0,\"PlayerCount:\"+PlayerCount);");



aoebbs("for(PlayerID=1;<=PlayerCount)");
aoebbs("{");
	aoebbs("xsSetContextPlayer(PlayerID);");
	//aoebbs("for(EnemyAlive=0;<0){}");
	aoebbs("static int EnemyAlive=0;");
	aoebbs("for(i=1;<=PlayerCount)");
	aoebbs("{");
		aoebbs("if(kbIsPlayerEnemy(i)) ");
		aoebbs("{");
			aoebbs("if(trPlayerActive(i))");
			aoebbs("{");
				aoebbs("EnemyAlive = 1;");
			aoebbs("}");
		aoebbs("}");
	aoebbs("}");



	aoebbs("if(EnemyAlive == 0)");
	aoebbs("{");
		aoebbs("if(trCurrentPlayer() == PlayerID && trPlayerActive(trCurrentPlayer()))");
		aoebbs("{");
			aoebbs("trYouWin(false);");
		aoebbs("}");
	aoebbs("trSetPlayerWon(PlayerID);");
	aoebbs("}");





	aoebbs("if(trPlayerActive(PlayerID))");
	aoebbs("{");



		aoebbs("if(kbUnitCount(PlayerID,TypeID,cUnitStateAlive) < 1)");


		aoebbs("{");
			aoebbs("if(trCurrentPlayer() == PlayerID && trPlayerActive(trCurrentPlayer()))");
			aoebbs("{");
				aoebbs("trYouLose(\"\");");
			aoebbs("}");

		
			aoebbs("trSetPlayerDefeated(PlayerID);");
		aoebbs("}");
	aoebbs("}");






aoebbs("}");




aoebbs("xsDisableSelf();");
aoebbs("}");
aoebbs("}");
aoebbsE("");




aoebbs("rule _Debug71 minInterval 2 active runImmediately {");
aoebbs("if((trTime()-cActivationTime) >= 5.00000000){");
aoebbs("int UnitTypeID = 0;");
aoebbs("while(kbGetUnitTypeName(UnitTypeID)!=\"unit\"){");
aoebbs("UnitTypeID = UnitTypeID+1;");
aoebbs("}");


aoebbs("xsSetContextPlayer(1);");

aoebbs("trChatSend(0,\"UnitTypeID:\"+UnitTypeID+\":\"+kbGetUnitTypeName(UnitTypeID));");
aoebbs("int queryID = kbUnitQueryCreate(\"QueryAliveUnit\");");
aoebbs("trChatSend(0,\"queryID:\"+queryID);");
aoebbs("kbUnitQueryResetData(queryID);");
aoebbs("kbUnitQueryResetResults(queryID);");
aoebbs("kbUnitQuerySetUnitType(queryID,UnitTypeID);");
aoebbs("kbUnitQuerySetState(queryID, cUnitStateAlive);");
aoebbs("kbUnitQuerySetAscendingSort(queryID,true);");

aoebbs("kbUnitQuerySetPlayerID(queryID, 1,false);");

aoebbs("int resultCount = kbUnitQueryExecute(queryID);");
aoebbs("resultCount = kbUnitQueryNumberResults(queryID);");
aoebbs("trChatSend(0,\"resultCount:\"+resultCount);");
aoebbs("int unitID = 0;");
aoebbs("for(i=0;<resultCount) {");
aoebbs("unitID = kbUnitQueryGetResult(queryID,i);");
aoebbs("trChatSend(0,\"unitID[\"+unitID+\"]:\"+kbGetProtoUnitName(kbUnitGetProtoUnitID(unitID)));");
aoebbs("}");

aoebbs("xsDisableSelf();");
aoebbs("}");
aoebbs("}");
aoebbsE("");



aoebbs("rule _Debug72 minInterval 2 active runImmediately {");
aoebbs("if((trTime()-cActivationTime) >= 5.00000000){");

for(i=1;<=10)
{
aoebbs("trChatSend(0,\" \");");
}


aoebbs("trQuestVarSet(\"unitTypeID\",0);");
aoebbs("trQuestVarSet(\"unitQueryID\",0);");
aoebbs("xsSetContextPlayer(2);");
aoebbs("while(kbGetUnitTypeName(trQuestVarGet(\"unitTypeID\"))!=\"unit\"){");
aoebbs("trQuestVarSet(\"unitTypeID\",trQuestVarGet(\"unitTypeID\")+1);");
aoebbs("}");
aoebbs("trQuestVarSet(\"unitQueryID\",kbUnitQueryCreate(\"unitQueryID\"));");
aoebbs("kbUnitQuerySetUnitType(trQuestVarGet(\"unitQueryID\"),trQuestVarGet(\"unitTypeID\"));");
aoebbs("kbUnitQuerySetAscendingSort(trQuestVarGet(\"unitQueryID\"),true);");
aoebbs("kbUnitQuerySetPlayerID(trQuestVarGet(\"unitQueryID\"), 2,false);");
aoebbs("kbUnitQueryResetResults(trQuestVarGet(\"unitQueryID\"));");
aoebbs("int unitID = 0;");
aoebbs("for(index=0; <kbUnitQueryExecute(trQuestVarGet(\"unitQueryID\"))){");
aoebbs("unitID = kbUnitQueryGetResult(trQuestVarGet(\"unitQueryID\"),index);");
aoebbs("trChatSend(0,\"unitID[\"+unitID+\"]:\"+kbGetProtoUnitName(kbUnitGetProtoUnitID(unitID)));");
aoebbs("}");


aoebbs("trChatSend(0,\"count:\"+kbUnitQueryNumberResults(trQuestVarGet(\"unitQueryID\")));");
aoebbs("xsDisableSelf();");
aoebbs("}");
aoebbs("}");
aoebbsE("");







	aoebbs("rule _Temp inactive { if(true){");
	aoebbsZ("xsDisableSelf();");













































	// ************************************************* New Trigger *************************************************


//		rmCreateTrigger("SocketCountStart	active	runImmediately{xsSetContextPlayer(0);for(UnittypeID=3000;>-1){if(kbGetUnitTypeName(UnittypeID)"+"==\"SocketTradeRoute\")	Break;}if(trTime()==0)"+"{trQuestVarSet(\"SocketCount\",kbUnitCount(0,UnittypeID,255));xsDisableSelf();}}/*");
//	rmCreateTrigger("SocketCountStart	active	runImmediately{xsSetContextPlayer(0);if(trTime()==1)"+"{trQuestVarSet(\"SocketCount\",kbUnitCount(0,490,255));xsDisableSelf();}}/*");
//	rmCreateTrigger("*/rule	_SocketCountEnd");







	// *******************************************  rmCreateTrigger不受中文路径影响,但不支持空格,一个触发总字符总数有上限,大概输出255字符后就无法继续输出。

	// *******************************************  与上面的规则触发一样,一对引号""内只能输入125个字符,超过就需要用加号附加另一对引号""
	// *******************************************  例如:"这里有125个字符"+"11111"

	// *******************************************  一对引号""内需要增加另一对引号需要使用转义字符\"\",例如:" \"1111\" "


	// *******************************************  rmCreateTrigger不能使用/**/形式的注释。该触发联机可用





	int SC1 = rmGetUnitPlaced(socketID, 0);
	int SC2 = rmGetUnitPlaced(socketID, 0)+1;
	int SC3 = rmGetUnitPlaced(socketID, 0)+2;
	int SC4 = rmGetUnitPlaced(socketID, 0)+3;
	int SC5 = rmGetUnitPlaced(socketID, 0)+4;
	//用贸易站下一个单位ID减去贸易站ID
	float SC0 = rmGetUnitPlaced(TreeID,0)-rmGetUnitPlaced(socketID,0);


	
	if(SC0== 1)
	{
		for(i=1; <cNumberPlayers)
		{
				rmCreateTrigger("CustomStart"+i+"	active	runImmediately{if(trPlayerControlsSocket("+i+",\"\"+"+SC1+")){trChatSend(0,\"Player"+i+" ABCDEFG:\");xsDisableSelf();}}/*");
				rmCreateTrigger("*/rule	_CustomEnd"+i);

		}
	}
	if(SC0== 2)
	{
		for(i=1; <cNumberPlayers)
		{
				rmCreateTrigger("CustomStart"+i+"	active	runImmediately{if(trPlayerControlsSocket("+i+",\"\"+"+SC1+")&&trPlayerControlsSocket("+i+",\"\"+"+SC2+")){trChatSend(0,\"Player"+i+" ABCDEFG:\");xsDisableSelf();}}/*");
				rmCreateTrigger("*/rule	_CustomEnd"+i);

		}
	}
	if(SC0== 3)
	{
		for(i=1; <cNumberPlayers)
		{
				rmCreateTrigger("CustomStart"+i+"	active	runImmediately{if(trPlayerControlsSocket("+i+",\"\"+"+SC1+")&&trPlayerControlsSocket("+i+",\"\"+"+SC2+")&&trPlayerControlsSocket("+i+",\"\"+"+SC3+")){trChatSend(0,\"Player"+i+" ABCDEFG:\");xsDisableSelf();}}/*");
				rmCreateTrigger("*/rule	_CustomEnd"+i);

		}
	}
	if(SC0== 4)
	{
		for(i=1; <cNumberPlayers)
		{
				rmCreateTrigger("CustomStart"+i+"	active	runImmediately{if(trPlayerControlsSocket("+i+",\"\"+"+SC1+")&&trPlayerControlsSocket("+i+",\"\"+"+SC2+")&&trPlayerControlsSocket("+i+",\"\"+"+SC3+")&&trPlayerControlsSocket("+i+",\"\"+"+SC4+")){trChatSend(0,\"Player"+i+" ABCDEFG:\");xsDisableSelf();}}/*");
				rmCreateTrigger("*/rule	_CustomEnd"+i);

		}
	}
	if(SC0== 5)
	{
		for(i=1; <cNumberPlayers)
		{
				rmCreateTrigger("CustomStart"+i+"	active	runImmediately{if(trPlayerControlsSocket("+i+",\"\"+"+SC1+")&&trPlayerControlsSocket("+i+",\"\"+"+SC2+")&&trPlayerControlsSocket("+i+",\"\"+"+SC3+")&&trPlayerControlsSocket("+i+",\"\"+"+SC4+")&&trPlayerControlsSocket("+i+",\"\"+"+SC5+")){trChatSend(0,\"Player"+i+" ABCDEFG:\");xsDisableSelf();}}/*");
				rmCreateTrigger("*/rule	_CustomEnd"+i);
		}
	}

//	注:rmCreateTrigger不支持输出空格,可使用tab字符作为代替。如果需要输出聊天时可以用StringID//	xsDisableSelf();为关闭触发本身,等同于rmSetTriggerLoop(false);;如果不关闭触发就会变成循环触发,等同于rmSetTriggerLoop(true);。




//	因为rmCreateTrigger要创建一个结束触发来辅助上一个触发生成,虽然没有影响,但是可以另开一个触发关闭这些触发。


				rmCreateTrigger("DisableStart	active	runImmediately{xsDisableSelf();for(p=1;<cNumberPlayers)"+"{xsDisableRule(\"_CustomEnd\"+p);xsDisableRule(\"_DisableEnd\");}}/*");
				rmCreateTrigger("*/rule	_DisableEnd");


//	注意rmCreateTrigger引号""里面的for循环不要有空格,否则会输出为字符_  ;就是这个字符“_”,然后导致触发程序失效。

/* //**********************************************************************************************************************************
	
    <Condition name="Player Controls Socket">
      <Param name="PlayerID" dispName="$$22301$" VarType="player">1</Param>
      <Param name="Socket" dispName="$$32975$" VarType="unit">default</Param>
      <Expression>trPlayerControlsSocket(%PlayerID%, "%Socket%")</Expression>
    </Condition>
	"%Socket%"为剧情名,所以不能使用加减法。例如""+1=1;""+1+1=11。加减法可以在RM层进行,往上搜索int SC2。

	旧版本触发,只列举5个贸易站,其他不列出

		for(i=1; <cNumberPlayers)
		{
		rmCreateTrigger("FourOfAKind"+i);
		rmSwitchToTrigger(rmTriggerID("FourOfAKind"+i));
		rmSetTriggerActive(true);
		rmSetTriggerRunImmediately(true);
		rmSetTriggerLoop(false);
		rmSetTriggerPriority(4);
		rmAddTriggerCondition("Player Controls Socket");
		rmSetTriggerConditionParamInt("PlayerID", i, false);
		rmSetTriggerConditionParam("Socket", ""+SC1, false);
		rmAddTriggerCondition("Player Controls Socket");
		rmSetTriggerConditionParamInt("PlayerID", i, false);
		rmSetTriggerConditionParam("Socket", ""+SC2, false);
		rmAddTriggerCondition("Player Controls Socket");
		rmSetTriggerConditionParamInt("PlayerID", i, false);
		rmSetTriggerConditionParam("Socket", ""+SC3, false);
		rmAddTriggerCondition("Player Controls Socket");
		rmSetTriggerConditionParamInt("PlayerID", i, false);
		rmSetTriggerConditionParam("Socket", ""+SC4, false);
		rmAddTriggerCondition("Player Controls Socket");
		rmSetTriggerConditionParamInt("PlayerID", i, false);
		rmSetTriggerConditionParam("Socket", ""+SC5, false);
		rmAddTriggerEffect("Send Chat");
		rmSetTriggerConditionParamInt("PlayerID", i, false);
		//旧版本触发不支持("PlayerID", 0, false);;ID 0为以大自然身份发送消息
		rmSetTriggerEffectParam("SetName","hc_revolution");
		rmSetTriggerEffectParam("Message","Player"+i+"ABCDEFG");
		}
*/ //********************************************************************************************************************************

	} //END