You must be logged in to post messages.
Please login or register

Modding and Scripting
Moderated by Yeebaagooon, nottud

Hop to:    
loginhomeregisterhelprules
Bottom
Topic Subject: RMS - Get location of player's settlement
posted 29 August 2021 08:53 AM EDT (US)   
I'm pulling my hair out at trying to figure out this one...

I'm working on a map with no extra settlements. I made a looping trigger that is supposed to invoke a god power at the location of the player's settlements. Gaia will use the GP, and has vision on each of the players' settlements with a Revealer to Player.

Now I struggle to find what to put here :

rmSetTriggerEffectParam("DstPoint1", ???);

What should I put there to precisely target the starting settlement of each player?
Replies:
posted 29 August 2021 05:29 PM EDT (US)     1 / 16  
You need to use custom triggers that requires injection. This is a dated guide I wrote explaining how to do custom triggers. Once figure out you can use any trigger in random maps. Simplest is prob to do a kb query for the settlements and invoke at their location.

https://aom.heavengames.com/cgi-bin/forums/display.cgi?action=ct&f=13,29516,,all
posted 29 August 2021 06:54 PM EDT (US)     2 / 16  
I think I can wrap my head around adding custom trigger code. So I would need something like this to retrieve the settlements in question :

kbUnitQuerySetPlayerID("querySettlement"+i, i, true)
kbUnitQuerySetUnitType("querySettlement"+i, "settlement")
kbUnitQueryExecute("querySettlement"+i)

But then what? I find it very difficult to work with those variables because I don't know in what form they are returned. None of the echo functions I saw displayed anything in the debugger so I'm working in the dark. I need to find a way to retrieve their location in a format that can be digested by the Invoke God Power GP but I'm not sure what is it either.
posted 30 August 2021 07:01 AM EDT (US)     3 / 16  
posted 31 August 2021 05:44 AM EDT (US)     4 / 16  
Okay this is looking good. I use the links and stripped some parts of the code to make it simpler, but something still prevents it to load, not sure what though. Any clue?

On a side note, I tried launching the EE with +debugRandomMaps but it doesn't change anything

int stringInvoke = "";
for(i=1; <cNumberPlayers) {

for(Qid=0;>1) {} //creating variables
for(UnitID=0;>1) {}
for(TempORVar=0;>1) {}
for(finalORResult=0;>1) {}
for(unitTypeID=0;>1) {}
for(pid=0;>1) {}
for(oldPlayer=xsGetContextPlayer();>99) {} //saving original player context
unitTypeID=kbGetProtoUnitID(2197);
pid=i;
xsSetContextPlayer(pid);
kbLookAtAllUnitsOnMap();
Qid = kbUnitQueryCreate("tp_query_convarea_1");
kbUnitQuerySetPlayerID(Qid, pid);
kbUnitQuerySetUnitType(Qid,unitTypeID);
kbUnitQuerySetState(Qid, 1*2);
kbUnitQuerySetAscendingSort(Qid, true);
for(j=kbUnitQueryExecute(Qid)-1;>-1){ //loop from number of units found by query down to zero
trUnitSelectClear();
UnitID = kbUnitQueryGetResult(Qid,j); //Saves the id of current unit in UnitID variable, which can be used in other effects in the same trigger.
trUnitSelectByID(UnitID); //Selects the unit.
invokeString = kbUnitGetPosition(unitID);

rmSwitchToTrigger(rmTriggerID("MeteorRain"+i));
rmSetTriggerPriority(3);
rmSetTriggerActive(true);
rmSetTriggerRunImmediately(false);
rmSetTriggerLoop(true);

rmAddTriggerEffect("Invoke God Power");
rmSetTriggerEffectParamInt("PlayerID", 0);
rmSetTriggerEffectParam("PowerName", "meteor");
rmSetTriggerEffectParam("DstPoint1", invokeString);
rmSetTriggerEffectParam("DstPoint2", invokeString);
}
}
}
posted 31 August 2021 06:18 AM EDT (US)     5 / 16  
You can't do it like that as you can only call xs and rm commands in the main script - have a look at my guide again. You need to use code tags for every line of code and use it in place of trigger effects. For some examples have a look at some of my scripts on my Steam workshop e.g. https://steamcommunity.com/sharedfiles/filedetails/?id=2585847403

