• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Virus Infection system

Status
Not open for further replies.
Level 3
Joined
Oct 19, 2007
Messages
51
**DISCLAIMER** : I am not sure if this is the proper location for this post, though it seemed there were other posts of a similar nature in this forum. I'm sorry if this is the wrong spot for this.
EDIT: IT occurred to me this belongs in the JASS section. Mod, help please?

So in a virus infection map I've been modding for a while now(near as I can tell, oldest version by Velex), I'm trying to make it so the body spawns red blood cells (workers which can mine from mines located around the body) at buildings called "bone marrow" and so that they spawn up to a limit that I can variably define on individual marrows (to facilitate upgrading the number of blood cells a single bone marrow.

Originally I tried using mana to do this, but the real to int (and vice versa) conversions were causing problems. I made the mistake of converting the trigger from gui to jass (which I am not terribly experienced with) AND trying to change it to work off of an ability on the bone marrow at the same time. The result (after LOTS of attempted syntax fixing), is a trigger, which, as far as I can tell, ought to work, but doesnt. There's something that's going on here which I don't understand. I've added debug messages, and from what I can see in the map, what's happening makes no sense to me.

It enters the first loop, says the message there, but does not go on to the next loop (suggesting the 'exitwhen' got a true, and left the loop prematurely), but the function never displays the "done" at the bottom of the trigger. Here's the Jass version I made, variables are pretty self-documenting in some cases, ambiguous cases will be explained below.


JASS:
function Trig_Marrowspawn_nearest_mine takes nothing returns boolean  
    return ( GetUnitTypeId(GetFilterUnit()) == 'n000' )
endfunction

function Trig_Marrowspawn_Actions takes nothing returns nothing
    local unit thismarrow  
    local unit compare
    local unit nearestmine
    local unit newblood
    local group g = CreateGroup() 
    local group nearbymines = CreateGroup() 
    local player marrowner
    local player comparehim
    local location thisplace
    local integer cv
    local integer count
    local group marrows
    set marrows = udg_marrows
    loop
        call DisplayTextToForce( GetPlayersAll(), "Starting marrowloop" )  
        set thismarrow = FirstOfGroup(marrows)
        call DisplayTextToForce( GetPlayersAll(), GetUnitName(thismarrow) )
        call DisplayTextToForce( GetPlayersAll(), UnitId2String(GetUnitTypeId(thismarrow)) )
        exitwhen ( thismarrow == null )                
        set thisplace = GetUnitLoc ( thismarrow )
        set cv = GetUnitUserData(thismarrow)
        set count=0
        call GroupEnumUnitsInRect( g , bj_mapInitialPlayableArea , null )
        loop
            call DisplayTextToForce( GetPlayersAll(), "Counting bloods loop" )
            call DisplayTextToForce( GetPlayersAll(), I2S(count) )  
            set compare = FirstOfGroup(g)
            exitwhen (compare == null)
            set comparehim = GetOwningPlayer(compare)
            if ( GetUnitUserData(compare) == cv ) and ( marrowner == comparehim ) then
                set count = count + 1
            endif
            call GroupRemoveUnit(g, compare)
        endloop
        if ( count < ( GetUnitAbilityLevel( thismarrow, 'A02E') - 1 ) ) then
            call DisplayTextToForce( GetPlayersAll(), "Trying to spawn" )
            call IncUnitAbilityLevel( thismarrow, 'A02E' )       
            set newblood = CreateUnitAtLoc( marrowner , 'u00O' , thisplace , GetRandomReal(0,360) )
            call SetUnitUserData( newblood, cv )
            set nearbymines = GetUnitsInRangeOfLocMatching( 500.00, thisplace, Condition(function Trig_Marrowspawn_nearest_mine))
            set nearestmine = FirstOfGroup( nearbymines )
            if ( nearestmine != null ) then
                call IssueTargetOrder( newblood, "harvest", nearestmine )
            endif
        endif              
        call GroupRemoveUnit(marrows, thismarrow)
    endloop
    set thismarrow = null
    set compare = null
    set nearestmine = null
    set newblood = null
    set marrowner = null
    set comparehim = null
    call DestroyGroup(g)  
    call DestroyGroup(nearbymines)
    call DestroyGroup(marrows)
    call RemoveLocation(thisplace)
    call DisplayTextToForce( GetPlayersAll(), "Done" )      
endfunction

//===========================================================================
function InitTrig_Marrowspawn takes nothing returns nothing
    set gg_trg_Marrowspawn = CreateTrigger(  )
    call TriggerRegisterTimerEventPeriodic( gg_trg_Marrowspawn, 5.00 )
    call TriggerAddAction( gg_trg_Marrowspawn, function Trig_Marrowspawn_Actions )
endfunction

This is the actual trigger that picks every bone marrow on the map (dynamically stored in the global unit group 'marrows' and checks to spawn a red blood cell at it.
What the trigger does is:
  1. Select a bone marrow from group marrows
  2. Count the number of red blood cells associated with that bone marrow (via matching custom value)
  3. If there are less red blood cells found than the current ability level of the tracking ability, it should spawn a red blood cell at the location of the bone marrow and order it to mine from the nearest gold mine.
  4. Display done before the trigger is done executing, regardless of what happened. (Debugging purposes only)

The Variables are as follows:
  1. Thismarrow - is the current 'bone marrow' unit being looked at.
  2. Compare - is the red blood cell the trigger is currently counting.
  3. nearestmine - is used to find the nearest gold mine in the event of a spawning.
  4. newblood - is used to store the new unit for modification
  5. g - is used to gather the red blood cells to be compared to 'thismarrow'
  6. nearbymines - ...
  7. marrowner - the owner of 'thismarrow'.
  8. comparehim - the owner of 'compare'
  9. thisplace - the location of 'thismarrow'
  10. cv - custom value of 'thismarrow'
  11. marrows - The local copy of the global group marrows(udg_marrows) so I can easily cycle through the list.
  12. udg_marrows - Complete list of every bone marrow that has been constructed and not destroyed, maintained by another trigger, and has not been modified since the last version, so I'm assuming there is nothing wrong with this group.


As previously stated, the trigger just seems to stop just after the first loop is entered...

I'm 100% open to any ideas for a way of redoing the system that would preserve it's functionality (and maybe improve performance [though this has not been found out be lacking in the old gui version,save for the little inaccuracy]). I, of course would be able to do it myself (help is appreciated!) but I'm just not doing too well in the ideas category. If you need the map itself, I can attach it; I can also post the original GUI working trigger, if it would help to see a "working" version of what I want accomplished. The main reason for switching to JASS was because the GUI version leaked so much, the map's max playtime was brought to about...err...12 mins?

Much appreciated,
KEvin [SkoobyDoo]
 
Last edited:
Level 3
Joined
Oct 19, 2007
Messages
51
Haha, mk.

In the game the two defending players have to mine gold from gold mines aorund the body. In previous versions, the player had to just build the blood cells (workers) individually. This proved too complicated for most users, and too labor-intensive for the rest. So what I'm trying to do here is make it so the player can make these buildings called bone marrow. Each bone marrow can sustain up to X number of blood cells, and will periodically spawn them until it's max has been sustained. For testing purposes I had the frequency set to 5s, and the max set to 3.

The trigger selects every bone marrow on the map, check's it's skill level of "bone marrow count" or whatever i named it, and if it's less than 4 (level 1 - 0 cells, 2 - 1, etc...) it spawns a blood cell at the location of the current bone marrow.

In case anyone's wondering, this makes it less micro-intensive because the player can just make a few bone marrows near each gold mine, and if any of the red blood cells get killed, the player doesn't even have to notice and they respawn.
 
Level 3
Joined
Oct 19, 2007
Messages
51
Here is the first draft GUI trigger if it helps at all. The loigic of the mechanic has not changed, and GUI does have the advantage of making logic more plain. It still uses mana to keep track of the number of red blood cells. I know it's messy, but I left a couple " + 0.00 " for easy manipulation of gui nastyness. The plus .5 was to make sure the game didn't just drop the decimal off of the number (in case the real value was 4.99 or something)

I realize those variables aren't REALLY local. I just use them in my triggers anywhere I need a quick int substitute/storing. I was surprised that even though they are used in so many triggers running simultaneously, i never saw a single bug related to it...

  • Marrowspawn
    • Events
      • Time - Every 5.00 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in marrows and do (Actions)
        • Loop - Actions
          • Set local_int = (Custom value of (Picked unit))
          • Set local_int2 = (Number of units in (Units in (Playable map area)(((Custom value of (Matching unit)) Equal to local_int) and ((Owner of (Picked unit)) Equal to (Owner of (Matching unit))))))
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • local_int2 Less than ((Integer(((Max mana of (Picked unit)) + 0.50))) + 0)
            • Then - Actions
              • Unit - Set mana of (Picked unit) to ((Real(local_int2)) + 0.00)
              • Unit - Create 1 Red Blood Cell (Clottable) for (Owner of (Picked unit)) at (Position of (Picked unit)) facing Default building facing (270.0) degrees
              • Unit - Set the custom value of (Last created unit) to (Custom value of (Picked unit))
              • Unit - Order (Last created unit) to Harvest (First unit of group (Units within 500.00 of (Position of (Picked unit)) matching ((Unit-type of (Matching unit)) Equal to Nucleus)))
            • Else - Actions
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Ok this is what I made. Im not sure if it works as im too lazy to check it but I do not see any reason for it not to.

This currently uses the units (marrows and bloodcells) custom value AND it uses the marrows MAX mana (current mana doesn't matter).
If you want to change the mana you can change it to basicly anything, for example: a skill level.

Custom Value - defines a unique group of units for each marrow, thus allowing you to control exacly how many bloodcells are "controlled" by every specific marrow.
Mana - defines the maximum number of bloodcells per marrow.
As I said, you can change it to basicly any integer number that you can use instead of unit's mana.

Now here's the code and a bit more explenation beneath it.
JASS:
scope bonemarrow
//===========================================================================

globals
    integer custom = 0 // This is the current marrow's custom value. Its a global just to make the filter more comfortable.
endglobals

//===========================================================================

function marrowfilter takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == 'h000' and GetUnitUserData(GetFilterUnit()) == custom and GetWidgetLife(GetFilterUnit()) > 0.4
endfunction
function bloodcellsfilter takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == 'h001'
endfunction
function minesfilter takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == 'h002'
endfunction

function actions takes nothing returns nothing
    local group marrows = CreateGroup()
    local group bloodcells = CreateGroup()
    local group mines = CreateGroup()
    local unit marrow
    local unit bloodcell
    local integer mana
    local real x
    local real y
    call GroupEnumUnitsInRect(marrows, bj_mapInitialPlayableArea , Condition(function marrowfilter)) 
    loop
        set marrow = FirstOfGroup(marrows)
        exitwhen marrow == null
        call GroupRemoveUnit(marrows, marrow)
        set custom = GetUnitUserData(marrow)
        set mana = R2I(GetUnitState(marrow, UNIT_STATE_MAX_MANA))
        call GroupEnumUnitsInRect(bloodcells, bj_mapInitialPlayableArea , Condition(function bloodcellsfilter))
        if CountUnitsInGroup(bloodcells) < mana then
            set x = GetUnitX(marrow)
            set y = GetUnitY(marrow)
            set bloodcell = CreateUnit(GetOwningPlayer(marrow), 'h001', x, y, 0)
            call GroupEnumUnitsInRange(mines, x, y, 500, Condition(function minesfilter))
            call IssueTargetOrder(bloodcell, "harvest", FirstOfGroup(mines))
        endif
    endloop
    call DestroyGroup(marrows)
    call DestroyGroup(bloodcells)
    call DestroyGroup(mines)
    set marrows = null
    set bloodcells = null
    set mines = null
    set marrow = null
    set bloodcell = null
endfunction

//===========================================================================
function InitTrig takes nothing returns nothing
    local trigger trig = CreateTrigger(  )
    call TriggerRegisterTimerEventPeriodic( trig, 5.00 )
    call TriggerAddAction( trig, function actions )
endfunction
//===========================================================================
endscope

Warning! this code requires JNGP (Jass New Gen Pack)! If you do not have it, continue reading and see how to change it!

This code basicly checks for each marrow's custom value, checks how much bloodcells with the same custom value are on the map, and then according to that checks if it needs to create more.
Notice that it also checks if the bloodcells are dead because if they are, it will still pick them if they have a decaying body.

Now this will require you to use a diffrent custom value for each marrow you create.
To do this, create a integer, and then whenever a player builds a marrow you will set its custom value to the integer and set the integer to its own value +1.
  • Example
    • Events
      • Unit - A unit Finishes construction
    • Conditions
      • (Unit-type of (Constructed structure)) Equal to marrow
    • Actions
      • Unit - Set the custom value of (Constructed structure) to integer
      • Set integer = (integer + 1)

The only real problem in this is that it doesn't allow you to use custom values on marrows/bloodcells for any other abilities/whatever.
Someone needs to create a system that checks for custom value digits already :(

Currently to implant it (if you have JNGP), just copy the code, put it in any trigger you want, and in the first line change the scope bonemarrow to scope your_trigger's_name.
If you do not have JNGP, copy the code, remove the first and the last lines, remove the globals part, create a global integer (in the variable editor) called custom and your done.

In case you want my map including this two things, here it is (requires JNGP).
 

Attachments

  • bonemarrow.w3x
    17.4 KB · Views: 85
Level 3
Joined
Oct 19, 2007
Messages
51
Thank you very much! I'll load it up and test it right after I clean the kitchen. Oh, and do you have to initialize groups with "= CreateGroup()" before you can add units to them? that might be the cause of my original problem...

If I could, I'd give you the rep point I have :)

With regards to the second trigger, I already have one that does the same thing, but is more complicated. Basically it has a hard coded max of 500 (arbitrary number), but it uses an array of bool values to keep track of what custom values are currently in use for marrows. Here it is if you're curious.

  • Marrow Creation
    • Events
      • Unit - A unit Finishes construction
    • Conditions
      • (Unit-type of (Triggering unit)) Equal to Bone Marrow
    • Actions
      • For each (Integer local_int2) from 1 to 499, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • marrowbool[local_int2] Equal to False
            • Then - Actions
              • Set local_int = local_int2
              • Set local_int2 = 499
            • Else - Actions
      • Unit Group - Add (Triggering unit) to marrows
      • Unit - Set the custom value of (Triggering unit) to local_int
      • Set marrowbool[local_int] = True
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Basicly you must create a group.
I do not think that your 'local group = global group' had any problems though since it didn't give any compile errors.

And thank me (or don't) after it works :p

[edit] You mean that when a marrow dies it will "free" the space in the array ? never really got why people make those systems.
They just use big loops that defiantly work harder then setting a integer to its value+1 and you can get to a awesomly big number with a integer lol.
 
Level 3
Joined
Oct 19, 2007
Messages
51
Didn't work :-\

Bout to play some company of heroes with my dad. Afterwards, I'll give the code a line by line look (I just glanced at it and it appeared largely similar to my original JASS-ification). The reason I changed to ability, is that I wanted the player be able to increase the blood cell capacity of individual bone marrows, and I couldn't find out a way to increase the maximum mana of individual bone marrows. The current mana was used to give the player an indication of how many red blood cells a particular bone marrow was currently supporting.

At any rate, thanks for giving it a shot! I'll let you know what I come up with after taking a look at it and adding some debug statements.

KEvin

EDIT: Turns out it got disabled when I initially tried to save it. Ok i just tried it, and it's still not working. *frustration*
 
Last edited:
Level 29
Joined
Jul 29, 2007
Messages
5,174
Whoops lol, my bad.
Put the custom value condition in the wrong boolexp.

By the way, do you know how to change those rawcodes for your units ? (for example 'h000')

JASS:
scope bonemarrow
//===========================================================================

globals
    integer custom = 0 // This is the current marrow's custom value. Its a global just to make the filter more comfortable.
endglobals

//===========================================================================

function marrowfilter takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == 'h000' and GetWidgetLife(GetFilterUnit()) > 0.4
endfunction
function bloodcellsfilter takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == 'h001' and GetUnitUserData(GetFilterUnit()) == custom and GetWidgetLife(GetFilterUnit()) > 0.4
endfunction
function minesfilter takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == 'h002' and GetWidgetLife(GetFilterUnit()) > 0.4
endfunction

function actions takes nothing returns nothing
    local group marrows = CreateGroup()
    local group bloodcells = CreateGroup()
    local group mines = CreateGroup()
    local unit marrow
    local unit bloodcell
    local integer mana
    local real x
    local real y
    call GroupEnumUnitsInRect(marrows, bj_mapInitialPlayableArea , Condition(function marrowfilter)) 
    loop
        set marrow = FirstOfGroup(marrows)
        exitwhen marrow == null
        call GroupRemoveUnit(marrows, marrow)
        set custom = GetUnitUserData(marrow)
        set mana = R2I(GetUnitState(marrow, UNIT_STATE_MAX_MANA))
        call GroupEnumUnitsInRect(bloodcells, bj_mapInitialPlayableArea , Condition(function bloodcellsfilter))
        if CountUnitsInGroup(bloodcells) < mana then
            set x = GetUnitX(marrow)
            set y = GetUnitY(marrow)
            set bloodcell = CreateUnit(GetOwningPlayer(marrow), 'h001', x, y, 0)
            call GroupEnumUnitsInRange(mines, x, y, 500, Condition(function minesfilter))
            call IssueTargetOrder(bloodcell, "harvest", FirstOfGroup(mines))
        endif
    endloop
    call DestroyGroup(marrows)
    call DestroyGroup(bloodcells)
    call DestroyGroup(mines)
    set marrows = null
    set bloodcells = null
    set mines = null
    set marrow = null
    set bloodcell = null
endfunction

//===========================================================================
function InitTrig takes nothing returns nothing
    local trigger trig = CreateTrigger(  )
    call TriggerRegisterTimerEventPeriodic( trig, 5.00 )
    call TriggerAddAction( trig, function actions )
endfunction
//===========================================================================
endscope
 
Level 3
Joined
Oct 19, 2007
Messages
51
No, I don't know how to change it, but i've never really sought a way to. One problem with your trigger (besides mysteriously not working, like mine) is that it could accidentally get a marrow that is still under construction, and since a unit with no custom value is treated as having a custom value of 0, it will make "rogue" blood cells while it's under construction. Do you know of any way to check for current construction status other than checking for max life?

and why the heck won't this run?...
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
It will never work if you do not change the rawcodes.
Rawcodes are the "real" value of each object (unit/item/ability/whatever).
You can see rawcodes by pressing Ctrl + d and by pressing again it will remove them.

The first rawcode (upper one which is currently h000) represents the marrows.
The second rawcode (middle one which is currently h001) represents the bloodcells.
The third rawcode (lower one which is currently h002) represents the mines.


About the building problem, I couldn't find any condition that has anything to do with buildings being constructed so I made a global group which you add the marrows to (and remove when they die). I think this is the easiest way.

JASS:
scope bonemarrow
//===========================================================================

globals
    integer custom = 0 // This is the current marrow's custom value. Its a global just to make the filter more comfortable.
    group globalmarrows = CreateGroup()
endglobals

//===========================================================================

function marrowfilter takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == 'h000' and GetWidgetLife(GetFilterUnit()) > 0.4 and IsUnitInGroup(GetFilterUnit(), globalmarrows)
endfunction
function bloodcellsfilter takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == 'h001' and GetUnitUserData(GetFilterUnit()) == custom and GetWidgetLife(GetFilterUnit()) > 0.4
endfunction
function minesfilter takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == 'h002' and GetWidgetLife(GetFilterUnit()) > 0.4
endfunction

function actions takes nothing returns nothing
    local group marrows = CreateGroup()
    local group bloodcells = CreateGroup()
    local group mines = CreateGroup()
    local unit marrow
    local unit bloodcell
    local integer mana
    local real x
    local real y
    call GroupEnumUnitsInRect(marrows, bj_mapInitialPlayableArea , Condition(function marrowfilter)) 
    loop
        set marrow = FirstOfGroup(marrows)
        exitwhen marrow == null
        call GroupRemoveUnit(marrows, marrow)
        set custom = GetUnitUserData(marrow)
        set mana = R2I(GetUnitState(marrow, UNIT_STATE_MAX_MANA))
        call GroupEnumUnitsInRect(bloodcells, bj_mapInitialPlayableArea , Condition(function bloodcellsfilter))
        if CountUnitsInGroup(bloodcells) < mana then
            set x = GetUnitX(marrow)
            set y = GetUnitY(marrow)
            set bloodcell = CreateUnit(GetOwningPlayer(marrow), 'h001', x, y, 0)
            call GroupEnumUnitsInRange(mines, x, y, 500, Condition(function minesfilter))
            call IssueTargetOrder(bloodcell, "harvest", FirstOfGroup(mines))
        endif
    endloop
    call DestroyGroup(marrows)
    call DestroyGroup(bloodcells)
    call DestroyGroup(mines)
    set marrows = null
    set bloodcells = null
    set mines = null
    set marrow = null
    set bloodcell = null
endfunction

//===========================================================================
function InitTrig takes nothing returns nothing
    local trigger trig = CreateTrigger(  )
    call TriggerRegisterTimerEventPeriodic( trig, 5.00 )
    call TriggerAddAction( trig, function actions )
endfunction
//===========================================================================
endscope

  • Untitled Trigger 001
    • Events
      • Unit - A unit Finishes construction
    • Conditions
      • (Unit-type of (Constructed structure)) Equal to Footman
    • Actions
      • Unit - Set the custom value of (Constructed structure) to integer
      • Set integer = (integer + 1)
      • Custom script: call GroupAddUnit(globalmarrows, GetConstructedStructure())

Well it seems that the Hive doesn't like me anymore and doesn't allow me to show Jass codes normally...
 
Last edited:
Level 3
Joined
Oct 19, 2007
Messages
51
Well I already knew how to view rawcodes. Do I have to include the parent rawcode? (in the object editor, say, bacteriophage's rawcode is 'h00H:hfoo' because it was based off of a footman. 'hfoo' is the default rawcode for footman.) every other trigger worked using the rawcodes as such...

and I did include the proper ones... =\
 
Level 3
Joined
Oct 19, 2007
Messages
51
Mk. Well I just realized the entire InitTrig part was completely wrong, and I got the trigger to run, but it never enters the if statement where it spawns a red blood cell. I'm going to take a more in depth look at it right now and hopefully edit this post shortly.
 
Level 12
Joined
Aug 20, 2007
Messages
866
Two things, kind of miniscule

One, there was some kind of special syntax for custom rawcodes (h000:hfoo) will not work properly with just 'hfoo'. Does anybody know it?

Two, instead of messing with the Integer to Real conversions with the +.5 and all that, just convert the custom value to real, and then compare (much less worrying about conversion bugs)
 
Level 3
Joined
Oct 19, 2007
Messages
51
(with regards to converting customs to reals) I'm converting to a diff system anyways methinks.

And I don't think the custom rawcode syntax matters, because the latter portion is just the unit that the custom unit is based off of. Plus when you convert a trigger that uses custom units in GUI, the extended syntax is not used.

Now, with regards to the trigger, I made the necessary changes to the new trigger suggested by ghost wolf so that it works; however the trigger adding constructed marrows that I previously had in effect spontaneously decided to not work...so I converted it to custom text (to get rid of the ridiculous global "local int 1" etc. And now I can't seem to get IT to work...

Here it is:
JASS:
function Trig_Marrow_Creation_Conditions takes nothing returns boolean
    if GetUnitTypeId(GetTriggerUnit()) == 'h00F' then
        return true
    endif
    return false
endfunction

function Trig_Marrow_Creation_Actions takes nothing returns nothing
    local integer i
    local integer j = 1
    loop
        exitwhen j > 500
        if ( udg_marrowbool[j] == false ) then
            set i = j
            set j = 500
        else
        endif
        set j = j + 1
    endloop
    call GroupAddUnit(udg_marrows, GetTriggerUnit())
    call SetUnitUserData( GetTriggerUnit(), i )
    set udg_marrowbool[i] = true
    call DisplayTextToForce( GetPlayersAll(), GetUnitName(FirstOfGroup(udg_marrows)) )
endfunction

//===========================================================================
function InitTrig_Marrow_Creation takes nothing returns nothing
    set gg_trg_Marrow_Creation = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Marrow_Creation, EVENT_PLAYER_UNIT_CONSTRUCT_FINISH )
    call TriggerAddCondition( gg_trg_Marrow_Creation, Condition( function Trig_Marrow_Creation_Conditions ) )
    call TriggerAddAction( gg_trg_Marrow_Creation, function Trig_Marrow_Creation_Actions )
endfunction

The original GUI trigger, which stopped working even though it remained unchanged...:
  • Marrow Creation
    • Events
      • Unit - A unit Finishes construction
    • Conditions
      • (Unit-type of (Triggering unit)) Equal to Bone Marrow
    • Actions
      • For each (Integer local_int2) from 1 to 500, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • marrowbool[local_int2] Equal to False
            • Then - Actions
              • Set local_int = local_int2
              • Set local_int2 = 500
            • Else - Actions
      • Unit Group - Add (Triggering unit) to marrows
      • Unit - Set the custom value of (Triggering unit) to local_int
      • Set marrowbool[local_int] = True
      • Game - Display to (All players) the text: (Name of (First unit of group marrows))
The display text was for debugging purposes, just to make sure SOMETHING was in marrows. Right about the time I fixed the spawning trigger, I noticed that this trigger stopped giving any output.

EDIT:

Symptoms are as follows:
As near as I can tell, nothing is added to 'udg_marrows', but the constructed unit IS getting a properly assigned custom value...

The new spawning trigger is getting into the loop and jumping out immediately, suggesting it's not finding any marrows in udg_marrows. I don't see why this code wouldn't add the unit properly to the global...

EDIT II:

I've confirmed that udg_marrows is not getting units added to it. I tried a simpler trigger (that doesn't use the bool array to reuse old custom values), and it's not working. WCIII just hates me...

Here it is. Please tell me there's some obvious stupid mistake I made...
  • marrowcreation
    • Events
      • Unit - A unit Finishes construction
    • Conditions
      • (Unit-type of (Triggering unit)) Equal to Bone Marrow
    • Actions
      • Unit - Set the custom value of (Triggering unit) to currentmarrow
      • Unit Group - Add (Triggering unit) to marrows
      • Set currentmarrow = (currentmarrow + 1)
Can someone tell me how to add those nifty (show)/(hide) things to their posts? IT would certainly help godawfully long posts like this one...

EDIT III: added hidden tags to make skipping past the post easier
 
Last edited:
Level 29
Joined
Jul 29, 2007
Messages
5,174
Try this.
And for hidden text put
and then a closing sentence (without the =name)


JASS:
function Trig_Marrow_Creation_Conditions takes nothing returns boolean
    return GetUnitTypeId(GetTriggerUnit()) == 'h00F'
endfunction

function Trig_Marrow_Creation_Actions takes nothing returns nothing
    local integer j = 1
    loop
        if ( udg_marrowbool[j] == false ) then
            set udg_marrowbool[j] = true
            exitwhen true
        endif
        if j > 500 then
            call BJDebugMsg("no available spaces")
            return
        endif
        set j = j + 1
    endloop
    call GroupAddUnit(udg_marrows, GetTriggerUnit())
    call SetUnitUserData( GetTriggerUnit(), j )
    call DisplayTextToForce( GetPlayersAll(), GetUnitName(FirstOfGroup(udg_marrows)) )
endfunction

//===========================================================================
function InitTrig_Marrow_Creation takes nothing returns nothing
    set gg_trg_Marrow_Creation = CreateTrigger( )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Marrow_Creation, EVENT_PLAYER_UNIT_CONSTRUCT_FINISH )
    call TriggerAddCondition( gg_trg_Marrow_Creation, Condition( function Trig_Marrow_Creation_Conditions ) )
    call TriggerAddAction( gg_trg_Marrow_Creation, function Trig_Marrow_Creation_Actions )
endfunction
 
Last edited:
Level 3
Joined
Oct 19, 2007
Messages
51
Once again, it it properly setting custom values, but not properly adding to the group, or even outputting the name, for that matter.

I'll upload the map so you can take a look at it yourself.

The triggers related are in the 'Body' folder at the bottom.
 

Attachments

  • VirusInfection beta20JASS.w3x
    1.2 MB · Views: 40
Level 3
Joined
Oct 19, 2007
Messages
51
Sorry for double post. I got it to actually spawn blood cells now. Unfortunately, it never stops. It gathers every bone marrow with a custom value over 0 (since 0 isnt used, and is only modified on construction). I'm removing udg_marrows, and i removed the reference from the creation trigger. I dunno why it's spawning blood cells indefinitely though.

JASS:
function marrowfilter takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == 'h00F' and GetWidgetLife(GetFilterUnit()) > 0.4 and GetUnitUserData(GetFilterUnit()) > 0
endfunction
function bloodcellsfilter takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == 'u00O' and GetUnitUserData(GetFilterUnit()) == udg_custom and GetWidgetLife(GetFilterUnit()) > 0.4
endfunction
function minesfilter takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == 'n000' and GetWidgetLife(GetFilterUnit()) > 0.4
endfunction

function Trig_Marrowspawn_Actions takes nothing returns nothing
    local group marrows = CreateGroup()
    local group bloodcells = CreateGroup()
    local group mines = CreateGroup()
    local unit marrow
    local unit bloodcell
    local integer mana
    local real x
    local real y
    call DisplayTextToForce( GetPlayersAll(), "starting bloodspawn" )  
    call GroupEnumUnitsInRect(marrows, bj_mapInitialPlayableArea , Condition(function marrowfilter))
    loop
        call DisplayTextToForce( GetPlayersAll(), "Starting marrowloop" )
        set marrow = FirstOfGroup(marrows)
        exitwhen marrow == null
        call GroupRemoveUnit(marrows, marrow)
        set udg_custom = GetUnitUserData(marrow)
        set mana = R2I(GetUnitState(marrow, UNIT_STATE_MAX_MANA))
        call DisplayTextToForce( GetPlayersAll(), I2S(mana) )
        call GroupEnumUnitsInRect(bloodcells, bj_mapInitialPlayableArea , Condition(function bloodcellsfilter))
        if CountUnitsInGroup(bloodcells) < mana then
            call DisplayTextToForce( GetPlayersAll(), "spawning a blood" )  
            set x = GetUnitX(marrow)
            set y = GetUnitY(marrow)
            set bloodcell = CreateUnit(GetOwningPlayer(marrow), 'u00O', x, y, 0)
            call GroupEnumUnitsInRange(mines, x, y, 500, Condition(function minesfilter))
            call IssueTargetOrder(bloodcell, "harvest", FirstOfGroup(mines))
        endif
    endloop
    call DestroyGroup(marrows)
    call DestroyGroup(bloodcells)
    call DestroyGroup(mines)
    set marrows = null
    set bloodcells = null
    set mines = null
    set marrow = null
    set bloodcell = null
    call DisplayTextToForce( GetPlayersAll(), "Done" )  
endfunction

//===========================================================================
function InitTrig_Marrowspawn takes nothing returns nothing
    set gg_trg_Marrowspawn = CreateTrigger(  )
    call TriggerRegisterTimerEventPeriodic( gg_trg_Marrowspawn, 5.00 )
    call TriggerAddAction( gg_trg_Marrowspawn, function Trig_Marrowspawn_Actions )
endfunction
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Well I chit chatted with HINDYhat and he said that when you put a global group in a local, its acutally a pointer so we destroyed the global when we destroyed the local o0

Anyway, he didn't find anything (yea that always what happens with my codes... un-reason-able-bugs-grrrrr) BUT he said that maybe we need to clear the groups though (we are not sure if the EnumUnits reset it or not), so use this code:
JASS:
native GroupClear takes group whichGroup returns nothing
 
Status
Not open for further replies.
Top