Jump to content

MOOSE - Mission Object Oriented Scripting Framework


Recommended Posts

@Scifer

 

Yes, the example that Pikey proposed should work, provided that the scheduler is defined in a variable.

 

It's just that MOOSE schedulers aren't my cup of tea, too complicated and "unwieldy" for my taste :cry:

 

Standard DCS schedulers are much simpler and easier to work with (at least for me), that's why I prefer them... but they're also more limited.

Link to comment
Share on other sites

For sure there are more lines to the moose one. But then when you use a single argument it becomes a run once after X seconds, when you add an argument you get a run once after X and repeat after x and when you add another it becomes the same but with a variance. So copy and paste it is :) I can't live without them, in fact if I had a script template it would have a scheduler at the bottom called "Main script", a bit like how I used another language which required a "While 1" in the main body

___________________________________________________________________________

SIMPLE SCENERY SAVING * SIMPLE GROUP SAVING * SIMPLE STATIC SAVING *

Link to comment
Share on other sites

Thanks for your help but Hardcard suggested a much more elegant way:

 

...

 

Can't MOOSE scheduler do the same?

 

 

Hi Scifer,

SCHEDULER has subtle arguments so that multiple things are achieved with differing optional arguments. But i think it was one of the more poorly documented classes.

With the first number argument it runs once after X seconds. With two, it runs repeatedly, with three it runs repeatedly but with a variance. With four it runs as before but now stops after X seconds. Which is much more flexible, if a tad longer for the basic timer.

 

 

Sure for a single use timer, it takes less characters to write timer lines, but if you were designing that class you would try to get the most out of a single function, so it's just the way it is, pick your poison.

___________________________________________________________________________

SIMPLE SCENERY SAVING * SIMPLE GROUP SAVING * SIMPLE STATIC SAVING *

Link to comment
Share on other sites

Is there a way to control a ship's speed with moose? Switch WP doesn't seem to work on ships unless I'm just doing it wrong which is entirely possible.

 

I want to have a radio command for the Carrier Group that will change their speed from 5kts to 25 kts, via radio command.

 

Is this possible?

Moe "Moespeeds" Colontonio

vVMA 231

http://www.vvma-231.com/

Looking for a serious US based Harrier Squadron? We are recruiting!

 

Link to comment
Share on other sites

Is there a way to control a ship's speed with moose? Switch WP doesn't seem to work on ships unless I'm just doing it wrong which is entirely possible.

 

I want to have a radio command for the Carrier Group that will change their speed from 5kts to 25 kts, via radio command.

 

Is this possible?

Frank does it with Airboss so it's possible, but I'm not sure how to do it, maybe have a look at his class.

___________________________________________________________________________

SIMPLE SCENERY SAVING * SIMPLE GROUP SAVING * SIMPLE STATIC SAVING *

Link to comment
Share on other sites

@Moe If you use TaskRouteToVec2() you can give it a speed.

 

or more simply,

 

https://flightcontrol-master.github.io/MOOSE_DOCS/Documentation/Wrapper.Controllable.html##(CONTROLLABLE).TaskRouteToZone

 

Can anyone verify that ARTY seems to be non-functional?

 

The dcs.log shows that they are activated correctly. When I use other methods to add illum to them, they show up in the log.

 

Specifically the breakage is in the part where the map marks are read/interpreted. When you click off the map mark, it's supposed to be read, but it isn't. The mark just remains there with no other activity.

 

Nothing in the logs at all.

 

It appears that DCS has changed something behind this, as even earlier MOOSE versions seem to not work.

 

I've tested/verified up to 2.5.0/devel.

 

ETA - Apparently the use of F10 marks in ARTY is "OFF" by default. When I set the method to use the marks, it started working!


Edited by fargo007
found the issue

 

Banner EDForum2020.jpg

Have fun. Don't suck. Kill bad guys. 👍

https://discord.gg/blacksharkden/

Link to comment
Share on other sites

Is it particularly difficult to automate who controls a base at a given time?? I'd like to be able to set up a script using moose so that if blue forces destroy all the red forces In a red airbase it triggers a chopper to spawn (don't care if it's in the air or not), fly to said ex-red airbase, land and drop off some troops thus turning the airbase blue) is this possible using moose and what would be the best way to go about it, just starting to learn MOOSE and thanks.

 

