[How-To] Improved vehicle spawn functions

Discussion in 'General Discussion' started by Doc, Dec 16, 2012.

  1. Doc

    Doc Valued Member!

    Joined:
    Nov 23, 2012
    Messages:
    355
    Likes Received:
    39
    HOTFIX** 01/01/2013 - UPDATE YOUR CODE
    There was an issue with the function creating vehicles with a NULL ObjectUID/Worldspace in some circumstances. I have updated line 53 of the code to fix this - please reapply the pSpawnVehicles function below

    The Current System
    The way vehicles are currently spawned is a bit strange and is better suited for low vehicle counts (<10). If you set your maximum cars to say, 40, and there are 40 or more spawn points available, then there will always be exactly 40 vehicles on the map. This is a bit silly, because it kind of nullifies the spawn chances - if the spawn chance is 0.1 (10%) and there are only 40 spawn locations then that car will always be in the map. This is why I have completely rescripted the vehicle spawn function.

    My New System
    In my new system, vehicles are spawned entirely based on their spawn chance - this is better for large vehicle counts. The old way of setting 40 or whatever vehicles as your iSpawnNumVeh in pMain is messy. It's more efficient to attempt to spawn every vehicle in your object_classes and see if their spawn chance let's them spawn or not. Welcome to the world of dynamic vehicle spawns! Some restarts they may be 20 vehicles on your server, on others there may be 40. This is a great way to stop all vehicles spawning at once and prevent people having a headstart on vehicle hoarding. You will no longer need to edit pMain, as it is obsolete (as is pSpawn). Instead all vehicle spawns are taken from object_classes. Every vehicle allowed to spawn in object_classes could appear on the map, but it all depends on it's chance parameter.

    RECOMMENDED
    Follow this HotFix ASAP (Even if you don't use this function)
    Follow this guide afterwards [How-To] Prevent persistent vehicles hacked into database

    Setup
    You do not need to delete/edit existing functions. Just create a new procedure called pSpawnVehicles (you can name it what you like) with the following code:

    pSpawnVehicles
    Code:
    BEGIN
     
        DECLARE iCurrentVehicles INT(4) DEFAULT 0;
        DECLARE loopCounter INT(4) DEFAULT 0;
        DECLARE iSpawnAttempts INT(4) DEFAULT 0;
        DECLARE iTotalClasses INT(4) DEFAULT 0;                 
     
        CALL pCleanup();
        CALL pFixMaxNum;
     
        SET iCurrentVehicles = fGetVehCount();
     
        SELECT COUNT(*)
                        INTO iTotalClasses
                        FROM object_classes;
     
        SELECT SUM(MaxNum) FROM object_classes INTO @iMaxNumTotal;
        IF (iCurrentVehicles > @iMaxNumTotal) THEN
            SET iSpawnAttempts = @iMaxNumTotal - iCurrentVehicles;
        END IF;
     
     
     
     
        WHILE (loopCounter < iTotalClasses) DO
     
                SELECT Classname, Chance, MaxNum, Damage, MaxFuel, Inventory, Hitpoints
                            INTO @rsClassname, @rsChance, @rsMaxNum, @rsDamage, @rsMaxFuel, @rsInventory, @rsHitpoints
                            FROM object_classes
                            LIMIT loopCounter, 1;
     
                SET @initialClassCount = fGetClassCount(@rsClassname);
     
                IF (@initialClassCount < @rsMaxNum) THEN
     
                    SET @classloop = 0;
                    SET @attemptsAtClass = @rsMaxNum - @initialClassCount;
     
                    WHILE (@classloop < @attemptsAtClass) DO
                        SET @luckyDip = fGetSpawnFromChance(@rsChance + (RAND() / 10000));
     
                        IF (@luckyDip = 1) THEN
     
                                    SELECT ObjectUID, Worldspace
                                                    INTO @spawnUID, @spawnWorldspace
                                                    FROM object_spawns o
                                                    WHERE Classname = @rsClassname AND NOT EXISTS (SELECT 1 FROM object_data e WHERE e.ObjectUID = o.ObjectUID)
                                                    ORDER BY RAND()
                                                    LIMIT 1;
     
                                    SET @fuel = (FLOOR( (RAND()*@rsMaxFuel) * 10000) / 10000);
     
                                    INSERT INTO object_data (ObjectUID, Instance, Landmark, Classname, Damage, CharacterID, Worldspace, Inventory, Hitpoints, Fuel, Datestamp)
                                                        VALUES (@spawnUID, '1', '0', @rsClassname, @rsDamage, '0', @spawnWorldspace, @rsInventory, @rsHitpoints, @fuel, SYSDATE());
                                                                                                                         
     
                        END IF;
                        SET @classloop = @classloop + 1;
                    END WHILE;
                END IF;
            SET loopCounter = loopCounter + 1;
        END WHILE;
     
    END
    
    fGetVehCount
    A small change can be made to fGetVehCount to utilize the Landmark parameter (read below)
    Code:
    BEGIN
     
        DECLARE iVehCount    SMALLINT(3) DEFAULT 0;
     
        SELECT COUNT(*)
            INTO iVehCount
            FROM object_data
                WHERE
                    Landmark = '0'
                    AND Classname != 'dummy'
                    AND Classname != 'TentStorage'
                    AND Classname != 'Hedgehog_DZ'
                    AND Classname != 'Wire_cat1'
                    AND Classname != 'Sandbag1_DZ'
                    AND Classname != 'TrapBear';
     
        RETURN iVehCount;
    END
    

    fGetSpawnFromChance
    If (like me) your fGetSpawnFromChance is empty, you will need to paste the code below in, and set the parameter to `chance` DECIMAL(6,5). Using Navicat, you may have trouble saving this function. To fix this, set the Data Access (in advanced tab) to READS SQL - paste your function/parameter - save the function - now set Data Access to NO SQL and it should save. No idea why it does that, but the method to save it works... somehow.
    Code:
    BEGIN
     
    DECLARE bspawn TINYINT(1) DEFAULT 0;
     
    IF (RAND() <= chance) THEN
    SET bspawn = 1;
    END IF;
     
    RETURN bspawn;
     
    END
    

    database structure changes (*Important)
    Nearly forgot this part...
    New column to objects_classes.
    MaxFuel - Varchar(10) DEFAULT 0
    (Reason for this should be self-explanatory - fuel on spawn is a random number up to MaxFuel)
    Inventory - Text(0) DEFAULT []
    (Allows you to set certain vehicles to spawn with a given inventory loadout)

    New column to object_data
    Landmark - TinyINT(1) DEFAULT 0
    (The reason for this is because if you use my guide to add land objects to the database, it interferes with the fGetVehCount. Instead of adding an exception for each new object, it's easier to classify all vehicles as landmark 0 and give all objects landmark 1 when you add them in. If you don't add objects in via object_data, just add this column anyway)

    Change to Chance column of object_classes
    make the chance column type DECIMAL with the length 6 and decimals 5. This is for consistency.


    If you are using pwnoz0rs launcher, now you just need to change pMain() to pSpawnVehicles by editing the .bat file.

    You are now good to go! Now you can add more vehicle spawn points to your object_spawns and object_classes and enjoy the new spawning method. If you ever decide to revert to the old pMain system, then just change which function you are calling.

    I will soon make an SQL script to add this all in and make the changes for you, but once I have time.
    -Doc

    EXTRA COURTESY FILES:
    - object_spawns.sql* - 92 vehicle spawn locations (comments in description say location)
    - object_classes.sql* - object_classes to complement the object_spawns
    You may have to tweak object_classes to work with any custom spawn points you added.
    I cant remember if description is a field in pwnaz0rs version, if it isn't just add a description text column
    *saved as .txt to bypass forum filter
     

    Attached Files:

    Vroom, Ekot and beowolfschaefer like this.
  2. Doc

    Doc Valued Member!

    Joined:
    Nov 23, 2012
    Messages:
    355
    Likes Received:
    39
    Changelog
    Added: Changes you are required to make to the database
    Added: fGetVehCount and fGetSpawnFromChance
    Added: object_classes and object_spawns for 92 vehicle spawn points
    Removed: My testing line from the code :3
     
  3. zedar

    zedar Moderator Staff Member

    Joined:
    Nov 2, 2012
    Messages:
    193
    Likes Received:
    6
    do you know the spawn method from Bliss?
     
  4. Doc

    Doc Valued Member!

    Joined:
    Nov 23, 2012
    Messages:
    355
    Likes Received:
    39
    No. but it should be in your readme file if I remember correctly.
     
  5. zedar

    zedar Moderator Staff Member

    Joined:
    Nov 2, 2012
    Messages:
    193
    Likes Received:
    6
    you must read the code and how the spawn bliss work to save a lot of effort in this project.
     
  6. Forgotten

    Forgotten Well-Known Member

    Joined:
    Oct 22, 2012
    Messages:
    142
    Likes Received:
    7
    I get a MySQL error 1064- You have an error in your SQL syntax '@rsClassname, @rsDamage,'0',@spawnWorldspace,@rsInventory,@rsHitpoints,@fue' at line 52.

    Happens when I try to save the new pSpawnVehicles function in navicat.
     
  7. Doc

    Doc Valued Member!

    Joined:
    Nov 23, 2012
    Messages:
    355
    Likes Received:
    39
    Sorry, that was because I removed my debug code without testing it - it should work now. By the way this is a procedure not a function :)
     
  8. Ekot

    Ekot New Member

    Joined:
    Dec 18, 2012
    Messages:
    2
    Likes Received:
    0
    Nice work :)
    Is it possible to ask for 2 features?
    1. Random Inventory in vehicle (based on chance and after a table), like in real life some cars would have a spare tire and other maybe a empty Jerrycan or even a full.
    2. Random Damage on vehicle upon spawn, like some cars maybe have a flat tire, some missing some windows and so on.
    that would make it alot more dynamic ;)
     
  9. Doc

    Doc Valued Member!

    Joined:
    Nov 23, 2012
    Messages:
    355
    Likes Received:
    39
    Good ideas - it's something I've thought about doing and planned to do but I need to learn more about what the car damage variables mean. I'm investing my free time into BanZ at the moment but I'll come back to this project soon :)
     
  10. Forgotten

    Forgotten Well-Known Member

    Joined:
    Oct 22, 2012
    Messages:
    142
    Likes Received:
    7
    Thanks for working on this, got it working, and it's a great feature to have for something that should have been included for server admins in the first place! Hopefully Rocket will either pay attention or be told about features like this.
     
  11. Doc

    Doc Valued Member!

    Joined:
    Nov 23, 2012
    Messages:
    355
    Likes Received:
    39
    UPDATE:

    Important typo spotted by myself:

    This line
    Code:
      SET iSpawnAttempts = @iMaxNumTotal - currentVehicles;
    Should be
    Code:
     SET iSpawnAttempts = @iMaxNumTotal - iCurrentVehicles;
     
  12. Ekot

    Ekot New Member

    Joined:
    Dec 18, 2012
    Messages:
    2
    Likes Received:
    0
    Also u might want to change
    Inventory - Text(0) DEFAULT []
    to
    Inventory - Varchar(999) DEFAULT []
    since Text with default is not possible in mysql on windows (proboably because strict mode)
     
  13. Doc

    Doc Valued Member!

    Joined:
    Nov 23, 2012
    Messages:
    355
    Likes Received:
    39
    I don't know about that, I mean I know what you are saying but varchar 999 is not long enough for a full URAL ;( infact that was why I changed it from varchar to text. Also varchar forces the data usage but text is variable. Up to each individual I guess
     
  14. James45x1997xST

    James45x1997xST New Member

    Joined:
    Dec 22, 2012
    Messages:
    3
    Likes Received:
    0
    Plz Vidéo ! :(
     
  15. James45x1997xST

    James45x1997xST New Member

    Joined:
    Dec 22, 2012
    Messages:
    3
    Likes Received:
    0
    :) Video Plz. because I Dunno How To Master the Vehicle :( . is the Master File Changes in the Cfg download the Boc ;) :( ! Plz The Video ! <3
     
  16. Forgotten

    Forgotten Well-Known Member

    Joined:
    Oct 22, 2012
    Messages:
    142
    Likes Received:
    7
    I see what Ekot was saying, though, Doc. I also could not set any Default when I had Inventory set to text. However, I had already run into the not enough lines in inventory issue, so mine is set at 3000.
     
  17. James45x1997xST

    James45x1997xST New Member

    Joined:
    Dec 22, 2012
    Messages:
    3
    Likes Received:
    0
    Alors Moi j'arive pâs a Maitre plus de Vehicule ! Commant Faire est se que il peux faire une Vidéo ou meme toi si tu veux. moi Je suis pâs trop cfg DayZ Mes Plus cfg Call of duty C est pas la méme Chose !

    est se que tu peux faire une Vidéo mot de ! stp
     
  18. Doc

    Doc Valued Member!

    Joined:
    Nov 23, 2012
    Messages:
    355
    Likes Received:
    39
    What?

    Whatever way works for your server is best :) Personally all my vehicles spawn empty, so I would rather save on data storage by using Text opposed to varchar (as varchar uses all of the data allowance even if it's empty). This is especially important as I have buildings in my object_data and I would end up using a lot of storage capacity purely by using varchar instead of Text. If you want loot in there though, you have to use varchar. :)
     
  19. Xentiran

    Xentiran New Member

    Joined:
    Dec 27, 2012
    Messages:
    8
    Likes Received:
    0
    I get this error "1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')
    BEGIN

    DECLARE iCurrentVehicles INT(4) DEFAULT 0;
    DECLARE loopCount' at line 1"

    whe I try to save a new procedure :s Please help xD
     
  20. Doc

    Doc Valued Member!

    Joined:
    Nov 23, 2012
    Messages:
    355
    Likes Received:
    39
    I just tried saving the code I wrote above as a new procedure in navicat and it worked fine. What I did was open hivemind and expand functions. I clicked on new function and selected the "procedure" option. I then pressed next all the way until it finished. I then pasted the pSpawnVehicles code above into it, making sure it deleted the crap Navicat puts in there by default. Pressing save asked me to name the function and it saved with no problems... :S I don't know what's the problem, but I messaged you my skype name. Message me with yours and I will try help you.
     

Share This Page