(旧版本)编辑XS文件;新版本请打开子目录



注意事项:

●C++大小写不相同的两个定义不一样,例如Unit不等于unit。

●不能出现两个相同的定义,例如出现两个int UnitID,会导致无法打开地图。

●定义必须从上往下使用,例如你没有定义(int Unit)却使用Unit,会导致无法打开地图。

●加上//是注释,带//后,后面整行语句不会影响到地图。

●/*这种也是注释,中间的文字无效。*/

●每一句末尾都要加上分号“;”。

●自己学习C++语法,作者写这个教程时没有学过,不保证一定准确,但在帝国绝对可以用。

●改一次测试一次,尽量不要批量修改,批量修改前先备份。

●不用担心改一次测试一次地图要退出游戏,放在自建地图文件夹中,进入游戏打开这张地图,然后修改xs文件并保存,在游戏里面直接按重新开始,只要你有改动,那么该地图会重新生成并产生变化,不需要像测试data文件夹的xml文件那样重新打开游戏。

●命令表的int数值0才是开头,例如0等于大自然,1=玩家1;0等于队伍1,1等于队伍2等。

●除了注释,不能出现任何一个中文字符。

●另外,光是看这个教程是没用的,因为c++语法不像xml那样那么规整,你要去地图自己试一遍才知道。

●不要因为一点小挫折打不开地图就放弃,回想你刚才改了什么,然后纠正错误语法,一般可能是忘记添加分号“;”。

●如果可以的话,希望你能把你制作的成品地图发到论坛去,分享给大家。



正文内容:

rmSetStatusText("",X.0); //读取地图时,屏幕下方显示的进度条,X.0是百分比数值,1.0是100%,进度条其实就是由多个rmSetStatusText语句拼合起来的。 /*如果你皮一点的话可以设定 rmSetStatusText("",0.1); rmSetStatusText("",1.0); rmSetStatusText("",0.2); rmSetStatusText("",0.95); rmSetStatusText("",0.4); rmSetStatusText("",0.2); rmSetStatusText("",0.01); rmSetStatusText("",0.0); rmSetStatusText("",0.8); rmSetStatusText("",0.4); rmSetStatusText("",0.8); rmSetStatusText("",0.1); rmSetStatusText("",1.0); 作者:皮皮虾都没你这么皮。 某人:请问是作者你皮还是我皮?*/

入门:

int是随便定义的,但是不能重复。 例如:int QWER = 1; int ASDF = QWER+1;//有必要说明一下,ASDF这里等于QWER的值+1,所以在这句之前,你必须先定义QWER。 float也是随便定义的,不能重复,只能输入数字。 例如:float ZXCV = 10.0; string还是随便定义的,不能重复,可以随便输入,但是要加上引号。 例如:string Xiaoyu = "XiaoYu is extremely intelligent"; string QQGroup = "85442352"; //有时候你会发现用这几个定义很方便的,例如将一张地图修改成另一张地图,资源分布大致相同,就只想把单位调用名什么的给改了,直接改string定义的值,而不用慢慢找语句,非常方便,唯一的缺点就是不利于别人理解你的地图。这个应该是优点才对。 //注:不要把分号给遗忘了。

变量:

cNumberPlayers为所有玩家数量。 cNumberNonGaiaPlayers为不计算大自然的所有玩家数量。 cNumberTeams为所有队伍数量

随机数:

rmRandInt(10,20); //随机返回其中一个数值,50%几率。例如返回20 rmRandInt(1,2); //随机返回其中一个数值,50%几率。例如返回1 rmRandFloat(0,5); //随机返回范围内一个数值,例如返回3.25(完全随机) rmRandFloat(30,70); //随机返回范围内一个数值,例如返回50.11(完全随机) /*帝国3命令: [( )] rmRandInt(int min, int max): Returns a random integer between min and max. [( )] rmRandFloat(float min, float max): Returns a random float between min and max. */

这个是设定地图大小:

int playerTiles = 12500; //定义定义playerTiles=12500 if(cNumberNonGaiaPlayers >4) playerTiles = 11500; //如果玩家人数大于4,改变playerTiles为11500(在这之前必须先用int定义playerTiles)。 if (cNumberNonGaiaPlayers >6) playerTiles = 10500; //如果玩家人数大于6,改变playerTiles为10500。 //重点来了,帝国3地图设定大小命令:[( )] rmSetMapSize( int x, int z ): Sets the size of the map. rmSetMapSize((2*sqrt(cNumberNonGaiaPlayers*playerTiles)), (2*sqrt(cNumberNonGaiaPlayers*playerTiles))); //设定地图X大小为2×√(玩家人数×playerTiles),Z为2×√(玩家人数×playerTiles) //sqrt的全称是Square Root Calculations,一个非负实数的平方根。这是帝国3的sqrt命令:[( )] sqrt(float x): Returns the square root of x.

