• 🏆 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!

[JASS] Fixing a JASS trigger (complicated)

Status
Not open for further replies.
Level 9
Joined
Sep 8, 2004
Messages
633
Hey guys,

My map (StarCraft ZoneControl) is at about 95% done. All I need to do is fix the last few JASS triggers and balance stuff out. Problem is that I can't JASS myself (used GUI), and the person that converted my entire map to JASS left the wc3 community. His JASS skills were among some of the better and I am not able to finish my map myself. Someone else tried to help me, but found himself unable to get the trigger to work, too! From there I've contacted several people to find help, but none had time, and some didnt't even respond to me. So now, I'm trying here. It's a complicated problem, and I could post the trigger here, but it would hardly make any sense, as the trigger refers to other triggers (uses CScache iirc). Who has the time and will to take a look at my map and see if he/she can help me get my map fixed? I will need someone on a really high level, as the triggers are all but simple. Thanks in advance!
 
Level 9
Joined
Sep 8, 2004
Messages
633
Well, to be honest, I'm not entirely sure! The trigger that doesn't work was made by someone else than the previous triggers. (which just need a little bit more bugfixing and optimising) Here's the code:

Code:
//TESH.scrollpos=198
//TESH.alwaysfold=0
library NewEndgame uses HelperFunctions, Awards

globals
    boolean array wraithWait
    private trigger array wraithInterrupt
    private boolean array isWraithInterrupt
    private triggeraction array trigact
    private dialog endgame_dialog = DialogCreate()
    private button endgame_button1
    private button endgame_button2
endglobals

function ShareCredit takes nothing returns nothing
    local player p = GetEnumPlayer()
    call SetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD)+bj_forLoopAIndexEnd)
    if GetPlayerController(p) == MAP_CONTROL_USER then
        call DisplayTextToPlayer(p, 0,0, "|cff32cd32You have received "+I2S(bj_forLoopAIndexEnd)+" gold from your defeated ally |r"+bj_lastPlayedMusic)
    endif
    set p = null
endfunction

function ShareCreditOfDefeatedPlayer takes player p returns nothing
    local force f = CreateForce()
    if GetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD) > 50 then
        call ForceEnumAllies(f, p, Filter(function IsInPlayers))
        set bj_forLoopAIndexEnd = GetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD) / CountPlayersInForceBJ(f)
        set bj_lastPlayedMusic = "|c" + GetPlayerColorString(p) + GetPlayerName(p) + "|r"
        call ForForce(f, function ShareCredit)
    endif   
    call DestroyForce(f)
    set f = null
endfunction

private function WraithExpire takes integer playerId returns nothing
    set wraithWait[playerId] = false
    if (isWraithInterrupt[playerId] == false) then
        call CreateUnit(Player(playerId), wraith_1, GetLocationX(building_loc[24 + playerId]), GetLocationY(building_loc[24 + playerId]), 0.00)
        call DisplayTimedTextToPlayer(Player(playerId), 0, 0, 5.00, "|cffc5dbffReinforcements have arrived!")
        call PingMinimapEx(GetLocationX(building_loc[24 + playerId]), GetLocationY(building_loc[24 + playerId]), 5.0, 0 , 255, 0, true)  
    endif
    call DestroyTrigger(wraithInterrupt[playerId])
    call TriggerRemoveAction(wraithInterrupt[playerId], trigact[playerId])
endfunction

private function WraithInterrupt takes nothing returns nothing
    local integer index = 0
    loop
        exitwhen (index == 9)
        if (GetTriggeringTrigger() == wraithInterrupt[index]) then
            exitwhen true
        endif
        set index = index + 1
    endloop
    if (GetUnitTypeId(GetTrainedUnit()) == wraith_1) or (GetUnitTypeId(GetTrainedUnit()) == wraith_2) or (GetUnitTypeId(GetTrainedUnit()) == wraith_3) then
        set isWraithInterrupt[index] = true
        call WraithExpire(index)
    endif
endfunction

