HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Shield System

06-12-2009, 12:15 PM#1
rain.mon
Click image for larger version

Name:	Shield System.JPG
Views:	39
Size:	32.0 KB
ID:	43707

Requirements:
- Jass NewGen Pack (uses vJASS)

A simple Shield System I created for easy creation of basic shields. It started as another random thing to do out of boredoom and cuz 1.23b will kill the other system that is here.

Any critisizm is highly welcomed

Collapse JASS:
//*****************************************************************
//*  Shield System - created by rain.mon
//*
//*         HOW TO USE
//*
//*     Just call CreateShield(whichUnit,shieldHP,BarColor,BuffID)
//*     whichUnit is the unit that you want to create a shield on.
//*     shieldHP is the damage the shield blocks in total.
//*     BarColor is the color of the custom floating bar which shows the shields hp.
//*     The color is the default color code that Warcraft 3 uses.
//*     BuffID can be either set to 0 or to a buff id. If it set to 0 that will
//*     make the shield last until destroyed and undispellable. If it is set to a
//*     real buff id it will get removed when the buff expires from the unit either
//*     from a dispell or from its duration.
//*
//*         CREDITS
//*
//*     shadow1500 - For getting the bar formula from his system.
//*****************************************************************
library ShieldSystem initializer Init

    globals
        private constant integer BarLenght = 32 // The number of BarChars for every shield bar.
        private constant string BarChar = "'" // The character which indicates the bars hp.
        private constant real BarSize = 12.5 // The font size of the Shield Bar
        private constant real BarOffsetX = -60. // The X offset from the shielded unit.
        private constant real BarOffsetY = 5. // The Y offset from the shielded unit.
    endglobals

    globals
        private group Registered = CreateGroup()
        private trigger Trig = CreateTrigger()
    endglobals
    
    struct shield
        unit u
        real hp
        real maxhp
        texttag tt
        string bar
        string color
        integer buffid
        
        static integer total = 0
        static shield array sa
        static constant timer stimer = CreateTimer()
        
        method onDestroy takes nothing returns nothing
            call DestroyTextTag(.tt)
        endmethod
        
        static method Damage takes nothing returns nothing
            local integer i = 0
            local shield s
            local unit damaged = GetTriggerUnit()
            local real damage = GetEventDamage()
            
            loop
                exitwhen i >= .total
                set s = shield.sa[i]
                if s.u == damaged then
                    if damage > s.hp then
                        call SetWidgetLife(s.u,GetWidgetLife(s.u)+s.hp)
                        call s.destroy()
                        set s.total = s.total - 1
                        set s.sa[i] = s.sa[s.total]
                        set i = i - 1
                    else
                        set s.hp = s.hp - damage
                        call SetWidgetLife(s.u,GetWidgetLife(s.u)+damage)
                    endif
                endif
                set i = i + 1
            endloop
            
            if s.total == 0 then
                call PauseTimer(shield.stimer)
            endif
        endmethod
        
        static method Update takes nothing returns nothing
            local integer i = 0
            local integer Y
            local boolean bool
            local real x
            local real y
            local shield s
            
            loop
                exitwhen i >= .total
                set s = shield.sa[i]
                set Y = 0
                set bool = false
                set s.bar = "["+s.color
                loop
                    exitwhen Y==BarLenght
                    if (not bool) and (s.hp < (Y * (s.maxhp/BarLenght))+1) then
                        set bool = true
                        set s.bar = s.bar+"|r|cFF000000"
                    else
                        set s.bar = s.bar+BarChar
                    endif
                    set Y = Y + 1
                endloop
                set s.bar = s.bar+"|r]"
                set x = GetUnitX(s.u)+BarOffsetX
                set y = GetUnitY(s.u)+BarOffsetY
                call SetTextTagText(s.tt,s.bar,BarSize * 0.023 / 10)
                call SetTextTagPos(s.tt,x,y,140)
                call SetTextTagVisibility(s.tt,IsUnitVisible(s.u,GetLocalPlayer()))
                if s.buffid != 0 and GetUnitAbilityLevel(s.u, s.buffid) <= 0 then
                    call s.destroy()
                    set s.total = s.total - 1
                    set s.sa[i] = s.sa[s.total]
                    set i = i - 1
                endif
                set i = i + 1
            endloop
        endmethod
    
        static method create takes unit u, real HP, string color, integer buffid returns shield
            local shield s = shield.allocate()
            local shield st
            local integer i = 0
            
            loop
                exitwhen i >= s.total
                set st = s.sa[i]
                if u == st.u then
                    call st.destroy()
                    set s.total = s.total - 1
                    set s.sa[i] = s.sa[s.total]
                    set i = i - 1
                endif
                set i = i + 1
            endloop
            
            set s.u = u
            set s.hp = HP
            set s.maxhp = HP
            set s.color = color
            set s.tt = CreateTextTag()
            set s.buffid = buffid
            call SetTextTagPermanent(s.tt,true)
            call SetTextTagVisibility(s.tt,IsUnitVisible(s.u,GetLocalPlayer()))
            
            if not IsUnitInGroup(s.u,Registered) then
                call TriggerRegisterUnitEvent(Trig,s.u,EVENT_UNIT_DAMAGED)
                call GroupAddUnit(Registered,s.u)
            endif
            
            if s.total == 0 then
                call TimerStart(s.stimer,0.01,true,function shield.Update)
            endif
            
            set s.sa[.total] = s
            set s.total = s.total + 1
            return s
        endmethod
    endstruct
    
    function CreateShield takes unit u, real hp, string color, integer buffid returns nothing
        call shield.create(u,hp,color,buffid)
    endfunction
    
    function Init takes nothing returns nothing
        call TriggerAddAction(Trig,function shield.Damage)
    endfunction
