Jump to content

Script request


Shahdoh

Recommended Posts

The Virtual Aerobatic server is having a problem with people coming in and selecting aircraft they are not authorized to fly. What then happens is that the AI takes over and flies a brief time. Usually this is not a problem till that same person jumps into a dozen different aircraft spawning that many different aircraft to the server and or the AI spams comms, sometimes causing the server to crash (we think).

 

1st, is there a way to keep this from happening, and if not, wondering if a script could be implemented to remove the AI aircraft. We have 2 tankers in the air so they would need to be left alone obviously.

 

Appreciate any help on the matter.

 

/Salute

Link to comment
Share on other sites

There are several different approaches to find a solution. Depends more or less on your sever operation.

 

1. Do you want random public players to be restricted to certain

a) types?

b) groups?

c)airfields?

 

2. Do want to remove all AI controlled planes, which do not meet the criteria type "KC-135"?

 

3. Do you want to limit certain planes to certain to be used only by certain players?

 

I didn´t test this, but you could try if it works: (This should remove every group left by a player)

 

removeidleplanes = {}    
function removeidleplanes:onEvent(event)
   if event.id == world.event.S_EVENT_PLAYER_LEAVE_UNIT 
   then
       local leftunit = event.initiator --if not working try = event.place
       local playername = Unit.getPlayerName(leftunit)
       trigger.action.outText(playername.." left his cockpit",5)
       local leftgroup = Unit.getGroup(leftunit)
       
       if Group.isExist(leftgroup)
           then
               leftgroup:destroy()
               trigger.action.outText("group removed",5)
       else
       trigger.action.outText("group does not exist",5)
       end

   end
end
world.addEventHandler(removeidleplanes)


Edited by SNAFU

[sIGPIC][/sIGPIC]

 

Unsere Facebook-Seite

Link to comment
Share on other sites

Thanks for the reply,

 

 

We don't want to restrict the players to anything, UNLESS there is a way to restrict them to what they are authorized to fly. But, I imagine if this was possible, DCS would already be doing it.

 

Your option 2 is basically what we are looking for, remove any AI controlled aircraft that we don't have an exception for (We run both the US tanker and the Russian).

 

Will give this code a shot and see how it works.

 

Thanks again

Link to comment
Share on other sites

Just using Unit.getPlayerName() should return nil if a client is not in the aircraft. Thus if you iterate through a list of client aircraft names and Unit.getPlayerName() is nil on an alive aircraft, then you can despawn the aircraft.

The right man in the wrong place makes all the difference in the world.

Current Projects:  Grayflag ServerScripting Wiki

Useful Links: Mission Scripting Tools MIST-(GitHub) MIST-(Thread)

 SLMOD, Wiki wishlist, Mission Editing Wiki!, Mission Building Forum

Link to comment
Share on other sites

The above code had errors. First error was trying to get player name on a unit that didn't have a player name anymore, code was not needed so I remarked it out. Then it error-ed on the

local leftgroup = Unit.getGroup(leftunit) line.

 

I looked at some other code for weapons use we run and tried to modify it for this purpose:

 

removeidleplanes = {}    
function removeidleplanes:onEvent(event)
   if event.id == world.event.S_EVENT_PLAYER_LEAVE_UNIT  then
	if event.initiator then
		local leftunit = event.initiator:getGroup()
		trigger.action.deactivateGroup(leftunit)
	end
   end    
end
world.addEventHandler(removeidleplanes)

 

 

It does not error, but it does not do anything either. We do not need to see any messages that it has done anything, just remove the AI.

 

Thanks

Link to comment
Share on other sites

Ok, I guess that it would make issues to get the player who just left the unit... ;) I use the trigger messages to check if something works as intended and remove them in the end, but it usually helps to find out where a script stuck.

 

I do not have a chance to fire up DCS and take a look before friday, but then I can take a look. I thought removing the plane previously used by player would be the most straight forward approach, but removing all AI units except the type "KC-135" should be "simple", too.

 

I would start with repeating function like:

 

local function removeAIexcept(_type)

   local exception = _type

   local allairunitsstart = nil
   local allairunitsstart = {}
   local allairunitsstart = mist.makeUnitTable('[plane]')
   
   allairunits = nil
   allairunits = {}
   
   for a = 1, #allairunitsstart
   do
       if Unit.getByName(allairunitsstart[a])
           then 
               if Unit.getPlayerName(Unit.getByName(allairunitsstart[a])) == nil
                   then
                       local AIunittype = Unit.getTypeName(Unit.getByName(allairunitsstart[a]))
                       if AIunittype ~= exception
                           then 
                               local AIunitgroup = Unit.getGroup(allairunitsstart[a])
                               AIunitgroup:destroy()
                       end
               end
       end
   end

