XS地图注入式代码(自定义)触发转换器
几年前有大佬写过一个触发转换器,但不太好用,我现在重写一个;该转换器作用是将类似下图的触发镶嵌到自定义函数里面,而自定义函数利用/**/把原有的触发给注释掉,导致可以注入代码的可能性;这绝对是判断不严谨导致的严重注入漏洞(该漏洞让我们实现了可以在xs地图中使用自定义触发,不再需要依赖trigger3/typetest.xml,带来了无限的可能性,百利无一害{:7_240:},但如果你的网站出现这样一个漏洞,你的网站没了);下图为大佬写的触发转换器
这个是我重写的触发转换器:https://www.aoebbs.net/tool_xstrigger.html
使用方法:
必要函数,添加在void(main)上面:
void aoebbsA(string xs="") {
rmAddTriggerEffect("SetIdleProcessing");
rmSetTriggerEffectParam("IdleProc", "false); "+xs+"/* trSetUnitIdleProcessing(false");
}
void aoebbsE(string xs="") {
rmAddTriggerEffect("SetIdleProcessing");
rmSetTriggerEffectParam("IdleProc", "false); */ "+xs+"/* trSetUnitIdleProcessing(false");
}
void aoebbsZ(string xs="") {
rmAddTriggerEffect("SetIdleProcessing");
rmSetTriggerEffectParam("IdleProc", "false); */ "+xs+" trSetUnitIdleProcessing(false");
}
void aoebbsR(string xs1="",string xs2="") {
rmCreateTrigger(xs1+" "+xs2+"/*");
rmCreateTrigger("*/rule _"+xs1+"End");
rmSetTriggerActive(false);
}
然后在void(main)里面,添加
//以下红色字体为必要设定,只需要添加一次,添加一次后,你就可以在CustomTrigger与_Temp之间任意插入xs触发。最后一句必须加上 `aoebbsE("");`,aoebbsE("")的双引号内可以插入触发程序代码。
rmCreateTrigger("CustomTrigger");
rmSwitchToTrigger(rmTriggerID("CustomTrigger"));
rmSetTriggerRunImmediately(true);
aoebbsA("}}");
//这个是xs触发示例:
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("}} ");
}
这里必须要以aoebbsZ结尾,不能用aoebbsE结尾
aoebbs("rule _Temp inactive { if(true){");
aoebbsZ("xsDisableSelf();");
BigFile5/xstrigger.mp4
BigFile5/rmCreateTrigger.mp4
原理:
首先来看一个正常的RM触发程序
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");
}
用转换器(https://www.aoebbs.net/tool_xstrigger.html)转换后获得以下代码
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("");
然后游戏中实测,打开trigtemp.xs获得以下代码;
trSetUnitIdleProcessing(false); */ rule _BuildLimit minInterval 2 active /* );
trSetUnitIdleProcessing(false); */ { /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypCastle", 1, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Outpost", 1, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Blockhouse", 1, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("WarHut", 1, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("YPOutpostAsian", 1, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypCastle", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Outpost", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Blockhouse", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("WarHut", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("YPOutpostAsian", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Caravel", 1, 10, 30); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Galley", 1, 10, 30); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Canoe", 1, 10, 60); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypFune", 1, 10, 30); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypWarJunk", 1, 10, 30); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Caravel", 2, 10, 30); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Galley", 2, 10, 30); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Canoe", 2, 10, 60); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypFune", 2, 10, 30); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypWarJunk", 2, 10, 30); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Monitor", 1, 10, 5); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Galleon", 1, 10, 5); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Fluyt", 1, 10, 5); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Frigate", 1, 10, 5); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypFuchuan", 1, 10, 5); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypAtakabune", 1, 10, 5); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypTekkousen", 1, 10, 5); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Fluyt", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Monitor", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Galleon", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Frigate", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypFuchuan", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypAtakabune", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypTekkousen", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ xsDisableRule("_BuildLimit"); /* );
trSetUnitIdleProcessing(false); */ } /* );
trSetUnitIdleProcessing(false); */ /*
为什么一定要插入在以下代码的中间内?因为上面的注释符号是不合规的,需要补齐
rmCreateTrigger("CustomTrigger");
rmSwitchToTrigger(rmTriggerID("CustomTrigger"));
rmSetTriggerRunImmediately(true);
aoebbsA("}}");
aoebbs("rule _Temp inactive { if(true){");
aoebbsZ("xsDisableSelf();"); aoebbs("rule _Temp inactive { if(true){");
aoebbsZ("xsDisableSelf();");
当把触发插入在上面两个触发之后会变成
rule _CustomTrigger
minInterval 4
active
runImmediately
{
bool bVar0 = (true);
bool tempExp = (bVar0);
if (tempExp)
{
trSetUnitIdleProcessing(true);
trSetUnitIdleProcessing(false); }}/* trSetUnitIdleProcessing(false);
trSetUnitIdleProcessing(false); */ rule _BuildLimit minInterval 2 active /* );
trSetUnitIdleProcessing(false); */ { /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypCastle", 1, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Outpost", 1, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Blockhouse", 1, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("WarHut", 1, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("YPOutpostAsian", 1, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypCastle", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Outpost", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Blockhouse", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("WarHut", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("YPOutpostAsian", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Caravel", 1, 10, 30); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Galley", 1, 10, 30); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Canoe", 1, 10, 60); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypFune", 1, 10, 30); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypWarJunk", 1, 10, 30); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Caravel", 2, 10, 30); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Galley", 2, 10, 30); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Canoe", 2, 10, 60); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypFune", 2, 10, 30); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypWarJunk", 2, 10, 30); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Monitor", 1, 10, 5); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Galleon", 1, 10, 5); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Fluyt", 1, 10, 5); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Frigate", 1, 10, 5); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypFuchuan", 1, 10, 5); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypAtakabune", 1, 10, 5); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypTekkousen", 1, 10, 5); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Fluyt", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Monitor", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Galleon", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Frigate", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypFuchuan", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypAtakabune", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypTekkousen", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ xsDisableRule("_BuildLimit"); /* );
trSetUnitIdleProcessing(false); */ } /* );
trSetUnitIdleProcessing(false); */ /* trSetUnitIdleProcessing(false);
trSetUnitIdleProcessing(false); */ rule _Temp inactive { if(true){ /* );
trSetUnitIdleProcessing(false); */ xsDisableSelf(); trSetUnitIdleProcessing(false);
xsDisableRule("_CustomTrigger");
trEcho("Trigger disabling rule CustomTrigger");
}
}
可能你有点看不懂,如果我把注释符号中的代码改成灰色,代表不生效那么你应该看得懂了
rule _CustomTrigger
minInterval 4
active
runImmediately
{
bool bVar0 = (true);
bool tempExp = (bVar0);
if (tempExp)
{
trSetUnitIdleProcessing(true);
trSetUnitIdleProcessing(false); }}/* trSetUnitIdleProcessing(false);
trSetUnitIdleProcessing(false); */ rule _BuildLimit minInterval 2 active /* );
trSetUnitIdleProcessing(false); */ { /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypCastle", 1, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Outpost", 1, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Blockhouse", 1, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("WarHut", 1, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("YPOutpostAsian", 1, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypCastle", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Outpost", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Blockhouse", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("WarHut", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("YPOutpostAsian", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Caravel", 1, 10, 30); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Galley", 1, 10, 30); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Canoe", 1, 10, 60); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypFune", 1, 10, 30); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypWarJunk", 1, 10, 30); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Caravel", 2, 10, 30); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Galley", 2, 10, 30); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Canoe", 2, 10, 60); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypFune", 2, 10, 30); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypWarJunk", 2, 10, 30); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Monitor", 1, 10, 5); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Galleon", 1, 10, 5); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Fluyt", 1, 10, 5); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Frigate", 1, 10, 5); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypFuchuan", 1, 10, 5); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypAtakabune", 1, 10, 5); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypTekkousen", 1, 10, 5); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Fluyt", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Monitor", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Galleon", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("Frigate", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypFuchuan", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypAtakabune", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ trModifyProtounit("ypTekkousen", 2, 10, 20); /* );
trSetUnitIdleProcessing(false); */ xsDisableRule("_BuildLimit"); /* );
trSetUnitIdleProcessing(false); */ } /* );
trSetUnitIdleProcessing(false); */ /* trSetUnitIdleProcessing(false);
trSetUnitIdleProcessing(false); */ rule _Temp inactive { if(true){ /* );
trSetUnitIdleProcessing(false); */ xsDisableSelf(); trSetUnitIdleProcessing(false);
xsDisableRule("_CustomTrigger");
trEcho("Trigger disabling rule CustomTrigger");
}
}
实际上生效的就只有以下代码(已作格式化处理):
rule _CustomTrigger
minInterval 4
active
runImmediately
{
bool bVar0 = (true);
bool tempExp = (bVar0);
if (tempExp)
{
trSetUnitIdleProcessing(true);
trSetUnitIdleProcessing(false);
}
}
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 _Temp inactive
{
if(true)
{
xsDisableSelf();
trSetUnitIdleProcessing(false);
xsDisableRule("_CustomTrigger");
trEcho("Trigger disabling rule CustomTrigger");
}
}
就这样,利用/**/成功注入代码,使原有的触发程序运行了不应该运行的代码;原本地图的触发程序只能限制于trigger3/typetest.xml,超出这个范围就没办法自定义触发,如果你新建一个xml可以,但没办法联机,因为这个代码注入,使自定义触发成为可能性;我们可以使用的代码函数有TR、XS、KB,甚至UI函数也可以使用;注:当初全效工作室把函数称为Command命令,别问我怎样知道的,我只能告诉你游戏内有内置接口。函数表在圣典有:
所有函数: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);
与这个类似的注入,剧情编辑器也是存在的;有兴趣的可以直接前往https://www.aoebbs.net/tutorial-16-2.html,里面有写到如何创建自定义rule
天书{:4_89:}
页:
[1]