Martin

Link to comment
Share on other sites

@Moe If you use TaskRouteToVec2() you can give it a speed.

 

or more simply,

 

https://flightcontrol-master.github.io/MOOSE_DOCS/Documentation/Wrapper.Controllable.html##(CONTROLLABLE).TaskRouteToZone

 

Can anyone verify that ARTY seems to be non-functional?

 

The dcs.log shows that they are activated correctly. When I use other methods to add illum to them, they show up in the log.

 

Specifically the breakage is in the part where the map marks are read/interpreted. When you click off the map mark, it's supposed to be read, but it isn't. The mark just remains there with no other activity.

 

Nothing in the logs at all.

 

It appears that DCS has changed something behind this, as even earlier MOOSE versions seem to not work.

 

I've tested/verified up to 2.5.0/devel.

 

 

hmm doesn't sound good, I think this would require the miz and log together, I dont have any arty to hand, if you are in the discord frank is online for a sanity check elsewise drop it here.

___________________________________________________________________________

SIMPLE SCENERY SAVING * SIMPLE GROUP SAVING * SIMPLE STATIC SAVING *

Link to comment
Share on other sites

Is it particularly difficult to automate who controls a base at a given time?? I'd like to be able to set up a script using moose so that if blue forces destroy all the red forces In a red airbase it triggers a chopper to spawn (don't care if it's in the air or not), fly to said ex-red airbase, land and drop off some troops thus turning the airbase blue) is this possible using moose and what would be the best way to go about it, just starting to learn MOOSE and thanks.

 

Martin

Hi Martin, there is not a control for base ownership, it is a calculated result of the ground troops inside an invisible 2km range around the centre that DCS itself makes, so always represents what is actually there. What we do is ask DCS for the blue airbases and take actions there. It might not be compeltely simple if you are starting out and I'm concerned I'd put you off, but the way i did it in words was;

 

 

Create a spawn object that is scheduled and limited to the amount of units in your group template that you want to appear. Set the SpawnScheduled() to off.

Create a SCHEDULER that asks if that airbase is blue and use and if statement if so, to start the scheduler or stop it if not.

 

Here's something i have in my snippets you could adapt:

 

 

function checkblue(ABname) 
local tmp = coalition.getAirbases(2)
  for i=1,#tmp do
      if  tmp[i]:getName() == ABname then
        return true
      end
 end
end

MySpawn = SPAWN:New("MyLateActivatedGroupName"):InitLimit(1,0):SpawnScheduled(500,.2)
MySpawn:SpawnScheduleStop()

SCHEDULER:New( nil,
  function() 
   if checkblue("Batumi") then
   MySpawn:SpawnScheduleStart()
   else
   MySpawn:SpawnScheduleStop()
   end
 end, {}, 15, 30)

That will keep the late activated template group called 'MyLateActivatedGroupName' respawning whilst the airbase is Blue. I think I did an entire campaign based on this code sample, it's so simple.

 

NOTE: THE INITLIMIT IS SET TO "ONE" YOU HAVE TO CHANGE THAT TO THE NUMBER OF UNITS IN THE GROUP.

If InitLimit() is higher than the number of units, then it will spawn again to fill the number, if it is smaller than the number of units, no spawn will happen at all, so before you go creating a large occupying force with 20 units in it, change initlimit or you will have problems.

 

 

HTH, join the moose Discord for help.

___________________________________________________________________________

SIMPLE SCENERY SAVING * SIMPLE GROUP SAVING * SIMPLE STATIC SAVING *

Link to comment
Share on other sites

Pikey, could you point me to an example of a mission using this? I understand the concept, but I'm clueless as to the actual implementation.

 

 

This should work on a group called Stennis and a zone called aZoneName:

 

 

 

MyGroup = GROUP:FindByName('Stennis')

MyGroup:TaskRouteToZone( ZONE:New( "aZoneName" ), true, 28)end)

Note if you ever implement AIRBOSS you need to get rid of this as the two will argue.

There are more examples in https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/GRP%20-%20Group%20Commands

___________________________________________________________________________

SIMPLE SCENERY SAVING * SIMPLE GROUP SAVING * SIMPLE STATIC SAVING *

Link to comment
Share on other sites