function MultiboardAddTimer takes multiboard mb, integer column, integer row, integer playerId returns nothing
    local multiboarditem mbi = MultiboardGetItem(mb, row, column)
    local integer index = 30
    loop
        call TriggerSleepAction(1.00)
        exitwhen (index == 0) or (isWraithInterrupt[playerId] == true) or (wraithWait[playerId] == false)
        call MultiboardSetItemValue(mbi, "|CFFDD1C240|R"+" - "+I2S(index)+"sec")
        set index = index - 1
    endloop
    call MultiboardSetItemValue(mbi, "|CFFDD1C240|R")
    call MultiboardReleaseItem(mbi)
    set mbi = null
    if (isWraithInterrupt[playerId] == false) then
        call WraithExpire(playerId)
    endif
endfunction

function ShowCinematic takes nothing returns nothing
    local location loc = GetRectCenter(bj_mapInitialPlayableArea)
    local integer index = 0
    local string s = "We have an incoming message from Terran headquarters! This cinematic is under construction."
    call CinematicFadeBJ(1, 1.00, "ReplaceableTextures\\CameraMasks\\Black_mask.blp", 0, 0, 0, 0)
    call PolledWait(1.00)
    call TransmissionFromUnitTypeWithNameBJ(bj_FORCE_ALL_PLAYERS, Player(8), 'e000', "Lieutenant Doomhammer", loc, null, s, 0, 5.00, true)
    loop
        exitwhen (index == 8)
        call CustomDefeatBJ(Player(index), "Thank you for playing!")
        set index = index + 1
    endloop
    call RemoveLocation(loc)
    set loc = null
endfunction

function ClickEndGameDialog takes nothing returns nothing
    if (GetClickedButton() == endgame_button1) then
        if GetLocalPlayer() == GetTriggerPlayer() then
            call ClearTextMessages()
        endif
        call DisplayTimedTextToPlayer(GetTriggerPlayer(), 0.00, 0.00, 5.00, "You chose to watch the cinematic!")
        call DialogDisplay(GetTriggerPlayer(), endgame_dialog, false)
    else
        call CustomDefeatBJ(GetTriggerPlayer(), "Thank you for playing!")
        call DialogDisplay(GetTriggerPlayer(), endgame_dialog, false)
    endif
endfunction

function ShowEndGameDialog takes nothing returns nothing
    local integer index = 0
    call DialogSetMessage(endgame_dialog, "|cffc5dbffWhat next?|R")
    set endgame_button1 = DialogAddButton(endgame_dialog, "|cffc5dbffWatch the cinematic|R", 0)
    set endgame_button2 = DialogAddButton(endgame_dialog, "|cffc5dbffQuit the game|R", 0)
    loop
        exitwhen (index == 8)
        if IsPlayerInForce(Player(index), humans) then
            call DialogDisplay(Player(index), endgame_dialog, true)
        endif
        set index = index + 1
    endloop
    call TriggerSleepAction(8.00)
    call DialogClear(endgame_dialog)
    set index = 0
    loop
        exitwhen (index == 8)
        call DialogDisplay(Player(index), endgame_dialog, false)
        set index = index + 1
    endloop
    call DialogDestroy(endgame_dialog)
    call ShowCinematic()
endfunction

function RemovePlayerUnitsAction takes nothing returns nothing
    if (GetUnitTypeId(GetEnumUnit()) != 'h006') then
        call SetUnitExploded(GetEnumUnit(), true)
        call KillUnit(GetEnumUnit())
    endif
endfunction

