Jump to content
NFG WhatHiMean

Random Vehicle spawn based of empty marker pos / rotation

Recommended Posts

I'm attempting to make a script for dynamic civ vehicle spawns in a city, right now I have my idea down on how I want to do it but I can't implement it properly. I'm still new to scripting and can't figure out exactly what I'm doing wrong here. Thanks for the help in advance!

 

Spoiler

// Define markers for the city of Voskovo
_VoskovoMarkers = [
    "voskovoMarker", "voskovoMarker_1", "voskovoMarker_2", "voskovoMarker_3",
    "voskovoMarker_4", "voskovoMarker_5", "voskovoMarker_6", "voskovoMarker_7",
    "voskovoMarker_8", "voskovoMarker_9", "voskovoMarker_10", "voskovoMarker_11"
];

// Define vehicles with their corresponding spawn weights (in percentages)
_vehiclesWithWeights = [
    ["C_Hatchback_01_F", 20],
    ["C_Hatchback_01_sport_F", 6],
    ["C_Offroad_02_unarmed_F", 14],
    ["C_Offroad_01_F", 20],
    ["C_SUV_01_F", 20],
    ["C_Van_01_transport_F", 5],
    ["RHS_Ural_Civ_01", 5],
    ["RHS_Ural_Civ_02", 5],
    ["RHS_Ural_Civ_03", 5]
];

// Function to pick a random vehicle based on weights
pickRandomVehicle = {
    params ["_vehicles"];
    _totalWeight = 0;
    
    // Calculate total weight and display a debug message
    {
        _totalWeight = _totalWeight + _x select 1;
        systemChat format["Adding %1 weight. Total weight: %2", _x select 1, _totalWeight];
    } forEach _vehicles;
    
    _randomNum = random _totalWeight;
    
    // Display a debug message for random number generated
    systemChat format["Random Number: %1", _randomNum];
    
    // Iterate through vehicles to find the one to spawn
    {
        if (_randomNum <= _x select 1) then {
            _result = _x select 0;
            systemChat format["Selected Vehicle: %1", _result];
            return;
        };
        _randomNum = _randomNum - (_x select 1);
    } forEach _vehicles;
    
    // Display a debug message if no vehicle is selected
    systemChat "No vehicle selected!";
};

// Iterate through each Voskovo marker and spawn a vehicle with debug messages
_spawnedVehicles = [];
{
    // Pick a random marker and get its position and rotation
    [_markerPos, _markerDir] = pickRandomMarker(_x);

    // Pick a random vehicle based on weights
    _vehicleClass = pickRandomVehicle(_vehiclesWithWeights);
    
    // Spawn the selected vehicle at the marker position with the specified rotation
    _vehicle = _vehicleClass createVehicle [_markerPos, [], 0, "NONE"];
    _vehicle setDir _markerDir;

    // Store spawned vehicle information for future reference if needed
    _spawnedVehicles pushBack _vehicle;
    
    // Display a debug message for the spawned vehicle
    systemChat format["Spawned Vehicle: %1 at Marker: %2", _vehicleClass, _x];
} forEach _VoskovoMarkers; // Iterate through Voskovo markers
 


I'm kinda lost atm, maybe I've been working on this too long lol

Share this post


Link to post
Share on other sites
1 hour ago, NFG WhatHiMean said:

I'm attempting to make a script for dynamic civ vehicle spawns in a city, right now I have my idea down on how I want to do it but I can't implement it properly. I'm still new to scripting and can't figure out exactly what I'm doing wrong here. Thanks for the help in advance!

 

  Reveal hidden contents

// Define markers for the city of Voskovo
_VoskovoMarkers = [
    "voskovoMarker", "voskovoMarker_1", "voskovoMarker_2", "voskovoMarker_3",
    "voskovoMarker_4", "voskovoMarker_5", "voskovoMarker_6", "voskovoMarker_7",
    "voskovoMarker_8", "voskovoMarker_9", "voskovoMarker_10", "voskovoMarker_11"
];

