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

Vampiric Strike v.46

Before viewing the code, note that this is for the spell only. There are two triggers that add the "Unit Takes Damage" events to this trigger. You will find these when you open the map.

JASS:
////////////////////////////////////////////////////////////////////
//  Vampiric Strike by 1)ark_NiTe                                 //
//  Originally made for Against the Darkness                      //
//                                                                //
//  dmg = Strength (you can change this to Agility or Intel)      //
//  Total damage = Strength + Real Damage                         //
//  Amount healed = (total damage) * (1 / (7 - Level of Ability)) //
//                                                                //
////////////////////////////////////////////////////////////////////

//==================================================================================================================================
// Start of constants. These provide the user with easier implementing//changing of the spell's rawcodes and effects. All of these can be changed.
//==================================================================================================================================

constant function Vamp_Strike_ID takes nothing returns integer
    return 'A002' // Vampiric Strike ability rawcode.
endfunction

constant function Vamp_Strike_Weapon_SFX takes nothing returns string
    return "Abilities\\Spells\\Human\\SpellSteal\\SpellStealTarget.mdl" // SFX created on the attacker's weapon.
endfunction

constant function Vamp_Strike_Link_SFX takes nothing returns string
    return "Abilities\\Spells\\NightElf\\ManaBurn\\ManaBurnTarget.mdl" // SFX created on both units to represent their link.
endfunction

constant function Vamp_Strike_Heal_SFX takes nothing returns string
    return "Abilities\\Spells\\Undead\\VampiricAura\\VampiricAuraTarget.mdl" // SFX created on the attacker's body to represent life healed.
endfunction

//==================================================================================================================================
//End of constants. Do not touch anything below this if you are unfamiliar with JASS.
//==================================================================================================================================

//==================================================================================================================================
//Spell conditions.
//==================================================================================================================================

function Vampiric_Strike_Conds takes nothing returns boolean
    return GetOwningPlayer(GetTriggerUnit()) != GetOwningPlayer(GetEventDamageSource()) and IsUnitType(GetTriggerUnit(), UNIT_TYPE_STRUCTURE) == false and IsUnitInGroup(GetEventDamageSource(), udg_JustCastSpell) == false and GetUnitAbilityLevel(GetEventDamageSource(), Vamp_Strike_ID()) >=1 and GetRandomInt(1, 100) <= 15
endfunction

//==================================================================================================================================
//Spell actions. Main block of coding
//==================================================================================================================================