private function Defeat takes integer playerId, integer teamId returns nothing
    local integer index = 0
    local integer index2
    local boolean win = true
    local group g = CreateGroup()
    if teamId != 0 then
        //Team Defeat
        call ForceRemovePlayer(players, Player(2 * teamId - 2))
        call ForceRemovePlayer(players, Player(2 * teamId - 1))
        if IsPlayerInForce(GetLocalPlayer(), bj_FORCE_ALL_PLAYERS) then
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0.00, 0.00, 5.00, "Team "+I2S(teamId)+" has been defeated!")
        endif
        call SetForceAllianceStateBJ(bj_FORCE_PLAYER[2 * teamId - 2], bj_FORCE_ALL_PLAYERS, bj_ALLIANCE_UNALLIED_VISION)
        call SetForceAllianceStateBJ(bj_FORCE_PLAYER[2 * teamId - 1], bj_FORCE_ALL_PLAYERS, bj_ALLIANCE_UNALLIED_VISION)
        set bj_lastCreatedFogModifier = CreateFogModifierRect(Player(2 * teamId - 2), FOG_OF_WAR_VISIBLE, bj_mapInitialPlayableArea, true, false)
        call FogModifierStart(bj_lastCreatedFogModifier)
        set bj_lastCreatedFogModifier = CreateFogModifierRect(Player(2 * teamId - 1), FOG_OF_WAR_VISIBLE, bj_mapInitialPlayableArea, true, false)
        call FogModifierStart(bj_lastCreatedFogModifier)
        call GroupEnumUnitsOfPlayer(g, Player(2 * teamId - 2), null)
        call ForGroup(g, function RemovePlayerUnitsAction)
        call GroupClear(g)
        call GroupEnumUnitsOfPlayer(g, Player(2 * teamId - 1), null)
        call ForGroup(g, function RemovePlayerUnitsAction)
        call CreateUnit(Player(2 * teamId - 2), 'H00C', GetLocationX(building_loc[24 + (2 * teamId - 2)]), GetLocationX(building_loc[24 + (2 * teamId - 2)]), 0.00)
        call CreateUnit(Player(2 * teamId - 1), 'H00C', GetLocationX(building_loc[24 + (2 * teamId - 1)]), GetLocationX(building_loc[24 + (2 * teamId - 1)]), 0.00)
    else
        //Player Defeat
        call ForceRemovePlayer(players, Player(playerId))
        if IsPlayerInForce(GetLocalPlayer(), bj_FORCE_ALL_PLAYERS) then
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0.00, 0.00, 5.00, "Player "+I2S(playerId)+" has been defeated!")
        endif
        call SetForceAllianceStateBJ(bj_FORCE_PLAYER[playerId], bj_FORCE_ALL_PLAYERS, bj_ALLIANCE_UNALLIED_VISION)
        set bj_lastCreatedFogModifier = CreateFogModifierRect(Player(playerId), FOG_OF_WAR_VISIBLE, bj_mapInitialPlayableArea, true, false)
        call FogModifierStart(bj_lastCreatedFogModifier)
        call GroupEnumUnitsOfPlayer(g, Player(playerId), null)
        call ForGroup(g, function RemovePlayerUnitsAction)
    endif
    call DestroyGroup(g)
    set g = null
    //Check if anyone won the game
    loop
        exitwhen (index == 8)
        set index2 = 0
        loop
            exitwhen (index2 == 8)
            if IsPlayerEnemy(Player(index), Player(index2)) and IsPlayerInForce(Player(index2), players) then
                set win = false
                exitwhen true 
            endif
            set index2 = index2 + 1
        endloop
        set index = index + 1
    endloop
    //If someone won, then..
    if (win == true) then
        set index = 0
        loop
            exitwhen (index == 8)
            if IsPlayerInForce(Player(index), players) then
                //Found a winning team or player
                call BJDebugMsg("Game Won!")
                if (game_mode < 2) then
                    //Normal/Simple game win actions
                    if (IsPlayerInForce(GetLocalPlayer(), bj_FORCE_ALL_PLAYERS)) then
                        call DisplayTimedTextToPlayer(GetLocalPlayer(), 0.00, 0.00, 5.00, "Team "+I2S(GetPlayerId(Player(index)) / 2 + 1)+" has won the game!
")
                        if (game_mode == 1) then
                            call BJDebugMsg("Team #"+I2S(GetPlayerId(Player(index)) / 2 + 1)+" has won the game in normal!")
                            call PanCameraToTimedForPlayer(GetLocalPlayer(), GetLocationX(lastBunker), GetLocationY(lastBunker), 0.00)  
                            call SetCameraRotateMode(GetLocationX(lastBunker), GetLocationY(lastBunker), bj_DEGTORAD * 360.00, 20.00)
                        else
                            call BJDebugMsg("Team #"+I2S(GetPlayerId(Player(index)) / 2 + 1)+" has won the game in normal!")
                            call PanCameraToTimedForPlayer(GetLocalPlayer(), GetLocationX(building_loc[31 + GetPlayerId(Player(index)) / 2 + 1]), GetLocationY(building_loc[31 + GetPlayerId(Player(index)) / 2 + 1]), 0.00)  
                            call SetCameraRotateMode(GetLocationX(building_loc[31 + GetPlayerId(Player(index)) / 2 + 1]), GetLocationY(building_loc[31 + GetPlayerId(Player(index)) / 2 + 1]), bj_DEGTORAD * 360.00, 20.00)
                        endif
                    endif
                else
                    //FFA game win actions
                    if (IsPlayerInForce(GetLocalPlayer(), bj_FORCE_ALL_PLAYERS)) then
                        call DisplayTimedTextToPlayer(GetLocalPlayer(), 0.00, 0.00, 5.00, "Player "+I2S(GetPlayerId(Player(index)))+" has won the game!
")
                        call BJDebugMsg("Player #"+I2S(GetPlayerId(Player(index)))+" has won the game in normal!")
                        call PanCameraToTimedForPlayer(GetLocalPlayer(), GetLocationX(building_loc[24 + GetPlayerId(Player(index)) / 2 + 1]), GetLocationY(building_loc[24 + GetPlayerId(Player(index)) / 2 + 1]), 0.00)  
                        call SetCameraRotateMode(GetLocationX(building_loc[24 + GetPlayerId(Player(index)) / 2 + 1]), GetLocationY(building_loc[24 + GetPlayerId(Player(index)) / 2 + 1]), bj_DEGTORAD * 360.00, 20.00)
                    endif
                endif
                call ShowAwards(null)
                call TriggerSleepAction(20.00)
                
                return
            endif
            set index = index + 1
        endloop
    endif
endfunction

private function DefeatTeam takes integer k returns nothing
    if (wraithWait[2 * k - 2] == true) then
        set isWraithInterrupt[2 * k - 2] = true
    endif
    if (wraithWait[2 * k - 1] == true) then
        set isWraithInterrupt[2 * k - 1] = true
    endif
    call Defeat(0, k)
endfunction

function DefeatCheck takes integer k, unit u returns nothing
    //Check defeat for FFA
    if game_mode == 2 and player_zones[k] <= 0 then
        call Defeat(k, 0)
        return
    endif
    //Check defeat for Simple
    if game_mode == 1 and player_zones[k] <= 0 then
        call ShareCreditOfDefeatedPlayer(Player(k))
        if (Player(k) != Player(2 * (k / 2 + 1) - 2)) and (IsPlayerInForce(Player(2 * (k / 2 + 1) - 2), players)) then
            call Defeat(k, 0)
            return
        elseif (Player(k) != Player(2 * (k / 2 + 1) - 1)) and (IsPlayerInForce(Player(2 * (k / 2 + 1) - 1), players)) then
            call Defeat(k, 0)
            return
        endif
        call Defeat(0, k / 2 + 1)
        return
    endif
    //Check defeat for Normal
    if game_mode == 0 and GetUnitTypeId(u) == 'h006' then
        call DefeatTeam(k / 2 + 1)
        return
    endif
    //This just starts the timer for new dropship
    if game_mode == 0 and player_zones[k] <= 0 and CountLivingPlayerUnitsOfTypeId(wraith_1, Player(k)) == 0 then
        set wraithInterrupt[k] = CreateTrigger()
        set trigact[k] = TriggerAddAction(wraithInterrupt[k], function WraithInterrupt)
        call TriggerRegisterPlayerUnitEvent(wraithInterrupt[k], Player(k), EVENT_PLAYER_UNIT_TRAIN_FINISH, null)
        call MultiboardAddTimer.execute(mboard, 1, mboard_spots[k] - 1, k)
        set wraithWait[k] = true
        set isWraithInterrupt[k] = false
    endif
endfunction

function InitTrig_New_Endgame takes nothing returns nothing
endfunction

endlibrary

If that makes sense to you, perhaps you can help. What this trigger does is check wheter or not players are winning or losing the game. You need a bit of background information to understand what needs to happen, so here goes:

It's a zone control map, bunkers are the structures that tell if a zone is taken, bunkers spawn the main units, marines.
The map has slots for 8 players. There's three gamemodes:

Normal - Players are divided in teams of 2 (1+2, 3+4, 5+6, 7+8). Every team has one energy generator which is shared between the two players in the team. The energy generator is normally very hard to kill (takes only one damage, no matter what the attack damage is). To make it vulnerable, all the team's bunkers must be destroyed. (then it starts taking normal damage) When the energy generator is destroyed, the team loses.
So for this gamemode, this trigger checks three things: 1) should the energy generator be vulnerable? (because there's 0 bunkers for both players in the team) and 2) Is the team defeated? 3) Is there only one team left? (If yes, end the game with awards etc.)

FFA - Same game, different rules. Each player fends for his own, there's no teams. A player loses when he/she has 0 bunkers. The last player standing wins. So the trigger checks: 1) Is a player dead? (0 bunkers), 2) Is there only one player left?

Simple - Another a bit different mode. The same teams as in the normal mode apply, but players can be defeated individually. There are no energy generators. When both players in the team have 0 bunkers, the team loses. The last team standing, again, wins.

So basically, the trigger checks conditions for all the gamemodes and then executes the proper actions. Some important actions:

Normal gamemode - when a player has 0 bunkers, a timer starts which gives the player with 0 bunkers a new dropship to create a new bunker after 30 seconds. This is canceled if the player makes a bunker himself, or if the team dies ofcourse.

All gamemodes - If a player/team is defeated, each defeated player gets to see a few personal awards (not sure if this is included yet). Alliances are set to Enemy with shared vision for everyone and a dialog pops up "you have been defeated, stay and watch or quit" after about 15 seconds.

All gamemodes - If a player/team wins, the endgame awards are shown and the camera's are centered on the winning team's energy generator (Normal gamemode) or last destroyed bunker (simple and FFA gamemodes). After about 20~25 seconds, a dialog pops up with two options: 1) Watch the cinematic or 2) Quit the game.

