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

Creation of Hero Spells

Status
Not open for further replies.
Level 19
Joined
Nov 16, 2006
Messages
2,165
Hey everyone, this is the official thread for spell creation!
Any format is welcome since we will attempt to fix it.
If you can, please make sure that the spells you create are:
(- MUI)
- Leakless (most important)
- Optimized

So, where can I find the spells which have to be created?
http://www.hiveworkshop.com/forums/...ves-battlefield-hero-concept-approved-172784/
At this thread you may find all heroes which are approved.

Feel free to pick a few spells, create them and post them here.
Your help is appreciated very much since it is a community map!

Let's finish this, mates.


Finished spells:
- [1/4] Septimus: Eye of God
- [1/4] Amigurumi: Burning Meteor
- [1/4] DonDustin: Volcano Skin
- [3/4] The_wand_mirror: Soul Steal, Possession, Spirit Burn
- [3/4] Dan van Ohllus: Steampunk Slam, Taunt, Forged Steel
- [1/4] Jaret: Heroic Offer
- [2/4] Xerex: Obliterate Mind, Soul Harvest
- [1/4] Xarwin: coming soon
- [2/4] Debode: Rupturing Strike, Hastening Fury
- [1/4] Numerion: Reality Rift, Sacrificial Cloak
- [1/4] WhereWolfThereWolf: Wind Weave
- [1/4] Cpt.ZnacK: Flame Wave
 
Last edited:
Level 14
Joined
Nov 18, 2007
Messages
1,084
I've finished Eye of God (Septimus) and Burning Meteor (Amigurumi). (Yeah, I did the easier ones first. :p)