@Pikey , I appreciate the reply and will take on-board what you guys say (I've been using LUA for exactly 4 days and am not at all experienced in it) , give me a few days to process what you said above haha.

 

In other news I was able to take much less elegant route to what I was trying to achieve. This is how I did it.

 

In the ME I created a Late Activated group of tanks (could be any ground Unit though) and I placed it inside the red airbase's aerodrome that I wanted the blue players to be able to take over)

 

I then created a trigger zone for each airbase that had red troops/Armour/defenses nearby and named it BTANKXXX where x is the base name. Being sure to include the actual red units inside the trigger zones.

 

Then in the trigger options of the ME i set triggers to All of Coalition Out of Zone>> activate group>>>>BTANKXXX again where XXX is name of the ground forces group.

 

It seems to work and with some quick testing when the red units get killed the blue ground units spawn and the base becomes blue.

 

Obviously i would much prefer to have this handled via lua (and probably have choppers/transport planes fly to the base and drop off troops/armor) rather than setting it up in the ME , but my 4 day coding experience isn't quite there yet!!!! (can we even see the code that the ME generates when you set stuff up using it rather than the scripts??)

 

 

 

As always thanks for creating MOOSE and keeping this community supported, you guys rock!

 

Martin

 

P.S. After having gone over and over the code you sent me Pikey and still not 100% understood it I think we mis-understood each other, or I'm just wrong, what i have is a bunch of red bases that id like to turn blue after the units/groups inside the DCS base radius have been destroyed, by spawning blue units upon the red units destruction in said airbase radius, preferably with a script. I'm not sure which parts of that script i should be changing to do this. The current bases I have set as red which id like to be able to turn to blue upon destruction of red forces are (Sochi, Gudauta, Sukhumi, Maykop, Mozdok, Nalchik, Beslan) It's highly likely that I screwed up the entire script , but heres what I changed:

 

 

function checkred(ABname)

local tmp = coalition.getAirbases(2)

for i=1,#tmp do

if tmp:getName() == ABname then

return true

end

end

end

 

BtankCapture = SPAWN:New("BtankCapture"):InitLimit(4,0):SpawnScheduled(500,.2)

BtankCapture:SpawnScheduleStop()

 

SCHEDULER:New( nil,

function()

if checkred("Sochi, Gudauta, Sukhumi, Maykop, Mozdok, Nalchik, Beslan") then

BtankCapture:SpawnScheduleStart()

else

BtankCapture:SpawnScheduleStop()

end

end, {}, 15, 30)

 

Thanks again

 

Martin


Edited by Badass1982
Link to comment
Share on other sites

@Pikey , I appreciate the reply and will take on-board what you guys say (I've been using LUA for exactly 4 days and am not at all experienced in it) , give me a few days to process what you said above haha.

 

In other news I was able to take much less elegant route to what I was trying to achieve. This is how I did it.

 

In the ME I created a Late Activated group of tanks (could be any ground Unit though) and I placed it inside the red airbase's aerodrome that I wanted the blue players to be able to take over)

 

I then created a trigger zone for each airbase that had red troops/Armour/defenses nearby and named it BTANKXXX where x is the base name. Being sure to include the actual red units inside the trigger zones.

 

Then in the trigger options of the ME i set triggers to All of Coalition Out of Zone>> activate group>>>>BTANKXXX again where XXX is name of the ground forces group.

 

It seems to work and with some quick testing when the red units get killed the blue ground units spawn and the base becomes blue.

 

Obviously i would much prefer to have this handled via lua (and probably have choppers/transport planes fly to the base and drop off troops/armor) rather than setting it up in the ME , but my 4 day coding experience isn't quite there yet!!!! (can we even see the code that the ME generates when you set stuff up using it rather than the scripts??)

 

 

 

As always thanks for creating MOOSE and keeping this community supported, you guys rock!

 

Martin

 

P.S. After having gone over and over the code you sent me Pikey and still not 100% understood it I think we mis-understood each other, or I'm just wrong, what i have is a bunch of red bases that id like to turn blue after the units/groups inside the DCS base radius have been destroyed, by spawning blue units upon the red units destruction in said airbase radius, preferably with a script. I'm not sure which parts of that script i should be changing to do this. The current bases I have set as red which id like to be able to turn to blue upon destruction of red forces are (Sochi, Gudauta, Sukhumi, Maykop, Mozdok, Nalchik, Beslan) It's highly likely that I screwed up the entire script , but heres what I changed:

 

 

function checkred(ABname)

local tmp = coalition.getAirbases(2)

for i=1,#tmp do

if tmp:getName() == ABname then

return true

end

end

end

 

BtankCapture = SPAWN:New("BtankCapture"):InitLimit(4,0):SpawnScheduled(500,.2)

BtankCapture:SpawnScheduleStop()

 

SCHEDULER:New( nil,

function()

if checkred("Sochi, Gudauta, Sukhumi, Maykop, Mozdok, Nalchik, Beslan") then

BtankCapture:SpawnScheduleStart()

else

BtankCapture:SpawnScheduleStop()

end

end, {}, 15, 30)

 

Thanks again

 

Martin

To turn an airbase blue after killing all the red in it, make it blue to begin with and that will just happen. Airbases revert to what they were set as in the ME when empty.

 

 

coalition.getAirbases(2) -- the "2" is for blue. 1 is for red. You can't change the name of a function and expect it to do what's inside differently.:)

 

As for the function execution, functions only accept the arguments they specify. In my case it's one argument, and it's a string and it's an airbase. So you need to go back to the working example and call them one at a time.

I do love your spirit though, being unafraid to try things. Just remember to keep looking at a log tailer and learning from all the "nopes" that Lua gives you, things will click, slowly at first, then with increasing speed. It might be the point now to read through the first four chapters of the Lua manual online now.


Edited by Pikey

___________________________________________________________________________

SIMPLE SCENERY SAVING * SIMPLE GROUP SAVING * SIMPLE STATIC SAVING *

Link to comment
Share on other sites

Assuming that "LaseCoordinate" works with the lastest version of Moose. How can I find the coordinates of a scenery knowing the object id value? Thanks :helpsmilie:

PC: i7-13700K - MSI RTX 4080 Gaming X Trio - 32GB DDR5 6200 - VPC MongoosT-50CM3 - VKB GF pro - MFG Crosswind - Msi MPG321UR-QD + Acer XB271HU - TrackIR5 - Rift S

Link to comment
Share on other sites

@Majinbot

 

What method are you using to find the ID of the scenery object? AFAIK, :getID() won't work on them and I don't think they can be found in the mission database either :huh:

 

Also, I don't know of any direct method to find specific scenery objects based on ID/Type/Name, etc.

 

Anyway, to get the coordinates of scenery objects (be it vec3 or LL DMS), I use world.searchObjects based on a zone (can be a moving zone), combined with a type filter (yes, type name must be known beforehand)... and pray there aren't other scenery objects of the same type around :lol:

 

local Scan_Zone = ZONE:New("ScanZone")

local Search_Area = {id = world.VolumeType.SPHERE, params = {point = Scan_Zone:GetVec3(0) , radius = 2000}}[color="Blue"] -- Radius must be at least 500 meters (~1600 feet) for the volume search to work!!![/color]

local function Evaluate_Zone(Scenery_Object)
        
   if Scenery_Object then
      
      if Scenery_Object:getPoint() and Scenery_Object:getTypeName() then
         
         if Scenery_Object:getTypeName() == "[color="Green"]Type of interest[/color]" then
            
              Scenery_Point = Scenery_Object:getPoint()
            
              Scenery_Coordinate = COORDINATE:NewFromVec3(Scenery_Point)
         
              Scenery_LLDMS = Scenery_Coordinate:ToStringLLDMS()
         end              
      end
   end
end

world.searchObjects(Object.Category.SCENERY, Search_Area, Evaluate_Zone)


Edited by Hardcard
Link to comment
Share on other sites

Assuming that "LaseCoordinate" works with the lastest version of Moose. How can I find the coordinates of a scenery knowing the object id value? Thanks :helpsmilie:

Hahah :) I like how you thought there was more chance of getting coordinate of scenery from DCS than a laser on a coordinate! We must have disappointed you greatly in the past! Not even the scenery id's are reliable in DCS, I have found duplicates and seen one explosion blow up something a mile away.

 

 