function Trig_Vampiric_Strike takes nothing returns nothing
    // Declares Local Variables
    local unit d = GetEventDamageSource()
    local unit t = GetTriggerUnit()
    local texttag tag
    local integer i = GetUnitAbilityLevel(d, Vamp_Strike_ID())
    local force f = CreateForce()
    local force g = CreateForce()
    local real a
    local real r
    local real rd
    local real dmg = GetHeroStr(GetEventDamageSource(), true)
    local real l = GetEventDamage()
    local trigger trig = GetTriggeringTrigger()
    call DisableTrigger(trig)
    set a = GetUnitArmor(t)
    set rd = GetFullDamage(dmg, a)
    set r = GetReducedDamage(rd, a)
    call DestroyEffect(AddSpecialEffectTarget(Vamp_Strike_Weapon_SFX(), d, "weapon"))
    call DestroyEffect(AddSpecialEffectTarget(Vamp_Strike_Link_SFX(), d, "origin"))
    call DestroyEffect(AddSpecialEffectTarget(Vamp_Strike_Heal_SFX(), d, "origin"))
    call DestroyEffect(AddSpecialEffectTarget(Vamp_Strike_Link_SFX(), t, "origin"))
    call DisableTrigger( GetTriggeringTrigger() )
    call UnitDamageTarget(d, t, r, true, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
    call EnableTrigger(trig)
    // If you wish to change the amount healed, you can do so in the line below.
    call SetWidgetLife(d, (GetWidgetLife(d)) + ((l + r) * (1.00 / (7.00 - I2R(i)))))
    call EnableTrigger( GetTriggeringTrigger() )
    // Creates Floating Text showing the Damage Dealt + Damage Healed
    set tag = CreateTextTagUnitBJ( ( "|cffFF0000" + ( I2S(R2I(( l + r ))) + ( "|r" + ( "/" + ( "|cff00FF00" + I2S(R2I(( ( l + r ) * ( 1 / ( 7.00 - i )))))))))), d, 0, 10, 100, 100, 100, 0 )
    if (IsPlayerInForce(GetLocalPlayer(), bj_FORCE_ALL_PLAYERS))then
        call SetTextTagVisibility(tag, false)
    endif
    call ForceEnumAllies(f, GetOwningPlayer(d), null)
    call ForceEnumAllies(g, GetOwningPlayer(t), null)
    if (IsPlayerInForce(GetLocalPlayer(), f)) or (IsPlayerInForce(GetLocalPlayer(), g)) then
        call SetTextTagVisibility(tag, true)
    endif
    call SetTextTagVelocity(tag, 0, 0.04)
    call SetTextTagPermanent(tag, false)
    call SetTextTagFadepoint(tag, 2.00)
    call SetTextTagLifespan(tag, 3.00)
    call DestroyForce(f)
    call DestroyForce(g)
    set tag = null
    set f = null
    set g = null
    set d = null
    set t = null
endfunction

//===========================================================================
function InitTrig_Vampiric_Strike takes nothing returns nothing
    set gg_trg_Vampiric_Strike = CreateTrigger(  )
    call TriggerAddCondition( gg_trg_Vampiric_Strike, Condition( function Vampiric_Strike_Conds ) )
    call TriggerAddAction( gg_trg_Vampiric_Strike, function Trig_Vampiric_Strike )
endfunction

Gives a 15% chance to deal the Hero's total Strength in extra damage on an attack and regain hit points by a factor of the extra damage.

Level 1 - 1/6 total damage regained.
Level 2 - 1/5 total damage regained.
Level 3 - 1/4 total damage regained.
Level 4 - 1/3 total damage regained.

This spell was originally made for my project Against the Darkness.

+Multi-Instanceable
+Leakless
+No Imports
+Easily Transferable


Known Error: This spell will trigger from Immolation damage. If anyone knows of a way to fix this then let me know.

Updates (recent to past):

v.46 (current):

-Removed unnecessary function I2R. Thanks Bribe!

v.45:

-Added Rising_Dusk's ArmorUtils system to very accurately damage units.

v.40:

-Added a trigger that prevents Vampiric Strike from executing when any negative ability is cast by the Hero.


v.35:

-Created constant functions to make replacing rawcodes and effects simple during spell implementation.
-Updated/expanded documentation

v.30:
-Fixed Force leaks
-Changed SetUnitState() to SetWidgetLife()

v.25:
-bj's fixed by Deuterium. Thanks :p

v.20:
-Changed effects
-Removed 'Swap' bj's
-Added groups to show text tags to
-Added natives inside "ShowTextTagForceBJ"
-Will no longer trigger if attacking structures

v.15:

-Replaced SetUnitLifeBJ() with SetUnitState()
-Fixed Text Tag Line because it was referencing wrong rawcode
-Added comment block to beginning of spell

Keywords:
Death Knight, Against the Darkness, Vampire, Vampiric Strike, Critical Strike, Strike, 1)ark_NiTe, AtD
Contents

Vampiric Strike (Map)

Reviews
18:25, 11th Jun 2009 hvo-busterkomo: A decent JASS spell, although lacking configuration the effect is nice. The strings of the effects should be configurable, as well the spell id. The only thing stopping me from approving this is the leaks. You...

Moderator

M

Moderator

18:25, 11th Jun 2009
hvo-busterkomo: A decent JASS spell, although lacking configuration the effect is nice. The strings of the effects should be configurable, as well the spell id.

The only thing stopping me from approving this is the leaks. You should be using DestroyForce, not ForceClear.

Edit: Changes made, looks good.
 
Level 25
Joined
Jun 5, 2008
Messages
2,572
Remove the floating text, those are rare and not so usefull in spells.
Btw why are you using so many bj's?
Use natives they are faster, bj functions just call another function making it slower.
Also please replace gg_trg_Vampiric_Strike with a local trigger t.
Make a settings block on the begining of the spell:
-dummy raw number
-ability raw number
-damage
and so on...
Not to be harsh but this looks like you just converted a GUI trigger and made little modifications :p
Again remove the bj functions and optionaly add a better damage detection system.
 