这个是设定河流、湖、海平面等高度:

rmSetSeaLevel(-6.0); // this is height of river surface compared to surrounding land. River depth is in the river XML.不用我说了吧,自己把-6修改成其他。

这个是设定地图类型:

rmSetMapType("default"); rmSetMapType("water"); rmSetSeaType("Coastal Japan"); rmSetMapType("yellowRiver"); //地图类型很重要的,宝藏虽然是随机生成的,但生成的时候,只会nuggets.xml定义的地图类型宝藏,如果你添加了rmSetMapType("yellowRiver");那么就会出现nuggets.xml定义了<maptype>yellowRiver</maptype>的宝藏。nuggets.xml传送门

设定地图照明类型:

rmSetLightingSet("Yukon"); //设定照明类型。自己参照剧情编辑器的照明设定,在这里输入剧情编辑器的照明名称即可。或者在art5.bar、art4.bar、art1.bar搜索.lgt,这些lgt的文件就是照明设定。如果要自定义照明的话,可以自己在art的lightsets文件夹添加lgt文件(不能联机使用,目测不会出现不同步,但是双方照明色是不一样的。)。

定义土著:

rmSetSubCiv(0, "Shaolin");//定义subCiv0 = Shaolin土著,只有定义了Shaolin才能建造少林寺贸易站 rmSetSubCiv(1, "Zen");//定义subCiv1 = Zen土著,只有定义了Zen才能建造禅宗贸易站 rmSetSubCiv(2, "Jesuit");//定义subCiv2 = Jesuit土著,只有定义了Jesuit才能建造耶稣会贸易站 //帝国3命令:[( )] rmSetSubCiv(int index, string civName, bool big) : Sets a given sub civ in the world. //命令表是这样写的,但是我也不知道第三个bool big有什么用。另外,留意一下string civName,你看见string没有?说明第二个值必须加引号,否则会出错。

定义规则

int AVTC=rmCreateTypeDistanceConstraint("LALLTOTC", "TownCenter", 30.0);//定义AVTC规则,距离地图上以生成TownCenter的大于等于30。 //帝国3命令:[(int )] rmCreateTypeDistanceConstraint(string name, int classID, float distance): Make a type distance constraint. //第一个string name是规则名称,要加双引号,而且不能出现相同的规则名称,虽然不会导致出错,但是会导致后面与这个名称相同的规则失效。 //第二个int classID可以直接加上双引号,然后写上单位标签或调用名;也可以使用rmClassID("XXXXX")在这之前你必须先用rmDefineClass("")把XXXXX定义了,否则无效,例如:int ABCD = rmDefineClass("XXXXX");,然后调用这个规则时,会避开有rmClassID("XXXXX")的设定【依然是距离大于或等于rmClassID("XXXXX")某个数值(特意用上某个数值这个词,其实就是第三个float distance)】;你必须使用rmAddAreaToClass将classID添加到生成单位、地形、河流等设定中。这样才会避开带有这个class的设定。看不懂?地图就是这么乱七八糟的,基本上无法解释清楚的,只能靠你自己编辑地图去理解。你自己在一些地图搜索一下Class应该就会懂了。 //第三个float distance就是距离,没什么好说的。 /* (知识扩展)帝国3命令: [(int )] rmDefineClass(string className): Define a class with the given name. [( )] rmClassID(string name): Gets class ID for given class name. [(bool )] rmAddAreaToClass(int areaID, int classID): Add given area to specified class. */

创建单位

