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

Shield System v.3.0

  • Like
Reactions: Devalut and Nuclear
This is a mui shield system, it's like in the game halo.

You are able to add shield points to any unit which work like additional life...

if the unit is attacked its shield loses hp but not the unit itself as long as the shield has hp left.
the shield can regenerate hp.

You can give a shield the following stats:
  • hp value
  • reg per second
  • no attack time till the shield regenerates (0 is constant reg)
  • a factor the damage the shield gets is multiplied with
  • the color of the remaining shieldpoints
  • a boolean whether the shield is destroyed when reaching 0 hp
  • a boolean to show or hide the shields bar
  • the duration the shield lasts (0 is a not timed shield)

functions to change nearly all of these values ingame are included (look at the documentation in the code)

with that it's possible to create powerfull shields^^

it's in vJass so it needs JNGP to work...

have fun^^
Update v.2.0: well,well after some points criticized by TriggerHappy a new update to make him actually "happy" :D
fixed the not destroyed timers, added a adjustable global for the interval, replaced a periodic trigger with a timer and fixed a bug

Update v.3.0: well Anachron has wrote nearly half of the comments here because of a bad size formula so with the help of Frunck I added a new one...
may you be satisfied now :D
In addition the shields can be timed now and they create an effect on the unit they protect


JASS:
library ShieldSystem initializer Init

// The_Witcher's Shield System
//
// This is an easy to use shield system.
// it allows you to add shield points to a unit
// the shield works like in the game halo:
// the attacked unit doesn't receive any dmg, the shield gets it
// when the shield is down the unit is damaged
// the shield can reload constantly or after some seconds of not beeing attacked
//
// to give a unit a shield just use (if duration is 0 the shield will stay without a time limit)
//
//  call AddShield( towhichunit, hitpoints, RegPerSec, TimeTillReg,  damage factor, colorcode, destroy when shieldhp = 0, show the bar, Duration  )
//                    unit         real       real        real         real           string       boolean                  boolean       real
//                                                                                                                  
// you can check whether a unit has already a shield with (it will return a boolean)
//  UnitHasShield( yourunit)
//                  unit
//
// to implement this system, just copy this trigger in your map
// it requires jngp to be edited/saved
//
// To get rid of a shield just use
//   call DestroyShield( which unit's)
//                         unit
//
// to show or hide the shield bar use
//   call ShowShield( WhichUnits, Show? )
//                      unit     boolean
//
// to get information about an existing shield use:
//    HP:           GetShieldHp(  unit  )
//    maxHP:        GetShieldMaxHp(  unit  )
//    percentHP:    GetShieldHpPercent(  unit  )
//    regeneration: GetShieldReg(  unit  ) 
//    TimeTillReg:  GetShieldTimeTillReg(  unit  )
//    DamageFactor: GetShieldDamageFactor(  unit  )
//
// to change the values of an existing shield use:
//    HP:           SetShieldHp(  unit, NewValue  )
//    maxHP:        SetShieldMaxHp(  unit, NewValue  )
//    percentHP:    SetShieldHpPercent(  unit, NewValue  )
//    regeneration: SetShieldReg(  unit, NewValue  )
//    TimeTillReg:  SetShieldTimeTillReg(  unit, NewValue  )
//    DamageFactor: SetShieldDamageFactor(  unit, NewValue  )
//
// have fun^^
// The (very small^^) Setup part
globals
    // the shieldbar's size (should be (7.5 * 0.023 / 10 - 0.00625) or 0.01(which isn't working for everyone) for a good result)
    private constant real size = 7.5 * 0.023 / 10 - 0.00625  
    
    // A ability which gives a high instant life bonus
    private constant integer lifeabi = 'A001'  
    
    // the timer interval (should be 0.01 but if laggy then just change it)
    private constant real interval = 0.01  
    
    //the path of the special effect for untis with a shield
    //another good effect: "Abilities\\Spells\\Human\\DivineShield\\DivineShieldTarget.mdl"
    private constant string sfx = "Abilities\\Spells\\NightElf\\Rejuvenation\\RejuvenationTarget.mdl" 
    
    //the attachement point for sfx
    private constant string AtPoint = "chest"
endglobals
// end of Setup!!
private struct shield
unit u
real hp
real fullhp
real reg
real f
string code
texttag t
real r
effect fx
real remain
timer time
boolean kill 
integer i
real damage = 0
boolean show
endstruct

globals
    private trigger trg = CreateTrigger()
    private group g = CreateGroup()
    private hashtable h = InitHashtable()
    private integer total = 0
    private unit array units
    private timer tim = CreateTimer()
endglobals

function UnitHasShield takes unit u returns boolean
    return LoadInteger(h,GetHandleId(u),0) != 0
endfunction

function DestroyShield takes unit whichunits returns nothing
    local shield dat = LoadInteger(h,GetHandleId(whichunits),0)
    local shield dat2 = LoadInteger(h,GetHandleId(units[total-1]),0)
    if dat != 0 then
        call DestroyTextTag(dat.t)
        call DestroyTimer(dat.time)
        call DestroyEffect(dat.fx)
        call FlushChildHashtable(h,GetHandleId(whichunits))
        set total = total - 1
        set units[dat.i] = units[total]
        set dat2.i = dat.i
        call dat.destroy()
    endif
    if total == 0 then
        call PauseTimer(tim)
    endif
