• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

need help making this "simple spell"

Status
Not open for further replies.
Level 4
Joined
Jul 13, 2017
Messages
30
im bad at this i admit, tried to find a way for 2 days, i havent find the solution..

so the spell is this:
->takes control of the enemy for 30 seconds, and then return ownership with the current hp and mp. <-

need to be MUI

works like sylvanas "charm" spell , but with a 30 sec timer.
 
Level 7
Joined
Mar 10, 2013
Messages
366
Are you able to indentify the cast of charm and the original owner before the cast occurs? Just try to save the owner of target abilty and wait for 30 seconds. After that you can just change the ownership of the unit back.
 
You will need a timer for the spell.

In pseudo-trigger:
  • Event
    • A unit starts effect of ability
  • Conditions
    • Cast ability equal to <your_ability>
    • Owner of <target_unit> is enemy of <trigger_player>
  • Actions
    • Set Unit Owner of <target_unit> to <trigger_player>
    • Wait 30. seconds using Timer
    • Set Unit Owner of <target_unit> to <orig_player>
If in JASS, (recommended)

Hashtable

Array



Create a new trigger. Name it Hashtable Init. Convert it to custom text.
Make a new hashtable variable. Copy and paste the following into your Hashtable Init trigger.

JASS:
function RestorePossession takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer index = GetHandleId(t)
    local unit which = LoadUnitHandle(<hash_var>, index, 2)
  
    call SetUnitOwner(which, Player(LoadInteger(<hash_var>, index, 1), true))
    call FlushChildHashtable(<hash_var>, index)

    call DestroyTimer(t)
  
    set t = null
    set which = null
endfunction

function StartPossession takes unit which, player newOwner, real duration returns nothing
    local timer t
    if delay <= 0. then
        // The duration is instantaneous, so the system guesses that it will be permanent
        call SetUnitOwner(which, newOwner, true)
    else
        // We create a timer to determine when the possession will exactly end.
        // By creating a timer, I am insinuating that TriggerSleepActions are generally not recommended in JASS.
        set t = CreateTimer()

        // We save the following data into our timer.
        call SaveInteger(<hash_var>, GetHandleId(t), 1, GetPlayerId(GetOwningPlayer(which)))
        call SaveUnitHandle(<hash_var>, GetHandleId(t), 2, which)
      
        // Change Ownership
        call SetUnitOwner(which, newOwner, true)
      
        // Start the timer with the specified duration.
        call TimerStart(t, duration, false, function RestorePossession)
        set t = null
    endif
endfunction

function InitTrig_Hashtable_Init takes nothing returns nothing
    set <hash_var> = InitHashtable()
endfunction

To use those functions, we call them via custom script:

Pseudo-Trigger:
  • Event
    • A unit starts effect of ability
  • Conditions
    • Cast ability equal to <your_ability>
    • Owner of <target_unit> is enemy of <trigger_player>
  • Actions
    • Custom Script: call StartPossession(GetSpellTargetUnit(), GetTriggerPlayer(), 30.)
Note: You will have to place the Pseudo-Trigger after the Hashtable Init trigger in order for the following script to compile.


You'll need the following arrays:

unit array <unit_arr>
integer array <int_arr>
timer array <tim_arr>

Dynamic Indexing will be used to simplify the code.
integer <index>

Create a new trigger. Name it Array Init. Convert it to custom text.
JASS:
function Possession_GetTimerId takes timer t returns integer
    local integer i = 1
    loop
        if i > <index> then
            set i = 0
            exitwhen true
        endif
        exitwhen <tim_arr>[i] == t
        set i = i + 1
    endloop
    return i
endfunction

function RestorePossession takes nothing returns nothing
    local integer index = Possession_GetTimerId(GetExpiredTimer())
 
    call SetUnitOwner(<unit_arr>[index], Player(<int_arr>[index]))
    call DestroyTimer(<tim_arr>[index])

    set <unit_arr>[index] = <unit_arr>[<index>]
    set <int_arr>[index] = <int_arr>[<index>]
    set <tim_arr>[index] = <tim_arr>[<index>]
   
    set <index> = <index - 1>
