Name | Type | is_array | initial_value |
JustCastSpell | group | No |
//TESH.scrollpos=64
//TESH.alwaysfold=0
////////////////////////////////////////////////////////////////////
// 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
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_Cast_Any_Spell_Conditions takes nothing returns boolean
return GetOwningPlayer(GetTriggerUnit()) != Player(PLAYER_NEUTRAL_AGGRESSIVE)
endfunction
function Trig_Cast_Any_Spell_Actions takes nothing returns nothing
// This trigger helps to avoid damage detection triggers from executing
// automatically when a unit has any type of negative spell cast on them.
local unit t = GetTriggerUnit()
call GroupAddUnit( udg_JustCastSpell, t )
call TriggerSleepAction( 0.15 )
call GroupRemoveUnit( udg_JustCastSpell, t )
set t = null
endfunction
//===========================================================================
function InitTrig_Cast_Any_Spell takes nothing returns nothing
set gg_trg_Cast_Any_Spell = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Cast_Any_Spell, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_Cast_Any_Spell, Condition( function Trig_Cast_Any_Spell_Conditions ) )
call TriggerAddAction( gg_trg_Cast_Any_Spell, function Trig_Cast_Any_Spell_Actions )
endfunction
//TESH.scrollpos=18
//TESH.alwaysfold=0
library Logarithm
globals
private constant integer ITERATIONS=20
endglobals
function Log takes real x returns real
local real min=-88.0
local real max= 88.0
local real mid
local integer i=ITERATIONS
loop
set mid=(min+max)/2
exitwhen(i<=0)
set i=i-1
if (Pow(bj_E,mid)>=x) then
set max=mid
else
set min=mid
endif
endloop
return mid
endfunction
function Logarithm takes real base, real x returns real
local real min=-88.0
local real max= 88.0
local real mid
local integer i=ITERATIONS
loop
set mid=(min+max)/2
exitwhen(i<=0)
set i=i-1
if (Pow(base,mid)>=x) then
set max=mid
else
set min=mid
endif
endloop
return mid
endfunction
endlibrary
//TESH.scrollpos=37
//TESH.alwaysfold=0
library ArmorUtils requires Logarithm, optional IntuitiveDamageSystem
//******************************************************************************
//* BY: Rising_Dusk
//*
//* This is used to get the exact armor of a given unit. It deals damage to the
//* unit in order to determine armor, meaning that damage detection systems will
//* detect it. If your map has the Intuitive Damage Detection System (IDDS) in
//* it, it will use that system's internal ignored damage type for the check.
//* Using that removes the need to disable/enable any damage detection triggers
//* to avoid infinite loops.
//*
//* The attacktype constant, ATTACK_TYPE_USED, is by default set to use
//* ATTACK_TYPE_CHAOS. Chaos is used because it deals 100% to all types, so if
//* you change it in your map, make sure you update the constant to some type
//* with 100% damage to all armor types.
//*
//* This system can also be used as a means to detect if a unit is invulnerable
//* or not. If GetUnitArmor returns ARMOR_INVULNERABLE, then the unit is
//* invulnerable. The value for it is entirely random and will never be the
//* actual armor value for a unit, so there should be no conflicts.
//*
//* Damage reduction in WC3 due to negative armor is capped at -71%, which has
//* an equivalent armor value of -20. If you have a unit with less than -20
//* armor, this system will always return exactly -20.
//*
//* Default WC3 gameplay constants have the 'Armor Damage Reduction Multiplier'
//* set to 0.06. If you change this constant for your map, be sure to adjust the
//* ARMOR_REDUCTION_MULTIPLIER constant in this script to match.
//*
//* Example Usage:
//* local real armor = GetUnitArmor(MyUnit)
//*
//* Two other functions are included in this library. They are used for
//* calculating a unit's base damage knowing armor-factoring damage and a unit's
//* armor-factoring damage knowing its base damage. These functions do not
//* consider armor type in their calculations. If you want armor type damage
//* adjusting, it is recommended to trigger it.
//*
//* Example Usage:
//* local real basedmg = GetFullDamage(MyUnit, Armor)
//* local real armodmg = GetReducedDamage(MyUnit, Armor)
//*
//* An objectmerger call is included in this script to automatically generate
//* the bonus life ability if necessary. If you do not modify the 'AIlz' ability
//* in your map, you can replace the LIFE_BONUS_SPELL_ID constant with it and
//* not use the objectmerger call. The
//*
globals
//Values that should be changed for your map
private constant real ARMOR_REDUCTION_MULTIPLIER = 0.06
private constant integer LIFE_BONUS_SPELL_ID = 'A002'
private constant attacktype ATTACK_TYPE_USED = ATTACK_TYPE_CHAOS
//Values that do not need to be changed
constant real ARMOR_INVULNERABLE = 917451.519
private constant real DAMAGE_TEST = 16.
private constant real DAMAGE_LIFE = 30.
private constant real NATLOG_094 =-0.061875
endglobals
////! external ObjectMerger w3a AIlz lif& anam "GetUnitArmorLifeBonus" ansf "" Ilif 1 30 aite 0
function GetUnitArmor takes unit u returns real
local real life = GetWidgetLife(u)
local real test = life
local real redc = 0.
local boolean enab = false
local trigger trig = GetTriggeringTrigger()
if u != null and life >= 0.405 then
if GetUnitState(u, UNIT_STATE_MAX_LIFE) <= DAMAGE_TEST then
//Add max life to keep it alive
call UnitAddAbility(u, LIFE_BONUS_SPELL_ID)
endif
if life <= DAMAGE_LIFE then
//If under the threshold, heal it for the moment
call SetWidgetLife(u, DAMAGE_LIFE)
set test = DAMAGE_LIFE
endif
static if LIBRARY_IntuitiveDamageSystem then
//Use the IGNORED type in the IDDS if present so it is 100% ignored
call UnitDamageTargetEx(u, u, DAMAGE_TEST, ATTACK_TYPE_USED, DAMAGE_TYPE_IGNORED, true)
else
if trig != null and IsTriggerEnabled(trig) then
//Disable the trigger to prevent it registering with damage detection systems
call DisableTrigger(trig)
set enab = true
endif
call UnitDamageTarget(u, u, DAMAGE_TEST, true, false, ATTACK_TYPE_USED, DAMAGE_TYPE_NORMAL, null)
if enab then
//Re-enable the trigger
call EnableTrigger(trig)
endif
endif
set redc = (DAMAGE_TEST-test+GetWidgetLife(u))/DAMAGE_TEST
//Remove the max life ability
call UnitRemoveAbility(u, LIFE_BONUS_SPELL_ID)
call SetWidgetLife(u, life)
set trig = null
if redc >= 1. then
//Invulnerable
return ARMOR_INVULNERABLE
elseif redc < 0. then
//Negative Armor
return -Log(redc+1.)/NATLOG_094
else
//Positive Armor
return redc/(ARMOR_REDUCTION_MULTIPLIER*(1.-redc))
endif
endif
set trig = null
return 0.
endfunction
function GetReducedDamage takes real baseDamage, real armor returns real
if armor >= 0. then
return baseDamage*(1.-((armor*ARMOR_REDUCTION_MULTIPLIER)/(1.+ARMOR_REDUCTION_MULTIPLIER*armor)))
else
return baseDamage*(2.-Pow(0.94,-armor))
endif
endfunction
function GetFullDamage takes real damage, real armor returns real
if armor >= 0. then
return damage/(1.-((armor*ARMOR_REDUCTION_MULTIPLIER)/(1.+ARMOR_REDUCTION_MULTIPLIER*armor)))
else
return damage/(2.-Pow(0.94,-armor))
endif
endfunction
endlibrary