Perhaps let us know what you are trying to achieve, you probably already have the coordinate, just disregard the scenery

___________________________________________________________________________

SIMPLE SCENERY SAVING * SIMPLE GROUP SAVING * SIMPLE STATIC SAVING *

Link to comment
Share on other sites

@Majinbot

What method are you using to find the ID of the scenery object? AFAIK, :getID() won't work on them and I don't think they can be found in the mission database either :huh:

[/code]

 

Thanks for the reply, I hope I haven't been wrong in writing my question. I use the new zone function of the editor:

InkedScreen_200411_130407_LI.thumb.jpg.91b6df9970afb67adf6e8d082e0d55eb.jpg

PC: i7-13700K - MSI RTX 4080 Gaming X Trio - 32GB DDR5 6200 - VPC MongoosT-50CM3 - VKB GF pro - MFG Crosswind - Msi MPG321UR-QD + Acer XB271HU - TrackIR5 - Rift S

Link to comment
Share on other sites

Hahah :) I like how you thought there was more chance of getting coordinate of scenery from DCS than a laser on a coordinate! We must have disappointed you greatly in the past! Not even the scenery id's are reliable in DCS, I have found duplicates and seen one explosion blow up something a mile away.

 

Perhaps let us know what you are trying to achieve, you probably already have the coordinate, just disregard the scenery

 

 