Level 18
Joined
Nov 1, 2006
Messages
1,612
Floating text is important in this spell to know what your extra damage dealt is and how much you were healed for. Why would I remove it?

I know bj's call other functions, however the remaining text tag bj's are really confusing to replace. The coding for them all to be replaced would be nearly 20 lines longer. I think in this case using those bj's is perfectly acceptable.

However, I just changed the SetUnitLifeBJ() to "SetUnitState()". Thanks for pointing that out.

I did originally convert the blank trigger from GUI, but all JASS the work was done in Jasscraft. That is only because I don't know how to create the bottom part from scratch. I'm pretty sure changing "gg_trg_Vampiric_Strike" to "t" is purely aesthetic though and wouldn't make a difference in efficiency. Correct me if I'm wrong.

Make a settings block on the begining of the spell:
-dummy raw number
-ability raw number
-damage

Done deal.
 
Level 17
Joined
Mar 17, 2009
Messages
1,349
Well you do use alot of BJ's. Here are some of the things you can fix:

JASS:
local integer i = GetUnitAbilityLevelSwapped('A002', d)

JASS:
call SetUnitState(d,UNIT_STATE_LIFE,((GetUnitStateSwap(UNIT_STATE_LIFE, d)) + ((l + r) * (1.00 / (7.00 - I2R(i))))))
Said simple, the keyword Swap means that the parameters in the parenthesis are swapped.

Example: BlaSwap(Bye, Hi) calls Bla(Hi, Bye)
So just remove that keyword and swap what's inside.

More:
JASS:
GetForceOfPlayer(GetOwningPlayer(d))

JASS:
GetPlayersAllies(GetOwningPlayer(t))

There might be one or two more. Btw, I ignored TextTags as those are very complicated if not BJ's...


EDIT:
I came back for some more!

Add some eyecandy :) and an effect to the weapon or something... some nice yet simple touch

And to help you further with BJ's as I missed these two very simple things:
JASS:
call ShowTextTagForceBJ( false, bj_lastCreatedTextTag, bj_FORCE_ALL_PLAYERS )
instead of,
JASS:
call ShowTextTagForceBJ( false, GetLastCreatedTextTag(), GetPlayersAll() )
 
Level 17
Joined
Mar 17, 2009
Messages
1,349
Hahaha I though you'll know how to fix these...

Here it is:

JASS:
    local force f = CreateForce()
    local force al = CreateForce()
    //all the actions
    call ForceAddPlayer(f, GetOwningPlayer(t))
    call ShowTextTagForceBJ( true, GetLastCreatedTextTag(), f )
    call ForceEnumAllies(al, GetOwningPlayer(t), null)
    call ShowTextTagForceBJ( true, GetLastCreatedTextTag(), al)
 
Level 17
Joined
Mar 17, 2009
Messages
1,349
hehe don't worry, now you knw xD

EDIT:
I should have mentioned this earlier but I didn't notice:
JASS:
bj_lastCreatedTextTag
instead of:
JASS:
GetLastCreatedTextTag()

EDIT:
Here's an edited one by me where I removed all BJ's except for one which whenever I remove bugs although I'm 100% I was doing it right!
I also nulled two locals you forgot to null...
ENJOY :D
 

Attachments

  • VampiricStrikeby1)ark_NiTev.20[Deut].w3x
    26.2 KB · Views: 169
Last edited:
Level 17
Joined
Mar 17, 2009
Messages
1,349
Well, some people say it needs to be nulled some say it doesnt. Now I always used to think like Purplepoot does and believe that nulling reals and integers is stupid, but most people do it, so we need some proof to which is better.

Well anyone who understands binary codes should be able to judge, I mean we just need to know if the binary code of the number zero takes space or nope, for it's binary code is simply made of a spam of zeroes...
 
Level 15
Joined
Jul 19, 2007
Messages
618
GetWidgetLife and SetWidgetLife are more safe and faster...

as well your hide for texttag is way to bad! its acceptable but i suggest fully leakless and fast way!

you where leaking this null filters and you had to first hide texttag and then do local player while my code does not leak at all, uses one force and simple hides it for players which are not ally of attacked unit or attacker (same as u did)