endlibrary
Attached Images
File type: jpgShield System.JPG (32.0 KB)
Attached Files
File type: w3xShield System v1.0.w3x (16.4 KB)
06-12-2009, 12:46 PM#2
akolyt0r
IMO this should use ARGB
and a DamageDetection System like Light Leakless Damage Detect
06-12-2009, 01:10 PM#3
Deaod
constant handles are nonsense, and will cause the Optimizer to introduce bugs into optimized maps.

Any reason why you didnt use Custom Bar System?

Oh, and im sure you wouldnt want me to modify u of the struct. So please add proper encapsulation.
06-12-2009, 01:28 PM#4
Rising_Dusk
Why does everyone use bars and stuff for shields? They're so unwieldy and ugly in-game. And the others are right, we are in the age of modularity, so this should use other scripts relevant to its design.

Also, this whole shield thing fails if the damage dealt to the unit is greater than the unit's maximum life... Furthermore, there's no way to interact with a shield after its creation without screwing with the struct, and there's no means by which to protect a user from his own idiocy. This has a long way to go. I am going to go ahead and move it to the triggers and scripts forum for the development it rightly deserves.
06-12-2009, 02:26 PM#5
rain.mon
Quote:
Originally Posted by akolyt0r
IMO this should use ARGB
and a DamageDetection System like Light Leakless Damage Detect

Give me a reason why it should use them and not just because you think it should.

Quote:
Originally Posted by Deaod
Any reason why you didnt use Custom Bar System?

Yes, its buggy and acts differently based on user resolution.

Quote:
Originally Posted by Deaod
Oh, and im sure you wouldnt want me to modify u of the struct. So please add proper encapsulation.
Erm, I didn't get that...

Quote:
Originally Posted by Rising_Dusk
Why does everyone use bars and stuff for shields?
Because they're used in almost every other game and people are used to them probably.

Quote:
Originally Posted by Rising_Dusk
And the others are right, we are in the age of modularity, so this should use other scripts relevant to its design.
And why is that ? So it can get soo complicated that most of the users that will need it wont be able to implement it in their map ? And anyway I don't see why I should use the things mentioned above when it works fine the way it is now.

Quote:
Originally Posted by Rising_Dusk
Also, this whole shield thing fails if the damage dealt to the unit is greater than the unit's maximum life...
I was worried about that too and i'll try to find a way around.

Quote:
Originally Posted by Rising_Dusk
Furthermore, there's no way to interact with a shield after its creation without screwing with the struct
Well afterall I said it was a just a simple shield system ^^. What more should i add ?

Thanks for the comments ^^
06-12-2009, 02:39 PM#6
Rising_Dusk
Quote:
Originally Posted by rain.mon
Give me a reason why it should use them and not just because you think it should.
Because this is 2009 and you submitted this resource to the WC3C database.
Quote:
Originally Posted by rain.mon
So it can get soo complicated that most of the users that will need it wont be able to implement it in their map ?
No, so it can abstract away complications into other scripts already approved in the database..
Quote:
Originally Posted by rain.mon
Well afterall I said it was a just a simple shield system ^^. What more should i add ?
How about making your struct private and having a series of interfacing functions that get inlined anyways?
06-12-2009, 02:52 PM#7
rain.mon
Quote:
Originally Posted by Rising_Dusk
Because this is 2009 and you submitted this resource to the WC3C database.
Was that a serious reason ?

Quote:
Originally Posted by Rising_Dusk
No, so it can abstract away complications into other scripts already approved in the database..
The thing is those complications will come with the addition of those scripts so what you're telling me is to make my system more complicated and then change that complications with other complicated scripts just cause they are approved. Why the hell would I want to make it complicated in the first place.

Unless you're telling me there is already something complicated in that system which I don't think...
06-12-2009, 03:00 PM#8
Rising_Dusk
Quote:
Originally Posted by rain.mon
Was that a serious reason ?
Yes, actually. We do not live in an era of WC3 modding where we copy and paste the same code a thousand times in our maps. We abstract it away to these things in vJass called libraries that are required by other libraries. This encapsulation for vJass submissions is a requirement by the resource submission rules and is simply good practice.
Quote:
Originally Posted by rain.mon
The thing is those complications will come with the addition of those scripts so what you're telling me is to make my system more complicated and then change that complications with other complicated scripts just cause they are approved
No, you are wrong. You don't include those other scripts with your submission. It does not complicate your script, it simplifies it by having other libraries do hard work for you. The user does not need to understand what the other scripts do, only you do as the author of the interface script.