I don't understand, maybe because English is my third language, but why all the sarcasm that I feel in the answer? I'm not disappointed, I'm not an moose expert, I only wanted to know if the last version of moose the I find in the site support "LaseCoordinate".

The script i want to create is to lase a scenery object...

 

local ClientGroup = GROUP:FindByName("Player")
local LasingJtac = UNIT:FindByName("Finger")  
local LaserCode = 1688
local TargetLaser = SCENERY:GetName(78383669):GetCoordinate() -- here I want to understand the right command
local TgCoord = TargetLaser:ToStringLLDDM()
local LaserTime = 600
local TimeMinutes = LaserTime / 60

local function LaseTimeTG()

if LasingJtac ~= nil and TargetLaser:IsAlive() then
   LasingJtac:LaseCoordinate(TargetLaser,LaserCode,LaserTime)
   MESSAGE:New("Finger is lasing\nLaser code = "..LaserCode.."\nLasing for "..TimeMinutes.." minutes\nTarget Coordinates = "..TgCoord,20):ToGroup(ClientGroup)
else 
   MESSAGE:New("The enemy hideout has already been destroyed",20):ToGroup(ClientGroup)
end
end

local function LasetargetCheck()

if LasingJtac ~= nil and LasingJtac:IsLasing() then
   MESSAGE:New("Finger is lasing the enemy hideout\nLaser code = "..LaserCode,20):ToGroup(ClientGroup)
else
   MESSAGE:New("Finger is not lasing the target",20):ToGroup(ClientGroup)
end
end

FingerMenu = MENU_GROUP:New(ClientGroup,"Finger Lasing Menu")
LaseAComma = MENU_GROUP_COMMAND:New(ClientGroup, "Lase enemy hideout", FingerMenu, LaseTimeTG)
LaseBComma = MENU_GROUP_COMMAND:New(ClientGroup, "Finger Lasing Status", FingerMenu, LasetargetCheck)

PC: i7-13700K - MSI RTX 4080 Gaming X Trio - 32GB DDR5 6200 - VPC MongoosT-50CM3 - VKB GF pro - MFG Crosswind - Msi MPG321UR-QD + Acer XB271HU - TrackIR5 - Rift S

Link to comment
Share on other sites

I think 78383669 is the id of the zone, not the scenery object.

 

I don't really understand but today with some changes I tried again with "LaseUnit" and I started the script with:

local Scan_Zone = ZONE:FindByName("tg1")
local Search_Area = {id = world.VolumeType.SPHERE, params = {point = Scan_Zone:GetVec3(0) , radius = 2000}}

local function Evaluate_Zone(Scenery_Object)       
   if Scenery_Object then 
      if Scenery_Object:getPoint() and Scenery_Object:getName() then
         if Scenery_Object:getName() == 78383669 then
              Scenery_Point = Scenery_Object:getPoint()
              TargetLaser = COORDINATE:NewFromVec3(Scenery_Point)
         end              
      end
   end
end

