• 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.

Can someone have a look at this?

Status
Not open for further replies.
Level 2
Joined
Feb 12, 2023
Messages
11
For no reason this map puts me into lobby just if something leaks but i'm sure it doesn't. Can someone take a look at it - I created a demo map with only this spell - because i don't know if it's script's fault or my editor, thanks!
 

Attachments

  • Test map ultima.w3x
    48.5 KB · Views: 11
Last edited:
Level 29
Joined
Sep 26, 2009
Messages
2,596
You need to enable jass helper (Trigger editor => JassHelper => Enable JassHelper). Once that is enabled and you validate map triggers, a bunch of errors will appear due to missing sounds that are used in the ultima script.

The sounds are gg_snd_DarkSummoningTarget1 and gg_snd_LightningBolt, my guess is that they are imported sounds

After commenting out a few lines of code for playing both sounds, I was able to start the map without any issues.
 
Level 2
Joined
Feb 12, 2023
Messages
11
I somehow managed to run the map aswell but now the spell quite don't work, the sphere doesn't appear. Also weird thing happened. After placing units (to test if maybe only animation doesn't play) I can't open the map again LMAO. after saving i can open it but... placed units aren't there. It's some black magic hahahaahha

Would you mind posting that |working| Jass script Nichilus? ofc if the spell works on your map
 
Last edited:
Level 2
Joined
Feb 12, 2023
Messages
11
I don't have a working version of it - I just commented out the lines that were trying to use the missing sounds so that the map can be started without crashing. I have no idea what those 3 scripts are even supposed to do
Uuuh I don't know why on the original map of the spell everything worked, but after copying it to mine - it doesn't even though every line of code is the same
 
Level 45
Joined
Feb 27, 2007
Messages
5,578
Please actually read the spell header and instructions for things you want to import/use. The author took the time to explain exactly what you need to do to make this spell work, and you straight ignored it. They write things like this for your benefit, not because they like doing it.
JASS:
//¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
//¤
//¤ ***************** 
//¤     - Ultima - 
//¤ *****************
//¤ KeyTimers version   
//¤
//¤ By: Daxtreme
//¤ 
//¤ --> How to implement in your map:
//¤                           
//¤     1. Copy the spell "Ultima" into your map.
//¤     2. Copy the unit named "Ultima" into your map.
//¤     3. Copy this trigger into your map.
//¤     4. Import the Invoke.mdx model into your map.
//¤     5. Import the "Textures\RibbonNE1_blue.blp" texture into your map. (Keep the path as is)
//¤     6. Import the "Textures\Blue_Glow2.blp" into your map. (Keep the path as is)
//¤     7. (Optional) Define as variables the warcraft3 sounds featured in the Sound Editor.
//¤        For this, you need to search the sounds by name and select "Use as sound" when found.
//¤     8. Copy the trigger named "KT" into your map.
//¤     9. Copy the trigger named "GT" into your map
//¤     10. Change the rawcodes in the configuration section so they fit with your map's.
//¤
//¤ --> How to customize it:
//¤
//¤     You can configure the spell using the few globals and functions just below. Change their values.
//¤     
//¤
//¤ CREDITS:
//¤
//¤     - JetFangInferno's CharmTarget.
//¤     - BuilderBob's sound edit.
//¤     - Jesus4Lyf's KeyTimers2 and GTrigger Events sytems.
//¤     - Tinki3's spell map test template.
//¤
//¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
(Optional) Define as variables the warcraft3 sounds featured in the Sound Editor. For this, you need to search the sounds by name and select "Use as sound" when found.
I do disagree with the word "optional" here because the code cannot be compiled without these sound variables existing (it could have been written in a way to make this somewhat easy to avoid instead of requiring you to comment out lines). In your map go to the sound editor and search for "LightningBolt" and "DarkSummoningTarget1"; right click them and select "use as sound". Done.

Note that trying to do this in the example map you posted above will cause the editor to crash. Why? I don't really know. I imagine it is because these sound files are already flagged as "use as sound" so doing it a second time is something the WE doesn't know how to deal with. Maybe it's just because the map is quite old? Anyway, I tried in a blank map and was able to flag them as "use as sound" without any issue.

If you really don't want to do those two steps, here's a copy of the code with the sound-related lines commented out. It should not change functionality.
JASS:
//TESH.scrollpos=3
//TESH.alwaysfold=0
scope Ultima initializer Init

//¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
//¤
//¤ ***************** 
//¤     - Ultima - 
//¤ *****************
//¤ KeyTimers version   
//¤
//¤ By: Daxtreme
//¤ 
//¤ --> How to implement in your map:
//¤                           
//¤     1. Copy the spell "Ultima" into your map.
//¤     2. Copy the unit named "Ultima" into your map.
//¤     3. Copy this trigger into your map.
//¤     4. Import the Invoke.mdx model into your map.
//¤     5. Import the "Textures\RibbonNE1_blue.blp" texture into your map. (Keep the path as is)
//¤     6. Import the "Textures\Blue_Glow2.blp" into your map. (Keep the path as is)
//¤     7. (Optional) Define as variables the warcraft3 sounds featured in the Sound Editor.
//¤        For this, you need to search the sounds by name and select "Use as sound" when found.
//¤     8. Copy the trigger named "KT" into your map.
//¤     9. Copy the trigger named "GT" into your map
//¤     10. Change the rawcodes in the configuration section so they fit with your map's.
//¤
//¤ --> How to customize it:
//¤
//¤     You can configure the spell using the few globals and functions just below. Change their values.
//¤     
//¤
//¤ CREDITS:
//¤
//¤     - JetFangInferno's CharmTarget.
//¤     - BuilderBob's sound edit.
//¤     - Jesus4Lyf's KeyTimers2 and GTrigger Events sytems.
//¤     - Tinki3's spell map test template.
//¤
//¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

//¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
//
// ***      Configuration Section      ***
//
//¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

globals

private constant integer RawCode = 'A000'   // The spell's rawcode in the editor
private constant integer dummyid = 'h000'   // The "ultima" unit's id
private constant real AreaEffect = 1000.    // Damage AoE of the spell at the end
private constant real dummylife = .25       // The dummy unit's life span. Keep this low (Below 1.5)
private constant real period = 0.01         // Defines the rate at which the sphere augments in proportions
                                              // I recommend keeping this very low if you don't want the sphere 
                                              // growing awkwardly as it is rather big at the end.
private constant real damage = 1000.        // Multiply this by the level of the spell for damage value.
                                              // Note that this spell wasn't meant to be balanced in a normal game.
private constant real duration = 5.         // In seconds. You must change this into the Object Editor too.
private constant real SphereIncrement = 1.  // Factor determining the sphere's growing speed. It is set to 1 meaning
                                              // that every (period), its size is set to
                                              // 100% + SphereIncrement * currentcount. In short, if period = 0.01,
                                              // the sphere increases in size by 1% every 0.01 second = 100 times a second.
private constant real NoReturnPoint = 1.  // Minimal duration needed before the spell gets out of control and finishes
                                              // unleashing, even if the caster no longer is casting.
                                              // Do not set this above 1., else the spell will never function.
                                              // Expects values as so 0 < NoReturnPoint <= 1, 0.5 meaning the spell
                                              // can be interrupted as long as the caster has been channeling
                                              // for 50% of the total duration. Exceeding this state will cause the spell
                                              // to trigger its end instantly when casting is stopped.
private constant attacktype AType = ATTACK_TYPE_NORMAL // Attack type. This one means "Spell".
private constant damagetype DType = DAMAGE_TYPE_UNIVERSAL // Damage type. This one means no damage reduction.
private filterfunc non_leaking_filter = null
private unit forFilter = null

endglobals

private function Damage takes unit u returns real
    return I2R(GetUnitAbilityLevel(u, RawCode)) * damage
endfunction

//¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
//
// ***       Spell Code       ***
//
// --> I highly recommend editing the following only if you know what you're doing.
//
//¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

private constant function DummyFilter takes nothing returns boolean
    return TRUE
endfunction

private function DeathConditions takes nothing returns boolean
    return GetUnitTypeId(GetTriggerUnit()) == dummyid
endfunction

private struct data
    unit die
    unit c
    integer lvl
    integer id
    real j = 0.
    real i = 0.
    real x
    real y
endstruct

private function FilterEnemies takes nothing returns boolean
    return IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(forFilter))
