- Joined
- Apr 24, 2012
- Messages
- 5,113
JASS:
//************************************************************************************
//*
//* Custom Element v1.0
//* by: Almia aka Radamantus
//*
//* --------------------------------------------------------------------------
//*
//* Description
//*
//* ------------------------------------------
//*
//* Custom Element is a damage modification system with unique features.
//* This system allows to modify damage depending on the target's element.
//*
//* Damage Modification for Elements has two effects : Amplification
//* and Reduction , while both these two has also two types, percentage
//* and static. Static Amplification and Reduction means that a damage
//* that is modified will either amplify or reduct damage by an exact value
//* assigned to both elements. Percentage Amplification and Reduction
//* amplifies or reducts damage by a percentage value of a damage assigned
//* to both elements.
//*
//* System also features Element Recognition,where elements of units are
//* determined by means of its special effects attached to them.
//*
//* The system allows custom effects, where you can add an effect when
//* damage modification happens. Custom Effects are handled by means
//* of Real variable Events. Events have 3 types, Amplification,
//* Reduction and No Modification. This will be run when some element
//* modification happens.
//*
//* The system features method of saving Attack Types and Damage Types.
//* The method is done via Typecasting. You can use it if you want.
//*
//* --------------------------------------------------------------------------
//*
//* Requires
//*
//* ------------------------------------------
//*
//* Bribe's Unit Indexer
//* [ hiveworkshop.com/forums/spells-569/gui-unit-indexer-1-2-0-2-a-197329/ ]
//* Bribe's Damage Engine
//* [ hiveworkshop.com/forums/spells-569/gui-damage-engine-v2-2-1-0-a-201016 ]
//*
//* --------------------------------------------------------------------------
//*
//* API
//*
//* ------------------------------------------
//*
//* function CreateElement takes nothing returns integer
//*
//* - Creates a new element
//*
//* function SetElementAmplification takes integer sourceElement, integer targetElement, real value, boolean static, attacktype a, damagetype d returns nothing
//*
//* - Registers a damage amplification of a source Element to its target element
//*
//* function SetElementReduction takes integer sourceElement, integer targetElement, real value, boolean static returns nothing
//*
//* - Same with Amplification, though this is reduction.
//*
//* function SetUnitTypeElement takes integer id, integer element returns nothing
//*
//* - Registers a unit type id ('hfoo', 'Hmkg', etc) to an element
//*
//* function SetElementEffect takes integer element, string model, string attachment returns nothing
//*
//* - Registers an effect model to an element
//* - This is for determining unit's element in-game
//*
//* function GetElementOfUnitType takes integer id returns integer
//*
//* - Gets the element of a given unit-type
//*
//* function GetElementEffect takes integer element returns string
//*
//* - Gets the element's effect
//*
//* function GetElementOfUnit takes unit u returns integer
//*
//* - Gets the unit's element via getting its unit type.
//*
//* --------------------------------------------------------------------------
//*
//* How to use
//*
//* ------------------------------------------
//*
//* - Create an element then use an integer variable that represents
//* the element.
//*
//* Example:
//* set Fire = CreateElement()
//*
//* - Register a unit-type via SetUnitTypeElement
//* ( call SetUnitTypeElement('hfoo', Fire))
//* [ The Example above registers the footman's element as fire ]
//*
//* - Register damage amplification via SetElementAmplification
//* - Register damage reduction via SetElementReduction
//*
//* - Register Variable Events to use Custom Effects
//* Here is the table:
//* Amplification - 1
//* Reduction - 2
//* No Modifiction - 3
//*
//* - Register Element special effects via SetElementEffect
//*
//* --------------------------------------------------------------------------
//*
//* Install
//*
//* ------------------------------------------
//*
//* - Create the variables listed below
//*
//* ElementTable = hashtable
//* ElementEvent = real
//* ElementEventTargetElement = integer
//* ElementEventSourceElement = integer
//* ElementEventSource = unit
//* ElementEventTarget = unit
//* ElementEventAmount = real
//* ElementCount = integer
//* Element = boolean array
//*
//* --------------------------------------------------------------------------
//*
//* Notes
//*
//* ------------------------------------------
//*
//* - No source elements can have two or more
//* amplificationto target elements at the
//* same time. Same goesto reduction.
//* - UnitTypes can't have more than one element
//* - Elements can't have more than one special effects
//*
//* --------------------------------------------------------------------------
//*
//* Credits
//*
//* ------------------------------------------
//*
//* Bribe
//* Magtheridon96
//*
//* --------------------------------------------------------------------------
//*
//* Settings
//*
//* ------------------------------------------
//*
//* Element damage modification
//*
//* ------------------------------------------
//*
constant function MaxElementDmgPercent takes nothing returns real
return 100.0 // 100 percent is the max Damage Modification percent value
endfunction
constant function ElementOverflow takes nothing returns integer
return JASS_MAX_ARRAY_SIZE // 8192
endfunction
//*
//* ------------------------------------------
//*
//* Element events
//*
//* ------------------------------------------
//*
constant function ELEMENT_EVENT_AMPLIFICATION takes nothing returns real
return 1.
endfunction
constant function ELEMENT_EVENT_REDUCTION takes nothing returns real
return 2.
endfunction
constant function ELEMENT_EVENT_NO_MOD takes nothing returns real
return 0.
endfunction
//*
//* ------------------------------------------
//*
//* Debug Mode
//*
//* ------------------------------------------
//*
constant function ElementDebugMode takes nothing returns boolean
return true
endfunction
constant function ExpectedElementError takes nothing returns string
return "Element |c00ff0000Code Error|r : |cffffcc00Expected an Element."
endfunction
constant function ElementOverflowError takes nothing returns string
return "Element |c00ff0000Code Error|r : |cffffcc00Element Overflow(8192 elements) reached"
endfunction
//*
//* --------------------------------------------------------------------------
//*
//* Tools
//*
//* ------------------------------------------
//*
//* Save/Load AttackType and DamageType
//*
//* ------------------------------------------
//*
function SaveAttackTypeHandle takes hashtable ht, integer pkey, integer ckey, attacktype typ returns nothing
call SaveInteger(ht, pkey, ckey, GetHandleId(typ))
endfunction
function SaveDamageTypeHandle takes hashtable ht, integer pkey, integer ckey, damagetype typ returns nothing
call SaveInteger(ht, pkey, ckey, GetHandleId(typ))
endfunction
function LoadAttackTypeHandle takes hashtable ht, integer pkey, integer ckey returns attacktype
return ConvertAttackType(LoadInteger(ht, pkey, ckey))
endfunction
function LoadDamageTypeHandle takes hashtable ht, integer pkey, integer ckey returns damagetype
return ConvertDamageType(LoadInteger(ht, pkey, ckey))
endfunction
//*
//* ------------------------------------------
//*
//* Fire Element Event
//*
//* ------------------------------------------
//*
function ElementFireEvent takes integer sElement, integer tElement, unit source, unit target, real amount, real Event returns nothing
set udg_ElementEventSource = source
set udg_ElementEventTarget = target
set udg_ElementEventAmount = amount
set udg_ElementEventSourceElement = sElement
set udg_ElementEventTargetElement = tElement
set udg_ElementEvent = Event
set udg_ElementEvent = 0
endfunction
//*
//* --------------------------------------------------------------------------
//*
//* System functions
//*
//* ------------------------------------------
//*
//* On Index/Deindex functions
//*
//* ------------------------------------------
//*
function ElementOnIndex takes nothing returns boolean
local integer id = GetUnitTypeId(udg_UDexUnits[udg_UDex])
local integer element = LoadInteger(udg_ElementTable, id, 0)
local string mdl = LoadStr(udg_ElementTable, element, 0)
local string attach = LoadStr(udg_ElementTable, element, 1)
call SaveEffectHandle(udg_ElementTable, GetHandleId(udg_UDexUnits[udg_UDex]), 0, AddSpecialEffectTarget(mdl, udg_UDexUnits[udg_UDex], attach))
return false
endfunction
function ElementOnDeIndex takes nothing returns boolean
call DestroyEffect(LoadEffectHandle(udg_ElementTable, GetHandleId(udg_UDexUnits[udg_UDex]), 0))
return false
endfunction
//*
//* ------------------------------------------
//*
//* System Core
//*
//* DO NOT TOUCH ANYTHING BELOW
//*
//* ------------------------------------------
//*
function ElementOnDamage takes nothing returns boolean
local real dmg = udg_DamageEventAmount
local integer id = GetUnitTypeId(udg_DamageEventSource)
local integer id2 = GetUnitTypeId(udg_DamageEventTarget)
local integer sElement = LoadInteger(udg_ElementTable, id, 0)
local integer tElement = LoadInteger(udg_ElementTable, id2, 0)
local boolean doAmplify = LoadBoolean(udg_ElementTable, sElement, tElement)
local boolean doReduct = LoadBoolean(udg_ElementTable, sElement, ElementOverflow() * 2 + tElement)
local boolean static
local real value
local trigger t
if doAmplify then
set value = LoadReal(udg_ElementTable, sElement, tElement)
set static = LoadBoolean(udg_ElementTable, sElement, ElementOverflow() + tElement)
if static then
set value = dmg
else
set value = value / MaxElementDmgPercent() * dmg
endif
set t = GetTriggeringTrigger()
call DisableTrigger(t)
call UnitDamageTarget(udg_DamageEventSource, udg_DamageEventTarget, value, false, false, LoadAttackTypeHandle(udg_ElementTable, sElement, tElement), LoadDamageTypeHandle(udg_ElementTable, sElement, ElementOverflow() + tElement), null)
call EnableTrigger(t)
call ElementFireEvent(sElement, tElement, udg_DamageEventSource, udg_DamageEventTarget, value, ELEMENT_EVENT_AMPLIFICATION())
endif
if doReduct then
set value = LoadReal(udg_ElementTable, sElement, ElementOverflow() + tElement)
set static = LoadBoolean(udg_ElementTable, sElement, ElementOverflow() * 3 + tElement)
if static then
set value = dmg
else
set value = value / MaxElementDmgPercent() + dmg
endif
call SetUnitState(udg_DamageEventTarget, UNIT_STATE_LIFE, GetUnitState(udg_DamageEventTarget, UNIT_STATE_LIFE) + value)
call ElementFireEvent(sElement, tElement, udg_DamageEventSource, udg_DamageEventTarget, value, ELEMENT_EVENT_REDUCTION())
endif
if not doAmplify and not doReduct then
call ElementFireEvent(sElement, tElement, udg_DamageEventSource, udg_DamageEventTarget, dmg, ELEMENT_EVENT_NO_MOD())
endif
set t = null
return false
endfunction
//*
//* ------------------------------------------
//*
//* Init Element System
//*
//* ------------------------------------------
//*
function InitElement takes nothing returns nothing
local trigger onIndex = CreateTrigger()
local trigger onDeIndex = CreateTrigger()
local trigger onDamage = CreateTrigger()
call TriggerRegisterVariableEvent(onIndex, "udg_UnitIndexEvent", EQUAL, 1)
call TriggerRegisterVariableEvent(onDeIndex, "udg_UnitIndexEvent", EQUAL, 2)
call TriggerRegisterVariableEvent(onDamage, "udg_DamageEvent", EQUAL, 1)
call TriggerAddCondition(onDeIndex, Condition(function ElementOnDeIndex))
call TriggerAddCondition(onIndex, Condition(function ElementOnIndex))
call TriggerAddCondition(onDamage, Condition(function ElementOnDamage))
set onIndex = null
set onDeIndex = null
set onDamage = null
endfunction
//*
//* ------------------------------------------
//*
//* Create Element
//*
//* ------------------------------------------
//*
function CreateElement takes nothing returns integer
if null == udg_ElementTable then
set udg_ElementTable = InitHashtable()
call InitElement()
endif
if ElementOverflow() > udg_ElementCount then
set udg_ElementCount = udg_ElementCount + 1
set udg_Element[udg_ElementCount] = true
return udg_ElementCount
elseif ElementDebugMode() then
call BJDebugMsg(ElementOverflowError())
endif
return 0
endfunction
//*
//* ------------------------------------------
//*
//* Set Element Amplification and Reduction
//*
//* ------------------------------------------
//*
function SetElementAmplification takes integer sourceElement, integer targetElement, real value, boolean static, attacktype a, damagetype d returns nothing
local real r
if udg_Element[sourceElement] and udg_Element[targetElement] then
call SaveBoolean(udg_ElementTable, sourceElement, targetElement, true)
if not static then
set r = MaxElementDmgPercent()
if value > r then
set value = r
endif
else
call SaveBoolean(udg_ElementTable, sourceElement, ElementOverflow() + targetElement, static)
endif
call SaveReal(udg_ElementTable, sourceElement, targetElement, value)
call SaveAttackTypeHandle(udg_ElementTable, sourceElement, targetElement, a)
call SaveDamageTypeHandle(udg_ElementTable, sourceElement, ElementOverflow() + targetElement, d)
elseif ElementDebugMode() then
call BJDebugMsg(ExpectedElementError())
endif
endfunction
function SetElementReduction takes integer sourceElement, integer targetElement, real value, boolean static returns nothing
local real r
if udg_Element[sourceElement] and udg_Element[targetElement] then
call SaveBoolean(udg_ElementTable, sourceElement,ElementOverflow() * 2 + targetElement, true)
if not static then
set r = MaxElementDmgPercent()
if value > r then
set value = r
endif
else
call SaveBoolean(udg_ElementTable, sourceElement, ElementOverflow() * 3 + targetElement, static)
endif
call SaveReal(udg_ElementTable, sourceElement, ElementOverflow() + targetElement, value)
elseif ElementDebugMode() then
call BJDebugMsg(ExpectedElementError())
endif
endfunction
//*
//* ------------------------------------------
//*
//* Register Element SFX and UnitTypes
//*
//* ------------------------------------------
//*
function SetUnitTypeElement takes integer id, integer element returns nothing
if udg_Element[element] then
call SaveInteger(udg_ElementTable, id, 0, element)
elseif ElementDebugMode() then
call BJDebugMsg(ExpectedElementError())
endif
endfunction
function SetElementEffect takes integer element, string model, string attachment returns nothing
if udg_Element[element] then
call SaveStr(udg_ElementTable, element, 0, model)
call SaveStr(udg_ElementTable, element, 1, attachment)
elseif ElementDebugMode() then
call BJDebugMsg(ExpectedElementError())
endif
endfunction
//*
//* ------------------------------------------
//*
//* Get Element
//*
//* ------------------------------------------
//*
function GetElementOfUnitType takes integer id returns integer
return LoadInteger(udg_ElementTable, id, 0)
endfunction
function GetElementEffect takes integer element returns string
if udg_Element[element] then
return LoadStr(udg_ElementTable, element, 0)
elseif ElementDebugMode() then
call BJDebugMsg(ExpectedElementError())
endif
return ""
endfunction
function GetElementOfUnit takes unit u returns integer
return GetElementOfUnitType(GetUnitTypeId(u))
endfunction
//*
//************************************************************************************
Im doing a damage system that uses Bribe's Damage Engine. There is something wrong here. I always get recursion error even though im disabling the trigger with Damage event and enabling it.
Here is the test map: