1. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  2. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still havn't received your rank award? Then please contact the administration.
    Dismiss Notice
  3. The Lich King demands your service! We've reached the 19th edition of the Icon Contest. Come along and make some chilling servants for the one true king.
    Dismiss Notice
  4. The 4th SFX Contest has started. Be sure to participate and have a fun factor in it.
    Dismiss Notice
  5. The poll for the 21st Terraining Contest is LIVE. Be sure to check out the entries and vote for one.
    Dismiss Notice
  6. The results are out! Check them out.
    Dismiss Notice
  7. Don’t forget to sign up for the Hive Cup. There’s a 555 EUR prize pool. Sign up now!
    Dismiss Notice
  8. The Hive Workshop Cup contest results have been announced! See the maps that'll be featured in the Hive Workshop Cup tournament!
    Dismiss Notice
  9. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

Mission Unit Spawn - Submission

Discussion in 'JASS Class' started by The_Spellweaver, Jun 27, 2017.

  1. The_Spellweaver

    The_Spellweaver

    Joined:
    Feb 20, 2013
    Messages:
    95
    Resources:
    2
    Models:
    2
    Resources:
    2
    A bit sloppy at the end, hopefully it's alright.

    Edit: Fixed some leaks

    Code (vJASS):

    scope UnitSpawn initializer Init
        globals
            private unit array barracks
            private integer array unitsData
        endglobals
       
        private function isPlayerForce takes nothing returns boolean
            return GetUnitTypeId(GetFilterUnit()) == 'hfoo' or GetUnitTypeId(GetFilterUnit()) == 'hrif'
        endfunction
       
        private function ExplodeAllUnits takes nothing returns nothing
            local unit u
            local group g = CreateGroup()
           
            call GroupEnumUnitsInRect(g, GetPlayableMapRect(), Filter(function isPlayerForce))
            loop
                set u = FirstOfGroup(g)
                exitwhen u == null
                call SetUnitExploded(u, true)
                call KillUnit(u)
                call GroupRemoveUnit(g, u)
            endloop
           
            call DestroyGroup(g)
            set g = null
            set u = null
        endfunction

        private function InitiateTraining takes nothing returns nothing
            local integer i = 0
            loop
                exitwhen i == 4
                if (barracks[i] != null) then
                    call IssueTrainOrderByIdBJ(barracks[i], unitsData[GetRandomInt(0,1)])
                endif
                set i = i + 1
            endloop
        endfunction
       
        private function VictoryCondition takes nothing returns boolean
            set unitsData[2] = unitsData[2] - 1
            if (unitsData[2] == 0) then
                call ExplodeAllUnits()
                set barracks[0] = null
                set barracks[1] = null
                set barracks[2] = null
                set barracks[3] = null
                call DisplayTextToForce(GetPlayersAll(), "You won!")
            endif
            return TRUE
        endfunction

        private function Init takes nothing returns nothing
            local integer i = 0
            local timer t = CreateTimer()
            local real x
            local real y
            local trigger unitDiesTrigger = CreateTrigger()
            local player playerHostile = Player(PLAYER_NEUTRAL_AGGRESSIVE)
            local unit u
           
            call TriggerRegisterPlayerUnitEvent(unitDiesTrigger, playerHostile, EVENT_PLAYER_UNIT_DEATH, null)
            call TriggerAddCondition(unitDiesTrigger, function VictoryCondition)
           
            set unitsData[0] = 'hfoo'
            set unitsData[1] = 'hrif'
           
            // Spawning neutral hostile units
            loop
                exitwhen i == 20
                // There are no units on some lvls so they don't spawn sometimes
                loop
                    set u = CreateUnit(playerHostile, ChooseRandomCreep(GetRandomInt(1, 10)), 0, 0, 0)
                    exitwhen u != null
                endloop
                set unitsData[2] = unitsData[2] + 1
                set i = i + 1
            endloop
           
            // Creating player barracks
            set i = 0
            loop
                exitwhen i == 4
                set x = 3000 * Cos(bj_PI * (i * 0.5 - 0.25))
                set y = 3000 * Sin(bj_PI * (i * 0.5 - 0.25))
               
                set barracks[i] = CreateUnit(Player(i), 'hbar', x, y, bj_UNIT_FACING)
                call IssuePointOrder(barracks[i], "smart", 0, 0)
                set i = i + 1
            endloop
           
            call TimerStart(t, 2.5, true, function InitiateTraining)
           
            set t = null
            set unitDiesTrigger = null
            set playerHostile = null
            set u = null
        endfunction
    endscope

     
     

    Attached Files:

    Last edited: Jun 27, 2017
  2. MyPad

    MyPad

    Spell Reviewer

    Joined:
    May 9, 2014
    Messages:
    1,306
    Resources:
    7
    Models:
    1
    Icons:
    2
    Spells:
    3
    JASS:
    1
    Resources:
    7
    It looks like we meet again.

    Anyway, I would suggest changing certain things:


    1.) Change
    GetPlayableMapRect()
    into
    bj_mapInitialPlayableArea

    2.) You can do away with the filterfunc
    isPlayerForce
    , replacing it with
    null
    and doing your filtering within the
    FirstOfGroup
    loop, copying the conditions of the former.
    3.) If you like, you can change
    IssueTrainOrderByIdBJ
    into
    IssueImmediateOrderById

     
  3. IcemanBo

    IcemanBo

    Joined:
    Sep 6, 2013
    Messages:
    6,181
    Resources:
    22
    Maps:
    3
    Spells:
    11
    Template:
    1
    Tutorials:
    4
    JASS:
    3
    Resources:
    22
  4. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    1,300
    Resources:
    16
    Tools:
    2
    Maps:
    2
    Spells:
    7
    Tutorials:
    4
    JASS:
    1
    Resources:
    16
    I assume that private means only visible in this scope ( I only used basic jass):
    The map test seemd overall fine except the end.
    there are some flaws in the code:
    • There is an likely bugg, to spawn new Player units after the game is won (appeared on testing).
    • you save UnitIds which you use for spawning. But in the "isPlayerForce"-filter you use hardcoded unitIds with the same values as the saved ones. ,maybe use the saved ones?
    • One could object: The units don't spawn every 2.5 seconds. they spawn every ( 2.5 * x + 2 ) seconds. Don't know how here the mission's goal is.
      1. Spawn 2.5 timer + 2 training time = 4.5
      2. Spawn 5 timer + 2 training time = 7
      3. Spawn 7.5 timer + 2 training time = 9.5
      4. and so on.
    • One could object that you did not check for the underlined Living Base and order possible dead ones to do stuff ( i did a simple test: the default barrack was removed, aka null, ca. 32 seconds after it was destroyed). -> Get 12 to 13 orders as dead ones before the null check works.
    • It is good habit and faster for Messages to use the natives with Player using GetLocalPlayer() as argument, this BJ asks anway is GetLocalPlayer() in the force.
    From the Blizzard.j:
    Code (vJASS):

    function DisplayTextToForce takes force toForce, string message returns nothing
        if (IsPlayerInForce(GetLocalPlayer(), toForce)) then
           // Use only local code (no net traffic) within this block to avoid desyncs.
            call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, message)
        endif
    endfunction
     


    • Offtopic: This check for GetLocalPlayer() applies for other Actions showing/hiding something not gamestate relevant using an force as argument from the BJs aswell.
    • Offtopic: Using GetLocalPlayer() as Player argument is really good as long you do nothing gamestate relevant.
     
  5. Jampion

    Jampion

    JASS Reviewer

    Joined:
    Mar 25, 2016
    Messages:
    1,285
    Resources:
    0
    Resources:
    0
    MyPad and Tasyen said pretty much everything already.
    I think there is still missing, that players 1-4 are allies, unless you did this in the force property menu.
    I already mentioned it in another submission of that mission, but I think that's not the focus of this mission, so it does not need to be considered I think:
    Some units have summon abilities, so in a real scenario 20 killed neutral units does not imply that there are none left.
    I like that you considered, that creeps of some levels might not exist.

    There is an easier solution:
    ChooseRandomCreep(-1)

    Using -1 as parameter will choose any level (it will not choose a level that does not exist). It will also change the random distribution I assume. It probably will give every unit the same chance, whereas yours would give every level the same chance, so if there is only 1 level 10 creep and 100 level 1 creeps, the specific level 10 creep will have a much higher chance than a specific level 1 creep.
    That's not something you need to change, but it's good to know, that -1 also works. If you look at the GUI equivalent it is explained there, but when only using JASS there is unfortunately no way to know this.