endfunction

private function Timer takes nothing returns boolean
    local data d = KT_GetData()
    local group g
    local unit targ
    local unit dummy
    local real advancement = ((d.i * period) * (1. / period)) / (duration * (1. / period))
    
// END OF SPELL
    
    if ( (GetUnitCurrentOrder(d.c) != d.id) and (advancement < NoReturnPoint ) ) then
        set dummy = CreateUnit(GetOwningPlayer(d.c), dummyid, d.x, d.y, 0)
        call UnitApplyTimedLife(dummy, 'BTLF', 1.5)   // 1.5: Optimal visual effect time
        call SetUnitScalePercent(dummy, 105. + (SphereIncrement * d.i), 105. + (SphereIncrement * d.i), 105. + (SphereIncrement * d.i))
        call data.destroy(d)
        set dummy = null
        set d.c = null
        return true
    elseif ( (GetUnitCurrentOrder(d.c) != d.id) and (advancement >= NoReturnPoint ) ) then
        set dummy = CreateUnit(GetOwningPlayer(d.c), dummyid, d.x, d.y, 0)
        call UnitApplyTimedLife(dummy, 'BTLF', .25)   // 0.25: Optimal visual effect time
        call SetUnitScalePercent(dummy, 10000., 10000., 10000.) 
        set g = CreateGroup()
        set forFilter = d.c
        call GroupEnumUnitsInRange(g, d.x, d.y, AreaEffect, Condition(function FilterEnemies))
        loop
            set targ = FirstOfGroup(g)
            exitwhen targ == null
            call UnitDamageTarget(d.c, targ, Damage(d.c), true, false, AType, DType, WEAPON_TYPE_WHOKNOWS)            
            call GroupRemoveUnit(g, targ)
        endloop