Just a note for Eye of God, the special effect doesn't seem to work well since there's a small delay before the laser strike is actually shown. Should I add a delay before damage is actually done? (The effect also doesn't have a sound effect.)

I'm working on Volcano Skin (DonDustin).
I'll edit this post with the map of those three spells when I finish.

Edit: Okay I finished those 3 spells.
I used any imported resources the hero creators wanted me to use.
I couldn't download the icon for Volcano Skin since the resource was unavailable.

Used libraries:
ABuff
GroupUtils
SpellEvent
Table
TimerUtils
xe system

Used Buffs: (In case of conflicting)
Cripple
Unholy Frenzy
 

Attachments

  • Pack1.w3x
    134.6 KB · Views: 1,867
Last edited:
Thread's title should be "Creation of hero spells".
I suggest using Rising_Dusk's Intuitive Damage Detection System.
Hell no... you can't even make decent shields with that crap to prevent damage. Besides, ABuff uses ADamage, which is why we decided to use it on the first place. You should NOT have two Damage Detection systems in the same project, as there will be conflicts. Either use one, or use the other, but NOT the two of them. I strongly suggest you toss anything Rising_Dusk may have done to the garbage.

Perhaps you guys could post some code ?
I would like some quick reviews for the simple spells in order to optimize them a little further.
 
Level 14
Joined
Nov 18, 2007
Messages
1,084
Hell no... you can't even make decent shields with that crap to prevent damage. Besides, ABuff uses ADamage, which is why we decided to use it on the first place. You should NOT have two Damage Detection systems in the same project, as there will be conflicts. Either use one, or use the other, but NOT the two of them. I strongly suggest you toss anything Rising_Dusk may have done to the garbage.
Actually, ABuff uses DamageEvent & DamageModifiers now.
It looks like DamageEvent can support IDDS in that it will interface with IDDS and not create its own damage detection triggers.
Perhaps you guys could post some code ?
It's not a bad idea. But I don't think this thread should be cluttered with posts that make it harder to find the submissions, like this one.
 
Actually, ABuff uses DamageEvent & DamageModifiers now.
It looks like DamageEvent can support IDDS in that it will interface with IDDS and not create its own damage detection triggers.
The problem with IDDS is that it does not allow you to create a shield spell (per example) because it is not meant to reduce damage but only to change it's type and amplify it. I had this problem in the early version of IDDS and that's why Rising_Dusk created a module to create shields (which didn't work properly iirc, dunoo if it is fixed now).

If you want to make shield spells I am quite sure you will be forced to use DamageModifiers because IIDS does not support shields. That's why ABuff is way better with DamageModifiers and not with IDDS.

And let us not forget that DamageEvent interfaces with IDDS and not with the other system of shields, thus not working properly. Correct me if I am wrong.
 
I strongly recommend you to use DamageEvent with DamageModifiers module. It is not hard and if you are in trouble I am sure I can give you some tips by reading the documentation.

Besides, it has the bonus of interacting shields with ABuff.
As for the preloading system, I suggest using xepreload. watermelon_1234 is already using the xe system, there is no reason to not use the preload module xe already offers.

Btw, may I ask why you need xe watermelon_1234? Because we are using Anachron's projectile system to simulate projectiles. Just making sure :p
 
Level 14
Joined
Nov 18, 2007
Messages
1,084
Btw, may I ask why you need xe watermelon_1234? Because we are using Anachron's projectile system to simulate projectiles. Just making sure :p
I only used xe cast and xe preload for Volcano Skin.
Yeah, I know we're using CustomMissile. :p I'm not really used to it though.

The only reason I think we wanted to use IDDS was for the custom damage types (like for spells) that were mentioned in the brainstorming.
 
Level 19
Joined
Nov 16, 2006
Messages
2,165
I am doubting to use so many customization.
Anachron really let me down.

I can lead this project because I have an average (+professional, depending on the resource/field) knowledge of most customizations in the world editor.
My knowledge for using those systems isn't that great. Don't get me wrong, I know how it works and how to use it but I'm afraid everything will fall on my back.

I know that I have these awesome people around me who help, but they can't help me like forever. And not everyone knows how to use a system like that.

In my case, I would like to focus on finishing the hero spells and continue to an alpha version with or without advanced systems. Because, what for are we using it anyway?
 
Such as the ultimate for M0rbid's hero, which is approved btw. Such as every type of channeling spell as well.
If you fear you don't understand things, I will explain them to you. They are not that hard to understand and you are a pretty smart boy.
Oh, and I forgot: spells that have projectiles will also use the system. Just checking :p

Everything is needed, otherwise we wouldn't have suggested it.
 
Level 14
Joined
Nov 18, 2007
Messages
1,084
I finished easy spells again: Heroic Offer (Jaret) and Obliterate Mind (Xerex)

Before I upload these super easy spells, I'm trying to finish Soul Harvest (Xerex). I'm having fun trying to prevent any kind of problems/bugs that can come up. (I'm trying to make it support Tome of Retraining and make it give the correct bonus)
For those that are curious about the code or can help me improve it (There probably is a lot that can be improved) I've put the code here.

I will update this post with a map when I'm done.

Okay, I think I fixed the spell. I won't bother posting the code for the first two spells since they're pretty pathetically easy and I doubt there will be much code optimization.

JASS:
//==========================================================================================
//Soul Harvest (Xerex) by watermelon_1234
//__________________________________________________________________________________________
//Description:
//  Corpses within 500 range of Dark Lord will bolster his offensive power.
//******************************************************************************************
//Libraries required:
//  - BonusMod
//  - GroupUtils
//  - TimerUtils
//##########################################################################################
//Importing:
//  1. Copy the ability, Soul Harvest, and its buff.
//  2. Copy this trigger.
//  3. Implement required libraries.
//  4. Configure the spell.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Notes:
//  Probably will recode this if we use an Aura system.
//  The level check may be inefficient as it always update to that manually. The nice thing 
//  is that this spell supports Tome of Retraining.
//==========================================================================================
scope SoulHarvest

    native UnitAlive takes unit id returns boolean  //A better way to check if a unit is alive.
    
    globals
        private constant integer SPELL_ID = 'A005' //Raw id of the Soul Harvest ability.
        private constant real TIMER_LOOP = 0.15 //How often the timer will loop.
        private boolexpr e
    endglobals
    
    //The range of the ability which enumerates corpses.
    private constant function Range takes integer lvl returns real
        return 500. + 0*lvl
    endfunction
    
    //The damage bonus gained for each corpse.
    private constant function DamageBonus takes integer lvl returns integer
        return 2 + 2*lvl
    endfunction
    
    //The max damage bonus that one can get from this ability.
    private constant function MaxDamageBonus takes integer lvl returns integer
        return 70 + 0*lvl
    endfunction    
    
    private struct Data
        unit hero               //The hero that learned the ability
        integer lvl = 1         //The level of the ability for the hero
        integer count           //Counts how many corpses there are near the hero
        integer oldCount = 0    //Stores the oldCount from the previous count. Used to update the attack damage bonus correctly.
        integer totalBonus = 0  //The total attack damage bonus the hero has.
        timer t
        private static thistype temp
        
        static method create takes unit h returns thistype
            local thistype this = thistype.allocate()
            set .hero = h
            set .t = NewTimer()
            call SetTimerData(.t,this)
            call TimerStart(.t,TIMER_LOOP,true,function thistype.onLoop)
            return this
        endmethod
        
        static method countCorpses takes nothing returns boolean
            if not UnitAlive(GetFilterUnit()) then
                set temp.count = temp.count + 1
            endif
            return false
        endmethod
        
        //Used so many times that I just made a method for this.
        method resetBonus takes nothing returns nothing
            call AddUnitBonus(.hero,BONUS_DAMAGE,-.totalBonus) 
        endmethod
        
        static method onLoop takes nothing returns nothing
            local thistype this = GetTimerData(GetExpiredTimer())
            local integer add
            local integer curLvl = GetUnitAbilityLevel(.hero,SPELL_ID)
            if curLvl == 0 then
                if .totalBonus > 0 then
                    call .resetBonus()
                endif
                call ReleaseTimer(.t)
                call .destroy()
            elseif UnitAlive(.hero) then                
                set .count = 0
                set temp = this
                call GroupEnumUnitsInArea(ENUM_GROUP,GetUnitX(.hero),GetUnitY(.hero),Range(.lvl),e)
                if .count == 0 and .oldCount != 0 then
                    call .resetBonus()
                    set .totalBonus = 0
                    set .oldCount = 0
                elseif .lvl != curLvl then
                    call .resetBonus()                     
                    if .count*DamageBonus(curLvl) > MaxDamageBonus(curLvl) then
                        set .totalBonus = MaxDamageBonus(curLvl)
                    else
                        set .totalBonus = .count*DamageBonus(curLvl)
                    endif
                    call AddUnitBonus(.hero,BONUS_DAMAGE,.totalBonus)
                    set .lvl = curLvl
                elseif .count != .oldCount then //The counts aren't the same so change the bonus             
                    if .count*DamageBonus(.lvl) > MaxDamageBonus(.lvl) then 
                        set add = MaxDamageBonus(.lvl) - .totalBonus
                    else
                        set add = .count*DamageBonus(.lvl) - .totalBonus
                    endif
                    call AddUnitBonus(.hero,BONUS_DAMAGE,add)                    
                    set .oldCount = .count 
                    set .totalBonus = .totalBonus + add 
                endif                 
            endif
        endmethod
        
        static method learnSkill takes nothing returns boolean
            if GetLearnedSkill() == SPELL_ID and GetUnitAbilityLevel(GetTriggerUnit(),SPELL_ID) == 1 then
                call thistype.create(GetTriggerUnit())
            endif
            return false
        endmethod
        
        static method onInit takes nothing returns nothing
            local trigger t = CreateTrigger()
            call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_HERO_SKILL)
            call TriggerAddCondition(t,Condition(function thistype.learnSkill))
            set e = Filter(function thistype.countCorpses)
        endmethod
    endstruct    
endscope
 
watermellon_1234

scope should be private, since it is a spell, we don't want to access it from the rest of the map (avoids naming conflicts and it is a security measure).

Having in mind you are using onloop, perhaps you should replace it by this script made by Vexorian, this way all members of the team will understand your code better.

Since this is an aura, and I find your code quite weird to read, I really think we should use Abuff Aura component of the system (since we are already using ABuff, I see no reason to not use it's aura modules...)

You use BonusMod, but I promised Xarwin I would search for UnitProperties and see which one was best. I am looking for a system that allows us (the team) to expand it's basic components by adding more functionalities. Unfortunately, I cannot find UP and so I can't re-evaluate it :S

Overall it is a good code. I am happy you are on the team.
Please make the changes I requested. This can be done easier with ABuff aura module.
I will add the scripts to the coders page.

Also please, post one of the spells you consider easy. I would like to check them.

As an encouragement for your work, I give you rep++
 
Level 14
Joined
Nov 18, 2007
Messages
1,084
Sorry, my internet is kind of slow right now which is why I was unable to attach the map to my post. I'll do it after I make the changes though.

I'm pretty sure that scope can't be private...? It shouldn't be too much of a problem though since everything that should be (like global variables and functions) are private.

I'll implement TimedLoop.

I'll see what I can do with ABuffAura.

Sorry for the code being confusing. I'll try to comment more.

I linked UP in my post in the Coders Thread. (It's also in the Jass section of this site) I think Litany removed it from Wc3Campaigns.

Here's the spell code for the easy spells.
JASS:
//==========================================================================================
//Heroic Offer (Jaret) by watermelon_1234
//__________________________________________________________________________________________
//Description:
//  When Heroic offer is casted, Jaret loses a certain amount of health, but another player 
//  gets a certain amount of health healed. This spell has a cooldown of 60 seconds.
//******************************************************************************************
//Libraries required:
//  - SpellEvent
//##########################################################################################
//Importing:
//  1. Copy the ability, Heroic Offer.
//  2. Copy this trigger.
//  3. Implement required libraries.
//  4. Configure the spell.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Notes:
//  Probably should change the healing done to match a system, if implemented.
//  Haven't made a check to make sure the caster cannot kill himself.
//==========================================================================================
scope HeroicOffer initializer Init
    globals
        //Configurable
        private constant integer SPELL_ID = 'A003'  //Raw id of the Heroic Offer ability
        
        //Not configurable
        private real array Sacrifice                //Used for level support
        private real array Heal                     //Used for level support
    endglobals
    
    //How much %life the caster will lose. In terms of max life.
    private function SetSacrificedLife takes nothing returns nothing
        set Sacrifice[1] = .05
        set Sacrifice[2] = .1
        set Sacrifice[3] = .05
        set Sacrifice[4] = .1
        set Sacrifice[5] = .05
    endfunction
    
    //How much %life the target will gain. In terms of max life.
    private function SetHealedLife takes nothing returns nothing
        set Heal[1] = .05
        set Heal[2] = .1
        set Heal[3] = .1
        set Heal[4] = .2
        set Heal[5] = .2
    endfunction
    
//-------------END OF CONFIGURATION-------------------

    private function SpellActions takes nothing returns nothing
        local integer lvl = GetUnitAbilityLevel(SpellEvent.CastingUnit,SPELL_ID)
        call SetWidgetLife(SpellEvent.CastingUnit,GetWidgetLife(SpellEvent.CastingUnit)-GetUnitState(SpellEvent.CastingUnit,UNIT_STATE_MAX_LIFE)*Sacrifice[lvl])
        call SetWidgetLife(SpellEvent.TargetUnit,GetWidgetLife(SpellEvent.TargetUnit)+GetUnitState(SpellEvent.TargetUnit,UNIT_STATE_MAX_LIFE)*Heal[lvl])
    endfunction
    
    private function Init takes nothing returns nothing
        call RegisterSpellEffectResponse(SPELL_ID,SpellActions)
        call SetSacrificedLife()
        call SetHealedLife()
    endfunction
endscope
JASS:
//==========================================================================================
//Obliterate Mind (Xerex) by watermelon_1234
//__________________________________________________________________________________________
//Description:
//  Deals direct damage to enemy hero and also burns some of its mana.
//******************************************************************************************
//Libraries required:
//  - SpellEvent
//##########################################################################################
//Importing:
//  1. Copy the ability, Obliterate Mind.
//  2. Copy this trigger.
//  3. Implement required libraries.
//  4. Configure the spell.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Notes:
//  Pretty simple. It was harder to do the tooltip.
//==========================================================================================
scope ObliterateMind initializer Init
    globals
        //Configurable
        private constant integer    SPELL_ID = 'A004'                   //Raw id of the Obliterate Mind ability
        private constant attacktype ATK_TYPE = ATTACK_TYPE_NORMAL       //Attack type of the spell damage
        private constant damagetype DMG_TYPE = DAMAGE_TYPE_UNIVERSAL    //Damage type of the spell damage
        private constant weapontype WPN_TYPE = null                     //Weapon type of the spell damage  
    endglobals
    
    //Damage dealt to enemy hero.
    private function Damage takes integer lvl returns real
        return 60.*lvl
    endfunction
    
    //How much mana the target will lose.
    private function ManaLoss takes integer lvl returns real
        return 30.*lvl
    endfunction
    
//-------------END OF CONFIGURATION-------------------

    private function SpellActions takes nothing returns nothing
        local integer lvl = GetUnitAbilityLevel(SpellEvent.CastingUnit,SPELL_ID)
        call UnitDamageTarget(SpellEvent.CastingUnit,SpellEvent.TargetUnit,Damage(lvl),false,true,ATK_TYPE,DMG_TYPE,WPN_TYPE)
        call SetUnitState(SpellEvent.TargetUnit,UNIT_STATE_MANA,GetUnitState(SpellEvent.TargetUnit,UNIT_STATE_MANA)-ManaLoss(lvl))
    endfunction
    
    private function Init takes nothing returns nothing
        call RegisterSpellEffectResponse(SPELL_ID,SpellActions)
    endfunction
endscope

Edit:
I feel uncertain about using ABuffAura for this because this spell doesn't really do anything special with buffs. It's also not really an aura because the spell is only counting dead units and not doing anything else with the units; it's focusing more on the hero. Using ABuffAura for this spell feels like it would make it more complicated to do this.

However, I'm probably just not thinking of using the system correctly.

Anyway, I attached a test-map of the three spells.
Here's the updated code:
JASS:
//==========================================================================================
//Soul Harvest (Xerex) by watermelon_1234
//__________________________________________________________________________________________
//Description:
//  Corpses within 500 range of Dark Lord will bolster his offensive power.
//******************************************************************************************
//Libraries required:
//  - BonusMod
//  - GroupUtils
//  - TimedLoop
//##########################################################################################
//Importing:
//  1. Copy the ability, Soul Harvest, and its buff.
//  2. Copy this trigger.
//  3. Implement required libraries.
//  4. Configure the spell.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Notes:
//  Probably will recode this if we use an Aura system.
//  The level check may be inefficient as it always update to that manually. The nice thing 
//  is that this spell supports Tome of Retraining.
//==========================================================================================
scope SoulHarvest

    native UnitAlive takes unit id returns boolean  //A better way to check if a unit is alive.
    
    globals
        private constant integer SPELL_ID = 'A005' //Raw id of the Soul Harvest ability.
        
        //Not configurable
        private boolexpr e //Used for group enumeration
    endglobals
    
    //The range of the ability which enumerates corpses.
    private constant function Range takes integer lvl returns real
        return 500. + 0*lvl
    endfunction
    
    //The damage bonus gained for each corpse.
    private constant function DamageBonus takes integer lvl returns integer
        return 2 + 2*lvl
    endfunction
    
    //The max damage bonus that one can get from this ability.
    private constant function MaxDamageBonus takes integer lvl returns integer
        return 70 + 0*lvl
    endfunction    
    
//-------------END OF CONFIGURATION-------------------
    
    private struct Data
        unit hero               //The hero that learned the ability.
        integer lvl = 1         //The level of the ability for the hero. Is updated at the end of every loop as it stores the past level.
        integer count           //Counts how many corpses there are near the hero.
        integer oldCount = 0    //Stores the count from the previous time the loop was run. Used to update the attack damage bonus correctly.
        integer totalBonus = 0  //The total attack damage bonus the hero has from this ability.
        private static thistype temp    //Used for the group filter so that we can set count of a struct instance correctly. 
        
        static method create takes unit h returns thistype
            local thistype this = thistype.allocate()
            set .hero = h
            call .startTimedLoop()
            return this
        endmethod
        
        //Note that this is a filter. Used only to count dead units for the bonus.
        static method countCorpses takes nothing returns boolean
            if not UnitAlive(GetFilterUnit()) then //Corpses count as units that are dead.
                set temp.count = temp.count + 1
            endif
            return false
        endmethod
        
        //Used so many times that I just made a method for this. Basically removes any bonus the hero gained from this spell.
        method resetBonus takes nothing returns nothing
            call AddUnitBonus(.hero,BONUS_DAMAGE,-.totalBonus) 
        endmethod
        
        method onTimedLoop takes nothing returns boolean
            local integer add   //Considers what attack damage bonus the spell needs to add 
            local integer curLvl = GetUnitAbilityLevel(.hero,SPELL_ID)
            //If the level is 0 that means the hero no longer has the ability. That means the spell should stop.
            if curLvl == 0 then
                //Only reset the bonus if .totalBonus is greater than 0.
                if .totalBonus > 0 then
                    call .resetBonus()
                endif
                return false
            elseif UnitAlive(.hero) then  
                set .count = 0 //Set to 0 first or else counting the corpses will be messed up.
                set temp = this
                call GroupEnumUnitsInArea(ENUM_GROUP,GetUnitX(.hero),GetUnitY(.hero),Range(.lvl),e)
                //No corpses but oldCount has a different number. Remove any bonus given to the hero and correctly set oldCount to 0.
                if .count == 0 and .oldCount != 0 then
                    call .resetBonus()
                    set .totalBonus = 0
                    set .oldCount = 0
                //Previous level is not updated with the current level. 
                //In this case, ignore any bonus the hero has received from last loop by resetting it and manually give the correct bonus. 
                elseif .lvl != curLvl then
                    call .resetBonus()       
                    //Make sure the bonus will not exceed MaxDamageBonus. 
                    //Remember: The bonus given to the hero is the # of corpses times the damage bonus each corpse gives but the bonus is capped.
                    if .count*DamageBonus(curLvl) > MaxDamageBonus(curLvl) then
                        set .totalBonus = MaxDamageBonus(curLvl)
                    else
                        set .totalBonus = .count*DamageBonus(curLvl)
                    endif
                    call AddUnitBonus(.hero,BONUS_DAMAGE,.totalBonus)
                    set .lvl = curLvl
                elseif .count != .oldCount then //The counts of the corpses aren't the same so change the bonus. Otherwise, don't do anything after this as all is well.             
                    //If the supposed bonus is bigger than MaxDamageBonus, limit it.
                    //add is the difference between the bonus the hero should have from the spell and the current bonus it has.
                    if .count*DamageBonus(.lvl) > MaxDamageBonus(.lvl) then 
                        set add = MaxDamageBonus(.lvl) - .totalBonus
                    else
                        set add = .count*DamageBonus(.lvl) - .totalBonus
                    endif
                    call AddUnitBonus(.hero,BONUS_DAMAGE,add)
                    //Update some variables to work for the next loop
                    set .oldCount = .count 
                    set .totalBonus = .totalBonus + add
                endif                 
            endif
            return true
        endmethod
        
        implement TimedLoop
        
        static method learnSkill takes nothing returns boolean
            if GetLearnedSkill() == SPELL_ID and GetUnitAbilityLevel(GetTriggerUnit(),SPELL_ID) == 1 then
                call thistype.create(GetTriggerUnit())
            endif
            return false
        endmethod
        
        static method onInit takes nothing returns nothing
            local trigger t = CreateTrigger()
            call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_HERO_SKILL)
            call TriggerAddCondition(t,Condition(function thistype.learnSkill))
            set e = Filter(function thistype.countCorpses)
        endmethod
    endstruct    
endscope
Note: You'll also see my attempt at making a spell with CustomMissile in the test-map. Don't actually use it as it's unfinished and doesn't even work.
 

Attachments

  • Pack2.w3x
    185.3 KB · Views: 163
Last edited:
Level 25
Joined
Jun 5, 2008
Messages
2,572
Just a question i have been wondering about:

Isn't this:

JASS:
  private real array Sacrifice[6]               
  private real array Heal[6]

More efficent than:

JASS:
  private real array Sacrifice   
  private real array Heal

Since you limit the array size to 6 members, thus you spend less memory for it.
Just wondering if it's better since I ain't sure, thus i am asking.
Afaik when you declare a array in WC3 it has a default size of 8191, not all your arrays need that size :p
 
I'm pretty sure that scope can't be private...? It shouldn't be too much of a problem though since everything that should be (like global variables and functions) are private.
Ops .. I don't know what I was thinking xD
I'll see what I can do with ABuffAura.
Last time I checked ABuffAura I found it quite simple to deal with. I am not sure if it has changed since then however. I will give it a look once I install wc3 again.

Heroic Offer
As for the simple spell, it can be improved in some ways:
1 - you should define a clear SETUP section according to the JESP standard. Do NOT mix SETUP globals with system globals. Instead, create another globals block. Check my tutorial to see how I organized globals, it will take you 5 seconds.

I really dislike the use of arrays for the SETUP, it makes no sense and it is hard for the user to change IMO. You should instead do something like:
JASS:
private function SetSacrificedLife takes integer level returns real
    return 0.05 * level
endfunction

And the same should apply for SetHealedLife. This approach has many advantages such as:
1 - requires less code
2 - it is easier to understand
3 - it is faster (nothing is faster than arrays, I give you that, but there is no need in using them here, it's not like this is a critical application)
4 - it works for ANY number of levels

Therefore I would really like you to change it.

Finally, you are not preloading the ability, thus there will be first cast lag. We want to avoid that. Please use AbilityPreload.
You should also add a version number to your spells. Per example, this would be version 1.0. It is just to keep track of the different versions a spell can have. When I was coding my project it helped me organize things, so I would like to do it here as well.

Other than that, I would say that code is pretty simple and pretty perfect. Good job. I would give you rep++ but THW fag rep system won't allow me ...

Obliterate Mind
Well, you should preload the ability. Other than that, it is perfect.

Suggestions for spells: Those spells are in deed simple .... so why not make them better? Players love eye candy above all things. I strongly suggest you add some effect to the caster and to the target. It can be a death coil effect, or you can search an imported effect because Xarwin allows for imported effects. If you don't have the time, I can do it.
I can also PM the creators of the hero concepts in order to ask them for effects they would like to see.

Soul Harvest
In method learnSkill you are making multiple accesses to GetTriggerUnit(). I suggest you save that unit into a variable so it it faster (accessing variables is faster than accessing functions).

In your onTimedLoop you are evaluating all dead units every period, which means, you evaluate the dead units around the hero every 0.025 seconds. I don't think it is necessary to do count down of all dead units every 0.025 seconds, perhaps you should make the count down every 0.5 seconds? You only need to add a counter to that method, and it will release the CPU of a significant amount of work.
Other than that, the code is not that bad. I admit it is quite confusing because you use a style of programming that is not my own, but if you say it works, I believe you :p
Though iirc, there is a native called "corpse" (or something like this) that represents corpses (thus you don't need to check if a unit is alive). This could significantly improve the efficiency of your spell.

One last thing, you should definitely add an effect to the hero when he is bolstered, like an orb arround his weapon or something. It makes him look cooler :p

EDIT
Bliazzard account is down for maintenence so I can't install wc3 yet :S
As for UP, you forgot to post the link xD

Since you limit the array size to 6 members, thus you spend less memory for it.
Just wondering if it's better since I ain't sure, thus i am asking.
Afaik when you declare a array in WC3 it has a default size of 8191, not all your arrays need that size :p
If, the default size of an array when declared is 8191, then making" real array[6]" or "real array" gives you no efficiency improvements in time, but allows you to have a significant efficiency improvement in memory. If however, the default size of an array is < 6, (lets say, if it is 1) then each time you add an element, you have to expand the array. Expanding an array is extremely costly because you have to create an array with more memory, and copy the content of the old array to the new one.
The answer lies on the default size of an array when created.
 
Level 25
Joined
Jun 5, 2008
Messages
2,572
@Flame_Phoenix

He is using arrays for the setup because the values aren't linear, they rise in exponential way.

JASS:
        set Heal[1] = .05
        set Heal[2] = .1
        set Heal[3] = .1
        set Heal[4] = .2
        set Heal[5] = .2

See my point?

I think the blizard makes the default size upon defining an array 8191, you can expand it by doing this:
JASS:
integer array Example[40000]
Making it an array with 40000 size, so i think the arrays aren't using the expanding method, but i might be wrong.
Also less memory the map (WC3) takes the better.
And predefining array size is only used when you know you won't be changing it, or you could use a constant integer and simply manipulate array size's by it.

EDIT:

Don't forget to preload dummy abilities if there are any, else it will still cause the 1st time cast lag.
 
@Kingz:
He is using arrays for the setup because the values aren't linear, they rise in exponential way.
I get it now. But I still dislike using arrays. It is not modular and follows no standard at all. I would prefer he would use the method I suggested with if-then-else.Truth is, we don't know if we are going to add more levels to the heroes in future versions.
Also less memory the map (WC3) takes the better.
less memory = less loading time (I agree)

I understand the spell is simple, but I would really like other people (like Xarwin and new coders) to be able to change the spell using only the SETUP section without needing to enter the core. It is a principle.

Another thing I really would like to add to Heroic Offer is AbortSpell. It makes no sense to heal a unit that is already full hp right? It is a waste of mana, and a waste of HP.
Therefore watermellon_1234 should make a check to see if the unit is full HP, and if it is full HP, it should abort the spell, show an error message and re-order the unit again. Fortunately for us, someone already made all this for us, thus the perfect library for this job is AbortSpell by Rising_Dusk. All requirements from this library are also allowable and OK to use.

I also noticed that you can heal your enemies this this spell ... it is most certainly a thing we want to avoid (though I suppose that can be changed using the right ability from WE).

This is how you make a simple spell like Heroic Offer something not so simple, but something great: add eye candy and pay attention to details.

I look forward to see how watermellon_1234 is going to change his spells. Notice that if you need any help you only need to ask me.
I would gladly code this spells myself and make the changes myself, but I would be stealing his work, plus I don't have wc3 installed now becayse Bliazzard account website is down ...

How are you spells going Kingz?
 
Last edited:
Level 14
Joined
Nov 18, 2007
Messages
1,084
I'm hesitant about using ABuffAura because I'm thinking it would be harder to refer to the struct and keep track of how many dead units there are.

I'll separate the non-configurable globals from the configurable globals.

Believe me, I like using functions for level support more than using arrays. However, I think if-then-else would just complicate it since you only need to add another line for each level if you used an array whereas you would need to add about two lines for each level you want to add.

The reason I didn't preload any abilities was that they could be preloaded along with the heroes that had the abilities. No dummy abilities were used so the abilities themselves shouldn't lag.

I'll add version number; does that mean I should have some kind of changelog for each spell?

I added all the special effects the spells used with the ability itself. I didn't add any extra effects if the hero creator didn't specify, except for Soul Harvest as I gave an Aura of Blight effect to the ability. It seems like a good idea to have an effect to show its bonus so I'll add it. (But I'll think I'll only have one sfx representing all the bonus the hero could get.)

I'll add timeCounter to make it loop less.

Instead of importing another library, I could just base Heroic Offer off of Healing Wave which gives an error if the target has full health.
That should also solve the problem of healing enemies which I overlooked. :p

I did link UP in the post I made in the Coders Thread, but I'll link it again:
Unit Properties (Cassiel is basically Litany)
 
I'm hesitant about using ABuffAura because I'm thinking it would be harder to refer to the struct and keep track of how many dead units there are.
ABuff has an argument of type "int" that can save structures. I believe this solves the problem. Also, please check the corpse type I talked about.

Believe me, I like using functions for level support more than using arrays. However, I think if-then-else would just complicate it since you only need to add another line for each level if you used an array whereas you would need to add about two lines for each level you want to add.
Well, I dislike arrays, but your approach has a point. I will allow you to use arrays, but please separate the globals.

The reason I didn't preload any abilities was that they could be preloaded along with the heroes that had the abilities. No dummy abilities were used so the abilities themselves shouldn't lag.
preloaded with the heroes? Heroes are units, they don't have an ability ID. Please preload the abilities in the spells.

I'll add version number; does that mean I should have some kind of changelog for each spell?
Yes. Why? Because I plan to make a pack called HB promotional pack and I intend to release it for promotional purposes (with your consent ofc, since you are the creator). This spellpack main idea is to promote the project and make publicity. Thus every spell must be perfect and must have a changelog, like most decent resources have.
Ofc, you will be given full credit for your work.

Instead of importing another library, I could just base Heroic Offer off of Healing Wave which gives an error if the target has full health.
That should also solve the problem of healing enemies which I overlooked. :p
That is a wise decision. Please mention the ability in the "Notes" when you are done.

I did link UP in the post I made in the Coders Thread, but I'll link it again:
Sry, I missed it :S

After checking both systems, I do think that BonusMod is easier to use. Therefore I would like to make BonusMod the official system for the project. All agree?
It is also nice because this mod was forged in THW :D
 
I meant that if heroes are preloaded in the map, then the abilities they have will be preloaded with them. If they aren't preloaded, then I'll preload the abilities.
When you pick a hero you can't preload an ability. How do you know which heroes the players will choose in the loading screen or when the timer clicks 0.0 seconds? You don't know, that is why we always preload all abilities at start. Preloading is simply, basically you choose a dummy unit and give it all the abilities you want to with the time set to zero. This will force the game to load the abilities even before the game starts.
 
Actually Dota preloads hero abilities once you pick them.
So it lags when you pick a hero, I think that's bad. God created loading screens for a reason, I say use them. We want to avoid all types of lag. I don't care if the players have to wait more 10 seconds than usual, they won't die because of it. Please preload those abilities.
 
Working atm on the Turret spell for Mortar's hero.
This is how I figured it would work, seeing as I'm not an advanced vJass I'm wondering if anyone has a more efficient method.

The spell to create the turrets could be easily made using a normal Blizz spell.

A trigger using the damage detection library would check everytime a unit is attacked by one of the turrets and set an integer of it (I figured I'd use a hash table to attach the integer to it via the units key) + 1, and when it gets to the maximum value it would kill the unit.

Would this be an appropriate usage of a hash table, or (since some coders dislike hash tables) is there a preferable alternative?
 
Level 13
Joined
May 11, 2008
Messages
1,198
about the obliterate mind spell, i was thinking the animate dead on target effect would look nice. perhaps make the attachment point be head.

another thing that could be good but is something that can be left to a more global system perhaps would be displaying the mana lost.

you might have to check with xarwin or someone else, but shouldn't the attack type be chaos and the damage type magic?
 
Level 25
Joined
Jun 5, 2008
Messages
2,572
Would this be an appropriate usage of a hash table, or (since some coders dislike hash tables) is there a preferable alternative?

There is a quite easy way without the use of a hash table.

JASS:
private struct damageDetect extends DamageModifier

 turret tStruct

 method onDamageDealt takes unit u, real damage returns real
     local turret t = this.tStruct
     set t.count = t.count - 1
     if t.count == 0 then
         t.destroy()
         this.destroy()
     endif
     return damage
 endmethod

endstruct

private struct turret

 unit t
 integer count

 damageDetect dd

    method InitExample takes nothing returns nothing
        local thistype this = thistype.allocate()
        //code...
       set .t = *unit*
       set .count = *number of attacks*
       set .dd = .dd.create(.t,0)
       set .dd.tStruct = this
    endmethod

endstruct

And i think you get the picture now.

EDIT:

I wrote this in here, not in WC3 so it may have compile errors.
 
Level 13
Joined
May 11, 2008
Messages
1,198
Actually Dota preloads hero abilities once you pick them.

Thus the lag when you pick a hero and not a long loading time.

Just pointing this out...

i noticed that you can get to this by making your init function public and then calling the init function when the hero is picked, and taking out the initializer part of the line with the scope declaration. in case someone was not aware of it.

also...where is the link to the system called bonusmod?
 
i noticed that you can get to this by making your init function public and then calling the init function when the hero is picked, and taking out the initializer part of the line with the scope declaration. in case someone was not aware of it.
Hell no. As far as I am concerned there are easier ways to do that. Methods such as Init are meant to be private and I will not allow inventions like this one.
Preload the damn abilities in the Init method or trigger. I want no excuses, people will not die for waiting 10 seconds.
And if you do not like my decision, we can always ask Xarwin.

also...where is the link to the system called bonusmod?
Adding it now !!
 
Level 14
Joined
Nov 18, 2007
Messages
1,084
By preloading heroes, I mean creating them at map init and then removing them. It won't work just to have them in a tavern.

If you wanted to remove any kind of lag, you would want to preload all the heroes since there's a bit of lag when a unit enters the map for the first time. Preloading the heroes would get rid of the need of separately preloading the abilities they would have, except for the dummy abilities that come with the spells.

This thread is starting to get off-topic...

Edit:
Flame_Phoenix was right about using ABuffAura. XD

@Flame_Phoenix:
I don't know what native you're talking about. (The one about corpses?)

Also, I forgot to respond to
In method learnSkill you are making multiple accesses to GetTriggerUnit(). I suggest you save that unit into a variable so it it faster (accessing variables is faster than accessing functions).
I only referred to GetTriggerUnit() twice so there wasn't really a need for a variable. Anyway, that shouldn't even matter anymore since I'm going to use ABuffHeroSkill and ABuffAura.

Edit 2: Or maybe Flame_Phoenix was wrong.
There's a problem with ABuffAura: I can't have ABuffs on dead units, making it impossible to count units with the system. D:
 
Last edited:
By preloading heroes, I mean creating them at map init and then removing them. It won't work just to have them in a tavern.
I see your point. However, regular creeps and units will also have special abilities. Thus, in the name of consistency, I want to preload abilities and not units (such as heroes and creeps).

If the team finds it necessary, I can arrange a meeting with Xarwin.
In fact, I think I will have to, because I need to report on progress and I need to decide if we should or should not use xecast and xepreload.

I don't know what native you're talking about. (The one about corpses?)
Yes, I will make a search for it once I have my damn wc3 account online and installed ...
I only referred to GetTriggerUnit() twice so there wasn't really a need for a variable. Anyway, that shouldn't even matter anymore since I'm going to use ABuffHeroSkill and ABuffAura.
I know you only used it twice, but I wanted to make sure that it didn't escape. I understand that a variable is not necessary, a few nano-seconds will not kill our players :p
i just hope the ability you create was for approve heroes :p
All abilities being done are from approved heroes afaik. Though I am not sure yet ...


Team, I need to know which heroes you are making xD
 
Status
Not open for further replies.
Top