// Define vehicles with their corresponding spawn weights (in percentages)
_vehiclesWithWeights = [
    ["C_Hatchback_01_F", 20],
    ["C_Hatchback_01_sport_F", 6],
    ["C_Offroad_02_unarmed_F", 14],
    ["C_Offroad_01_F", 20],
    ["C_SUV_01_F", 20],
    ["C_Van_01_transport_F", 5],
    ["RHS_Ural_Civ_01", 5],
    ["RHS_Ural_Civ_02", 5],
    ["RHS_Ural_Civ_03", 5]
];

// Function to pick a random vehicle based on weights
pickRandomVehicle = {
    params ["_vehicles"];
    _totalWeight = 0;
    
    // Calculate total weight and display a debug message
    {
        _totalWeight = _totalWeight + _x select 1;
        systemChat format["Adding %1 weight. Total weight: %2", _x select 1, _totalWeight];
    } forEach _vehicles;
    
    _randomNum = random _totalWeight;
    
    // Display a debug message for random number generated
    systemChat format["Random Number: %1", _randomNum];
    
    // Iterate through vehicles to find the one to spawn
    {
        if (_randomNum <= _x select 1) then {
            _result = _x select 0;
            systemChat format["Selected Vehicle: %1", _result];
            return;
        };
        _randomNum = _randomNum - (_x select 1);
    } forEach _vehicles;
    
    // Display a debug message if no vehicle is selected
    systemChat "No vehicle selected!";
};

// Iterate through each Voskovo marker and spawn a vehicle with debug messages
_spawnedVehicles = [];
{
    // Pick a random marker and get its position and rotation
    [_markerPos, _markerDir] = pickRandomMarker(_x);

    // Pick a random vehicle based on weights
    _vehicleClass = pickRandomVehicle(_vehiclesWithWeights);
    
    // Spawn the selected vehicle at the marker position with the specified rotation
    _vehicle = _vehicleClass createVehicle [_markerPos, [], 0, "NONE"];
    _vehicle setDir _markerDir;

    // Store spawned vehicle information for future reference if needed
    _spawnedVehicles pushBack _vehicle;
    
    // Display a debug message for the spawned vehicle
    systemChat format["Spawned Vehicle: %1 at Marker: %2", _vehicleClass, _x];
} forEach _VoskovoMarkers; // Iterate through Voskovo markers
 


I'm kinda lost atm, maybe I've been working on this too long lol

 

I recommend checking out the syntax pages on the biki again 😉

SQF does not have all the neat features many modern languages do.

Spoiler

// Define markers for the city of Voskovo
private _VoskovoMarkers = [ //-- This is fine, I would put a private keyword ahead as good practice to avoid overriding variables in the caller's scope
    "voskovoMarker", "voskovoMarker_1", "voskovoMarker_2", "voskovoMarker_3",
    "voskovoMarker_4", "voskovoMarker_5", "voskovoMarker_6", "voskovoMarker_7",
    "voskovoMarker_8", "voskovoMarker_9", "voskovoMarker_10", "voskovoMarker_11"
];

// Define vehicles with their corresponding spawn weights (in percentages)
private _vehiclesWithWeights = [ //-- Same as above
    ["C_Hatchback_01_F", 20],
    ["C_Hatchback_01_sport_F", 6],
    ["C_Offroad_02_unarmed_F", 14],
    ["C_Offroad_01_F", 20],
    ["C_SUV_01_F", 20],
    ["C_Van_01_transport_F", 5],
    ["RHS_Ural_Civ_01", 5],
    ["RHS_Ural_Civ_02", 5],
    ["RHS_Ural_Civ_03", 5]
];

