[Log in / Register]
| News | Chat | Pastebin | Donations | Tutorials | Rules | Forums |
| Maps | Skins | Icons | Models | Spells | Tools | Jass | Packs | Hosted Projects | Starcraft II Modding | Starcraft II Resources | Galaxy Wiki |
(Keeps Hive Alive)
Go Back   The Hive Workshop > Spells


Reply
 
Thread Tools
The Hive Workshop Spells:
HeroImage
by Ruke
Images
Highslide JS
Details
Uploaded:07:23, 6th Aug 2012
Last Updated:01:59, 20th Jan 2013
Keywords:aos, stats, hero, heroes
Type:System
Category:vJASS

This is an old idea that I had a long time ago. The code itself explains what this monster do. Enjoy it :3.

Comments, suggestions, etc. are welcome.

Jass:
library HeroImage /* v1.0.0.0
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
*   HeroImage it's a simple library (very useful for AoS maps) who can
*   be used to show the stats (life and mana) of our allies heroes.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*  
*   struct UnitIndex
*  
*       static method create takes unit u returns thistype
*           -   Creates the copy for "u"
*
*       method destroy takes nothing returns nothing
*           -   Destroys the copy
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
*   Thanks to
*  
*       -   Magtheridon96 from hiveworkshop.com
*       -   rulerofiron99 from hiveworkshop.com
*       -   Jesus4Lyf from thehelper.net
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    globals
        // Lower value = higher quality but more lag
        private constant real TIMEOUT = 1
       
        private constant trigger TARGET_ORDER = CreateTrigger()
        private constant trigger SELECTION = CreateTrigger()
        private constant trigger LEARN_SPELL = CreateTrigger()
       
        private constant hashtable HASHTABLE = InitHashtable()
    endglobals

    struct HeroImage
        private thistype prev
        private thistype next
   
        readonly unit original
        readonly unit array copies[12]
       
        method destroy takes nothing returns nothing
            local integer n = 0
           
            set this.original = null
           
            loop
                set n = n + 1
                exitwhen this.copies[n] == null
               
                call RemoveUnit(this.copies[n])
                set this.copies[n] = null
            endloop
           
            set this.prev.next = this.next
            set this.next.prev = this.prev
           
            call this.deallocate()
        endmethod

        private static method getInstance takes integer id returns thistype
            return LoadInteger(HASHTABLE, id, 0)
        endmethod
       
        private static method periodic takes nothing returns nothing
            local thistype this = thistype(0).next
            local real originalHp
            local real originalMp
            local integer originalXp
            local integer originalSkillPoints
            local integer originalLevel
            local unit copy
            local integer slot = 0
            local integer array originalItem
            local integer n = 0
           
            loop
                exitwhen this == 0
               
                if (this.original == null) then
                    call this.destroy()
                else
                    set originalHp = GetWidgetLife(this.original)
                    set originalMp = GetUnitState(this.original, UNIT_STATE_MANA)
                    set originalXp = GetHeroXP(this.original)
                   
                    set originalSkillPoints = GetHeroSkillPoints(this.original)
                   
                    set originalLevel = GetHeroLevel(this.original)
                   
                    // Items
                    loop
                        exitwhen (slot > 6)                
                        set originalItem[slot] = GetItemTypeId(UnitItemInSlot(this.original, slot))
                        set slot = slot + 1
                    endloop
                   
                    loop
                        set n = n + 1
                        exitwhen this.copies[n] == null
                       
                        set copy = this.copies[n]
                       
                        // Cheking if the copy isn't dead
                        if (GetWidgetLife(copy) <= 0.405) then
                            call ReviveHero(copy, GetRectMaxX(GetWorldBounds()), GetRectMaxY(GetWorldBounds()), false)
                        endif
                       
                        // HP
                        if (originalHp <= 0.405) then
                            call SetWidgetLife(copy, 1)
                        else                        
                            call SetWidgetLife(copy, originalHp)
                        endif
                       
                        // MP
                        call SetUnitState(copy, UNIT_STATE_MANA, originalMp)
                   
                        // Level
                        call SetHeroXP(copy, originalXp, false)
                       
                        // Items
                        set slot = 0
                       
                        loop
                            exitwhen (slot > 6)
                           
                            if (originalItem[slot] != GetItemTypeId(UnitItemInSlot(copy, slot))) then
                                call UnitRemoveItemFromSlot(copy, slot)
                                call UnitAddItemToSlotById(copy, originalItem[slot], slot)
                                call SetItemCharges(UnitItemInSlot(copy, slot), GetItemCharges(UnitItemInSlot(this.original, slot)))
                            endif
                           
                            set slot = slot + 1
                        endloop
                    endloop
                endif
               
                set this = this.next
            endloop
           
            set copy = null
        endmethod
       
        private static method order takes nothing returns boolean
            local unit target = GetOrderTargetUnit()
            local thistype this = thistype.getInstance(GetHandleId(target))
            local boolean redirect = false
            local integer n = 0
           
            loop
                set n = n + 1
                exitwhen this.copies[n] == null
               
                if (target == this.copies[n]) then
                    set redirect = true
                    exitwhen true
                endif
            endloop
           
            if (redirect) then
                call IssueTargetOrder(GetTriggerUnit(), OrderId2String(GetIssuedOrderId()), this.original)
            endif
           
            set target = null
           
            return false
        endmethod
       
        private static method selection takes nothing returns boolean
            local unit original
            local unit copy
           
            if (GetLocalPlayer() == GetTriggerPlayer()) then
                set copy = GetTriggerUnit()
                set original = thistype.getInstance(GetHandleId(copy)).original
               
                call ClearSelection()
           
                call SelectUnit(copy, false)
                call SelectUnit(original, true)
                call SetCameraPosition(GetUnitX(original), GetUnitY(original))

                set copy = null
                set original = null
            endif
           
            return false
        endmethod
       
        private static method learnSpell takes nothing returns boolean
            local unit originalUnit = GetLearningUnit()
            local thistype this = thistype.getInstance(GetHandleId(originalUnit))
           
            local integer spellId = GetLearnedSkill()
            local integer spellLevel = GetLearnedSkillLevel()
           
            local unit copy
            local integer n = 0
           
            loop
                set n = n + 1
                exitwhen this.copies[n] == null
               
                set copy = this.copies[n]
               
                if (GetUnitAbilityLevel(copy, spellId) != 0) then
                    call SetUnitAbilityLevel(copy, spellId, spellLevel)
                else
                    call UnitAddAbility(copy, spellId)
                endif
               
                call UnitModifySkillPoints(copy, -1)
            endloop
           
            set originalUnit = null
            set copy = null
           
            return false
        endmethod
       
        static method create takes unit u returns thistype
            local thistype this
            local integer id
            local player playerOwner
            local player p
            local unit copy
            local integer unitTypeId
            local real x
            local real y
            local rect worldBounds
            local integer i = 0
            local integer n = 0
           
            if (IsUnitType(u, UNIT_TYPE_HERO)) then
                set id = GetHandleId(u)
           
                if (HaveSavedInteger(HASHTABLE, id, 0)) then
                    debug call BJDebugMsg("HeroImage ERROR: That unit has already a copy or it is one")
                else
                    set this = thistype.allocate()
                   
                    // thanks Jesus4Lyf =3
                    set thistype(0).next.prev = this
                    set this.next = thistype(0).next
                    set thistype(0).next = this
                    set this.prev = thistype(0)
                   
                    set playerOwner = GetOwningPlayer(u)
                    set unitTypeId = GetUnitTypeId(u)
                    set worldBounds = GetWorldBounds()
                    set x = GetRectMaxX(worldBounds)
                    set y = GetRectMaxY(worldBounds)
                   
                    set this.original = u
                   
                    call TriggerRegisterUnitEvent(LEARN_SPELL, u, EVENT_UNIT_HERO_SKILL)
                   
                    call SaveInteger(HASHTABLE, id, 0, this)
               
                    loop
                        exitwhen i == bj_MAX_PLAYERS
                       
                        set p = Player(i)
                       
                        if (IsPlayerAlly(p, playerOwner) and p != playerOwner) then
                            set copy = CreateUnit(p, unitTypeId, x, y, 0)
                           
                            call SaveInteger(HASHTABLE, GetHandleId(copy), 0, this)
                           
                            set n = n + 1
                            set this.copies[n] = copy
                           
                            call TriggerRegisterUnitEvent(SELECTION, copy, EVENT_UNIT_SELECTED)
                        endif
                       
                        set i = i + 1
                    endloop
                   
                    set playerOwner = null
                    set copy = null
                    set worldBounds = null
                endif
            else
                debug call BJDebugMsg("HeroImage ERROR: You can not create a copy of a non-hero unit")
            endif
           
            return this
        endmethod
       
        private static method onInit takes nothing returns nothing
            call TimerStart(CreateTimer(), TIMEOUT, true, function thistype.periodic)
       
            call TriggerRegisterAnyUnitEventBJ(TARGET_ORDER, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER)
            call TriggerAddCondition(TARGET_ORDER, Condition(function thistype.order))
            call TriggerAddCondition(SELECTION, Condition(function thistype.selection))
            call TriggerAddCondition(LEARN_SPELL, Condition(function thistype.learnSpell))
        endmethod
    endstruct
endlibrary

Changelog

v1.0.0
  • Now does not desync
  • Re-writed
Rating - 0.00 (0 votes)
(Hover and click)
Moderator Comments
Not Rated
04:29, 8th Aug 2012
Magtheridon96: GetWorldBounds() leaks.
You should store it into a rect variable and use RemoveRect to delete it.

Other than that, wonderful spell! ^_^

edit
Just realized that this also leaks events.
It would be better to have the events registered for all units instead of specific ones, and you would figure out when to run your spell's code based on the triggering unit. (You have a hashtable in there, so you are capable of attaching data to units. Store a boolean into the hashtable using the handle id and any key so that you keep track of units that should have code run for them upon the firing of the event.)

This spell is awaiting update.


Download HeroImage.w3m
(18.42 KB, 208 Downloads)

Old 08-06-2012, 07:55 AM   #2 (permalink)
Registered User zv27
The real me RnR forever
 
zv27's Avatar
 
Join Date: Aug 2010
Posts: 236
zv27 has disabled reputation
It looks interesting.
__________________
zv27 is offline   Reply With Quote
Old 08-06-2012, 09:05 AM   #3 (permalink)
Forum Moderator Magtheridon96
JESUS MAN
 
Magtheridon96's Avatar
Resource Moderator
 
Join Date: Dec 2008
Posts: 5,699
Magtheridon96 has a brilliant future (1808)
Merit Badge - Level 0: This user has proven to be extremely valuable to the Warcraft III Modding Community. 
Use a doubly linked list.
Your current list-remove method is not totally functional since you're using dynamic indexing like that.

Jass:
// insert to list:
set next[this] = 0
set prev[this] = prev[0]
set next[prev[0]] = this
set prev[0] = this

// remove from list:
set next[prev[this]] = next[this]
set prev[next[this]] = prev[this]

// iterate over list, pretty much the same thing you're doing here
local thistype this = next[0]
loop
    exitwhen this == 0

    set this = next[this]
endloop

My method is using arrays now, but it can be easily changed to use the '.' operator, and it would still be the same thing.

edit
By the way, you can use 0.03125 without the trailing 0's. I debunked that myth about inaccuracy a very long time ago.
You need to run the map for a year to be a few seconds off. <.<
__________________
Magtheridon96 is offline   Reply With Quote
Old 08-06-2012, 12:23 PM   #4 (permalink)
Registered User Ironside
aka. GHH
 
Ironside's Avatar
 
Join Date: Feb 2009
Posts: 2,865
Ironside is just really nice (396)Ironside is just really nice (396)Ironside is just really nice (396)Ironside is just really nice (396)Ironside is just really nice (396)
Is it just me or it doesn't work at all?
The bellow trigger, it created a paladin but no clone.

GUI
Events
Map initialization
Conditions
Actions
Set point = (Center of (Playable map area))
-------- New hero for player 1 --------
Unit - Create 1 Paladin for Player 1 (Red) at point facing 0.00 degrees
Set unit = (Last created unit)
-------- Creating his copy... --------
Custom script: call HeroImage_Add(udg_unit)
-------- Don't forget the leaks >:] --------
Custom script: call RemoveLocation(udg_point)
Set unit = No unit
__________________
GHH aka. Rikudou Sennin


Ironside is offline   Reply With Quote
Old 08-06-2012, 03:29 PM   #5 (permalink)
Registered User Ruke
( > *_*)>
 
Ruke's Avatar
 
Join Date: Sep 2011
Posts: 136
Ruke has little to show at this moment (33)Ruke has little to show at this moment (33)Ruke has little to show at this moment (33)Ruke has little to show at this moment (33)
Quote:
My method is using arrays now, but it can be easily changed to use the '.' operator, and it would still be the same thing.

edit
By the way, you can use 0.03125 without the trailing 0's. I debunked that myth about inaccuracy a very long time ago.
You need to run the map for a year to be a few seconds off. <.<
Ok, I will use the '.' method to make it more readable.

Quote:
Originally Posted by Ironside View Post
Is it just me or it doesn't work at all?
The bellow trigger, it created a paladin but no clone.

GUI
Events
Map initialization
Conditions
Actions
Set point = (Center of (Playable map area))
-------- New hero for player 1 --------
Unit - Create 1 Paladin for Player 1 (Red) at point facing 0.00 degrees
Set unit = (Last created unit)
-------- Creating his copy... --------
Custom script: call HeroImage_Add(udg_unit)
-------- Don't forget the leaks >:] --------
Custom script: call RemoveLocation(udg_point)
Set unit = No unit
It doesn't create another copy of your hero (why you want two icons on the top?).
__________________

PHP, Javascript & CSS programmer.
Ruke is offline   Reply With Quote
Old 08-06-2012, 04:29 PM   #6 (permalink)
Registered User Ruke
( > *_*)>
 
Ruke's Avatar
 
Join Date: Sep 2011
Posts: 136
Ruke has little to show at this moment (33)Ruke has little to show at this moment (33)Ruke has little to show at this moment (33)Ruke has little to show at this moment (33)
Updated, thanks Magtheridon96.

I was thinking on add an alert when our allies heroes are being attacked.

But if I try with

call UnitDamageTarget(this.copyUnit, this.copyUnit, 1, true, true, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, null)

It doesn't alert you (red icon)... any ideas?.

Greetings
__________________

PHP, Javascript & CSS programmer.
Ruke is offline   Reply With Quote
Old 08-06-2012, 04:32 PM   #7 (permalink)
Forum Moderator Magtheridon96
JESUS MAN
 
Magtheridon96's Avatar
Resource Moderator
 
Join Date: Dec 2008
Posts: 5,699
Magtheridon96 has a brilliant future (1808)
Merit Badge - Level 0: This user has proven to be extremely valuable to the Warcraft III Modding Community. 
It usually doesn't alert you.
Sometimes it does, sometimes it doesn't.
It depends on a lot of factors including the last time it alerted you, how often you're taking damage, can you see the unit taking damage, etc...
__________________
Magtheridon96 is offline   Reply With Quote
Old 08-06-2012, 04:41 PM   #8 (permalink)
Registered User maddeem
moo moo
 
maddeem's Avatar
 
Join Date: Jan 2011
Posts: 1,047
maddeem is a jewel in the rough (228)maddeem is a jewel in the rough (228)maddeem is a jewel in the rough (228)
Quite a nice system. I believe this was done in tKoK, and it is a fantastic idea.
Only problem is, what if they target the ally with some healing spell and it does either of two things.
Error: Out of Range
Or
It heals the image and not the real unit

I'm wondering if you covered this or not, but if you didn't keep it in mind :p
__________________
maddeem is offline   Reply With Quote
Old 08-06-2012, 04:54 PM   #9 (permalink)
Registered User Ruke
( > *_*)>
 
Ruke's Avatar
 
Join Date: Sep 2011
Posts: 136
Ruke has little to show at this moment (33)Ruke has little to show at this moment (33)Ruke has little to show at this moment (33)Ruke has little to show at this moment (33)
Quote:
Originally Posted by maddeem View Post
Quite a nice system. I believe this was done in tKoK, and it is a fantastic idea.
Only problem is, what if they target the ally with some healing spell and it does either of two things.
Error: Out of Range
Or
It heals the image and not the real unit

I'm wondering if you covered this or not, but if you didn't keep it in mind :p
Orders are redirected to its original.

Check 'order' method
__________________

PHP, Javascript & CSS programmer.
Ruke is offline   Reply With Quote
Old 08-08-2012, 01:58 AM   #10 (permalink)
Registered User Ruke
( > *_*)>
 
Ruke's Avatar
 
Join Date: Sep 2011
Posts: 136
Ruke has little to show at this moment (33)Ruke has little to show at this moment (33)Ruke has little to show at this moment (33)Ruke has little to show at this moment (33)
@Mag: The problem with removing the local player' block, is that the local player will have two icons on the top (one real, and one copy).

Mmm, maybe with a dummy unit...

I will check it out, thanks.
__________________

PHP, Javascript & CSS programmer.
Ruke is offline   Reply With Quote
Old 01-20-2013, 09:27 AM   #11 (permalink)
Registered User CoLd Bon3
The Hive's Breakdancer
 
CoLd Bon3's Avatar
 
Join Date: Aug 2010
Posts: 963
CoLd Bon3 will become famous soon enough (108)CoLd Bon3 will become famous soon enough (108)CoLd Bon3 will become famous soon enough (108)
This is a cool thing. But is there a way you can make it show the stats (above the unit's model) without having the user hold the "Alt" key?
I am not saying to put this in the system. I ask this "off-topically".
__________________
"You don't get what you wish for. You get what you work for!"
My resources : ||Spinning Blade 4.0v||Charge-Slash 2.0v||Damage Calculating System 1.3v [GUI]||Charge Spell-System 1.0v||
CoLd Bon3 is offline   Reply With Quote
Old 01-21-2013, 06:48 PM   #12 (permalink)
Registered User -Kobas-
★ SotP Project Leader ★
 
-Kobas-'s Avatar
 
Join Date: Jan 2010
Posts: 5,869
-Kobas- has a reputation beyond repute (2066)-Kobas- has a reputation beyond repute (2066)-Kobas- has a reputation beyond repute (2066)-Kobas- has a reputation beyond repute (2066)-Kobas- has a reputation beyond repute (2066)
Hero Contest #6 - Winner: Alora, the Priestess of Moonlight was found to be the most succesful defender against the Armies of the Burning Legion! A hero by -Kobas-. Former Staff Member: This user used to be on the Hive Workshop staff. Hero Contest #5 - Winner: Stormbringer was -Kobas-'s entry, who incorporated lightnings as the power of future weaponry. Despite the instability of lightnings, this entry was stable enough to be approved by judges and public. A hero by -Kobas-. Mini-Game Mapping Contest #4: -Kobas- has won the fourth edition of The Hive Workshop's Mini-Game Mapping Contest with his entry: "Hunted". Check out the Arena if you want to participate on competitions as well! 
Not big deal, more like a hint. When you use debug messages it's always better to state name of functions.
In your example
Jass:
call BJDebugMsg("HeroImage ERROR: That unit has already a copy or it is one")
//Can be
call BJDebugMsg("HeroImage_HeroImage.create() -> That unit has already a copy or it is one")

Someday you will code 500-600 even 1000 lines of code long script, and you will get lost without good "documentation".
__________________

New version is out!
Shadows of the Past v0.9.3.0
Monday, March 25 2013 22:20
Check it out -> ★ Shadows of the Past ★
------------------------------------------------------
We got our Writer, please, welcome Noxx-
-Kobas- is offline   Reply With Quote
Old 02-27-2013, 07:01 AM   #13 (permalink)
Registered User ck5524209
User
 
Join Date: Nov 2012
Posts: 21
ck5524209 has little to show at this moment (5)
call IssueTargetOrder(GetTriggerUnit(), OrderId2String(GetIssuedOrderId()), this.original)
-->
call IssueTargetOrderById(GetTriggerUnit(), GetIssuedOrderId(), this.original)
ck5524209 is offline   Reply With Quote
Reply

Bookmarks

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are Off
Refbacks are Off


All times are GMT. The time now is 11:48 PM.





Powered by vBulletin
Copyright 2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.5.1 PL2
Copyright © Ralle