endfunction

private function regeneration takes nothing returns nothing
    local shield dat
    local string s = "''''''''''''''''''''''''''''''''''''''''''''''''''"
    local integer k
    local integer i = 0
    loop
        exitwhen i >= total
        set dat = LoadInteger(h,GetHandleId(units[i]),0)
        if TimerGetRemaining(dat.time) == 0 then
            if dat.hp < dat.fullhp then
                set dat.hp = dat.hp + dat.reg
            else
                set dat.hp = dat.fullhp
            endif
        endif
        if dat.remain > 0 then
            set dat.remain = dat.remain - interval
        elseif dat.remain != -100 then
            call DestroyShield(dat.u)
        endif
        set k = R2I(50 * (dat.hp / dat.fullhp))
        call SetTextTagText(dat.t, dat.code + SubString(s,0, k ) + "|r"  + SubString(s,k + 1,StringLength(s)) , size)
        call SetTextTagPos(dat.t,GetUnitX(dat.u) -40, GetUnitY(dat.u),-100)
        if dat.damage != 0 then
            if dat.hp > (dat.damage * dat.f) then
                set dat.hp = dat.hp - (dat.damage * dat.f)
                call SetWidgetLife( dat.u,GetWidgetLife(dat.u) + dat.damage)
            else
                call SetWidgetLife( dat.u,GetWidgetLife(dat.u) + dat.hp)
                set dat.hp = 0
            endif
            set dat.damage = 0
        endif
        call UnitRemoveAbility(dat.u,lifeabi)
        if dat.hp <= 0 and dat.kill == true then
            call DestroyShield(dat.u)
            set i = i - 1
        endif
        set i = i + 1
    endloop
    set s = null
endfunction

private function attack takes nothing returns nothing
    local shield dat = LoadInteger(h,GetHandleId(GetTriggerUnit()),0)
    local timer t 
    if dat != 0 then
        if dat.hp > 0 then
            set dat.damage = dat.damage + GetEventDamage()
        endif     
        call TimerStart(dat.time,dat.r,false,null)
    endif
endfunction

function AddShield takes unit towhich, real hp, real RegPerSec, real TimeTillReg, real dmgfactor, string colorcode, boolean destroy, boolean ShowBar, real Duration returns nothing
    local shield dat
    if LoadInteger(h,GetHandleId(towhich),0) != 0 then
        call DestroyShield(towhich)
    endif
    set dat = shield.create()
    set dat.u = towhich
    set dat.fullhp = hp
    set dat.hp = hp
    set dat.reg = RegPerSec / 100
    set dat.f = dmgfactor
    set dat.code = colorcode
    set dat.r = TimeTillReg
    set dat.kill = destroy
    set dat.time = CreateTimer()
    set dat.t = CreateTextTag()
    set dat.show = ShowBar
    set dat.fx = AddSpecialEffectTarget(sfx, dat.u, AtPoint)      
    set dat.remain = Duration
    if dat.remain == 0 then
        set dat.remain = -100 
    endif
    call SetTextTagVisibility(dat.t,ShowBar)
    set dat.i = total
    if not IsUnitInGroup(dat.u,g) then
        call GroupAddUnit(g,dat.u)
        call TriggerRegisterUnitEvent( trg, towhich, EVENT_UNIT_DAMAGED )
    endif
    set units[total] = dat.u
    set total = total + 1
    call SaveInteger(h,GetHandleId(dat.u),0,dat)
    if total == 1 then
        call TimerStart(tim,interval,true,function regeneration)
    endif
endfunction

private function kill takes nothing returns nothing
    call DestroyShield(GetTriggerUnit())
endfunction

function ShowShield takes unit u, boolean flag returns nothing
    local shield dat = LoadInteger(h,GetHandleId(u),0)
    if dat != 0 then
        set dat.show = flag
        call SetTextTagVisibility(dat.t,flag)
    endif
endfunction

function GetShieldHpPercent takes unit u returns real
    local shield dat = LoadInteger(h,GetHandleId(u),0)
    if dat != 0 then
        return dat.hp / dat.fullhp * 100.0
    endif
    return .0
endfunction

function GetShieldHp takes unit u returns real
    local shield dat = LoadInteger(h,GetHandleId(u),0)
    if dat != 0 then
        return dat.hp
    endif
    return .0
endfunction

function GetShieldMaxHp takes unit u returns real
    local shield dat = LoadInteger(h,GetHandleId(u),0)
    if dat != 0 then
        return dat.fullhp
    endif
    return .0
endfunction

function GetShieldReg takes unit u returns real
    local shield dat = LoadInteger(h,GetHandleId(u),0)
    if dat != 0 then
        return dat.reg*100
    endif
    return .0
endfunction

