• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Shield Spell

Status
Not open for further replies.
Level 4
Joined
Aug 12, 2004
Messages
76
Can someone help me make a shield spell that absorbs 100 damage and stacks? I know that since this has multiple instances you must use JASS, but is it possible not to use handle variables?
 
Level 4
Joined
Aug 12, 2004
Messages
76
Well, I want it to be able to be able to cast it on another unit. Besides, manashield takes mana and doesn't absorb specific amount of damage, does it?
 
Level 11
Joined
Feb 22, 2006
Messages
752
By handle variables I'm assuming you mean attaching handles with gamecache. Yes, it is possible. However, you will need to use vJass and structs and units' custom values if you want to avoid gamecache.

The overall idea is to detect the casting of a dummy spell (your shield spell basically) and then to create a trigger for the unit with the shield that detects whenever the unit is damaged (or dies). If the unit is damaged, modify the damage by adding the damage back to its life so that it looks like it never took the damage. Then you subtract that damage from the shield's life using variables and such. When the shield "collapses" destroy the trigger. When the unit dies also destroy the trigger to avoid leaking triggers. Make the original trigger (the one that detects spell cast) also check to see if there is ALREADY a shield on the targeted unit. If there is, then don't create a new trigger detecting damage and such, just add 100 (or w/e value u want) to the shield's life (through variables).

JASS:
struct shielddata
    trigger t = CreateTrigger()
    triggeraction taction
    real shieldmaxlife = 100.00
    real shieldlife = 100.00
    method onDestroy takes nothing returns nothing
        call TriggerRemoveAction( .t, .taction )
        call DestroyTrigger( .t )
    endmethod
endstruct

globals
    group shieldgroup = CreateGroup()
endglobals

function Shield_Damage takes nothing returns nothing
    local unit target = GetTriggerUnit()
    local shielddata data = GetUnitUserData( target )
    local real damage = GetEventDamage()
    local real life = GetWidgetLife( target )
    local real maxlife = GetUnitState( target, UNIT_STATE_MAX_LIFE )
    local real lifeback
    if ( life < 0.405 ) then
        //unit is dead, we destroy shield and trigger and don't worry about it anymore
        call data.destroy()
        call GroupRemoveUnit( shieldgroup, target )
        return
    endif
    if ( data.shieldlife - damage <= 0.00 ) then
        //shield is dead because it took too much damage, we manipulate life given back to match shield's remaining life before it "died"
        set lifeback = data.shieldlife
        call data.destroy()
        call GroupRemoveUnit( shieldgroup, target )
    else
        //shield is still alive, so all damage is blocked
        set lifeback = damage
    endif
    if ( life + lifeback >= maxlife ) then
        call SetWidgetLife( target, maxlife )
    else
        call SetWidgetLife( target, life + lifeback )
    endif
    set target = null
endfunction

function Trig_Shield_Spell_Conditions takes nothing returns boolean
    return ( GetSpellAbilityId == 'A000' ) //change rawcode to match one in your map
endfunction

function Trig_Shield_Spell_Actions takes nothing returns nothing
//this is your trigger action for the trigger that detects spell cast
    local shielddata data
    local unit target = GetSpellTargetUnit()
    if ( IsUnitInGroup( target, shieldgroup ) ) then
        //unit already has shield, so we simply add to shield's life and max life
        set data = GetUnitUserData( target )
        set data.shieldmaxlife = data.shieldmaxlife + 100.00
        set data.shieldlife = data.shieldlife + 100.00
    else
        //unit doesn't have shield, so we create one
        set data = shielddata.create()
        call TriggerRegisterUnitEvent( data.t, target, EVENT_UNIT_DAMAGED )
        call TriggerRegisterUnitEvent( data.t, target, EVENT_UNIT_DEATH )
        set data.taction = TriggerAddAction( data.t, function Shield_Damage )
        call SetUnitUserData( target, data )
        call GroupAddUnit( shieldgroup, target )
    endif
    set target = null
endfunction

function InitTrig_Shield_Spell takes nothing returns nothing
     local integer i = 0
     set gg_trg_Shield_Spell = CreateTrigger()
     loop
         exitwhen( i > 11 )
         call TriggerRegisterPlayerUnitEvent( gg_trg_Shield_Spell, Player(i), EVENT_UNIT_SPELL_EFFECT, null )
         set i = i + 1
     endloop
     call TriggerAddCondition( gg_trg_Shield_Spell, Condition ( function Trig_Shield_Spell_Conditions ) )
     call TriggerAddAction( gg_trg_Shield_Spell, function Trig_Shield_Spell_Actions )
endfunction

You will need vJass, and easiest way to get it is from JNGP:

http://www.wc3campaigns.net/showthread.php?t=90999

Make sure you DISABLE WE syntax checker in the Grimoire menu in WE when you start up newgen WE.

EDIT: this is just a skeleton script. It doesn't have any special effects and it assumes shields are permanent until destroyed. If you need something else (like special effects or timed shields) or want me to change how something works, let me know.
 
Status
Not open for further replies.
Top