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

[JASS] Unknown Recursion

Status
Not open for further replies.
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:
 

Attachments

  • CustomElement v1.0.w3x
    32.6 KB · Views: 32
Level 26
Joined
Aug 18, 2009
Messages
4,097
In FireDmgEv, you set the variable DamageEvent, which you have an event registered for in your header, triggering ElementOnDamage. The UnitDamageTarget-line there starts OnDmgEvent again from Damage Engine. The trigger you disable in ElementOnDamage is not the one from Damage Engine.
 
Status
Not open for further replies.
Top