int TreeCount = (cNumberNonGaiaPlayers * 8); //定义TreeCount=8 int UnitID = rmCreateObjectDef("Unit"); //定义UnitID,并创建1组单位,rmCreateObjectDef("XXXX");的string name不能重复,虽然不会错误,但是会导致后面同名的设定无效。 rmAddObjectDefItem(UnitID,"ypTreeBorneo",TreeCount,12.0); //单位对象为ypTreeBorneo,创建1组单位数量为TreeCount(在此句之前你必须先定义TreeCount),创建1组单位创建单位离创建单位的中心的最大距离为12。 rmSetObjectDefMinDistance(UnitID,0.0); //每创建1次(与上面的1组同理,但是不是同一个,这个创建单位时的定位点偏移)单位,离中心点的最小距离为0 rmSetObjectDefMaxDistance(UnitID,rmXFractionToMeters(0.03)); //每创建1次单位,离中心点的最大距离为rmXFractionToMeters(0.03),当然你要可以将rmXFractionToMeters(0.03)改成10、20、30之类的数值。 rmPlaceObjectDefAtLoc(UnitID,0,0.44,0.10,5); //给大自然创建(0是大自然),地图位置坐标为0.44,0.10,总共创建5次。 那么创建5次等于创建了5组(奇怪,我为什么要这样说废话....?直接说成一组不就好了吗...)5组的话,再乘上TreeCount,两个玩家的时候就有5*2*8=80棵树。 rmAddObjectDefConstraint(UnitID,AVTC) //生成1次单位的必须遵循AVTC规则,(在这句之前你必须先定义AVTC,自己往上看一下吧),如果AVTC设定城镇中心,距离为30,那么创建这些树木会在城镇中心30距离外生成。 /* int AXXXX = rmCreateObjectDef("XXXXX"); rmAddObjectDefItem(AXXXX, "protoname", 数量, 生成1组的范围【如果为0,即使你设定数量为100都只能放置一个,一般6-12足够使用】); rmSetObjectDefMinDistance(AXXXX,最少定位可偏移距离,即为中心点位置偏移); rmSetObjectDefMaxDistance(AXXXX,最大定位可偏移距离,即为中心点位置偏移); rmPlaceObjectDefAtLoc(AXXXX, 玩家ID, X坐标, Z坐标, 放置数量【与上面的数量不一样,上面的数量是这个的子集,例如上面是2,这里是3,那么总共是6个,2个一组】); rmAddObjectDefConstraint(AXXXX,已定义的规则)

这个是作者的中国地图给台湾岛生成娃娃鱼的语句:

int HerdTaiwanID = rmCreateObjectDef("HerdTaiwan"); rmAddObjectDefItem(HerdTaiwanID, "ypGiantSalamander", 5, 8.0); rmSetObjectDefMinDistance(HerdTaiwanID, 0.0); rmSetObjectDefMaxDistance(HerdTaiwanID, rmXFractionToMeters(0.05)); rmSetObjectDefCreateHerd(HerdTaiwanID, true); rmPlaceObjectDefAtLoc(HerdTaiwanID, 0, 0.46, 0.11, 1); 与上面的差不多,不过多了一个rmSetObjectDefCreateHerd(HerdTaiwanID, true);,这个是用来定义猎物被打猎或者受到伤害会跑。 另外还可以这样写的,多添加几个单位,而不是创建一个新定义,注意一下每一组的范围不能一样,否则会导致某些单位无法生成: int GoldID = rmCreateObjectDef("LandGold "); rmAddObjectDefItem(GoldID, "mineGold", 1, 5.0); rmAddObjectDefItem(GoldID, "MineTin", 1, 8.0); rmAddObjectDefItem(GoldID, "MineCopper", 1, 11.0); rmAddObjectDefItem(GoldID, "ypSPCRockCrate", 10, 13.0); rmSetObjectDefMinDistance(GoldID, 0.0); rmSetObjectDefMaxDistance(GoldID, rmXFractionToMeters(0.01)); rmPlaceObjectDefAtLoc(GoldID, 0, 0.46, 0.66, 1); (知识扩展)帝国3命令: [( )] rmCreateObjectDef(string name): Creates an object definition. [( )] rmAddObjectDefItem(int defID, string unitName, int count, float clusterDistance): Add item to object definition. [( )] rmSetObjectDefMinDistance(int defID, float dist): Set the minimum distance for the object definition (in meters). [( )] rmSetObjectDefMaxDistance(int defID, float dist): Set the maximum distance for the object definition (in meters). [( )] rmSetObjectDefCreateHerd(int defID, bool on): Creates a herd out of all units placed in this object def. [( )] rmPlaceObjectDefAtLoc(int defID, int playerID, float xFraction, float zFraction, int placeCount): Place object definition at specific location for given player. [( )] rmXFractionToMeters(float meters): Converts a fraction of the map in the x direction to meters.

这个是创建单位的模板:

