HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

make bomb solid (after getting off it)

07-28-2007, 06:22 AM#1
fps-doug
hey everyone I have a bit of a problem. In my bomberman map that Im making I'm trying to figure out how to make it so the bombs you place become unpathable after you get off of them. In real bomberman games, when you set them they go under your character wherever you set them (they get centered on the grid tho of course), and your character can still move freely as if nothing was there. As soon as you move off the square with the bomb though, you can no longer pass through the bomb and you'll be blocked by it.

So the problem with doing this in my map is multiple players. If it was just one player I was dealing with it would be easy, just wait for him to leave a rect then make a unit with collision on the spot of the bomb. But what if another player walks on the bomb before the 1st one leaves it? Then the collision unit will be placed at an offset or maybe not even created at all... I think you see my problem. What should have happened in the above situation was the 2nd player attempting to enter the area with the bomb would be blocked, but the 1st player could still move on it because he was always on top of it and never moved off of it.

I dont even think this is possible to do, but if anything close to it can be achieved please feel free to explain to me how to do it.


note: also there is a bomberman map I found in which the creator claims 'bombs become solid after you walk off of them', and in testing this solo I found this to be true, but I have been unable to test it with other players and see if it actually works as intended with multiple players or not. (and the map is protected )
07-28-2007, 08:26 AM#2
Pyrogasm
Is your map based on a grid system? If so, you could simply trigger all of your movement. Then, you could add in a check to see if there is an enemy player and his bomb on the tile you're moving too.
07-28-2007, 09:22 PM#3
fps-doug
no, I guess its not on a grid system, it doesnt really read rects at all. Basically my 'grid' is circles of power covering all of the stage, and all the triggers that work with the gameplay are based off the circles of power that players are currently standing on...

The reason I did this was so I didn't have to create 120 rects for each stage, and my plan is to include many different stages (I have 2 so far). All I do is place scout towers (unbreakable blocks), farms (breakable blocks), and then I cover everything with circles of power, change a couple of variables, and bam, I have a new stage in the game fully playable.


what Im looking at right now is making a function for this. All of my bombs being set, explosions, and blast collision detection for all of the players is done in 1 jass trigger (which has 2 or 3 functions). I think that for when a bomb is set, I need to call the function for all players and check to see if they try to enter the space with the bomb...

My guess is to create a temporary rect where the bomb is, and call a function for each player that will stop their character (and move him back a little) if he enters the area with the bomb. But then how would I know when/how to destroy or end that function when the bomb explodes? I think I am sort of rambling but I am confused as to what I should do... I'll post the trigger for my bombs in a sec when I figure out the tags..
07-28-2007, 09:24 PM#4
fps-doug
Im sorry if this is a little cryptic to read, but if you have any suggestions as to how I go about doing this I would appreciate it .

Collapse JASS:
function Trig_Set_Bomb_Conditions takes nothing returns boolean
    if ( not ( udg_bool_bombsaway == true ) ) then
        return false
    endif
    return true
endfunction

function terminate takes nothing returns nothing
    if ( GetUnitTypeId(GetEnumUnit()) == 'n001' ) then //'n001' is the circle of passive power
        return
    else
        call KillUnit( GetEnumUnit() )
    endif
endfunction

function blast takes integer radii, location origin, player owner, string direction returns nothing
    local integer xmod
    local integer ymod
    local integer i = 1
    local rect square
    local location newloc
    local integer j = 1
    local integer jend = 11
    local unit immolator

    if ( direction == "left" ) then
        set xmod = -1
        set ymod = 0
        call dbug("blast LEFT")
    elseif ( direction == "right" ) then
        set xmod = 1
        set ymod = 0
        call dbug("blast RIGHT")
    elseif ( direction == "up" ) then
        set xmod = 0
        set ymod = 1
        call dbug("blast UP")
    elseif ( direction == "down" ) then
        set xmod = 0
        set ymod = -1
        call dbug("blast DOWN")
    endif

    loop
        exitwhen ( i > radii )

        set newloc = OffsetLocation(origin, ( 128.00 * i * xmod ), ( 128.00 * i * ymod ))
        set square = RectFromCenterSizeBJ(newloc, 128.00, 128.00)
