Follow Ship Code (Full Version)

All Forums >> [New Releases from Matrix Games] >> Command: Modern Operations series >> Mods and Scenarios >> Lua Legion



Message


BDukes -> Follow Ship Code (1/1/2022 9:54:32 PM)

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.






Parel803 -> RE: Follow Ship Code (1/2/2022 12:52:54 PM)

nice, thx. Always fun to try lua stuff
regards GJ




BDukes -> RE: Follow Ship Code (1/2/2022 2:30:26 PM)

Updated with the reference point cleanup lines in.

Mike




Parel803 -> RE: Follow Ship Code (1/2/2022 4:37:24 PM)

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




BDukes -> RE: Follow Ship Code (1/2/2022 4:46:25 PM)


quote:

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




Parel803 -> RE: Follow Ship Code (1/3/2022 2:53:04 PM)

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




Parel803 -> RE: Follow Ship Code (2/6/2022 12:35:30 PM)

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




BDukes -> RE: Follow Ship Code (2/6/2022 1:56:18 PM)


quote:

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 **** 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




Parel803 -> RE: Follow Ship Code (2/6/2022 2:04:18 PM)

Mike,
Np thanks for answering
regards GJ




BDukes -> RE: Follow Ship Code (2/6/2022 2:06:37 PM)


quote:

ORIGINAL: Parel803

Mike,
Np thanks for answering
regards GJ



Good luck if it's your jam! That's how I roll.

M




musurca -> RE: Follow Ship Code (2/6/2022 9:17:10 PM)

quote:

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/main/src/pbem_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 -> RE: Follow Ship Code (2/6/2022 10:45:01 PM)

quote:

which is (I think) the only place in the API where this is the case.

My own memory tells me you are correct there.




Parel803 -> RE: Follow Ship Code (2/7/2022 6:10:18 PM)

Thank you,
Going to check it out.
best regards GJ




BDukes -> RE: Follow Ship Code (2/7/2022 7:05:24 PM)

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




Parel803 -> RE: Follow Ship Code (2/7/2022 7:45:13 PM)

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




KnightHawk75 -> RE: Follow Ship Code (2/8/2022 3:17:02 AM)

@parel803
These may be helpful, more than you need for your exact specifics, but also flexible for other uses.

function getUpdatedSideTable()
  local sides = VP_GetSides();
  local t ={}
  for k,v in pairs(sides) do t[v.name] = v.guid; end
  return t;
end
--// 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
      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

--// 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();
      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)
--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"));




Parel803 -> RE: Follow Ship Code (2/8/2022 6:15:25 AM)

Thanks for answers and your time.
It's going very slow but learning all the time.

regards GJ




Page: [1]

Valid CSS!




Forum Software © ASPPlayground.NET Advanced Edition 2.4.5 ANSI
2.75