int Unit1ID = rmCreateObjectDef("Unit1"); rmAddObjectDefItem(Unit1ID, "protoname",1,5.0); rmSetObjectDefMinDistance(Unit1ID,0.0); rmSetObjectDefMaxDistance(Unit1ID,30.0); rmPlaceObjectDefAtLoc(Unit1ID,0,0.50,0.50,1); int Hred1ID = rmCreateObjectDef("Hred1"); rmAddObjectDefItem(Hred1ID, "protoname",1,5.0); rmSetObjectDefMinDistance(Hred1ID,0.0); rmSetObjectDefMaxDistance(Hred1ID,30.0); rmSetObjectDefCreateHerd(Hred1ID,true); rmPlaceObjectDefAtLoc(Hred1ID,0,0.50,0.50,1); 其实你在XS文件随便复制一组语句就是一个模板了。
*/

创建群组(单位,例如土著,具体参考剧情编辑器的群组编辑器)


int shaolinID = rmCreateGrouping("shaolin A", "native shaolin temple mongol 04"); //定义shaolinID,并创建群组,群组名称为shaolin A;群组调用名为native shaolin temple mongol 04(自己参考剧情编辑器的群组编辑器,或者参考帝国3目录的RM3文件夹,有个groupings文件夹,里面的xml文件名就是群组调用名。注:如果不是MOD就不能自定义群组。)
rmSetGroupingMinDistance(shaolinID, 0.0); //放置群组可偏移定位点最少距离
rmSetGroupingMaxDistance(shaolinID, rmXFractionToMeters(0.05)); //放置群组可偏移定位点最少距离
rmPlaceGroupingAtLoc(shaolinID, 0,0.40,0.80); //放置群组定位点(地图XZ坐标)
rmAddGroupingConstraint(shaolinID, avoidTC); //放置群组时遵循AVTC规则 /* (知识扩展)帝国3命令: [( )] rmSetGroupingMinDistance(int defID, float dist): Set the minimum distance for the grouping (in meters). [( )] rmSetGroupingMaxDistance(int defID, float dist): Set the maximum distance for the grouping (in meters). [(bool )] rmPlaceGroupingAtLoc(int groupingID, int playerID, float xFraction, float zFraction, int placeCount): Place grouping at specified location. [(bool )] rmAddGroupingConstraint(int GroupingID, int constraintID): Add specified constraint to a grouping. /* 宗教-少林:
int shaolinID = rmCreateGrouping("shaolin A", "native shaolin temple mongol 01");
rmSetGroupingMinDistance(shaolinID, 0.0);
rmSetGroupingMaxDistance(shaolinID, rmXFractionToMeters(0.05));
rmPlaceGroupingAtLoc(shaolinID, 0,0.40,0.80);
rmAddGroupingConstraint(shaolinID, 群组规则自己定义或删除); 宗教-禅宗:
int ZenID = rmCreateGrouping("Zen A", "native zen temple ceylon 04");
rmSetGroupingMinDistance(ZenID, 0.0);
rmSetGroupingMaxDistance(ZenID,rmXFractionToMeters(0.05));
rmAddGroupingConstraint(ZenID, 群组规则自己定义或删除);
rmPlaceGroupingAtLoc(ZenID, 0,0.48,0.62); 宗教-基督:
int JesuitID = rmCreateGrouping("Jesuit A", "native jesuit mission borneo 03");
rmSetGroupingMinDistance(JesuitID, 0.0);
rmSetGroupingMaxDistance(JesuitID, rmXFractionToMeters(0.05));
rmAddGroupingConstraint(JesuitID, 群组规则自己定义或删除);
rmPlaceGroupingAtLoc(JesuitID, 0,0.60,0.40); 土著-西米诺尔人:
int SeminoleID = rmCreateGrouping("seminole", "native seminole village 1");
rmSetGroupingMinDistance(SeminoleID, 0.0);
rmSetGroupingMaxDistance(SeminoleID, rmXFractionToMeters(0.1));
rmPlaceGroupingAtLoc(SeminoleID, 0,0.60,0.05);
rmAddGroupingConstraint(SeminoleID, 群组规则自己定义或删除); 土著-印加人:
int IncaID = rmCreateGrouping("inca", "native inca village 05");
rmSetGroupingMinDistance(IncaID, 0.0);
rmSetGroupingMaxDistance(IncaID, rmXFractionToMeters(0.05));
rmPlaceGroupingAtLoc(IncaID, 0,0.50,0.90);
rmAddGroupingConstraint(IncaID, 群组规则自己定义或删除); */

添加地形