I'm currently still working on the Cinematic in GUI, which the trigger eventually will only have to run, no need to convert that.

I know it's a whole lot of text, but this is basically what I need. Thanks in advance!
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
To be honest, I do not understand why you didn't make this in GUI if you don't know Jass, it can all be done and its pretty simple, just a long trigger.

It does use vJass but a really little portion of it (mostly declaring globals in the trigger instead of the Variable Editor), but it will take me ages to read that and im kinda sleepy at the moment so im not gonna do it right now.

Again, you can just do this in GUI.

the camera's are centered on the winning team's energy generator (Normal gamemode) or last destroyed bunker (simple and FFA gamemodes)

Liked that, its like in UT2004 :D (just there you see the losers base exploding...).
 
Level 9
Joined
Sep 8, 2004
Messages
633
Well.. Yes, I can make it in GUI, since I've done that before. Big downside is that I'll have to re-create ALL the variables (global), since I can't use the JASS variables. Second, JASS is just plain better. I understand that it'll take some time to read and see what happened. May I ask you, if you can find the time and heart, can you help me to finish this? I can give you more information and help through another medium, like for instance MSN Messenger. Also, I'd send you the map to work with, which would make it much easier.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Well, to fix that trigger to work efficiently in the map, you need to re-write portions of the map systems... if it were a simple trigger fix, I would have done it myself, but some of it needs to be re-written because it was written so poorly, heh.

Angelusz, I'll teach you JASS some time, I imagine you'd be a great JASS programmer if only you knew how ^_^. Oh well, Angelusz, as a subscriber, I can teach you how. I won't write up the triggers etc for you, that's against protocol, but I'd be more than happy to teach you how to program in JASS.

Up to you, you know my MSN.
 
Level 9
Joined
Sep 8, 2004
Messages
633
Thanks Nessie, I'd love some JASS Class sometime soon ;) As for this trigger though, at the moment the goal is not to totally optimise it, but at least to get it to work, without me having to redo it all in GUI. The only thing I'm asking for is a working trigger. Let's see if we can get it that far.
 
Status
Not open for further replies.
Top