endfunction

function StartPossession takes unit which, player newOwner, real duration returns nothing
    if delay <= 0. then
        call SetUnitOwner(which, newOwner, true)
    else
        set <index> = <index> + 1

        set <tim_arr>[<index>] = CreateTimer()
        set <int_arr>[<index>] = GetPlayerId(GetOwningPlayer(which))
        set <unit_arr>[<index>] = which
        
        call SetUnitOwner(which, newOwner, true)
      
        call TimerStart(<tim_arr>[<index>], duration, false, function RestorePossession)
    endif
endfunction

function InitTrig_Array_Init takes nothing returns nothing
    // This is to clear the pre-initialized array value of the timer variable at index 1
    call DestroyTimer(<tim_arr>[1])
endfunction



Disclaimer: The methods above do not consider when the possessed unit has already been possessed before and would cause some errors in logic as a result.
 
Last edited:
Level 4
Joined
Jul 13, 2017
Messages
30
You will need a timer for the spell.

In pseudo-trigger:
  • Event
    • A unit starts effect of ability
  • Conditions
    • Cast ability equal to <your_ability>
    • Owner of <target_unit> is enemy of <trigger_player>
  • Actions
    • Set Unit Owner of <target_unit> to <trigger_player>
    • Wait 30. seconds using Timer
    • Set Unit Owner of <target_unit> to <orig_player>
If in JASS, (recommended)

Hashtable



Create a new trigger. Name it Hashtable Init. Convert it to custom text.
Make a new hashtable variable. Copy and paste the following into your Hashtable Init trigger.

JASS:
function RestorePossession takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer index = GetHandleId(t)
    local unit which = LoadUnitHandle(<hash_var>, index, 2)
   
    call SetUnitOwner(which, Player(LoadInteger(<hash_var>, index, 1), true)
    call FlushChildHashtable(<hash_var>, index)

    call DestroyTimer(t)
   
    set t = null
    set which = null
endfunction

function StartPossession takes unit which, player newOwner, real duration returns nothing
    local timer t
    if delay <= 0. then
        // The duration is instantaneous, so the system guesses that it will be permanent
        call SetUnitOwner(which, newOwner, true)
    else
        // We create a timer to determine when the possession will exactly end.
        // By creating a timer, I am insinuating that TriggerSleepActions are generally not recommended in JASS.
        set t = CreateTimer()

        // We save the following data into our timer.
        call SaveInteger(<hash_var>, GetHandleId(t), 1, GetPlayerId(GetOwningPlayer(which)))
        call SaveUnitHandle(<hash_var>, GetHandleId(t), 2, which)
       
        // Change Ownership
        call SetUnitOwner(which, newOwner, true)
       
        // Start the timer with the specified duration.
        call TimerStart(t, duration, false, function RestorePossession)
        set t = null
    endif
endfunction

function InitTrig_Hashtable_Init takes nothing returns nothing
    set <hash_var> = InitHashtable()
endfunction

To use those functions, we call them via custom script:

Pseudo-Trigger:
  • Event
    • A unit starts effect of ability
  • Conditions
    • Cast ability equal to <your_ability>
    • Owner of <target_unit> is enemy of <trigger_player>
  • Actions
    • Custom Script: call StartPossession(GetSpellTargetUnit(), GetTriggerPlayer(), 30.)
Note: You will have to place the Pseudo-Trigger after the Hashtable Init trigger in order for the following script to compile.
Youre a genius! so we have to use hashtables for this simple spell.. thanks +rep
 
Level 5
Joined
Mar 6, 2015
Messages
130
Im curious , if this is possible to make using GUI unit indexer? instead of hashtables?
you can use both methods but i wouldnt make this kind of spells with Unit indexer the point is the Unit indexer method is faster than hashtables so when it comes to a global system that runs too many times at a moment its better to use unit indexer for example the damage System or a projectile system
 
Status
Not open for further replies.
Top