/*
        call SetSoundPosition(gg_snd_LightningBolt, d.x, d.y, 0.)
        call SetSoundVolume(gg_snd_LightningBolt, PercentToInt(100., 127))
        if (gg_snd_LightningBolt != null) then
            call StartSound(gg_snd_LightningBolt)
        endif
*/
        call DestroyGroup(g)
        call data.destroy(d)
        set d.c = null
        set dummy = null
        set g = null
        set targ = null
        return true
    endif
    
// SPHERE INCREASING IN SIZE

    set d.i = d.i + 1.
    set dummy = CreateUnit(GetOwningPlayer(d.c), dummyid, d.x, d.y, 0)
    call UnitApplyTimedLife(dummy, 'BTLF', dummylife)
    call SetUnitScalePercent(dummy, 100.00 + (SphereIncrement * d.i), 100.00 + (SphereIncrement * d.i), 100.00 + (SphereIncrement * d.i)) 
    set dummy = null
    return false
endfunction

private function Actions takes nothing returns boolean
    local data d = data.create()
 
    set d.c = GetTriggerUnit()
    set d.x = GetUnitX(d.c)
    set d.y = GetUnitY(d.c)
    set d.id = GetUnitCurrentOrder(d.c)
/*
    call SetSoundPosition(gg_snd_DarkSummoningTarget1, d.x, d.y, 0.)
    call SetSoundVolume(gg_snd_DarkSummoningTarget1, PercentToInt(100., 127))
    if (gg_snd_DarkSummoningTarget1 != null) then
        call StartSound(gg_snd_DarkSummoningTarget1)
    endif
*/
    set d.lvl = GetUnitAbilityLevel(d.c, RawCode)
    call KT_Add(function Timer, d, period)
    return false
endfunction

private function DeathCallBack takes nothing returns boolean
    local data d = KT_GetData()
    
    if d.j > .1 / period then // 0.1: optimal remove timer.
        call RemoveUnit(d.die)
        set d.die = null
        return true
    endif
    set d.j = d.j + 1.
    return false
endfunction

private function DeathActions takes nothing returns nothing
    local data d = data.create()
    
    set d.die = GetTriggerUnit()
    call KT_Add(function DeathCallBack, d, period)
endfunction

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

private function Init takes nothing returns nothing
    local trigger t = CreateTrigger(  )
    local integer index = 0
    set non_leaking_filter = Filter( function DummyFilter )
    loop
        call TriggerRegisterPlayerUnitEvent(t, Player(index), EVENT_PLAYER_UNIT_DEATH, non_leaking_filter)
        set index = index + 1
        exitwhen index == bj_MAX_PLAYER_SLOTS
    endloop
    call TriggerAddCondition( t, Condition( function DeathConditions ) )
    call TriggerAddAction( t, function DeathActions )
    set t = null
    call GT_AddActionToStartsEffectEvent(RawCode, function Actions)
endfunction

endscope
 
Level 2
Joined
Feb 12, 2023
Messages
11
Wow, this actually worked, thank you so much! And it's my bad not doing EVERY steps in the implementation guide, thought that if that's opttional then I don't have to actually do anything with the sounds. Should've known that the code is designed using these sound variables :grin:
 
Level 45
Joined
Feb 27, 2007
Messages
5,578
I’m not saying you should ‘just know’.

If you had read the error it showed when you tried to save, or looked at the problem code it pointed to, it should have been obvious that there was something wrong with the sound. Even with no JASS or programming knowledge: “the word ‘sound’ is involved… wait didn’t I read something about optional sounds in the description/instructions?”

I’m not specifically trying to belittle you or be condescending. Unwillingness to read clear instructions and just ignoring the specific error JASSHelper tells you it’s having (because you don’t know the programming language) are behaviors that bother me immensely and are very common here. Learning to interpret errors via language and deduction is a valuable skill, even when you do not know any programming languages.
 
Status
Not open for further replies.
Top