And it is not 'just because they are approved.' They are approved because they work and are useful and if your script has use of them, that all the more shows just how useful they are. We are not telling you to use other libraries for the hell of it, and if you think we are then I really have nothing more to say to you.
06-12-2009, 03:00 PM#9
akolyt0r
Quote:
Originally Posted by rain.mon
Give me a reason why it should use them and not just because you think it should.

ARGB: It would be easier for the users to use this.
LLDD: Your Damage Detection implementation is very bad, and you leak a triggerevent...

and in your Damage method you should check if the unit is still registered before you do your great O(n) linear search...
06-12-2009, 03:09 PM#10
Anitarf
Quote:
Originally Posted by akolyt0r
and in your Damage method you should check if the unit is still registered before you do your great O(n) linear search...
Oh my goodness.

See, this is why you should use already approved resources. They do stuff better than your code does.
06-12-2009, 03:17 PM#11
rain.mon
I still don't get why are you insisting on using other scripts when it works the way I want it to work right now. The only thing that has a valid reason to be used is LLDD because of the triggerevent leak but still I've seen many maps with that same leak that still work fine and I've read that LLDD is not safe.

>>And it is not 'just because they are approved.' They are approved because they work and are useful and if your script has use of them, that all the more shows just how useful they are.

And how does my script has use of them when you can see it works fine without them ? Its like saying you have use of a spoon when you're eating meat only because the fork is on the other end of the table.

Why is me wanting to make it standalone a bad thing ?
06-12-2009, 04:27 PM#12
akolyt0r
when you say "it works fine" you mean "it does what it should do in most cases, in my opinion", but "it works fine" should mean something like "it works without errors, its useful, has a nice user interface, and its pretty effective"

yours is totally uneffective performance wise, has errors, and hasnt got a nice user interface...

and acutally its more like we want you to use that fork, but you insist on using your own rusty spoon
06-12-2009, 04:28 PM#13
Deaod
Quote:
Yes, its buggy and acts differently based on user resolution.
Yours also works different on different resolutions.
But that aside, where are the bugs? If there are any, dont hesitate to report them.

Quote:
Erm, I didn't get that...
Well, i can declare a struct of type shield, initialize it and then change the member u. There you are, a bug.

Edit:

Quote:
Why is me wanting to make it standalone a bad thing ?
Making things standalone is not a good concept anymore. Abstract your code to other resources competent coders made before you. In almost all cases of resources in this database you can rest assured they are far more advanced than your replication will ever be.
06-12-2009, 05:00 PM#14
Flame_Phoenix
I understand your point rain.mon
By using other people libraries you will be increasing the dependency of your system thus making it hard for others to import and use in some cases.
Also, you will be limited to the updates other people do on their own systems.

However, there is a reason why standalone is now deprecated. That reason is modularity. You see, time told wc3c that users prefer easy codes to implement. By using other people libs, you will divide your system into several modules, thus separating it's various complicated tasks and making the code easier to read, and update.
I won't lie to you, some people here see modularity as the holy graal, the solution for all evilness in codes, but I don't, I know it has problems, and I've been through some of them.Per example, if you use a module in your system that is wrong, your entire system will have a problem, and if you didn't create that module, then you will be forced to wait for the owner to make the update. Sometimes the necessary update even breaks compatibility with your own code, and so you get screwed.
Also, some libs conflict, and if a user already has lib A and if you use lib B (which conflicts with A) then the user will not use your system.

But all this chat has a simple solution: choose your libs wisely. Make a search, see on who you can trust.

I believe you now say "hey modularity is evil !!".
But that is not completely true. By isolating your huge system into modules you will gain:
- easier debug. Divide and conquer applies well to modules.
- some modules are already done by others. If you are sure they work, then you can use them because they will save you a lot of work. This way both users and coders will use your system easily.
- easy to update. When a critical update comes, you will only need to update a few modules, not the entire system. Just check ABuff and it's complement ADamage. Because they are modulized, Anitarf (the creator) will only need to update Table and TimerUtils when the new patch comes out, without the need of changing 1 line of code in his systems.
- some modules offer extra features in efficiency or interface that you can use to favor yourself. Why not?

These are most of the good reasons. I hope you now understand why they want you (force you) to use approved scripts - because by using them, you will access all this advantages.
If however, you think a particular lib (module) sucks, you can always try to make a better one and submit it here. You have nothing to lose.

As for shields, I use ADamage with xedamage. You may want to have a look on it since it is quite good.

Finally, I don't know where you come from, but if you come from THW; don't get mad at people. They are just doing what they think it's best for you, and they just can't understand why you refuse their advices.
Please note things here are very hard, they will only approve your system if you do what they think it's best. Sometimes it is hard to know what is best because there are many points of view, many opinions, but I think they all speak the same voice here, they all say: be modular, use libs made by others.

Hope I helped...
06-12-2009, 06:58 PM#15
Tyrande_ma3x
> and I've read that LLDD is not safe.
Probably, but nobody has reported that his map got corrupted/got random errors while using it so we can assume LLDD is quite stable. I personally don't have complaints about it and it works just perfectly.