// Function to pick a random vehicle based on weights,
private _pickRandomVehicle = { 
	//-- Note that any variable that doesn't start with '_' will be declared as a 'global' variable in missionNamespace and be accessible in all scripts for the duration of the session, to be avoided unless required.
	//-- Again good practice to use 'private' keyword

    params ["_vehicles"];
    private _totalWeight = 0;
    
    // Calculate total weight and display a debug message
    {
        _totalWeight = _totalWeight + (_x select 1); //-- Brackets added since + takes precedence over select, could have also changed select to a #
        systemChat format["Adding %1 weight. Total weight: %2", _x select 1, _totalWeight];
    } forEach _vehicles;
    
    private _randomNum = random _totalWeight;
    
    // Display a debug message for random number generated
    systemChat format["Random Number: %1", _randomNum];
    
	// -- Define _result for return
	private _result = "";
    // Iterate through vehicles to find the one to spawn
    {
        if (_randomNum <= _x select 1) then {
            _result = _x select 0;
            systemChat format["Selected Vehicle: %1", _result];
            
            //-- return is not a valid keyword in SQF, instead the result of the last executed statement in the code is always returned, therefore we put _result; to be "executed" at the end.
            //-- We still have to break the loop though, for that we can use break;
            //return;
            break;
        };
        _randomNum = _randomNum - (_x select 1);
    } forEach _vehicles;
	
	// -- Since we can't easily just return in SQF we have to check our data at the end of the loop
	if( _result == "" ) exitWith {
		// Display a debug message if no vehicle is selected
    	systemChat "No vehicle selected!";
	};

    // Return
	_result;
};

// Iterate through each Voskovo marker and spawn a vehicle with debug messages
private _spawnedVehicles = [];
{
    // Pick a random marker and get its position and rotation
	//-- Nope no need, '_x' already contains the current element of the array, magic variables ftw...
    //[_markerPos, _markerDir] = pickRandomMarker(_x);

	private _marker = _x;
	private _markerPos = markerPos _marker;
	private _markerDir = markerDir _marker;

	// Pick a random vehicle based on weights
	// -- Note that functions in SQF are just a variable pointing to data of CODE-type hence we can't directly execute them
	// -- We need to use call (synchronous, can return) or spawn (asynchronous, cannot return)
	private _vehicleClass = [_vehiclesWithWeights] call _pickRandomVehicle;
	// -- We could also use command 'selectRandomWeighted' but that requires a special format on the array and would be less educational ;)

	// Spawn the selected vehicle at the marker position with the specified rotation
	// -- createVehicle requires all parameters on the right hand side when using the extended syntax
    private _vehicle = createVehicle [_vehicleClass, _markerPos, [], 0, "NONE"];
    _vehicle setDir _markerDir;

	// Store spawned vehicle information for future reference if needed
    _spawnedVehicles pushBack _vehicle;

	// Display a debug message for the spawned vehicle
    systemChat format["Spawned Vehicle: %1 at Marker: %2", _vehicleClass, _x];
} forEach _VoskovoMarkers; // Iterate through Voskovo markers

// For testing
TST_vehicles = _spawnedVehicles;

 

 

  • Like 1

Share this post


Link to post
Share on other sites
33 minutes ago, mrcurry said:

 

I recommend checking out the syntax pages on the biki again 😉

SQF does not have all the neat features many modern languages do.

  Hide contents


// Define markers for the city of Voskovo
private _VoskovoMarkers = [ //-- This is fine, I would put a private keyword ahead as good practice to avoid overriding variables in the caller's scope
    "voskovoMarker", "voskovoMarker_1", "voskovoMarker_2", "voskovoMarker_3",
    "voskovoMarker_4", "voskovoMarker_5", "voskovoMarker_6", "voskovoMarker_7",
    "voskovoMarker_8", "voskovoMarker_9", "voskovoMarker_10", "voskovoMarker_11"
];

// Define vehicles with their corresponding spawn weights (in percentages)
private _vehiclesWithWeights = [ //-- Same as above
    ["C_Hatchback_01_F", 20],
    ["C_Hatchback_01_sport_F", 6],
    ["C_Offroad_02_unarmed_F", 14],
    ["C_Offroad_01_F", 20],
    ["C_SUV_01_F", 20],
    ["C_Van_01_transport_F", 5],
    ["RHS_Ural_Civ_01", 5],
    ["RHS_Ural_Civ_02", 5],
    ["RHS_Ural_Civ_03", 5]
];