//if scout tower blocks the way, its immortal block, so dont even make explosion, just return now and forget this ever happened
        if ( UnitTypeIsInRegion(square, 'h001') == true ) then //h001 is scout tower
            call dbug("blast going " + direction + ", blocked by scout tower")
            return
        endif
//		call dbug("made a blast here")
//		call makeblast(newloc)

//so theres no unbreakable block here, now see if thers a breakable one here which would stop the blast from spreading past this tile
        if ( UnitTypeIsInRegion(square, 'h000') == true ) then //h000 is farm
            call dbug("breakable block in the way, blowing it up and stopping furthur blasts in this direction")

            call ForGroupBJ( GetUnitsInRectAll(square), function terminate )

//			call UnitDamagePointLoc( udg_player_bomberman[GetConvertedPlayerId(owner)], 0, 64.00, newloc, 1337.00, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL )
            return
        endif

        call dbug("ALL CLEAR")
        call makeblast(newloc) //nothing in the way (well basically no blocks in the way) so make a explosion here and keep going
//		call UnitDamagePointLoc( udg_player_bomberman[GetConvertedPlayerId(owner)], 0, 64.00, newloc, 1337.00, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL )

        call ForGroupBJ( GetUnitsInRectAll(square), function terminate )
//immolating guy for the lingering death effect
//		call CreateNUnitsAtLoc( 1, 'n00F', Player(PLAYER_NEUTRAL_AGGRESSIVE), origin, 270 )
//		set immolator = GetLastCreatedUnit()
//		call UnitApplyTimedLifeBJ( 0.65, 'BTLF', immolator )

        loop
            exitwhen ( j > jend )

            if ( RectContainsUnit(square, udg_player_bomberman[j]) == true ) then
                call KillUnit( udg_player_bomberman[j] )
                call dbug("rect contained a bomber, bomber destroyed")
            endif

            set j = ( j + 1 )
        endloop

        call RemoveLocation(newloc)
        call RemoveRect(square)
        set i = ( i + 1 )
    endloop

//	call RemoveLocation(origin) //THIS THING IS A PROBLEM!!! DONT REMOVE IT IF IT CAME FROM THE ARGUMENTS OR BUGS OCCUR

//	call TriggerExecute( gg_trg_Special_Effects )
endfunction    

//if the neutral circle that the player is on has a cv of 1, theres a bomb already on it
//if u can set another bomb on a valid spot, the bomb is placed with expiration timer
//function then waits till the bomb is dead, then makes all the kaboom stuff
//**************************************************
//**************************************************
function Trig_Set_Bomb_Actions takes nothing returns nothing
    local player owner = GetTriggerPlayer()
    local integer playernum = GetConvertedPlayerId(owner)
    local unit sapper = udg_player_bomberman[playernum]

    local unit neutralcircle = udg_player_neutralcircle[playernum]
    local unit playercircle = udg_player_circle[playernum]
    local unit bomb

    local integer cv = GetUnitUserData(neutralcircle)
    local location temploc
    local real hp
    local integer radii

    local rect center
    local integer j = 1
    local integer jend = 11

    if ( (cv) == (1) ) then
        call dbug("cv is 1, bomb already here")
        return
    endif

//	if ( (udg_bombs_live[playernum]) == (udg_bombs_max[playernum]) ) then
    if ( (udg_bombs_live[playernum]) == GetPlayerState(owner, PLAYER_STATE_RESOURCE_LUMBER) ) then


        call dbug("max number of bombs out right now")
        return
    endif

    call SetUnitUserData( neutralcircle, 1 )
    call SetUnitColor( neutralcircle, PLAYER_COLOR_RED )

    set temploc = GetUnitLoc(neutralcircle)

    call CreateNUnitsAtLoc( 1, 'h002', owner, temploc, 270 )
    set bomb = GetLastCreatedUnit()
    call UnitApplyTimedLifeBJ( 4.00, 'BTLF', bomb )