int TerrainID1=rmCreateArea("grass"); //定义TerrainID1并创建地形 rmSetAreaSize(TerrainID1, 1.0, 1.0); //范围XZ大小,这个是按照地图百分比计算的,0.01很大的,1.0为全图 rmSetAreaLocation(TerrainID1, .5, .5); //中心点(定位点)为0.5,0.5; [.5是0.5的意思] rmSetAreaWarnFailure(TerrainID1, true); rmSetAreaSmoothDistance(TerrainID1, 10); //平滑距离?在非凝聚性地形,数值较小会比数值较大的更加分散。 rmSetAreaCoherence(TerrainID1, .8); //凝聚性?数值为1.0的时候,会凝聚成一个圆;数值为0.0则会变成无规律地形。 rmSetAreaBaseHeight(TerrainID1, 4.0); //设定地形高度,删除这句后直接把地形贴上去,不会影响到水域或悬崖。 rmSetAreaMix(TerrainID1, "yellow_river_forest"); //地形,具体参考剧情编辑器,以及用AOE3ED在art1-5.bar搜索 rmBuildArea(TerrainID1); //确认创建地形TerrainID1 /* 其他: rmAddAreaInfluenceSegment(TerrainID, 1.0, 1.0, 0.0, 0.0);添加后,如果定位点在rmAddAreaInfluenceSegment的直线范围里面,会额外生成一条直线地形。例如rmSetAreaLocation为0.5,0.5;而rmAddAreaInfluenceSegment第一个点为1.0,1.0,第二个点为0.0,0.0,那么1.0,1.0到0.0,0.0之间会生成额外地形,大小依然为rmSetAreaSize定义的大小。

  int TestID=rmCreateArea("Test ID Area");
  rmSetAreaSize(TestID, 0.10, 0.10);
  rmSetAreaLocation(TestID, .5, .5);
  rmSetAreaWarnFailure(TestID, true);
  rmSetAreaSmoothDistance(TestID, 50);
  rmSetAreaCoherence(TestID, 1.0);
  rmSetAreaMix(TestID, "himalayas_a");
  rmSetAreaElevationType(TestID, cElevTurbulence);
  rmSetAreaElevationVariation(TestID, 4.0);
  rmSetAreaBaseHeight(TestID, 4.0);
  rmSetAreaElevationOctaves(TestID, 3);
  rmAddAreaInfluenceSegment(TestID, 1.0, 1.0, 0.0, 0.0);
  rmSetAreaObeyWorldCircleConstraint(TestID, false);
  rmBuildArea(TestID);


  int TestID=rmCreateArea("Test ID Area");
  rmSetAreaSize(TestID, 0.05, 0.09);
  rmSetAreaLocation(TestID, .3, .8);
  rmSetAreaWarnFailure(TestID, true);
  rmSetAreaSmoothDistance(TestID, 0);
  rmSetAreaCoherence(TestID, 0.0);
  rmSetAreaMix(TestID, "himalayas_a");
  rmSetAreaElevationType(TestID, cElevTurbulence);
  rmSetAreaElevationVariation(TestID, 4.0);
  rmSetAreaBaseHeight(TestID, 4.0);
  rmSetAreaElevationOctaves(TestID, 3);
  rmSetAreaObeyWorldCircleConstraint(TestID, false);
  rmBuildArea(TestID);

 

  int TestID=rmCreateArea("Test ID Area");
  rmSetAreaSize(TestID, 0.05, 0.09);
  rmSetAreaLocation(TestID, .3, .8);
  rmSetAreaWarnFailure(TestID, true);
  rmSetAreaSmoothDistance(TestID, 50);
  rmSetAreaCoherence(TestID, 0.0);
  rmSetAreaMix(TestID, "himalayas_a");
  rmSetAreaElevationType(TestID, cElevTurbulence);
  rmSetAreaElevationVariation(TestID, 4.0);
  rmSetAreaBaseHeight(TestID, 4.0);
  rmSetAreaElevationOctaves(TestID, 3);
  rmSetAreaObeyWorldCircleConstraint(TestID, false);
  rmBuildArea(TestID);


  int TestID=rmCreateArea("Test ID Area");
  rmSetAreaSize(TestID, 0.05, 0.09);
  rmSetAreaLocation(TestID, .3, .8);
  rmSetAreaWarnFailure(TestID, true);
  rmSetAreaSmoothDistance(TestID, 50);
  rmSetAreaCoherence(TestID, 1.0);
  rmSetAreaMix(TestID, "himalayas_a");
  rmSetAreaElevationType(TestID, cElevTurbulence);
  rmSetAreaElevationVariation(TestID, 4.0);
  rmSetAreaBaseHeight(TestID, 4.0);
  rmSetAreaElevationOctaves(TestID, 3);
  rmSetAreaObeyWorldCircleConstraint(TestID, false);
  rmBuildArea(TestID);