JASS:
function VS_EnumPlayers takes nothing returns boolean
    if not ( IsPlayerAlly(GetOwningPlayer(GetTriggerUnit(), GetFilterPlayer()) or IsPlayerAlly(GetOwningPlayer(GetEventDamageSource(), GetFilterPlayer())) ) then
        if (GetLocalPlayer() == GetFilterPlayer()) then
            call SetTextTagVisibility(bj_lastCreatedTextTag, false)
        endif
    endif
    return false
endfunction

local force f = CreateForce()
    local filterfunc ff = Filter(function VS_EnumPlayers)
    call ForceEnumPlayers(f, ff)
    call DestroyFilter(ff)
    call DestroyForce(f)
    set f = null
    set ff = null

all other is fine, well ofc damage detection is way to bad, but until i release my librarys there is currently no better way of doing it... and yeah your trigger will fire even if an spell deals an damage... as well not possible until libs are done!

i expect that you will fix this filter leaks and make spell more configurable!

in default jass its done by writing constant functions which are very fast!

JASS:
constant function VS_DamageEffect takes nothing returns string
    return "Abilities\\Spells\\Human\\SpellSteal\\SpellStealTarget.mdl"
endfunction

constant function VS_AttachPoint takes nothing returns string
    return "weapon"
endfunction

call DestroyEffect(AddSpecialEffectTarget(VS_DamageEffect(), d, VS_AttachPoint()))

like that ofc give your own names to functions!

for now its 3/5!
but ill give it a 4/5 once you fix leaks and make it easy editable!

Greets!
~Dark Dragon
 
GetWidgetLife and SetWidgetLife are more safe and faster...
They are not safer, they are simply faster. Even if you change them, you will win only a few nanoseconds.

However I agree you should use them, in the name of code readability.

all other is fine, well ofc damage detection is way to bad, but until i release my librarys there is currently no better way of doing it.
There are other ways...
- IDDS
- LLDD
- ADamage
- xedamage
....

all systems of high quality made by other people ...
 
Level 15
Joined
Jul 19, 2007
Messages
618
They are not safer, they are simply faster. Even if you change them, you will win only a few nanoseconds.

However I agree you should use them, in the name of code readability.


There are other ways...
- IDDS
- LLDD
- ADamage
- xedamage
....

all systems of high quality made by other people ...

i know about other damage detection systems but my will be the on the top, and will be able to unregister and register + many more... all in all better damage detection then my are not possible, but of same quality it is possible! i did not saw all dd systems but that what i saw is not too good!

ofc this sounds like i am talking that others are ****, but no i like other peopls work but i canot accept such an mass even leaks! if you will be interested to check the code when its out it will be great ;)

about SetWidgetLife... there is not to much to say thats its safe or not (both are) but coz widget life sets only life and does not need a constant its more safe! through this all sounds stupid to u so ill leave it as you said (they are equal safe) yes faster and more readable!

Best Regards!
~Dark Dragon
 
i know about other damage detection systems but my will be the on the top, and will be able to unregister and register + many more... all in all better damage detection then my are not possible, but of same quality it is possible! i did not saw all dd systems but that what i saw is not too good!
Careful, the world of damage detection is very poisoned, there is no real solution for it yet.

The DD (damage detection) system I said here are the best up to date. Some of them are even modular, thus making it easy to update.
It seems you don't know them, allow me to link you to them:
- IDDS
- ADamage
- Moyack recycler + damage system
- xedamage (not a damage detection system, but can be used instead of one)
- LLDD (coudln't find link, but it is in wc3c)
but coz widget life sets only life and does not need a constant its more safe!
Ahh, you are referring to human error when making the code. In that case, I agree with you.
 
Level 15
Joined
Jul 19, 2007
Messages
618
it seems that IDDS is the only one that could be used, but leaks events and uses custom UnitDamageTarget action... well if i make that then there is no prob in making dd system :D

my is simply event leakless, fast, optimized... lol u will see when its out!
anyway ty for telling me about the dd systems i actually never check other people work coz i feel like i am stealing there ideas even through they made it for us.. but heh!

about widget yeah u got me ;)

Well regards!
~Dark Dragon
 
Level 7
Joined
Apr 12, 2011
Messages
124
If you would like you could give whoever wants to use this spell the option to turn on/off floating text.
Set udg_FloatingText = true/false
EDIT:
@ 1)ark_NiTe
idk, but it's always better with more options i think
 
Last edited:
Top