• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[vJASS] CreateDestructibleZ does not work consistently

Status
Not open for further replies.
Level 21
Joined
Aug 21, 2005
Messages
3,699
Under what circumstances will CreateDestructibleZ not work?

I'm currently creating a dungeon generator, using destructibles. For the most part it works, but sometimes (randomly?) some destructibles just aren't created.
In the attached screenshot you can see the bug at work. On the bottom-right is a stairs with 2 statues (one on each side). On the center is a stairs with only 1 statue. 2 statues are supposed to be created.

It's not that bad when it's only decoration, but this bug sometimes happens on stairs. Not having stairs to get to the next room can... suck.
I've verified the OP limit isn't the problem. The bug doesn't seem to happen on ordinary walls / gates / floors. It just happens on stairs, and some decorative doodads. To test the map, enter "-dg 12345"
 

Attachments

  • destructible-bug.jpg
    destructible-bug.jpg
    332 KB · Views: 138
  • Dungeon Generator 0.3.69.w3x
    153.6 KB · Views: 40
Level 21
Joined
Aug 21, 2005
Messages
3,699
I'm not going to post 1500 lines of code spread over 15 triggers.

The part that seems somewhat relevant:
JASS:
library DGDestructible uses DGConfig, DGEntity

struct DG_Destructible extends DG_Entity
    private static integer iterations = 0
    
    private integer id
    private real z
    private real distance
    private real angle
    private real face
    private real minScale
    private real maxScale
    private integer maxVariation
    
    public static method create takes integer id, real x, real y, real z, real face, real minScale, real maxScale, integer maxVariation returns DG_Destructible
        local DG_Destructible this = DG_Destructible.allocate()
        set this.id = id
        set this.distance = SquareRoot(x*x + y*y)
        set this.angle = Atan2(y, x)
        set this.z = z
        set this.face = face
        set this.minScale = minScale
        set this.maxScale = maxScale
        set this.maxVariation = maxVariation
        return this
    endmethod
    
    // convenience method
    public method copy takes real x, real y, real z, real face returns DG_Destructible
        local DG_Destructible copy = DG_Destructible.allocate()
        set copy.id = this.id
        set copy.distance = SquareRoot(x*x + y*y)
        set copy.angle = Atan2(y, x)
        set copy.z = z
        set copy.face = face
        set copy.minScale = this.minScale
        set copy.maxScale = this.maxScale
        set copy.maxVariation = this.maxVariation
        return copy
    endmethod
    
    // Angle in radians
    public method instance takes real x, real y, real z, real angle returns nothing
        local real a = angle * bj_DEGTORAD + this.angle
        local real rx = x + this.distance * Cos(a) + DG_EPSILON
        local real ry = y + this.distance * Sin(a) + DG_EPSILON
        local real scale = this.minScale
        local real face = this.face
        local integer variation = 0
        
        if (face == -1) then
            set face = GetRandomReal(0, 360)
        endif
        
        // set scale if variable
        if (scale != this.maxScale) then
            set scale = GetRandomReal(this.minScale, this.maxScale)
        endif
        
        // set variation if variable
        if (variation != this.maxVariation) then
            set variation = GetRandomInt(0, this.maxVariation)
        endif
        
        // TO DO: register destructible (to be removed) ?
        call CreateDestructableZ(this.id, rx, ry, this.z + z, angle + face, scale, variation)
        
        set DG_Destructible.iterations = DG_Destructible.iterations + 1
        if (DG_Destructible.iterations >= DG_WORKLOAD) then
            set DG_Destructible.iterations = 0
            call TriggerSleepAction(0)
        endif
    endmethod
    
endstruct

endlibrary

But I don't think there's any problem here.
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,191
Debug the trigger by verifying each destructible is created. This can be done by printing out the destructible information before it is created and using TriggerSleepAction to delay the creation for a visible amount of time.

You will probably get 1 of 3 results.
1. The destructible creation is skipped (no text printed when you expected it). This means that it is skipping the generation of that specific destructible so you can ignore the actual creation part.
2. The text is shown but no destructible is created. This could be due to some invalid argument in the actual destructible creation that can be correlated looking at the parameters. An example could be trying to place a destructible with pathing at an improper offset for the pathing map used. Could also be placement problems such as the location is blocked.
3. It works perfectly with everything being created as should. This means that you are hitting the op-limit in some way or that there is some limit to simultaneous destructible creation.
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
I use .execute so waits are allowed. Besides, waits are all over the place. As soon as the first room is finished, the system would fail, and it doesn't.
Hitting the op-limit would cause a complete trigger stop, wouldn't it? The entire system still runs & finishes, it just skips some doodads.

I'll try DSG's suggestion, but it sounds awfully impractical with a thousand doodads being created.
 
Status
Not open for further replies.
Top