(知识扩展)帝国3命令: [( )] rmCreateArea(string name, int parentAreaID): Creates an area. [( )] rmSetAreaSize(float minFraction, float maxFraction): Set the area size to a min/max fraction of the map. [( )] rmSetAreaLocation(int areaID, float xFraction, float zFraction): Set the area location. [( )] rmSetAreaWarnFailure(int areaID, bool warn): Sets whether the area build process will warn if it fails. [( )] rmSetAreaSmoothDistance(int areaID, int smoothDistance): Sets area edge smoothing distance (distance is number of neighboring points to consider in each direction). [( )] rmSetAreaCoherence(int areaID, float coherence): Sets area coherence (0-1). [( )] rmSetAreaMix(int areaID, string mixName): Sets the mix for an area. Overrides terrain type if it is also set. [( )] rmSetAreaElevationType(int areaID, int type): Sets the area elevation variation type (cElevNormal, cElevFractalSum, cElevTurbulence). [( )] rmSetAreaElevationVariation(int areaID, float variation): Sets the area elevation variation height (amount to vary +- from area base height). [( )] rmSetAreaBaseHeight(int areaID, float height): Sets the base height for an area. [( )] rmSetAreaElevationOctaves(int areaID, int octaves): Sets the area elevation variation noise octaves. [( )] rmSetAreaObeyWorldCircleConstraint(int areaID, bool constrain): Determines whether an area obeys world circle constraint. [( )] rmAddAreaInfluenceSegment(int areaID, float xFraction1, float zFraction1, float xFraction2, float zFraction2): Adds an area influence segment. [( )] rmBuildArea(int areaID): Builds the specified area. */

添加贸易路线,把当成贸易路线固有格式吧:

注:由地图生成器的贸易站地点不会因地形变换方向,而这个会变换方向。 int tradeRouteID = rmCreateTradeRoute(); int socketID=rmCreateObjectDef("sockets to dock Trade Posts"); rmAddObjectDefItem(socketID, "SocketTradeRoute", 1, 0.0); rmAddObjectDefConstraint(socketID, 注意这里生成规则,复制的时候一定要修改掉); rmSetObjectDefAllowOverlap(socketID, true); rmSetObjectDefMinDistance(socketID, 0.0); rmSetObjectDefMaxDistance(socketID, 8.0); 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.75, 0.75); rmAddTradeRouteWaypoint(tradeRouteID, 0.80, 0.71); rmAddTradeRouteWaypoint(tradeRouteID, 0.39, 0.81); rmAddTradeRouteWaypoint(tradeRouteID, 1.00, 0.70); bool placedTradeRoute = rmBuildTradeRoute(tradeRouteID, "water"); if(placedTradeRoute == false) rmEchoError("Failed to place trade route"); // add the sockets along the trade route. rmSetObjectDefTradeRouteID(socketID, tradeRouteID); vector socketLoc = rmGetTradeRouteWayPoint(tradeRouteID, 0.07); rmPlaceObjectDefAtPoint(socketID, 0, socketLoc); socketLoc = rmGetTradeRouteWayPoint(tradeRouteID, 0.22); rmPlaceObjectDefAtPoint(socketID, 0, socketLoc); socketLoc = rmGetTradeRouteWayPoint(tradeRouteID, 0.40); rmPlaceObjectDefAtPoint(socketID, 0, socketLoc); socketLoc = rmGetTradeRouteWayPoint(tradeRouteID, 0.53); rmPlaceObjectDefAtPoint(socketID, 0, socketLoc); socketLoc = rmGetTradeRouteWayPoint(tradeRouteID, 0.69); rmPlaceObjectDefAtPoint(socketID, 0, socketLoc); socketLoc = rmGetTradeRouteWayPoint(tradeRouteID, 0.90); rmPlaceObjectDefAtPoint(socketID, 0, socketLoc); /*

语句作用解释在下方