[This message has been edited by nottud (edited 08-31-2021 @ 08:13 AM).]

posted 31 August 2021 07:58 PM EDT (US)     6 / 16  
Okay yea I see my mistake now. This is what I got now :
string invokeString = "";
for(i=1; <cNumberPlayers) {

for(Qid=0;>1) {} //creating variables
for(UnitID=0;>1) {}
for(unitTypeID=0;>1) {}
for(pid=0;>1) {}
code("unitTypeID=kbGetProtoUnitID(2197);");
pid=i;
code("xsSetContextPlayer(pid);");
code("kbLookAtAllUnitsOnMap();");
code("Qid=kbUnitQueryCreate(\"tp_query_convarea_1\");");
code("kbUnitQuerySetPlayerID(Qid, pid);");
code("kbUnitQuerySetUnitType(Qid,unitTypeID);");
code("kbUnitQuerySetState(Qid, 1*2);");
code("kbUnitQuerySetAscendingSort(Qid, true);");
code("for(j=kbUnitQueryExecute(Qid)-1;>-1){"); //loop from number of units found by query down to zero
code("trUnitSelectClear();");
code("UnitID = kbUnitQueryGetResult(Qid,j);"); //Saves the id of current unit in UnitID variable, which can be used in other effects in the same trigger.
code("trUnitSelectByID(UnitID);"); //Selects the unit.
code("invokeString = kbUnitGetPosition(unitID);");

rmCreateTrigger("MeteorRain"+i);
rmSwitchToTrigger(rmTriggerID("MeteorRain"+i));
code("trTechInvokeGodPower(0, \"Meteor\", invokeString, invokeString);");
rmSetTriggerPriority(3);
rmSetTriggerActive(true);
rmSetTriggerRunImmediately(false);
rmSetTriggerLoop(true);
code("}");
}


The result is the map doesn't crash any longer, although inside the triggers that it created it's just full of SetIdleProcessing. It's as if he jumped over the "trTechInvokeGodPower" line. I checked your code carefully to catch any glaring inconsistencies but I have a hard time seeing what I'm doing wrong.
posted 01 September 2021 06:34 AM EDT (US)     7 / 16  
If the trigger code is not valid the triggers will not run full stop which is probably what is going on. The SetIdleProcessing s are part of the hack to put the custom code in.

The for loops for creating variables should be inside code tags and the code above the trigger should be in the trigger above your invoke?
invokeString = kbUnitGetPosition(unitID);
This is not valid since it returns a vector not a string.

To get a good idea what is generated look at trigtemp after launching your map in trigger 2 folder to see what generated. For easier reading strip out the SetIdleProcessing calls.
posted 01 September 2021 08:56 PM EDT (US)     8 / 16  
Sorry to eternize the matter... here' what I got now.
for(i=1; <cNumberPlayers) {

code("for(Qid=0;>1) {}"); //creating variables
code("for(UnitID=0;>1) {}");
code("for(unitTypeID=0;>1) {}");
code("for(pid=0;>1) {}");
code("pid=i;");
rmCreateTrigger("MeteorRain"+i);
code("unitTypeID=kbGetProtoUnitID(2197);");
code("xsSetContextPlayer(pid);");
code("kbLookAtAllUnitsOnMap();");
code("Qid=kbUnitQueryCreate(\"tp_query_convarea_1\");");
code("kbUnitQuerySetPlayerID(Qid, pid);");
code("kbUnitQuerySetUnitType(Qid,unitTypeID);");
code("kbUnitQuerySetState(Qid, 1*2);");
code("kbUnitQuerySetAscendingSort(Qid, true);");
code("for(j=kbUnitQueryExecute(Qid)-1;>-1){"); //loop from number of units found by query down to zero
code("trUnitSelectClear();");
code("UnitID = kbUnitQueryGetResult(Qid,j);"); //Saves the id of current unit in UnitID variable, which can be used in other effects in the same trigger.
code("trUnitSelectByID(UnitID);"); //Selects the unit.
code("vector invokeString = kbUnitGetPosition(unitID);");
rmSwitchToTrigger(rmTriggerID("MeteorRain"+i));
code("trTechInvokeGodPower(0, \"Meteor\", invokeString, invokeString);");
rmSetTriggerPriority(3);
rmSetTriggerActive(true);
rmSetTriggerRunImmediately(false);
rmSetTriggerLoop(true);
code("}");
}


