Jump to content
Sign in to follow this  
bigshotking

Need help with Mission Calling Script

Recommended Posts

while {true} do {
  If (missionfinished) then {

            missionfinished = false;
            // this just selects a random number.
            _missionnum = floor(random 100);

            // this will take that random number and put it into a string that we can use to execVM.
             _missionstr = format ["mission%1.sqf",_missionnum];

             // Here we use the string to execute the random mission.
             _randommissionstrt = [] execVM  _missionstr;
     };
sleep 60;
};

I got this wonderful script from Riouken and I need one more thing to add to it.

I need to add an array of some kind that once one of the missions is called on it won't be called on again once this script is called on again.

Thanks in advance for any help

-Bigshot

Share this post


Link to post
Share on other sites

This is very confusing to me...

So I need to set a case for EACH mission? I have 100+ missions, Riouken said he would give me a simple example but he has seemed to have disapperead :(

Is there a simpler way to do this?

-Bigshot

Share this post


Link to post
Share on other sites

The thing is there is no set method of doing this. Any type of "multiple missions" thing is going to be custom coded and there's about a million different ways of doing it. Individual sqf files for each mission, some giant array of 100 different something. There's no standard way of doing what you want to do. :)

Share this post


Link to post
Share on other sites

private ["_missionNum","_unusedMissions","_missionStr","_randomMissionStrt","_numberOfMissions"];

_numberOfMissions = 100;
_unusedMissions = [];
//No mission used yet so add all of them (numbers)
for "_i" from 0 to (_numberOfMissions-1) do {
   _unusedMissions set [_i, _i];
};

while {true} do {
   If (missionFinished) then {

       missionFinished = false;
       //Pick random mission
       _missionNum = _unusedMissions select (floor (random (count _unusedMissions)));
       //Remove it from the available missions
       _unusedMissions = _unusedMissions - [_missionNum];
       // this will take that random number and put it into a string that we can use to execVM.
       _missionStr = format ["mission%1.sqf",_missionNum];

       // Here we use the string to execute the random mission.
       _randomMissionStrt = [] execVM  _missionStr;

   };
   sleep 60;
};

You might want to add this to the loop to make i stop starting missions then the list is empty:

while {true && count _unusedMissions > 0} do {

Edited by Muzzleflash

Share this post


Link to post
Share on other sites

Thank you for the edited script Muzzleflash!

So if I want to add that extra line to the script it would look like this correct?

private ["_missionNum","_unusedMissions","_missionStr","_randomMissionStrt","_numberOfMissions"];

_numberOfMissions = 100;
_unusedMissions = [];
//No mission used yet so add all of them (numbers)
for "_i" from 0 to (_numberOfMissions-1) do {
   _unusedMissions set [_i, _i];
};

while {true} do {
   If (missionFinished) then {

       missionFinished = false;
       //Pick random mission
       _missionNum = _unusedMissions select (floor (random (count _unusedMissions)));
       //Remove it from the available missions
       _unusedMissions = _unusedMissions - [_missionNum];
       // this will take that random number and put it into a string that we can use to execVM.
       _missionStr = format ["mission%1.sqf",_missionNum];

       // Here we use the string to execute the random mission.
       _randomMissionStrt = [] execVM  _missionStr;

       while {true && count _unusedMissions > 0} do {
       endmission "End1";
       };

   };
   sleep 60;
};

Share this post


Link to post
Share on other sites

while {true && count _unusedMissions > 0} do {

endmission "End1";

};

[/php]

Actually this is not right, this will end the game immediately for the server. If you try reading it as an english sentence you can see what is wrong:

count _unusedMissions > 0 means that there is still missions not played.

Then the whole while becomes

"While true and (there is still missions not played" then "end the game" - which is not what you want.

This is better:

if (count _unusedMissions <= 0) then {
   endMission "End1";
};

However, this is not MP-safe (I assume the mission scripts are only run on the server). A safe way to do it would be to create a trigger in the editor like this:

Condition: endTheGame
On Act: endMission "End1";

And instead of the previous if - use this:

if (count _unusedMissions <= 0) then {
   //Activate the trigger
   endTheGame = true;
   //Make sure other players also know that endTheGame is
   //true now so the trigger will activate for them too thus
   //ending the game for them too.
   publicVariable "endTheGame";
};

If you did it the without this trigger/publicVariable stuff, the game would only end for the server and everybody else would keep playing. This way everybody get's the end screen.

Edited by Muzzleflash

Share this post


Link to post
Share on other sites

Thank you once again Muzzle I'll be sure to credit you in the mission for your help as well as Kylania since he has helped me on another part.

Thanks again!

-Bigshot

Share this post


Link to post
Share on other sites

waitUntil {(isDedicated) || !(isNull player)};

private ["_missionNum","_unusedMissions","_missionStr","_randomMissionStrt","_numberOfMissions"];

_numberOfMissions = 11;
_unusedMissions = [];
//No mission used yet so add all of them (numbers)
for "_i" from 0 to (_numberOfMissions-1) do {
   _unusedMissions set [_i, _i];
};

while {true} do {
   If (missionFinished) then {

       	missionFinished = false;
       	//Pick random mission
       	_missionNum = _unusedMissions select (floor (random (count _unusedMissions)));
       	//Remove it from the available missions
       	_unusedMissions = _unusedMissions - [_missionNum];
       	// this will take that random number and put it into a string that we can use to execVM.
      	 _missionStr = format ["objscripts\mission%1.sqf",_missionNum];

      	 // Here we use the string to execute the random mission.
       	_randomMissionStrt = [] execVM  _missionStr;

       	if (count _unusedMissions <= 0) then {
   		endTheGame = true;
   		publicVariable "endTheGame";
	}; 

};
   sleep 60;
};  

if (true) exitWith {};

I seem to be having a few issues with this script, it works great if I'm the only one in the server. But if someone joins in the script runs for them and it gives them a separate objective!

Is there a way that this script could only be run through the server?

And also is there a way to make it so that when someone joins the game, they see the objective already? Cause when they join in they don't see an objective marker.

Thanks in advance

-Bigshot

Share this post


Link to post
Share on other sites

Well I need that script to run on the server so that when a new player joins the script doesn't run, it will only run when a mission is complete...

Here is a mission script that I made:

// by 42nd|Bigshot //
waitUntil {(isDedicated) || !(isNull player)};

waitUntil{!(isNil "BIS_MPF_InitDone")};

private ["_mrk","_trg1","_enemyi1","_enemyi1_1","_enemyi1_2","_enemyi1_3","_comp1","_heli"];

tsk11 = player createSimpleTask ["Destroy Attack Chopper"];
tsk11 setSimpleTaskDescription ["Destroy a Mi-24!", "Destroy", "Destroy"];
tsk11 setSimpleTaskDestination (getMarkerPos "m11");
taskhint ["New Objective...\nDestroy Mi-24", [1, 1, 1, 1], "taskNew"];

if (!isServer) exitWith {};

_mrk = createMarker ["m11", position player ];
_mrk setmarkershape "ICON";
_mrk setmarkersize [1,1];
_mrk setMarkerColor "ColorRed";
"m11" setMarkerType "Warning";
"m11" setMarkerPos getMarkerPos "m11";

_enemyi1 = [markerPos "m11_1", "Infantry", 50, ["BIS_TK"]] execVM "crB_scripts\crB_taskPatrol.sqf";
_enemyi1_1 = [markerPos "m11_2", "Infantry", 50, ["BIS_TK"]] execVM "crB_scripts\crB_taskPatrol.sqf";
_enemyi1_2 = [markerPos "m11_3", "Infantry", 50, ["BIS_TK"]] execVM "crB_scripts\crB_taskPatrol.sqf";
_enemyi1_3 = [markerPos "m11_4", "Infantry", 50, ["BIS_TK"]] execVM "crB_scripts\crB_taskPatrol.sqf";
_enemym1 = [markerPos "m11_5", "Armored", 50, ["BIS_TK"]] execVM "crB_scripts\crB_taskPatrol.sqf";
_comp1 = [getmarkerpos "m11_6",0, "HeliParking1_RU"] call (compile (preprocessFileLineNumbers "ca\modules\dyno\data\scripts\objectMapper.sqf"));
_heli = "Mi24_D_TK_EP1" createVehicle (getMarkerPos "m11_7");

_trg1 = createTrigger["EmptyDetector", getMarkerPos "m11_8"];
_trg1 setTriggerArea[500,500,0,false];
_trg1 setTriggerActivation["EAST","NOT PRESENT",false];
_trg1 setTriggerStatements["this","[nil,nil,rHINT,""AREA CLEAR""] call RE;",""];

waitUntil {!alive _heli};

taskhint ["Objective Complete!\nMi-24 Destroyed!", [0.600000,0.839215,0.466666,1], "taskDone"];
deleteMarker "m9";
deleteVehicle _trg1;
player removeSimpleTask tsk9;
sleep 10;
nul = ["MARINE"] execVM "scripts\missionreward.sqf";
missionsfinished = true;

if (true) exitWith {};

I'm not sure how to make this JIP compatible...

Share this post


Link to post
Share on other sites

waitUntil {(isDedicated) || !(isNull player)};

This part says that if you are a dedicated then you run the script. Or wait and see if it is a player then run the script - this mean the script is run for everybody.

Typically you only want the server to run certain scripts so that objects only get spawned once and etc.. You can use this instead:

if (!isServer) exitWith {};

Which says if this is not the server then don't run this. Just be sure that you do not have anything below that statement that you actually do want to run on any clients - eg. a hint for example.

Making markers work for JIP is kinda tricky. Yes you can use the RE framework as Demonized suggests, however, the hard part is removing the old marker for the new mission. This might work:

We keep the objective marker named "OBJ_MARKER". We also use the *local versions of the commands since I think they are more reliable :S.

Whenever a new mission is created you do this:

//If server is also a player, then delete old marker.
//.....
PV_Marker_Data = ["ICON", MY_POS, "Dot", "ColorRed"];
publicVariable "PV_Marker_Data";
//Also if the server is also a player then create the marker from the data in PV_Marker_Data.
//......

This sends the information (PV_Marker_Data) to everybody else connected, and let JIP know the info too.

When any player joins you create the marker the same way using that information. Example of part of the init.sqf:

[] spawn {
   CreateMarkerCode = {
         //Delete old marker here
         //...
         _newData = _this;
         //You have the all the info in _newData now, type, pos, color
         //Create the marker local.
   };
   //Everytime the server updates the variable info we create a new marker based on the new info - delete the old one first.
   "PV_Marker_Data" addPublicVariableEventHandler {
         (_this select 1) call CreateMarkerCode ;
    };
    //First time we join the above code won't run so we just create it from the info again
    waitUntil {!isNil "PV_Marker_Data"};
    PV_Marker_Data call CreateMarkerCode;
}

For this to work, it is important to use local version of the marker commands, eg. createMarkerLocal, deleteMarkerLocal, setMarkerShapeLocal. And keep the marker name same everywhere - It is the first argument to createMarker*.

Edited by Muzzleflash

Share this post


Link to post
Share on other sites

Well thank you very much for the info Muzzle, can the same apply to this script?

This script is what calls on the missions randomly, it only needs to be run on the server so that when a new client joins they don't get a random objective that is not the current one. Also after testing this, there was an issue while I had several people with me testing they each got a random objective. So I guess making sure that this script runs on the server will allow only one mission to be selected so that everyone has the same mission to complete.

if (!isServer) exitWith {};

private ["_missionNum","_unusedMissions","_missionStr","_randomMissionStrt","_numberOfMissions"];

_numberOfMissions = (paramsArray select 8);
_unusedMissions = [];
//No mission used yet so add all of them (numbers)
for "_i" from 0 to (_numberOfMissions-1) do {
   _unusedMissions set [_i, _i];
};

while {true} do {
   If (missionFinished) then {

       	missionFinished = false;
       	//Pick random mission
       	_missionNum = _unusedMissions select (floor (random (count _unusedMissions)));
       	//Remove it from the available missions
       	_unusedMissions = _unusedMissions - [_missionNum];
       	// this will take that random number and put it into a string that we can use to execVM.
      	 _missionStr = format ["objscripts\mission%1.sqf",_missionNum];

      	 // Here we use the string to execute the random mission.
       	_randomMissionStrt = [] execVM  _missionStr;

       	if (count _unusedMissions <= 0) then {
   		endTheGame = true;
   		publicVariable "endTheGame";
	}; 

};
   sleep 60;
};  

if (true) exitWith {}; 

Thanks in advance for any help

-Bigshot

EDIT: Is this how you properly delete a marker?

PV_Marker_Data = ["ICON", getMarkerPos "m1", "Dot", "ColorRed"];
publicVariable "PV_Marker_Data";

deleteMarkerLocal PV_Marker_Data;

Edited by bigshotking

Share this post


Link to post
Share on other sites

I assume the code that calls the mission scripts is your init.sqf? I added some code at the top to help with the marker syncing:

// [POS, ICON_TYPE, COLOR, TEXT]

//Used to create marker
UpdateMarker = {
   private ["_mrk", "_data"];
   _mrk = "obj_marker";
   _data = _this;
   //Create the marker if necessary
   if (getMarkerPos "obj_marker" select 0 == 0) then {
       //About the coordinate - it will be moved anyway
       createMarkerLocal [_mrk, [0, 0, 0]];
   };
   //Setup the marker - _data looks like this:
   // [POS, ICON_TYPE, COLOR, TEXT]
   _mrk setMarkerShapeLocal "ICON";
   _mrk setMarkerTypeLocal (_data select 1);
   _mrk setMarkerColorLocal (_data select 2);
   _mrk setMarkerPosLocal (_data select 0);
   _mrk setMarkerTextLocal (_data select 3);
};

//Used to delete marker
DeleteTheMarker = {
   deleteMarkerLocal "obj_marker";
};

//All players must have the marker
if (!isServer) then {
   [] spawn {
       //A marker exists in "serverland"
       if (!isNil "PV_Marker_Data") then {
           //Create it
           PV_Marker_Data call UpdateMarker;
       };
       //Make sure we perform any update the server sends
       "PV_Marker_Data" addPublicVariableEventHandler {
           _data = _this select 1;
           //Update?
           if (typeName _data == typeName []) then {
               _data call UpdateMarker;
           } else {
               //If we don't send array, eg. "DELETE" then remove the marker.
               call DeleteTheMarker;
           };
       };
   };
};

if (isServer) then {
   SendUpdateMarker = {
       //Just ignore bad data.
       if (isNil "PV_Marker_Data") exitWith {};
       publicVariable "PV_Marker_Data";
       //The server might be a player and the "publicVar" won't run, so do it manually.
       //Update?
       if (typeName PV_Marker_Data == typeName []) then {
           PV_Marker_Data call UpdateMarker;
       } else {
           //If we don't send array, eg. "DELETE" then remove the marker.
           call DeleteTheMarker;
       };
   };
};

if (!isServer) exitWith {};

private ["_missionNum","_unusedMissions","_missionStr","_randomMissionStrt","_numberOfMissions"];

_numberOfMissions = (paramsArray select 8);
_unusedMissions = [];
//No mission used yet so add all of them (numbers)
for "_i" from 0 to (_numberOfMissions-1) do {
   _unusedMissions set [_i, _i];
};

while {true} do {
   If (missionFinished) then {

           missionFinished = false;
           //Pick random mission
           _missionNum = _unusedMissions select (floor (random (count _unusedMissions)));
           //Remove it from the available missions
           _unusedMissions = _unusedMissions - [_missionNum];
           // this will take that random number and put it into a string that we can use to execVM.
           _missionStr = format ["objscripts\mission%1.sqf",_missionNum];

           // Here we use the string to execute the random mission.
           _randomMissionStrt = [] execVM  _missionStr;

           if (count _unusedMissions <= 0) then {
           endTheGame = true;
           publicVariable "endTheGame";
       }; 

   };
   sleep 60;
};  

With this setup, don't use createMarker or createMarkerLocal. Instead do this in your missions (assume you want the marker to be on the object named 'target'):

// [POS, ICON_TYPE, COLOR, TEXT]
PV_Marker_Data = [getPos target, "Dot", "ColorRed", "Destroy"];
call SendUpdateMarker;

This will (should) automatically update the marker for all current players (including if the server is also a player) and JIP's, and if the marker does not exist it will create it. If you later change PV_Marker_Data then do 'call SendUpdateMarker;' and it will be updated for all as well. If you want to delete the marker then set PV_Marker_Data to something that is not an array, like "Delete" for example:

PV_Marker_Data ="DELETE";
call SendUpdateMarker;

This is not tested, but squint validated it and it should work.

This you don't ever need:

if (true) exitWith {};

Share this post


Link to post
Share on other sites

Thank you for all your help! I greatly appreciate it! I'll be sure to Credit you in the mission!

Again Thankyou for the all the help!

-Bigshot

Share this post


Link to post
Share on other sites

Once again Muzzle thankyou for all your help, there is only one issue remaining out of the hundreds that have been fixed!

No one can seem to see the Tasks pop-up on screen now or in the tasks menu, nor can they see them when they JIP.

Here is how the script is creating the task:

// by 42nd|Bigshot //
waitUntil {(isDedicated) || !(isNull player)};

waitUntil{!(isNil "BIS_MPF_InitDone")};

private ["_enemy","_hvt","_trg1","_enemyi1","_enemyi1_1","_enemyi1_2","_enemyi1_3","_enemym1","_enemym1_1"];

tsk5 = player createSimpleTask ["Kill HVT"];
tsk5 setSimpleTaskDescription ["Kill a HVT that is a known Taliban Associate!", "Kill HVT", "Kill HVT"];
tsk5 setSimpleTaskDestination (getMarkerPos "m5");
taskhint ["New Objective...\nKill HVT", [1, 1, 1, 1], "taskNew"];

if (!isServer) exitWith {};

rest of script...

I have a feeling it might be this at the top:

waitUntil {(isDedicated) || !(isNull player)};

Am I correct in my assumption?

Thanks in advance for any help

-Bigshot

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×