int tradeRouteID = rmCreateTradeRoute(); 定义tradeRouteID,并创建贸易路线 int socketID=rmCreateObjectDef("sockets to dock Trade Posts"); 定义socketID并创建单位 rmAddObjectDefItem(socketID, "SocketTradeRoute", 1, 0.0); 创建贸易站地点,数量为1,范围0(即为定位点所在位置) rmAddObjectDefConstraint(socketID, AVTC); 生成贸易站地点(SocketTradeRoute)时遵循AVTC规则 rmSetObjectDefAllowOverlap(socketID, true); 允许重叠??? rmSetObjectDefMinDistance(socketID, 0.0); 定位点最小偏移距离 rmSetObjectDefMaxDistance(socketID, 8.0); 定位点最大偏移距离 rmAddTradeRouteWaypoint(tradeRouteID, 0.00, 0.52); 设定贸易路线起点(地图XZ坐标);注:rmAddTradeRouteWaypoint第一句为起点这不明摆着废话吗?。 rmAddTradeRouteWaypoint(tradeRouteID, 0.20, 0.51); 设定贸易路线中续点(地图XZ坐标) rmAddTradeRouteWaypoint(tradeRouteID, 0.40, 0.40); 设定贸易路线中续点(地图XZ坐标) rmAddTradeRouteWaypoint(tradeRouteID, 0.55, 0.45); 设定贸易路线中续点(地图XZ坐标) rmAddTradeRouteWaypoint(tradeRouteID, 0.75, 0.75); 设定贸易路线中续点(地图XZ坐标) rmAddTradeRouteWaypoint(tradeRouteID, 0.80, 0.71); 设定贸易路线中续点(地图XZ坐标) rmAddTradeRouteWaypoint(tradeRouteID, 0.39, 0.81); 设定贸易路线中续点(地图XZ坐标) rmAddTradeRouteWaypoint(tradeRouteID, 1.00, 0.70); 设定贸易路线终点(地图XZ坐标);注:最后一句为终点。废话+1。 bool placedTradeRoute = rmBuildTradeRoute(tradeRouteID, "water"); 亚洲地图类型为water,还有一个叫dirt;如果water不能升级贸易路线就改成dirt;如果dirt不能升级贸易路线就改成water,如果后面有时间的话,我可能会会制作水上贸易路线的教程。17:15 2019/3/25 除了这些还有其他,例如snow,如果你有兴趣的话,可以自己看一下Art5.bar的terrain\traderoutes.xml与Data3.bar的traderoutes.xml。 if(placedTradeRoute == false) rmEchoError("Failed to place trade route"); // add the sockets along the trade route. rmSetObjectDefTradeRouteID(socketID, tradeRouteID); vector socketLoc = rmGetTradeRouteWayPoint(tradeRouteID, 0.07); 设定第一个贸易站地点在贸易路线的长度7%(0.07)位置。 rmPlaceObjectDefAtPoint(socketID, 0, socketLoc); socketLoc = rmGetTradeRouteWayPoint(tradeRouteID, 0.22); 设定第二个贸易站地点在贸易路线的22%位置。 rmPlaceObjectDefAtPoint(socketID, 0, socketLoc); socketLoc = rmGetTradeRouteWayPoint(tradeRouteID, 0.40); 设定第三个贸易站地点在贸易路线的40%位置。 rmPlaceObjectDefAtPoint(socketID, 0, socketLoc); socketLoc = rmGetTradeRouteWayPoint(tradeRouteID, 0.53); 设定第四个贸易站地点在贸易路线的53%位置。 rmPlaceObjectDefAtPoint(socketID, 0, socketLoc); socketLoc = rmGetTradeRouteWayPoint(tradeRouteID, 0.69); 设定第五个贸易站地点在贸易路线的69%位置。 rmPlaceObjectDefAtPoint(socketID, 0, socketLoc); socketLoc = rmGetTradeRouteWayPoint(tradeRouteID, 0.90); 设定第六个贸易站地点在贸易路线的90%位置。 rmPlaceObjectDefAtPoint(socketID, 0, socketLoc); 注:从起点开始算。如果将贸易路线坐标反过来又不一样了。你看一下我的中国地图,设定了随机方向,50%几率从南到北,50%从北到南,贸易站的位置基本是一样的(我知道你想说什么,我的中国地图贸易站还有随机数量,而我这里说的是南到北,北到南的贸易站位置是一样的),但是贸易站长度的定义却不是像贸易路线的定义反过来的(实际上贸易路线的地点也进行了微调)。 另外,你可以自行复制,多添加几个贸易站地点。 */

创建河流:

int RiverID = rmRiverCreate(-1, "Great Lakes", 1, 1, 5.0, 5.0); //定义RiverID,并创建河流,Great Lakes大湖区的湖,两个5.0是水域的大小,注:不能小于3.0 rmRiverAddWaypoint(RiverID, 0.45, 0.55 ); //河流起点 rmRiverAddWaypoint(RiverID, 0.55, 0.45 ); //河流中续点 rmRiverAddWaypoint(RiverID, 0.50, 0.50 ); //河流中续点 rmRiverAddWaypoint(RiverID, 0.55, 0.55 ); //河流中续点 rmRiverAddWaypoint(RiverID, 0.45, 0.45 ); //河流终点;注:两个相连的点不能是一样的,否则无法计算,生成地图的时候会一直卡主,只能alt+f4 rmRiverSetBankNoiseParams(IDRiver,0.00, 0, 0.0, 0.0, 0.0, 0.0); rmRiverBuild(IDRiver); /*(知识扩展)帝国3命令: [( )] rmRiverCreate(int areaID, string waterType, int breaks, int offset, int minR, int maxR): make a river dude. [( )] rmRiverAddWaypoint(riverID, xFraction, zFraction): Add waypoint to a river. Don't mix with rmRiverSetConnections or rmRiverConnectRiver [( )] rmRiverSetBankNoiseParams(riverID, frequency, octaves, persistence, sineLength, sineAmt, variation); [( )] rmRiverBuild(int areaID): Builds the specified area. */

给河流添加浅滩设定,在上面的语句添加这两句:

rmRiverAddShallow(RiverID,1.0); //添加浅滩 rmRiverAddShallows(RiverID,10.00,8); //设定浅滩数量为10,半径为8 /*(知识扩展)帝国3命令: [( )] rmRiverAddShallow(riverID, distancePct); [( )] rmRiverAddShallows(riverID, count, radius); */ //这个是模板: int River1 = rmRiverCreate(-1, "Great Lakes", 1, 1, 5.0, 5.0); rmRiverAddWaypoint(River1, 0.45, 0.55 ); rmRiverAddWaypoint(River1, 0.55, 0.45 ); rmRiverAddWaypoint(River1, 0.50, 0.50 ); rmRiverAddWaypoint(River1, 0.55, 0.55 ); rmRiverAddWaypoint(River1, 0.45, 0.45 ); rmRiverSetBankNoiseParams(River1,0.00, 0, 0.0, 0.0, 0.0, 0.0); rmRiverSetShallowRadius(River1,16); //若不需要浅滩,请把下面两句删除。 rmRiverAddShallow(River1,1.0); rmRiverAddShallows(River1,1.0,8); rmRiverBuild(River1);

给出一些常见的地图错误例子:

我遇见其他错误,基本上都是int定义的问题(没有定义这个元素但有语句调用了这个元素,导致无法打开地图) 例如你复制了其他地图的语句,却没有复制int那个定义。
地图编辑就这样吧,剩下的内容看似简单,但是很难写教程,只能靠你自己研究了,最好的办法是照搬原有的地图。 例如地图生成器生成的地图游牧时代开局还是一个城镇中心,照搬其他地图就可以了。
  地图生成器生成的地图.XS - 记事本 ____ X
文件(F)  编辑(E)  格式(O)  查看(V)  帮助(H)
int TCID = rmCreateObjectDef("player TC");
rmAddObjectDefItem(TCID, "TownCenter", 1, 0.0);
 int playerMarketID = rmCreateObjectDef("player market");
 rmAddObjectDefItem(playerMarketID, "market", 1, 0);
 rmAddObjectDefConstraint(playerMarketID, avoidTradeRoute);
 rmSetObjectDefMinDistance(playerMarketID, 10.0);
 rmSetObjectDefMaxDistance(playerMarketID, 18.0);
 rmAddObjectDefConstraint(playerMarketID, playerEdgeConstraint);
 rmAddObjectDefConstraint(playerMarketID, mediumShortAvoidImpassableLand);
  自己去地图地图复制粘贴语句,修改后.XS - 记事本 ____ X
文件(F)  编辑(E)  格式(O)  查看(V)  帮助(H)

int TCID = rmCreateObjectDef("player TC");
if (rmGetNomadStart())
{
rmAddObjectDefItem(TCID, "CoveredWagon", 1, 0.0);
}
else{
rmAddObjectDefItem(TCID, "TownCenter", 1, 0.0);
int playerMarketID = rmCreateObjectDef("player market");
rmAddObjectDefItem(playerMarketID, "market", 1, 0);
rmAddObjectDefConstraint(playerMarketID, avoidTradeRoute);
rmSetObjectDefMinDistance(playerMarketID, 10.0);
rmSetObjectDefMaxDistance(playerMarketID, 18.0);
rmAddObjectDefConstraint(playerMarketID, playerEdgeConstraint);
rmAddObjectDefConstraint(playerMarketID, mediumShortAvoidImpassableLand);
}