//	call PauseUnitBJ( true, bomb )

    set udg_bombs_live[playernum] = ( udg_bombs_live[playernum] + 1 )
    
    set hp = GetUnitState(bomb, UNIT_STATE_LIFE)

    loop
        exitwhen ( hp <= 0 )
        call dbug("waittill bomb dead")

        call TriggerSleepAction(0.1)
        set hp = GetUnitState(bomb, UNIT_STATE_LIFE)
    endloop

    call dbug("BOMB DEAD")

    set udg_bombs_live[playernum] = ( udg_bombs_live[playernum] - 1 )
    call SetUnitUserData( neutralcircle, 0 )
    call SetUnitColor( neutralcircle, PLAYER_COLOR_BROWN )
//	set radii = udg_bombs_radius[playernum]
    set radii = GetPlayerState(owner, PLAYER_STATE_RESOURCE_GOLD)


//kill those that standing directly on bomb
    set center = RectFromCenterSizeBJ(temploc, 128.00, 128.00)
    loop
        exitwhen ( j > jend )
        if ( RectContainsUnit(center, udg_player_bomberman[j]) == true ) then
            call KillUnit( udg_player_bomberman[j] )
            call dbug("rect contained a bomber, bomber destroyed")
        endif
        set j = ( j + 1 )
    endloop
    
    call blast(radii, temploc, owner, "left")
    call blast(radii, temploc, owner, "right")
    call blast(radii, temploc, owner, "up")
    call blast(radii, temploc, owner, "down")
    call RemoveLocation(temploc)



endfunction

//===========================================================================
function InitTrig_Set_Bomb takes nothing returns nothing
    set gg_trg_Set_Bomb = CreateTrigger(  )
    call TriggerRegisterPlayerEventEndCinematic( gg_trg_Set_Bomb, Player(0) )
    call TriggerRegisterPlayerEventEndCinematic( gg_trg_Set_Bomb, Player(1) )
    call TriggerRegisterPlayerEventEndCinematic( gg_trg_Set_Bomb, Player(2) )
    call TriggerRegisterPlayerEventEndCinematic( gg_trg_Set_Bomb, Player(3) )
    call TriggerRegisterPlayerEventEndCinematic( gg_trg_Set_Bomb, Player(4) )
    call TriggerRegisterPlayerEventEndCinematic( gg_trg_Set_Bomb, Player(5) )
    call TriggerRegisterPlayerEventEndCinematic( gg_trg_Set_Bomb, Player(6) )
    call TriggerRegisterPlayerEventEndCinematic( gg_trg_Set_Bomb, Player(7) )
    call TriggerRegisterPlayerEventEndCinematic( gg_trg_Set_Bomb, Player(8) )
    call TriggerAddCondition( gg_trg_Set_Bomb, Condition( function Trig_Set_Bomb_Conditions ) )
    call TriggerAddAction( gg_trg_Set_Bomb, function Trig_Set_Bomb_Actions )
endfunction

07-28-2007, 09:40 PM#5
Pyrogasm
Aside from leaking when you return prematurely, you also have a fair amount of BJ functions and inefficient lines.

This would be much easier with timers instead of polledwait loops.
07-28-2007, 11:08 PM#6
fps-doug
ok so I guess ill forget about making collision for my bombs for now and fix my code... Im guessing I have to change all the bj's because they are slow or some such?

And about timers... I'm reading up on them right now. It looks like when you start a timer, the rest of the function doesnt wait for it. If thats true, what should I do about waiting for the bomb to explode? I can't just wait for 3 seconds, I need to wait for it to explode because it can prematurely blow up from other bombs. Does that loop that waits for the bomb to blow up have any way for it to be optimized with timers ?
07-28-2007, 11:19 PM#7
Pyrogasm
This is a BJ, and why they're bad:
Collapse JASS:
function PauseUnitBJ takes boolean flag, unit whichUnit returns nothing
    call PauseUnit(whichUnit, flag)
endfunction

Just make the timer repeat with a fast interval. You can check every time to see if the bomb has exploded.