// Function to pick a random vehicle based on weights,
private _pickRandomVehicle = { 
	//-- Note that any variable that doesn't start with '_' will be declared as a 'global' variable in missionNamespace and be accessible in all scripts for the duration of the session, to be avoided unless required.
	//-- Again good practice to use 'private' keyword

    params ["_vehicles"];
    private _totalWeight = 0;
    
    // Calculate total weight and display a debug message
    {
        _totalWeight = _totalWeight + (_x select 1); //-- Brackets added since + takes precedence over select, could have also changed select to a #
        systemChat format["Adding %1 weight. Total weight: %2", _x select 1, _totalWeight];
    } forEach _vehicles;
    
    private _randomNum = random _totalWeight;
    
    // Display a debug message for random number generated
    systemChat format["Random Number: %1", _randomNum];
    
	// -- Define _result for return
	private _result = "";
    // Iterate through vehicles to find the one to spawn
    {
        if (_randomNum <= _x select 1) then {
            _result = _x select 0;
            systemChat format["Selected Vehicle: %1", _result];
            
            //-- return is not a valid keyword in SQF, instead the result of the last executed statement in the code is always returned, therefore we put _result; to be "executed" at the end.
            //-- We still have to break the loop though, for that we can use break;
            //return;
            break;
        };
        _randomNum = _randomNum - (_x select 1);
    } forEach _vehicles;
	
	// -- Since we can't easily just return in SQF we have to check our data at the end of the loop
	if( _result == "" ) exitWith {
		// Display a debug message if no vehicle is selected
    	systemChat "No vehicle selected!";
	};

    // Return
	_result;
};

// Iterate through each Voskovo marker and spawn a vehicle with debug messages
private _spawnedVehicles = [];
{
    // Pick a random marker and get its position and rotation
	//-- Nope no need, '_x' already contains the current element of the array, magic variables ftw...
    //[_markerPos, _markerDir] = pickRandomMarker(_x);

	private _marker = _x;
	private _markerPos = markerPos _marker;
	private _markerDir = markerDir _marker;

	// Pick a random vehicle based on weights
	// -- Note that functions in SQF are just a variable pointing to data of CODE-type hence we can't directly execute them
	// -- We need to use call (synchronous, can return) or spawn (asynchronous, cannot return)
	private _vehicleClass = [_vehiclesWithWeights] call _pickRandomVehicle;
	// -- We could also use command 'selectRandomWeighted' but that requires a special format on the array and would be less educational ;)

	// Spawn the selected vehicle at the marker position with the specified rotation
	// -- createVehicle requires all parameters on the right hand side when using the extended syntax
    private _vehicle = createVehicle [_vehicleClass, _markerPos, [], 0, "NONE"];
    _vehicle setDir _markerDir;

	// Store spawned vehicle information for future reference if needed
    _spawnedVehicles pushBack _vehicle;

	// Display a debug message for the spawned vehicle
    systemChat format["Spawned Vehicle: %1 at Marker: %2", _vehicleClass, _x];
} forEach _VoskovoMarkers; // Iterate through Voskovo markers

// For testing
TST_vehicles = _spawnedVehicles;

 

 

This is super helpful! Love the comments! 🙂 I realize now that I didn't implement it the way I wanted it. I plan to run this script for multiple cities and I want only one or two vehicles to spawn instead of every marker spawning. Quick other question is there a way to change the loading screen from whatever map to a custom image? I've looked around for a answer and I couldn't find anything other then the tiny loading image which I got working fine.

 

Spoiler

// Define markers for the city of Voskovo
private _VoskovoMarkers = [ //-- This is fine, I would put a private keyword ahead as good practice to avoid overriding variables in the caller's scope
    "voskovoMarker", "voskovoMarker_1", "voskovoMarker_2", "voskovoMarker_3",
    "voskovoMarker_4", "voskovoMarker_5", "voskovoMarker_6", "voskovoMarker_7",
    "voskovoMarker_8", "voskovoMarker_9", "voskovoMarker_10", "voskovoMarker_11"
];

private _VelikayaMarkers = [
    "velikayaMaker", "velikayaMaker_1", "velikayaMaker_2", "velikayaMaker_3", "velikayaMaker_4",
    "velikayaMaker_5", "velikayaMaker_6", "velikayaMaker_7", "velikayaMaker_8", "velikayaMaker_9",
    "velikayaMaker_10", "velikayaMaker_11", "velikayaMaker_12", "velikayaMaker_13", "velikayaMaker_14", 
    "velikayaMaker_15"
];