return timer.getTime() + 2
end
timer.scheduleFunction(removeAIexcept, "KC-135", timer.getTime() + 5)

Again, I am currently travelling and have no chance to the check, so this is just theoretically... ;)


Edited by SNAFU

[sIGPIC][/sIGPIC]

 

Unsere Facebook-Seite

Link to comment
Share on other sites

Ok, did I mention, that this function requires MIST?

 

But let me take a look tomorrow, when I have time. This is itching myself for some time, when I am hosting myself. The problem with left player planes doesn´t occure on our squadron server strangely...

[sIGPIC][/sIGPIC]

 

Unsere Facebook-Seite

Link to comment
Share on other sites

I just checked this issue, but I couldn´t find a good solution.

 

Its easy to remove all AI except a define type from the map, but client planes are not included and somehow I cannot get the mist-function refreshed, which creates a table.

 

Another approach was to trigger different events, but this approach gets problems if I call units in events, which are not existing yet, when the function ist called. "On start up" event gets me a "pure virtual funciton error", whatever that is...

 

I tried to call up a delayed function on the birth event, but still get an error I cannot get straight ... I simply cannot see it at the moment, or I just don´t understand, whatever...

 

 

 

But testing in multiplayer enviroment I do not have any issues with AI taking over planes left by clients. I only have this issue in Mission editor enviroment. So I got lost and do not understand the problem with your server.

 

Here the part where I gave up... it works once, even if I get en error message (I do not understand the cause, because the syntax usually works), but the next time it doesn´t work anymore... so here I gave up...

 

(trigger messages are for debugging, and you see the try to delay the function, think it has issues calling up units not existing at the moment the event takes place...)

 

playersbirth = {}

function removeAIexcept()

   for a = 1, #playersbirth
   do
trigger.action.outText("test1", 400000)  --testing
       if playersbirth[a].unit~= nil
           then 
trigger.action.outText("test2", 400000)  --testing
               actualunit = playersbirth[a].unit
trigger.action.outText("test2", 400000)  --testing
               if Unit.getPlayerName(actualunit) == nil
                   then
trigger.action.outText("test3", 400000)  --testing
                       actualgroup = actualunit:getGroup()
trigger.action.outText("test4", 400000)  --testing
                       actualgroup:destroy()
               end



       end
   end
   
local allairunitsstartTable = mist.utils.tableShow(playersbirth)--for testing
trigger.action.outText("All planes on map: " ..allairunitsstartTable, 4) --testing


return timer.getTime() + 10
end
timer.scheduleFunction(removeAIexcept, nil , timer.getTime() + 5)


removeidleplanes = {}    
function removeidleplanes:onEvent(event)
   if event.id == world.event.S_EVENT_BIRTH
   then
       if event.initiator~= nil
           then
               _leftunitname = event.initiator:getName()
