Moderator
M
Moderator
11 Nov 2011
Bribe: Very good resource. Nice configurables and clean code.
Bribe: Very good resource. Nice configurables and clean code.
// ********************************************************************************* //
// This spells requires the CTL library //
// ********************************************************************************* //
// ********************************************************************************* //
// HOW TO IMPLEMENT //
// ********************************************************************************* //
// //
// 1. Copy the Maledict Ability (object editor) //
// 2. Copy the Maledict Buff (object editor) //
// 3. Copy this trigger //
// 4. Enjoy :), but remember, this spell requires CTL //
// //
// ********************************************************************************* //
library Maledict requires CTL
globals
// ***************************************************************************** //
// CONFIGURABLES //
// ***************************************************************************** //
// Rawcode of the curse and the curse buff
private constant integer MALEDICT_RAWCODE = 'A001'
private constant integer MALEDICT_BUFF_RAWCODE = 'B000'
// @SPECIAL_EFFECT = Path of the special effect
// @EFFECT_ATTACHMENT = Position of the special effect
private constant string SPECIAL_EFFECT = "Abilities\\Spells\\Undead\\DeathPact\\DeathPactCaster.mdl"
private constant string EFFECT_ATTACHMENT = "overhead"
// @ONLY_HERO = If it is true, MALEDICT will only affect
// HERO type units
private constant boolean ONLY_HERO = false
// @DAMAGE_TYPE_EVERY_SECOND = Here you can choose what kind of damage
// the curse will do every second
private constant damagetype DAMAGE_TYPE_EVERY_SECOND = DAMAGE_TYPE_UNIVERSAL
// @DAMAGE_TYPE = Type of damage that the spell will do
// in the extra damage
// @ATTACK_TYPE = Type of attack that the spell will do
// in the extra damage and normal damage
private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_MAGIC
private constant attacktype ATTACK_TYPE = ATTACK_TYPE_NORMAL
// Area of effect of the curse (do not touch the +50)
private constant real AoE = 165. + 50.
// @EXTRA_DAMAGE_PERIOD = Seconds that needs to pass to make the extra damage
private constant real EXTRA_DAMAGE_PERIOD = 4.
// @PERIODIC_DAMAGE = Seconds that needs to pass to make the periodic damage
private constant real PERIODIC_DAMAGE = 1.
// @PRELOAD = To preload the special effect
private constant boolean PRELOAD = true
// ***************************************************************************** //
// END CONFIGURABLES //
// ***************************************************************************** //
// @G = "Units" affected by the curse - DO NOT TOUCH THIS!
private constant group G = bj_lastCreatedGroup
endglobals
// ********************************************************************************* //
// CONFIGURABLE //
// ********************************************************************************* //
// Returns the extra damage
// ((HP OF THE TARGET WHEN ADQUIERE THE CURSE - ACTUAL LIFE OF TARGET) / 100) * (10 * LEVEL OF THE CURSE)
private function getExtraDamage takes unit target, real hp, integer level returns real
local real damage
set damage = ((hp - GetWidgetLife(target)) / 100) * (10. * level)
if damage < 0 then
set damage = 0
endif
return damage
endfunction
// Returns the periodic damage
private function getPeriodicDamage takes integer level returns real
return 5. * level
endfunction
// Returns the unit that can be affected by the curse
private function affectedUnit takes unit target, player p returns boolean
static if ONLY_HERO then
return IsUnitType(target, UNIT_TYPE_HERO) and IsUnitEnemy(target, p) and not(IsUnitType(target, UNIT_TYPE_DEAD)) and not(IsUnitType(target, UNIT_TYPE_MAGIC_IMMUNE))
else
return IsUnitEnemy(target, p) and not(IsUnitType(target, UNIT_TYPE_DEAD)) and not(IsUnitType(target, UNIT_TYPE_MAGIC_IMMUNE))
endif
endfunction
// ********************************************************************************* //
private keyword Init
private struct Spell extends array
private static integer instanceCount = 0
private static thistype recycle = 0
private thistype recycleNext
private unit caster // Caster
private unit target // Curse target
private real hp // HP of target
private integer level // Spell level
private real period // @period will serve to know if PERIODIC_DAMAGE seconds has passed
private real period_extraDamage // Same as period, but for the extra damage
implement CTL
implement CTLExpire
// If the target has the curse and is not dead...
if 0 < GetUnitAbilityLevel(this.target, MALEDICT_BUFF_RAWCODE) and not(IsUnitType(this.target, UNIT_TYPE_DEAD)) then
// Let's see if PERIODIC_DAMAGE seconds has passed
if PERIODIC_DAMAGE < this.period then
// If was, reset period to 0
set this.period = 0.
// Making the periodic damage (only if the unit
// is not inmmune to magic)
if not(IsUnitType(this.target, UNIT_TYPE_MAGIC_IMMUNE)) then
call UnitDamageTarget(this.caster, this.target, getPeriodicDamage(this.level), false, false, ATTACK_TYPE, DAMAGE_TYPE_EVERY_SECOND, null)
endif
else
// If was not, add the expired seconds to period (seconds
// of the CTL timer)
set this.period = this.period + 0.031250000
endif
// Let's see if the EXTRA_DAMAGE_PERIOD seconds has passed
if EXTRA_DAMAGE_PERIOD < this.period_extraDamage then
// If was, reset period_extraDamage to 0
set this.period_extraDamage = 0.
// Making the damage and special effect only if the
// damage is greater than 0
if getExtraDamage(this.target, this.hp, this.level) > 0 then
// Only make the damage if the target is not inmmune to magic
if not(IsUnitType(this.target, UNIT_TYPE_MAGIC_IMMUNE)) then
call DestroyEffect(AddSpecialEffectTarget(SPECIAL_EFFECT, this.target, EFFECT_ATTACHMENT))
call UnitDamageTarget(this.caster, this.target, getExtraDamage(this.target, this.hp, this.level), false, false, ATTACK_TYPE, DAMAGE_TYPE, null)
endif
endif
else
// If was not (the seconds has not passed)...
set this.period_extraDamage = this.period_extraDamage + 0.031250000
endif
else
// If the unit is dead or not has
// the buff...
set this.caster = null
set this.target = null
call this.destroy()
set recycleNext = recycle
set recycle = this
endif
implement CTLNull
implement CTLEnd
private static method run takes nothing returns boolean
local unit j
local thistype this
// If the ability being cast is the Rupture and the target can be affected
// (units that can be affected can be changed in the affectedUnit function)
if GetSpellAbilityId() == MALEDICT_RAWCODE then
call GroupEnumUnitsInRange(G, GetSpellTargetX(), GetSpellTargetY(), AoE, null)
loop
set j = FirstOfGroup(G)
exitwhen j == null
call GroupRemoveUnit(G, j)
if affectedUnit(j, GetTriggerPlayer()) then
set this = thistype.create()
if (recycle == 0) then
set instanceCount = instanceCount + 1
set this = instanceCount
else
set this = recycle
set recycle = recycle.recycleNext
endif
set this.caster = GetTriggerUnit()
set this.level = GetUnitAbilityLevel(this.caster, MALEDICT_RAWCODE)
set this.target = j
set this.hp = GetWidgetLife(j)
endif
endloop
endif
return false
endmethod
implement Init
endstruct
private module Init
private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Condition(function thistype.run))
// Preload the special effect...
static if PRELOAD then
call Preload(SPECIAL_EFFECT)
endif
endmethod
endmodule
endlibrary