こはね 发表于 2024-7-28 23:29:29

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


こはね 发表于 2024-7-29 00:06:59

原理:
首先来看一个正常的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);






こはね 发表于 2024-7-29 00:24:18

与这个类似的注入,剧情编辑器也是存在的;有兴趣的可以直接前往https://www.aoebbs.net/tutorial-16-2.html,里面有写到如何创建自定义rule

藤藤菜在路上 发表于 2024-8-2 14:29:57

天书{:4_89:}
页: [1]
查看完整版本: XS地图注入式代码(自定义)触发转换器