// Define vehicles with their corresponding spawn weights (in percentages)
private _vehiclesWithWeights = [ //-- Same as above
    ["C_Hatchback_01_F", 20],
    ["C_Hatchback_01_sport_F", 6],
    ["C_Offroad_02_unarmed_F", 14],
    ["C_Offroad_01_F", 20],
    ["C_SUV_01_F", 20],
    ["C_Van_01_transport_F", 5],
    ["RHS_Ural_Civ_01", 5],
    ["RHS_Ural_Civ_02", 5],
    ["RHS_Ural_Civ_03", 5]
];

// Function to pick a random vehicle based on weights,
private _pickRandomVehicle = { 
    //-- Note that any variable that doesn't start with '_' will be declared as a 'global' variable in missionNamespace and be accessible in all scripts for the duration of the session, to be avoided unless required.
    //-- Again good practice to use 'private' keyword

    params ["_vehicles"];
    private _totalWeight = 0;
    
    // Calculate total weight and display a debug message
    {
        _totalWeight = _totalWeight + (_x select 1); //-- Brackets added since + takes precedence over select, could have also changed select to a #
        systemChat format["Adding %1 weight. Total weight: %2", _x select 1, _totalWeight];
    } forEach _vehicles;
    
    private _randomNum = random _totalWeight;
    
    // Display a debug message for random number generated
    systemChat format["Random Number: %1", _randomNum];
    
    // -- Define _result for return
    private _result = "";
    // Iterate through vehicles to find the one to spawn
    {
        if (_randomNum <= _x select 1) then {
            _result = _x select 0;
            systemChat format["Selected Vehicle: %1", _result];
            
            //-- return is not a valid keyword in SQF, instead the result of the last executed statement in the code is always returned, therefore we put _result; to be "executed" at the end.
            //-- We still have to break the loop though, for that we can use break;
            //return;
            break;
        };
        _randomNum = _randomNum - (_x select 1);
    } forEach _vehicles;
    
    // -- Since we can't easily just return in SQF we have to check our data at the end of the loop
    if( _result == "" ) exitWith {
        // Display a debug message if no vehicle is selected
        systemChat "No vehicle selected!";
    };

    // Return
    _result;
};

// Iterate through each Voskovo marker and spawn a vehicle with debug messages
private _voskSpawnedVehicles = [];
{
    
    
    private _marker = _x;
    private _markerPos = markerPos _marker;
    private _markerDir = markerDir _marker;

    // Pick a random vehicle based on weights
    // -- Note that functions in SQF are just a variable pointing to data of CODE-type hence we can't directly execute them
    // -- We need to use call (synchronous, can return) or spawn (asynchronous, cannot return)
    private _vehicleClass = [_vehiclesWithWeights] call _pickRandomVehicle;
    // -- We could also use command 'selectRandomWeighted' but that requires a special format on the array and would be less educational 😉

    // Spawn the selected vehicle at the marker position with the specified rotation
    // -- createVehicle requires all parameters on the right hand side when using the extended syntax
    private _vehicle = createVehicle [_vehicleClass, _markerPos, [], 0, "NONE"];
    _vehicle setDir _markerDir;

    _voskSpawnedVehicles pushBack _vehicle;

    // Display a debug message for the spawned vehicle
    systemChat format["Spawned Vehicle: %1 at Marker: %2", _vehicleClass, _x];
} forEach _VoskovoMarkers;

private _veliSpawnedVehicles = [];
{
    private _marker = _x;
    private _markerPos = markerPos _marker;
    private _markerDir = markerDir _marker;

    private _vehicleClass = [_vehiclesWithWeights] call _pickRandomVehicle;

    private _vehicle = createVehicle [_vehicleClass, _markerPos, [], 0, "NONE"];
    _vehicle setDir _markerDir;
    
    _veliSpawnedVehicles pushBack _vehicle;

    systemChat format["Spawned Vehicle: %1 at Marker: %2", _vehicleClass, _x];
} forEach _VelikayaMarkers;


I'm not that great at coding (chatgpt is genuinely useful for this lmao, that's part of why the syntax was wrong)

 

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

×