And the output looks like this :
trSetUnitIdleProcessing(true);
trSetUnitIdleProcessing();unitTypeID=kbGetProtoUnitID(2197);//);
trSetUnitIdleProcessing();xsSetContextPlayer(pid);//);
trSetUnitIdleProcessing();kbLookAtAllUnitsOnMap();//);
trSetUnitIdleProcessing();Qid=kbUnitQueryCreate("tp_query_convarea_1");//);
trSetUnitIdleProcessing();kbUnitQuerySetPlayerID(Qid, pid);//);
trSetUnitIdleProcessing();kbUnitQuerySetUnitType(Qid,unitTypeID);//);
trSetUnitIdleProcessing();kbUnitQuerySetState(Qid, 1*2);//);
trSetUnitIdleProcessing();kbUnitQuerySetAscendingSort(Qid, true);//);
trSetUnitIdleProcessing();for(j=kbUnitQueryExecute(Qid)-1;>-1){//);
trSetUnitIdleProcessing();trUnitSelectClear();//);
trSetUnitIdleProcessing();UnitID = kbUnitQueryGetResult(Qid,j);//);
trSetUnitIdleProcessing();trUnitSelectByID(UnitID);//);
trSetUnitIdleProcessing();vector invokeString = kbUnitGetPosition(unitID);//);
trSetUnitIdleProcessing();trTechInvokeGodPower(0, "Meteor", invokeString, invokeString);//);
trSetUnitIdleProcessing();}//);
trSetUnitIdleProcessing();for(Qid=0;>1) {}//);
trSetUnitIdleProcessing();for(UnitID=0;>1) {}//);
trSetUnitIdleProcessing();for(unitTypeID=0;>1) {}//);
trSetUnitIdleProcessing();for(pid=0;>1) {}//);
trSetUnitIdleProcessing();pid=i;//);
xsDisableRule("_MeteorRain1");
trEcho("Trigger disabling rule MeteorRain1");
trDelayedRuleActivation("_MeteorRain1");

It looks like the same thing pretty much, so I guess my trigger works is the issue?
posted 03 September 2021 08:03 AM EDT (US)     9 / 16  
The entire code needs to be inside where you create and switch the trigger - i.e. where the invoke is. For getting variable i in you need to do "+i+" to substitute it in.

My advice is to start with some simple pieces of code and get them working and find what does and doesn't work and work your way up to what you want. I think trying to big bang the whole lot when you are not familiar is proving difficult.