function GetShieldTimeTillReg takes unit u returns real
    local shield dat = LoadInteger(h,GetHandleId(u),0)
    if dat != 0 then
        return dat.r
    endif
    return .0
endfunction

function GetShieldDamageFactor takes unit u returns real
    local shield dat = LoadInteger(h,GetHandleId(u),0)
    if dat != 0 then
        return dat.f
    endif
    return .0
endfunction

function SetShieldHpPercent takes unit u, real new returns nothing
    local shield dat = LoadInteger(h,GetHandleId(u),0)
    if dat != 0 then
        set dat.hp = dat.fullhp * new
        if dat.fullhp < dat.hp then
            set dat.hp = dat.fullhp
        endif
    endif
endfunction

function SetShieldHp takes unit u, real new returns nothing
    local shield dat = LoadInteger(h,GetHandleId(u),0)
    if dat != 0 then
        set dat.hp = new
        if dat.fullhp < dat.hp then
            set dat.hp = dat.fullhp
        endif
    endif
endfunction

function SetShieldMaxHp takes unit u, real new returns nothing
    local shield dat = LoadInteger(h,GetHandleId(u),0)
    if dat != 0 then
        set dat.fullhp = new
        if dat.fullhp < dat.hp then
            set dat.hp = dat.fullhp
        endif
    endif
endfunction

function SetShieldReg takes unit u, real new returns nothing
    local shield dat = LoadInteger(h,GetHandleId(u),0)
    if dat != 0 then
        set dat.reg = new/100
    endif
endfunction
                                                                            
function SetShieldTimeTillReg takes unit u, real new returns nothing
    local shield dat = LoadInteger(h,GetHandleId(u),0)
    if dat != 0 then
        set dat.r = new
        call TimerStart(dat.time,dat.r,false,null)
    endif
endfunction

function SetShieldDamageFactor takes unit u, real new returns nothing
    local shield dat = LoadInteger(h,GetHandleId(u),0)
    if dat != 0 then
        set dat.f = new
    endif
endfunction

private function Init takes nothing returns nothing
    local trigger tt = CreateTrigger()
    call TriggerAddAction(tt, function kill)
    call TriggerRegisterAnyUnitEventBJ( tt, EVENT_PLAYER_UNIT_DEATH )    
    
    call TriggerAddAction(trg, function attack)    
endfunction

endlibrary

Keywords:
shield, halo, vjass, hp, regeneration, mui, defend, bar, system, customize, effect, protect
Contents

Shield System (Map)

Reviews
17:37, 9th Nov 2009 TriggerHappy187: Decent enough to be approved.
Level 6
Joined
May 15, 2008
Messages
146
Yo man I've downloaded your system while it was still GUI ('bout a year ago), and it insipired me to create damage systems based on your own also in GUI for my map Guild Arena: the BattleChasers, cuz i'm not that good at Jass, but now I see that you have a Jass version of system so i'll be sure to check it out and maybe implement it into some of the next updates my map.


All in all

+Rep for the old system and inspiration that it gave me
+5 to rating



TNX alot :thumbs_up:
 
Level 13
Joined
May 11, 2008
Messages
1,198
oh yeah this is the spell you made that i'm using already. good work. it's a favorite of mine. although i'm pretty lazy i didn't add the graphics yet. i have good excuse, though...i had needed time to find the correct graphics model. i'll have to say, though...i found the shield bar didn't work...not that i care.
 
Level 4
Joined
Apr 19, 2013
Messages
86
Hey cool system man,

Quick question about tweaking it a bit, I thought it would be cool if instead of deactivating the shield (like in the demo map), once you use the spell again, it grants another shield. So in other words, the shield would stack.

I mean that could be done just by increasing the absorbed damage I suppose, but I want it to actually look like 2 shields, so that means there would have to be another private variable, lets just call it sfx2.

So could you post an example script of this stacking shield tweak? Letting it stack if cast twice, and it would be cool if you could code it so that the two shields die one by one, like as each shield dies the respective sfx is destroyed, as opposed to simultaneously dying.
 
Level 39
Joined
Feb 27, 2007
Messages
5,010
It should. Instead of just saying "it doesn't work" you could at least quote the error message you got, or screenshot the error dialogue, or identify the line that is causing errors, or upload the map with the trigger disabled, or.... The error dialog on save is actually, you know, trying to help you figure out what the problem is.
 
Level 4
Joined
Sep 29, 2018
Messages
74
It should. Instead of just saying "it doesn't work" you could at least quote the error message you got, or screenshot the error dialogue, or identify the line that is causing errors, or upload the map with the trigger disabled, or.... The error dialog on save is actually, you know, trying to help you figure out what the problem is.


Oh I'm sorry I'll show you the lines later. And actually even tried saving the spell's map itself and worldeditor still won't let me.
 
Level 4
Joined
Sep 29, 2018
Messages
74
Either you're using some old version of the WE/something like WEX or JNGP... or your install is borked. It saves just fine for me without any errors. Is your game updated?

My game is updated but I just noticed I can't also sabe damage detection for me so I think my install is borked. Well, thank you for helping me and sorry for saying that this spell doesn't work.
 
Top