world.searchObjects(Object.Category.SCENERY, Search_Area, Evaluate_Zone)

 

...and it seems to work properly

PC: i7-13700K - MSI RTX 4080 Gaming X Trio - 32GB DDR5 6200 - VPC MongoosT-50CM3 - VKB GF pro - MFG Crosswind - Msi MPG321UR-QD + Acer XB271HU - TrackIR5 - Rift S

Link to comment
Share on other sites

local TargetLaser = SCENERY:GetName(78383669):GetCoordinate() -- here I want to understand the right command

 

That's not how SCENERY:GetName() works, think of it as UNIT:GetName(), the object needs to be defined first for it to work... and that's precisely the problem with scenery objects, you can't simply find them by name / id.

 

Again, I don't know of any direct way to get information from specific scenery objects, the volume search workaround is the best alternative I've found so far.

 

if Scenery_Object:getName() == 78383669 then

 

Now that's a surprise, I seem to recall that scenery objects wouldn't return a name (or it was invalid) back when I tested all this stuff.

 

Again, how are you getting the name/id of the scenery object? Did you perform a volume search beforehand to find out the correct values?


Edited by Hardcard
Link to comment
Share on other sites

That's not whow SCENERY:GetName() works, think of it as UNIT:GetName(), the object needs to be defined first for it to work... and that's precisely the problem with scenery objects, you can't simply find them by name / id.

 

Again, I don't know of any direct way to get information from specific scenery objects, the volume search workaround is the best alternative I've found so far.

 

 

 

Now that's a surprise, I seem to recall that scenery objects wouldn't return a name (or it was invalid) back when I tested all this stuff.

 

Again, how are you getting the name/id of the scenery object? Did you perform a volume search beforehand to find out the correct values?

 

Look at the photo attached to my previous message. In the editor, if you right-click on a building, the word "assign as" appears, if you click on the word, a trigger zone connected to the building is created. I use the number that I find in the object id value. Then with the following script a create a DEAD event for the building destruction:

Handler = {}
function Handler:onEvent(event)
if event.id == world.event.S_EVENT_DEAD and event.IniUnitName == 78383669 then
trigger.action.setUserFlag('30', true) 
end
end
world.addEventHandler(Handler)

 

Sorry if I don't explain myself well but I'm a noob..

PC: i7-13700K - MSI RTX 4080 Gaming X Trio - 32GB DDR5 6200 - VPC MongoosT-50CM3 - VKB GF pro - MFG Crosswind - Msi MPG321UR-QD + Acer XB271HU - TrackIR5 - Rift S

Link to comment
Share on other sites

Super frustrated at this point. How do we get moose installed? The documentation is terrible!

 

Install Eclipse LDT on your Windows 64 bit system. This is a free lua editor based on the Eclipse ecosystem. The advantage of LDT is that it greatly enhances your lua development environment with intellisense, better search capabilities etc. You may have to install java first. Ensure you install the 64-bit versions of both Eclipse LDT and java!

Install GITHUB desktop. We use GITHUB desktop to sync the moose repository to your system.

Link the MOOSE repository on GITHUB to your freshly installed GITHUB desktop. Do this by browing to the MOOSE repository at GITHUB, and select the green button Clone or Download -> Open in Desktop.

Specify a local directory on your PC where you want to store the MOOSE repository contents.

Sync the MOOSE repository to a defined local MOOSE directory on your PC using GITHUB desktop (press the sync button).

On your local MOOOSE directory, execute the batch file DCS_Folder_Sync.bat. This will sync the dcs folder in the MOOSE repository from the submodule DCS API.

As a result, you have installed the MOOSE repository on your PC, and it is fully synced.

 

DCS_Folder_Sync.bat is not in the Moose Directory.

Link to comment
Share on other sites

Super frustrated at this point. How do we get moose installed? The documentation is terrible!

Looks like Moose is not for you. Just move on.

A warrior's mission is to foster the success of others.

i9-12900K | MSI RTX 3080Ti Suprim X | 128 GB Ram 3200 MHz DDR-4 | MSI MPG Edge Z690 | Samung EVO 980 Pro SSD | Virpil Stick, Throttle and Collective | MFG Crosswind | HP Reverb G2

RAT - On the Range - Rescue Helo - Recovery Tanker - Warehouse - Airboss

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

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