Follow Ship Code
Moderators: angster, RoryAndersonCDT, michaelm75au, MOD_Command
Follow Ship Code
JM posted a question here about some code to follow a ship.
https://www.matrixgames.com/forums/tm.asp?m=5122003
Here's a solution. Its is not detection-based (bigger project) but should be suitable for the AI to just trail something.
--AI chase solution. Not perfect as its cheating abit as its not based on detection but will model a unit following a unit at a distance.
-- Setup is to create a support mission with a reference point and assign your chasing unit to it. Place the unit at a distance that makes sense.
--You set the script below to run periodically. You can determine what's reasonable.
local MeepMeep = ScenEdit_GetUnit({guid='1T8G9D-0HMED9MJH8QTB'})--Unit to be Followed
local MeepCounter = ScenEdit_GetKeyValue("Meeps");--Of coarse you can store meeps ya Maroon!
local MeepCounterF = tonumber(MeepCounter)
if MeepCounterF == nil then
MeepCounterF = 0;
end
MeepCounterF = MeepCounterF +1;
local MeepDel = (MeepCounterF) -1;
if MeepMeep ~= Nil then
ScenEdit_SetKeyValue("Meeps", tostring(MeepCounterF));
ScenEdit_AddReferencePoint({side='WilyECoyote', name=tostring(MeepCounterF),latitude=MeepMeep.latitude, longitude=MeepMeep.longitude, highlighted=true})--Drops a reference point at the targets position
ScenEdit_SetMission('WilyECoyote', 'RoadrunnerChase',{zone={(MeepCounterF)}}) --Adds the reference point to your support mission mission and unassings the old points.
ScenEdit_SetUnit({name='Coyote', guid='1T8G9D-0HMED9MJH8R7N',manualSpeed=(MeepMeep.speed)})--matches target speed
ScenEdit_DeleteReferencePoint({side='WilyECoyote', name=(MeepDel)})--Cleaning up the last reference point
else
end
Attached file has the code in an event action and special action so you can see how to set it up.
https://www.matrixgames.com/forums/tm.asp?m=5122003
Here's a solution. Its is not detection-based (bigger project) but should be suitable for the AI to just trail something.
--AI chase solution. Not perfect as its cheating abit as its not based on detection but will model a unit following a unit at a distance.
-- Setup is to create a support mission with a reference point and assign your chasing unit to it. Place the unit at a distance that makes sense.
--You set the script below to run periodically. You can determine what's reasonable.
local MeepMeep = ScenEdit_GetUnit({guid='1T8G9D-0HMED9MJH8QTB'})--Unit to be Followed
local MeepCounter = ScenEdit_GetKeyValue("Meeps");--Of coarse you can store meeps ya Maroon!
local MeepCounterF = tonumber(MeepCounter)
if MeepCounterF == nil then
MeepCounterF = 0;
end
MeepCounterF = MeepCounterF +1;
local MeepDel = (MeepCounterF) -1;
if MeepMeep ~= Nil then
ScenEdit_SetKeyValue("Meeps", tostring(MeepCounterF));
ScenEdit_AddReferencePoint({side='WilyECoyote', name=tostring(MeepCounterF),latitude=MeepMeep.latitude, longitude=MeepMeep.longitude, highlighted=true})--Drops a reference point at the targets position
ScenEdit_SetMission('WilyECoyote', 'RoadrunnerChase',{zone={(MeepCounterF)}}) --Adds the reference point to your support mission mission and unassings the old points.
ScenEdit_SetUnit({name='Coyote', guid='1T8G9D-0HMED9MJH8R7N',manualSpeed=(MeepMeep.speed)})--matches target speed
ScenEdit_DeleteReferencePoint({side='WilyECoyote', name=(MeepDel)})--Cleaning up the last reference point
else
end
Attached file has the code in an event action and special action so you can see how to set it up.
- Attachments
-
- Test Chase.zip
- (14.32 KiB) Downloaded 17 times
Don't call it a comeback...
RE: Follow Ship Code
nice, thx. Always fun to try lua stuff
regards GJ
regards GJ
RE: Follow Ship Code
Updated with the reference point cleanup lines in.
Mike
Mike
Don't call it a comeback...
RE: Follow Ship Code
Mike, thx.
I tried to learn from it in my own test scen, works great. From another lesson I got, I took how to put the RP in another position. Thx KH.
I put what I made in here, you or someone else might see stupid things or addons. Love to hear if thats the case.
A question, when allowed: could you make some sort of a condition that a specific unit is detected by the AGI side?
local shadowed = ScenEdit_GetUnit({guid='P7ML9T-0HMECC07850U3'})--Unit to be Followed
local ShCounter = ScenEdit_GetKeyValue("ShRps");--Of coarse you can store ShRps ya Maroon!
local ShCounterF = tonumber(ShCounter)
local Brg1 = 090;
local Dist1 = 10;
local pt = World_GetPointFromBearing({LATITUDE=shadowed.latitude,LONGITUDE=shadowed.longitude,BEARING=Brg1, DISTANCE=Dist1});
if ShCounterF == nil then
ShCounterF = 0;
end
ShCounterF = ShCounterF +1;
if shadowed ~= Nil then
ScenEdit_SetKeyValue("ShRps", tostring(ShCounterF));
ScenEdit_AddReferencePoint({side='Brown', name='Sh'..tostring(ShCounterF), lat=pt.latitude,lon=pt.longitude, highlighted=true})--Drops a reference point at the targets position
ScenEdit_DeleteReferencePoint ({side='Brown', name='Sh'..tostring(ShCounterF-1)}) -- deletes old Sh RP's
ScenEdit_SetMission('Brown', 'ShadowByAgi',{zone={('Sh'..tostring(ShCounterF))}}) --Adds the reference point to your support mission mission and unassings the old points.
ScenEdit_SetUnit({name='AGI#1', guid='P7ML9T-0HMEDSB8JT06O',manualSpeed=10})--matches target speed
else
end
regards GJ
ps Claude I don't wanna steel your question, just like to possibilities
I tried to learn from it in my own test scen, works great. From another lesson I got, I took how to put the RP in another position. Thx KH.
I put what I made in here, you or someone else might see stupid things or addons. Love to hear if thats the case.
A question, when allowed: could you make some sort of a condition that a specific unit is detected by the AGI side?
local shadowed = ScenEdit_GetUnit({guid='P7ML9T-0HMECC07850U3'})--Unit to be Followed
local ShCounter = ScenEdit_GetKeyValue("ShRps");--Of coarse you can store ShRps ya Maroon!
local ShCounterF = tonumber(ShCounter)
local Brg1 = 090;
local Dist1 = 10;
local pt = World_GetPointFromBearing({LATITUDE=shadowed.latitude,LONGITUDE=shadowed.longitude,BEARING=Brg1, DISTANCE=Dist1});
if ShCounterF == nil then
ShCounterF = 0;
end
ShCounterF = ShCounterF +1;
if shadowed ~= Nil then
ScenEdit_SetKeyValue("ShRps", tostring(ShCounterF));
ScenEdit_AddReferencePoint({side='Brown', name='Sh'..tostring(ShCounterF), lat=pt.latitude,lon=pt.longitude, highlighted=true})--Drops a reference point at the targets position
ScenEdit_DeleteReferencePoint ({side='Brown', name='Sh'..tostring(ShCounterF-1)}) -- deletes old Sh RP's
ScenEdit_SetMission('Brown', 'ShadowByAgi',{zone={('Sh'..tostring(ShCounterF))}}) --Adds the reference point to your support mission mission and unassings the old points.
ScenEdit_SetUnit({name='AGI#1', guid='P7ML9T-0HMEDSB8JT06O',manualSpeed=10})--matches target speed
else
end
regards GJ
ps Claude I don't wanna steel your question, just like to possibilities
RE: Follow Ship Code
ORIGINAL: Parel803
Mike, thx.
I tried to learn from it in my own test scen, works great. From another lesson I got, I took how to put the RP in another position. Thx KH.
I put what I made in here, you or someone else might see stupid things or addons. Love to hear if thats the case.
A question, when allowed: could you make some sort of a condition that a specific unit is detected by the AGI side?
local shadowed = ScenEdit_GetUnit({guid='P7ML9T-0HMECC07850U3'})--Unit to be Followed
local ShCounter = ScenEdit_GetKeyValue("ShRps");--Of coarse you can store ShRps ya Maroon!
local ShCounterF = tonumber(ShCounter)
local Brg1 = 090;
local Dist1 = 10;
local pt = World_GetPointFromBearing({LATITUDE=shadowed.latitude,LONGITUDE=shadowed.longitude,BEARING=Brg1, DISTANCE=Dist1});
if ShCounterF == nil then
ShCounterF = 0;
end
ShCounterF = ShCounterF +1;
if shadowed ~= Nil then
ScenEdit_SetKeyValue("ShRps", tostring(ShCounterF));
ScenEdit_AddReferencePoint({side='Brown', name='Sh'..tostring(ShCounterF), lat=pt.latitude,lon=pt.longitude, highlighted=true})--Drops a reference point at the targets position
ScenEdit_DeleteReferencePoint ({side='Brown', name='Sh'..tostring(ShCounterF-1)}) -- deletes old Sh RP's
ScenEdit_SetMission('Brown', 'ShadowByAgi',{zone={('Sh'..tostring(ShCounterF))}}) --Adds the reference point to your support mission mission and unassings the old points.
ScenEdit_SetUnit({name='AGI#1', guid='P7ML9T-0HMEDSB8JT06O',manualSpeed=10})--matches target speed
else
end
regards GJ
ps Claude I don't wanna steel your question, just like to possibilities
Nice work and good idea about getting it detection based!
Mike
Don't call it a comeback...
RE: Follow Ship Code
Good afternoon,
I made same event but with two RP's (no doubt in very ineffective way). I left the speed line out to make use of the mission speeds for ship. My AGI goes with transit speed to a couiple of NM from line and switched to station speed.
I was wondering if the point were she switch to station speed is a fixed distance to the support mission line?
Realazing it's not a LUA question but maybe someone already having the answer.
best regards GJ
I made same event but with two RP's (no doubt in very ineffective way). I left the speed line out to make use of the mission speeds for ship. My AGI goes with transit speed to a couiple of NM from line and switched to station speed.
I was wondering if the point were she switch to station speed is a fixed distance to the support mission line?
Realazing it's not a LUA question but maybe someone already having the answer.
best regards GJ
RE: Follow Ship Code
Good afternoon,
A question:
Can I make a condition (to put in the event) that an unit a contact is for a specific side?
This works great in an event, like said bit cheating. Could I somehow make a condition that only lets it fire when the AGI side has this unit (that is shadowed) on a sensor as a contact.
Hope it makes some sense.
best regards GJ
A question:
Can I make a condition (to put in the event) that an unit a contact is for a specific side?
This works great in an event, like said bit cheating. Could I somehow make a condition that only lets it fire when the AGI side has this unit (that is shadowed) on a sensor as a contact.
Hope it makes some sense.
best regards GJ
RE: Follow Ship Code
ORIGINAL: Parel803
Good afternoon,
A question:
Can I make a condition (to put in the event) that an unit a contact is for a specific side?
This works great in an event, like said bit cheating. Could I somehow make a condition that only lets it fire when the AGI side has this unit (that is shadowed) on a sensor as a contact.
Hope it makes some sense.
best regards GJ
There is a get contact so you can probably evaluate it a bunch of different ways. The problem is- its a shit to of time to sort to little gain other than a -yeah me! Do I want to spend a Saturday/Sunday playing the game or writing code for a small thing? Sometime letting things go is the smarter play in the overall scheme of things. So basically I have an awesome excuse for not taking this up for a long time[8D]
Mike
Don't call it a comeback...
RE: Follow Ship Code
Mike,
Np thanks for answering
regards GJ
Np thanks for answering
regards GJ
RE: Follow Ship Code
ORIGINAL: Parel803
Mike,
Np thanks for answering
regards GJ
Good luck if it's your jam! That's how I roll.
M
Don't call it a comeback...
RE: Follow Ship Code
Can I make a condition (to put in the event) that an unit a contact is for a specific side?
For an example of using GetContact to determine what your side knows about a particular Unit, check out lines 169-184 of this: https://github.com/musurca/IKE/blob/mai ... m_msgs.lua
Basically, every Unit has a field called .ascontact which is a table of how it appears as a Contact to all sides in the scenario. You can query this table to get the GUIDs of the corresponding Contacts, their apparent positions, and how much is known about what they actually are. (The .classificationlevel field of the Contact wrapper is particularly useful, as it tells you on a scale 0-4 how much is known about the Contact. A value of 3, for example, means that the Unit class is known, but not the name.)
The tricky thing about the .ascontact table is that the Contacts are not indexed by Side name, but by Side GUID -- which is (I think) the only place in the API where this is the case. You can find the GUID that corresponds to a Side via VP_GetSides().
-
KnightHawk75
- Posts: 1850
- Joined: Thu Nov 15, 2018 7:24 pm
RE: Follow Ship Code
My own memory tells me you are correct there.which is (I think) the only place in the API where this is the case.
RE: Follow Ship Code
Thank you,
Going to check it out.
best regards GJ
Going to check it out.
best regards GJ
RE: Follow Ship Code
PITA stuff like this would be worth a paying into patreon, Kofi or something like that. I'd gladly pay out few clams to make the pain of doing this go away.
Mike
Mike
Don't call it a comeback...
RE: Follow Ship Code
I tried this:
local u = ScenEdit_GetUnit({name='P 840 Holland', guid='P7ML9T-0HMFADT2S1EQI'})
--print (u.ascontact)
for k, contact in ipairs(u.ascontact) do
if contact.side == 'P7ML9T-0HMECBS5C0K1S' then
local c = ScenEdit_GetContact({side='P7ML9T-0HMECBS5C0K1S', guid=contact.guid})
--print (c.guid)
if (c) ~= nil then
return true
else
return false
end
end
end
At first glance this looks like what I intended in the condition of the event. I do apologize if I do not understand all the English words and phrases on the forum.
If there are obvious mistake I would like to hear it, realizing time is a precious thing. It's not by understanding on my part but copy/paste & trial/error.
best regards GJ
local u = ScenEdit_GetUnit({name='P 840 Holland', guid='P7ML9T-0HMFADT2S1EQI'})
--print (u.ascontact)
for k, contact in ipairs(u.ascontact) do
if contact.side == 'P7ML9T-0HMECBS5C0K1S' then
local c = ScenEdit_GetContact({side='P7ML9T-0HMECBS5C0K1S', guid=contact.guid})
--print (c.guid)
if (c) ~= nil then
return true
else
return false
end
end
end
At first glance this looks like what I intended in the condition of the event. I do apologize if I do not understand all the English words and phrases on the forum.
If there are obvious mistake I would like to hear it, realizing time is a precious thing. It's not by understanding on my part but copy/paste & trial/error.
best regards GJ
-
KnightHawk75
- Posts: 1850
- Joined: Thu Nov 15, 2018 7:24 pm
RE: Follow Ship Code
@parel803
These may be helpful, more than you need for your exact specifics, but also flexible for other uses.
Usage:
Assume 4FH7PU-0HMFAK0FJQ7F5 is some Blue ship guid (unit being followed)
Assume 4FH7PU-0HMFAK0FJQ94G is some Red Unit guid (who you want to know if it specifically has spotted the ship recently)
These may be helpful, more than you need for your exact specifics, but also flexible for other uses.
Code: Select all
function getUpdatedSideTable()
local sides = VP_GetSides();
local t ={}
for k,v in pairs(sides) do t[v.name] = v.guid; end
return t;
end
Code: Select all
--// function to determine if a contact has been detected by a side in a given amount of time.
--// optionally can either do it based on detection age overall, or specific to a particular unit, or age and particular.
--//requires: build 1147.34+ (contact last detection table added)
---@param viewSidename string - required name of the side the contact guid is associated with.
---@param contactGuid string - required guid of the contact object.
---@param ageSeconds? number - optional number of seconds; last detection time qualifier. (less than or eq)
---@param detectorGuid? string - optional guid of the unit doing the detecting. ie has this particular unit detected the contact recently.
---@return boolean - true|false - true if qualified match found.
function isContactRecentlyDetectedBySide(viewSidename,contactGuid,ageSeconds,detectorGuid)
local retval,c = pcall(ScenEdit_GetContact,{side=viewSidename,guid=contactGuid});
if (retval) and c ~=nil then
if c.lastDetections ~=nil then
Code: Select all
for i=1,#c.lastDetections do
if ageSeconds < 0 and detectorGuid ==nil then --error
print('age and detector guid can not both be empty, aborting.'); return false;
elseif ageSeconds < 0 and detectorGuid ~=nil then -- no age check just unit.
if (c.lastDetections[i].detector_guid ~=nil) and c.lastDetections[i].detector_guid == detectorGuid then
return true;
end
elseif ageSeconds > 0 and detectorGuid ~=nil then --specific unit and age check for that unit.
if (c.lastDetections[i].age ~=nil and c.lastDetections[i].detector_guid ~=nil) and c.lastDetections[i].age <= ageSeconds and c.lastDetections[i].detector_guid == detectorGuid then
return true;
end
elseif ageSeconds > 0 and detectorGuid ==nil then -- just age
if (c.lastDetections[i].age ~=nil) and c.lastDetections[i].age <= ageSeconds then
return true;
end
end
end
end
else print('Contact guid does not exist on that side.');
end
return false;
end
Code: Select all
--// Return true if unit is a contact on a given side.
--// Can optionally further check if contact was last detected in a given amount of seconds.
--// Can optionally further check if contact was as last detected in given time, specific unit, or both
--//requires: build 1147.34+
---@param unitGuid string - The guid of the unit.
---@param bySideName string - The sidename to search for this unit as a contact on.
---@param ageSeconds? number - Optional time age in seconds (< or eq to this time)
---@param detectorGuid? string - optional guid of the unit doing the detecting. ie has this particular unit detected the contact recently.
---@return boolean - true|false - true if qualifying match
function isContactByUnitGuid(unitGuid,bySideName,ageSeconds,detectorGuid)
if unitGuid == nil then print ('Missing unitGuid param. aborting.'); return false; end
if bySideName == nil then print('Missing bySideName param aborting.'); return false; end
if ageSeconds == nil then ageSeconds = -1; end
local retval,realUnit = pcall(ScenEdit_GetUnit,{guid=unitGuid});
if ((retval) and realUnit ~=nil) then
if realUnit.ascontact ~=nil then
local sidetable = getUpdatedSideTable();
Code: Select all
for _,c in pairs(realUnit.ascontact) do
if c.side == sidetable[bySideName] then
if ageSeconds == -1 then return true; --skip recent detection check.
elseif isContactRecentlyDetectedBySide(bySideName,c.guid,ageSeconds,detectorGuid) then return true; end
end
end
end
else print("A unit with that guid does not exist.");
end
return false;
end
Usage:
Assume 4FH7PU-0HMFAK0FJQ7F5 is some Blue ship guid (unit being followed)
Assume 4FH7PU-0HMFAK0FJQ94G is some Red Unit guid (who you want to know if it specifically has spotted the ship recently)
Code: Select all
--Is this unit a contact on side Red?
print(isContactByUnitGuid('4FH7PU-0HMFAK0FJQ7F5',"Red")); --all you need if I read the thread right.
--Is this unit a contact on side Red, and if so has it been seen in the last 60 seconds by any Red unit.
print(isContactByUnitGuid('4FH7PU-0HMFAK0FJQ7F5',"Red",180)); -- if you want to make sure the contact is reasonably fresh.
--Is this unit a contact on side Red, and if so has it been seen in the last 60 seconds by a specific unit.
print(isContactByUnitGuid('4FH7PU-0HMFAK0FJQ7F5',"Red",60,"4FH7PU-0HMFAK0FJQ94G"));
RE: Follow Ship Code
Thanks for answers and your time.
It's going very slow but learning all the time.
regards GJ
It's going very slow but learning all the time.
regards GJ