Start with a single trigger that say changes the lighting with a custom command - e.g. sunColor(255, 0, 0); will set lighting to red. If you get that working you know your triggers are running.
posted 08 September 2021 05:44 PM EDT (US)     10 / 16  
Yeah, the lightning color trick has proven itself very useful. Now I know that the following is working:
for(i=1; <cNumberPlayers) {
defineTrigger("meteorRain"+i+"r", true, false, true);

code("for(Qid=0;>1) {}"); //creating variables
code("for(unitID=0;>1) {}");
code("for(unitTypeID=0;>1) {}");
code("for(pid=0;>1) {}");
code("pid="+i+";");
code("unitTypeID=kbGetProtoUnitID(\"Settlement Level 1\");");
code("xsSetContextPlayer(pid);");
code("kbLookAtAllUnitsOnMap();");
code("Qid=kbUnitQueryCreate(\"tp_query_convarea_1\");");
code("kbUnitQuerySetPlayerID(Qid, pid);");
code("kbUnitQuerySetUnitType(Qid,unitTypeID);");
code("kbUnitQuerySetState(Qid, 1*2);");
code("kbUnitQuerySetAscendingSort(Qid, true);");
code("unitID = kbUnitQueryGetResult(Qid,kbUnitQueryExecute(Qid));"); //Saves the id of current unit in UnitID variable, which can be used in other effects in the same trigger.
code("trUnitSelectByID(unitID);"); //Selects the unit.
/*code("tempV = getPosition(unitID);");
code("tempV2 = xsVectorSet(xsVectorGetX(tempV), 0.0, xsVectorGetZ(tempV));");
code("trTechInvokeGodPower(0, \"Meteor\", tempV2, tempV2);");*/
}

It helped me narrow the problem down to those lines (uncommenting those breaks the lightning code):

code("tempV = getPosition(unitID);");
code("tempV2 = xsVectorSet(xsVectorGetX(tempV), 0.0, xsVectorGetZ(tempV));");
code("trTechInvokeGodPower(0, \"Meteor\", tempV2, tempV2);");

So back at it again, I have trouble getting the vector in a form that the game will digest.

I also tried using this method, but it still siltently fails.

code("invokeString = kbUnitGetPosition(unitID);");

So my guess now is that the query went through, because the syntax is valid and such, but it returned nothing.
posted 10 September 2021 10:52 AM EDT (US)     11 / 16  
tempV and tempV2 are undeclared that's why. You need to declare them:

code("vector tempV = getPosition(unitID);");
code("vector tempV2 = xsVectorSet(xsVectorGetX(tempV), 0.0, xsVectorGetZ(tempV));");
posted 15 September 2021 05:31 AM EDT (US)     12 / 16  
Even then, it still doesn't fire the triggers.

I was starting to suspect that unitID was empty or wrong, but the line just before about selecting the unit works fine; it selects my town center, but anything past that won't work proprely.
posted 21 September 2021 03:12 AM EDT (US)     13 / 16  
getPosition call where is that coming from? That isn't an existing game function (Might be one of my internal functions).

Replace with: kbGetBlockPosition(kbGetBlockID(\"\"+unitID))

[This message has been edited by nottud (edited 09-21-2021 @ 03:12 AM).]

posted 21 September 2021 05:16 AM EDT (US)     14 / 16  
Oh yes, it was one of your functions, I completely missed this one.

So I tried :
code("tempV = kbGetBlockPosition(kbGetBlockID(\"\"+unitID));");

but that makes the SunColor thing not fire. For justice, I also tried :
code("tempV = kbUnitGetPosition(unitID);");

This one doesn't interrupt the SunColor, but it does nothing unfortunately.

For safety I checked if my triggers worked if I input the vectors manually, and they do.
posted 21 September 2021 02:51 PM EDT (US)     15 / 16  
Ah apologies I gave the wrong command - it should be:

code("tempV = kbGetBlockPosition(\"\"+trGetUnitScenarioNameNumber(unitID));");
posted 23 September 2021 08:53 PM EDT (US)     16 / 16  
Darn it, it still doesn't work... The sun color thing doesn't wear off though, which I guess is a good sign. Knowing that if I put the vectors manually it works, and that the query selects the right unit, the issue probably can't be anywhere else.
Age of Mythology Heaven » Forums » Modding and Scripting » RMS - Get location of player's settlement
Top
You must be logged in to post messages.
Please login or register
Hop to:    
Age of Mythology Heaven | HeavenGames