Name | Type | is_array | initial_value |
JustCastSpell | group | No |
//TESH.scrollpos=51
//TESH.alwaysfold=0
////////////////////////////////////////////////////////////////////
// Enhanced Critical Strike by 1)ark_NiTe //
// //
// i = Level of Enhanced Critical Strike //
// r = Extra Damage Dealt (Real Damage * Level of Ability) //
// //
////////////////////////////////////////////////////////////////////
//==================================================================================================================================
// Start of constants. These will need to be changed by you. They provide the user with easier implementing//changing of the spell's rawcodes and effects.
//==================================================================================================================================
constant function Crit_Strike_ID takes nothing returns integer
return 'A001' // Enhanced Critical Strike ability rawcode.
endfunction
constant function Crit_Struck_ID takes nothing returns integer
return 'A000' // Critically Struck (Dummy) ability rawcode.
endfunction
constant function Dummy_Unit_ID takes nothing returns integer
return 'h002' // Dummy Unit rawcode.
endfunction
//==================================================================================================================================
// End of constants. Do not touch anything below this unless you are familiar with JASS.
//==================================================================================================================================
function Enhanced_Critical_Strike_Conds takes nothing returns boolean
return GetOwningPlayer(GetTriggerUnit()) != GetOwningPlayer(GetEventDamageSource()) and GetUnitAbilityLevel(GetEventDamageSource(), 'A001') >=1 and IsUnitInGroup(GetEventDamageSource(), udg_JustCastSpell) == false and GetRandomInt(1, 100) <= 15
endfunction
function Trig_Enhanced_Critical_Strike takes nothing returns nothing
// Declares Local Variables
local unit e
local unit d = GetEventDamageSource()
local unit t = GetTriggerUnit()
local force f = CreateForce()
local force g = CreateForce()
local texttag tag
local integer i = GetUnitAbilityLevel(d, Crit_Strike_ID())
local real dmg = ( GetEventDamage() * i )
local real a
local real fd
local real r
local trigger trig = GetTriggeringTrigger()
call DisableTrigger(trig)
set a = GetUnitArmor(t)
set fd = GetFullDamage(dmg, a)
set r = GetReducedDamage(fd, a)
call UnitDamageTarget(d, t, r, true, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
call EnableTrigger(trig)
// Creates Floating Text showing the Damage Dealt (dmg+r)
set tag = CreateTextTagUnitBJ( ( "|cffFF0000" + ( I2S(R2I(( ( r / i ) + r ))) + "|r" ) ), 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)
if GetWidgetLife(t) > 0 then
set e = CreateUnit(GetOwningPlayer(d), Dummy_Unit_ID(), GetUnitX(t), GetUnitY(t), 0)
call UnitApplyTimedLife(e, 'BTLF', 1.00)
call UnitAddAbility(e, Crit_Struck_ID())
call IssueTargetOrder( e, "drunkenhaze", t )
else
// Does not create dummy unit because unit has died
endif
set tag = null
set trig = null
set f = null
set g = null
set e = null
set d = null
set t = null
endfunction
//===========================================================================
function InitTrig_Enhanced_Critical_Strike takes nothing returns nothing
set gg_trg_Enhanced_Critical_Strike = CreateTrigger( )
call TriggerAddCondition( gg_trg_Enhanced_Critical_Strike, Condition( function Enhanced_Critical_Strike_Conds ) )
call TriggerAddAction( gg_trg_Enhanced_Critical_Strike, function Trig_Enhanced_Critical_Strike )
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_Cast_Any_Spell_Conditions takes nothing returns boolean
return GetUnitTypeId(GetTriggerUnit()) != Dummy_Unit_ID() and 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 = 'A03E'
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