trigger.action.outText("btest2-".._leftunitname, 4)  --testing
               
               timer.scheduleFunction(listPlayer, nil , timer.getTime() + 1)
               --[[
               if Unit.isExist(Unit.getByName(_leftunitname))
                   then
                   _leftunit = Unit.getByName(_leftunitname)
   trigger.action.outText("btest4-", 4)  --testing
                   _playername = Unit.getPlayerName(_leftunit)
   trigger.action.outText("btest5-".._playername, 4)  --testing
                   playersbirth[#playersbirth +1] =
                   {
                   unit = _leftunit,
                   name = _playername
                   }
               end
               --]]
       end
   end    
end
world.addEventHandler(removeidleplanes)

function listPlayer()
   if Unit.isExist(Unit.getByName(_leftunitname))
                   then
                   _leftunit = Unit.getByName(_leftunitname)
   trigger.action.outText("btest4-", 4)  --testing
                   _playername = Unit.getPlayerName(_leftunit)
   trigger.action.outText("btest5-".._playername, 4)  --testing
                   playersbirth[#playersbirth +1] =
                   {
                   unit = _leftunit,
                   name = _playername
                   }
   end
end

[sIGPIC][/sIGPIC]

 

Unsere Facebook-Seite

Link to comment
Share on other sites

Ok, thanks for trying. Do you have all modules? We have a bit of everything, including the Hawk and F-18 mod. You can come and see for yourself on the Virtual Aerobatic Public server. Jump into an aircraft you don't own or have the mod for and you will see an AI fly the plane, Your name ( or whoever did it) will be shown but you will not be in control.

 

Now if you have the mod for the aircraft, and the same happens, more then likely the aircraft is tied up with AI by someone who selected that aircraft without owning the module for it. That AI controlled aircraft will stay in game till it lands and certain amount of time goes by, or the person who spawned it leaves the server. It can also be collided with to destroy, but generally takes multiple attempts (weapons are not permitted on the server).

 

I'm trying to use what Grimes said by checking for if it has a player tied to it, if not to remove it. Can deal with saving the tankers once I get it working.

Link to comment
Share on other sites

Since you are using mist...

 

for unitName, unitData in pairs(mist.DBs.humansByName) do

if Unit.getByName(unitName) and not Unit.getByName(unitName):getPlayerName() then

Unit.getByName(unitName):destroy()

end

end

 

Run that periodically. What it does is the mist.DBs.humansByName is populated by all aircraft set to the skill of "client" or "player" in the mission editor. So it only consists of units that can ever be clients. It checks if the unit exists (Unit.getByname) and then checks if nothing is returned with Unit.getPlayerName, if not, then it destroys the unit.

The right man in the wrong place makes all the difference in the world.

Current Projects:  Grayflag ServerScripting Wiki

Useful Links: Mission Scripting Tools MIST-(GitHub) MIST-(Thread)

 SLMOD, Wiki wishlist, Mission Editing Wiki!, Mission Building Forum

Link to comment
Share on other sites

At first it was looking like it was working perfectly, when testing multi-player flying on server I hosted. With the current code, it looks like it never even creates the AI. But, when a client connects and chooses an aircraft they don't own, it stays around like before.

 

Here is the code as I have it in the mission, being called in by a one time trigger call (after Mist 3.2 loads of course):

 

 

local function removeclientAI()
for unitName, unitData in pairs(mist.DBs.humansByName) do
	if Unit.getByName(unitName) and not Unit.getByName(unitName):getPlayerName() then
		Unit.getByName(unitName):destroy()
	end
end
end
   local AIHandler = function(event)
       if event.id ~= nil then
                   timer.scheduleFunction(removeclientAI, nil, timer.getTime() + 0.1)
       end
   end
mist.addEventHandler(AIHandler)

 

Link to comment
Share on other sites

Says right in the script docs that the destroy method is local only.

 

"destroys the object without making damage to it and generation any event. The object just disappear. For now it is impossible to destroy remote objects."

 

http://en.wiki.eagle.ru/wiki/Simulator_Scripting_Engine/DCS:_World/Part_2#Object

 

 

However, from my old script research I found that group:destroy() does work remotely, which is why my troop drop/pickup scripts operated on the group level, not individual units.


Edited by Deck
Link to comment
Share on other sites

Pretty sure the documentation is not accurate in this regard. I've tested it on a client aircraft and it despawned him just fine. But that was tested a while ago.

The right man in the wrong place makes all the difference in the world.

Current Projects:  Grayflag ServerScripting Wiki

Useful Links: Mission Scripting Tools MIST-(GitHub) MIST-(Thread)

 SLMOD, Wiki wishlist, Mission Editing Wiki!, Mission Building Forum

Link to comment
Share on other sites

I suspect the AI aircraft spawned by clients are still returning a client name with that script. :(

 

Add an env.info() before it tries to destroy the unit to see if it is actually running Object.destroy() on the client aircraft.

The right man in the wrong place makes all the difference in the world.

Current Projects:  Grayflag ServerScripting Wiki

Useful Links: Mission Scripting Tools MIST-(GitHub) MIST-(Thread)

 SLMOD, Wiki wishlist, Mission Editing Wiki!, Mission Building Forum

Link to comment
Share on other sites

Ok, I didnt do the env.info thing, but used messages so I had a more direct feedback of what was happening.

 

1st test was that the event handler was calling the function. That proved successful.

2nd test was a msg right before the destroy statement, which worked when the host created the AI by spawning into an aircraft not owned (Mi8 in this case). Client connected, function call msg worked, but AI not deleted.

 

Knowing the function call was working, I remarked out that message, and inserted some others as shown in the code here:

 

local function removeclientAI()
totaltxt = ''
for unitName, unitData in pairs(mist.DBs.humansByName) do
--trigger.action.outText('lookin for AI', 2)
	if Unit.getByName(unitName) and not Unit.getByName(unitName):getPlayerName() then
		totaltxt = totaltxt ..'destroy the AI'
		Unit.getByName(unitName):destroy()
	elseif Unit.getByName(unitName) and Unit.getByName(unitName):getPlayerName() then
			totaltxt = totaltxt .. Unit.getByName(unitName).. " & " ..Unit.getByName(unitName):getPlayerName()
	else
	
		totaltxt = totaltxt .. 'Something else happening, conditions not met' 
	end
	trigger.action.outText(totaltxt, 5)
end
end
   local AIHandler = function(event)
       if event.id ~= nil then
                   timer.scheduleFunction(removeclientAI, nil, timer.getTime() + 0.1)
       end
   end
mist.addEventHandler(AIHandler)

 

 

Either I got something wrong (quite possible, not that great with Lua), or something is up with the if statements, in that even with people on the server flying owned aircraft, the checks are falling through to the ELSE statement. If more then 1 client is on the server, the code quits working for the host as well. I am even more confused then I was before.. :cry:

Link to comment
Share on other sites

Get the group class for the unit. Apparently a Unit object can't be destroyed... which is kind of weird, but whatever.

 

Unit.getByName(unitName):getGroup():destroy()

  • Like 1

The right man in the wrong place makes all the difference in the world.

Current Projects:  Grayflag ServerScripting Wiki

Useful Links: Mission Scripting Tools MIST-(GitHub) MIST-(Thread)

 SLMOD, Wiki wishlist, Mission Editing Wiki!, Mission Building Forum

Link to comment
Share on other sites

New results, but not the ones we are wanting.

 

The new code you provided is working to destroy the AI, but again, only if the aircraft is generated by the host. Also found out that cold start aircraft entered by the host is created and destroyed, where hot start aircraft are not created at all. This is the cause of the confusion from the previous test results.

 

The same does not happen for client created aircraft. The aircraft is spawned and not destroyed as the code still sees the player assigned to the aircraft (new messaging helped identify that) no matter if it is a hot or cold start.

 

local function removeclientAI()
totaltxt = ''
for unitName, unitData in pairs(mist.DBs.humansByName) do
trigger.action.outText('lookin for AI', 2)
	if Unit.getByName(unitName) and not Unit.getByName(unitName):getPlayerName() then
		totaltxt = totaltxt ..' *** destroy the AI *** '
		Unit.getByName(unitName):getGroup():destroy()
	elseif Unit.getByName(unitName) and Unit.getByName(unitName):getPlayerName() then
			totaltxt = totaltxt .. " %%% Found Player %%% " 
	else
	
		totaltxt = totaltxt .. ' --- not met --- ' 
	end
	trigger.action.outText(totaltxt, 5)
end
end

Link to comment
Share on other sites

Found success!! Putting it on the VA Public server for verification, but so far testing looks good.

Since it was still showing that it found a player for the client in the aircraft, I then listed player name as well. Ended up it was blank. So, the the argument to see if player name was false wasn't working for the client. Added an elseif to also check if the player name is blank and it is now removing the AI created by a client. Now if the player stays in the slot for the aircraft he does not own, the name stays on and the AI will not be removed. When he moves to another aircraft or goes to specatators, any event will trigger the removal of the empty AI.

 

local function removeclientAI()
for unitName, unitData in pairs(mist.DBs.humansByName) do
	if Unit.getByName(unitName) and not Unit.getByName(unitName):getPlayerName() then
		Unit.getByName(unitName):getGroup():destroy()
	elseif Unit.getByName(unitName) and Unit.getByName(unitName):getPlayerName() == '' then
		Unit.getByName(unitName):getGroup():destroy()
	elseif Unit.getByName(unitName) and Unit.getByName(unitName):getPlayerName() then
			
	else
	
	end
	--trigger.action.outText(totaltxt, 5)
end
end

   local AIHandler = function(event)
       if event.id ~= nil then
                   timer.scheduleFunction(removeclientAI, nil, timer.getTime() + 0.1)
       end
   end
mist.addEventHandler(AIHandler)

 

Thank you Grimes!

 

** Edited to included complete script - must have Mist loaded before this runs **


Edited by Shahdoh
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...