• 🏆 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!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Transformations v1.2

Transformations v1.2

Brief Descripton:
- This system was made coz it was requested by somebody in this site, so I made a decision to post it here as a full system.
- Basically, this is just like the Bear Ability but uses items as a requirement to acquire the said ability.
- Heroes can change to 'another' hero depending on what item he's wearing as seen in the sample GUI setup below.
- For example, the Pandaren can transform into an Alternate Form if the items have been registered to him.
- Unregistered heroes cannot use the item that has been registered, nor a registered hero can use the transformation ability if the item is not for him.
- Registered items for a particular hero can't be equipped twice by the same unit.


JASS:
/*
=====Transformations v1.2
=====Created by Mckill2009

HOW TO INSTALL:
- Make a new trigger and convert to custom text via EDIT >>> CONVERT CUSTOM TEXT
- Copy ALL that is written here (overwrite the existing texts in the trigger)
- Copy all the required lilbraries to your map

HOW TO USE:
- Normal and Alternate Units must have the custom Bear Ability (see object editor for sample)
- Normal and Alternate Units must have an inventory or a hero
- You must register the units and items and first before using (see below)
- If you dont follow these HOW TO USE, it wont work

WARNING:
- It is strongly recommended that the number of items being registered EQUALS to the level of the ability
- It means, if the ability is only level 5, the items for a particular hero should be 5 pcs as well

API:
static method RegisterUnit takes unit hero, integer abilityid returns nothing
    - Registers the unit, unregistered unit cannot take the item that is registered
    - Saving the bear ability of the hero
    - Removes the saved bear ability but will be added again when hero acquires a registered specified item for him
    - This is the FIRST thing you will call

static method RegisterItem takes unit hero, integer itemid returns nothing
    - Registers the item that a particular hero is using
    - Sets the AbilityLevel and the COUNTER for the items registered for a particular hero
    - This is the SECOND thing you will call

CREDITS and REQUIREMENTS:
- RegisterPlayerUnitEvent by Magtheridon96
- SimError by Vexorian
*/

library Transformation uses SimError, RegisterPlayerUnitEvent

globals
    //===NON-CONFIGURABLES:
    private constant hashtable                    HT = InitHashtable()
    private constant integer           CHILD_UNIT_ID = 10000
    private constant integer      CHILD_ABIL_ITEM_ID = 20000   
    private integer AbilityLevel = 0 //Sets the level of ability per item acquired
    //===============================================================
    //=====CONFIGURABLES:
    private constant string             DOUBLED_ITEM = "you can't have 2 items of the same type!"
    private constant string      UNIT_NOT_REGISTERED = "this unit is not registered!"   
endglobals

//! textmacro REG2 takes FUNC, B, C
private function Is$FUNC$ takes unit u, item itm returns boolean
    local integer i = 0
    local integer unitID = GetHandleId(u)
    local integer itemcount = LoadInteger(HT, unitID, CHILD_ABIL_ITEM_ID)
    loop
        if GetItemTypeId(itm)==LoadInteger(HT, unitID, i) and $C$ then
            $B$
            return true
        endif
        set i = i + 1
        exitwhen i > itemcount       
    endloop
    return false
endfunction
//! endtextmacro
//! runtextmacro REG2("UnitRegistered","set AbilityLevel = i+1","not HaveSavedHandle(HT, unitID, CHILD_UNIT_ID+2)")
//! runtextmacro REG2("ItemDoubled","//","HaveSavedHandle(HT, unitID, CHILD_UNIT_ID+2)")

struct TR extends array
    private static method getItem takes nothing returns nothing
        local unit u = GetTriggerUnit()
        local item itm = GetManipulatedItem()
        local integer uID
        local integer abilityID
        local real x = GetUnitX(u)
        local real y = GetUnitY(u)
        if HaveSavedHandle(HT,GetHandleId(u),0x9876) then
            if IsUnitRegistered(u, itm) then
                set uID = GetHandleId(u) 
                set abilityID = LoadInteger(HT, uID, CHILD_UNIT_ID)
                call UnitAddAbility(u, abilityID) 
                call SetUnitAbilityLevel(u, abilityID, AbilityLevel)
                call SaveItemHandle(HT, uID, CHILD_UNIT_ID+2, itm)
            elseif IsItemDoubled(u, itm) then
                call UnitDropItemPoint(u, itm, x, y) 
                call SimError(GetTriggerPlayer(), DOUBLED_ITEM)
            endif       
        elseif HaveSavedInteger(HT,GetItemTypeId(itm),0) then
            call UnitDropItemPoint(u, itm, x, y) 
            call SimError(GetTriggerPlayer(), UNIT_NOT_REGISTERED)
        endif
        set itm = null
        set u = null
    endmethod
    
    private static method dropItem takes nothing returns nothing
        local unit u = GetTriggerUnit()
        local integer it
        local integer uID
        if GetManipulatedItem()==LoadItemHandle(HT, GetHandleId(u), CHILD_UNIT_ID+2) then
            call RemoveSavedHandle(HT, GetHandleId(u), CHILD_UNIT_ID+2)
            call UnitRemoveAbility(u, LoadInteger(HT, GetHandleId(u), CHILD_UNIT_ID))
        endif  
        set u = null
    endmethod  
        
    private static method unitDies takes nothing returns nothing
        local unit u = GetTriggerUnit()
        local integer unitID
        if IsUnitType(u, UNIT_TYPE_HERO) then
            set unitID = GetHandleId(u)
            if HaveSavedInteger(HT, unitID, CHILD_UNIT_ID) then //ability that is saved
                call RemoveSavedInteger(HT, unitID, CHILD_UNIT_ID+3)
                call SetItemDroppable(LoadItemHandle(HT, unitID, CHILD_UNIT_ID+2), true) 
            endif    
        endif         
        set u = null
    endmethod
    
    private static method castOk takes unit u returns nothing
        local integer unitID = GetHandleId(u)
        local item itm
        if UnitHasItem(u, LoadItemHandle(HT, unitID, CHILD_UNIT_ID+2)) then 
            set itm = LoadItemHandle(HT, unitID, CHILD_UNIT_ID+2)
            if HaveSavedInteger(HT, unitID, CHILD_UNIT_ID+3) then
                call RemoveSavedInteger(HT, unitID, CHILD_UNIT_ID+3)
                call SetItemDroppable(itm, true) 
            else
                call SaveInteger(HT, unitID, CHILD_UNIT_ID+3, 0)
                call SetItemDroppable(itm, false) 
            endif
        endif       
        set itm = null
    endmethod
    
    private static method castAbility takes nothing returns nothing
        if GetSpellAbilityId()==LoadInteger(HT, GetHandleId(GetTriggerUnit()), CHILD_UNIT_ID) then
            call thistype.castOk(GetTriggerUnit())
        endif    
    endmethod    
    
    private static method onInit takes nothing returns nothing
        call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_PICKUP_ITEM, function thistype.getItem) 
        call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DROP_ITEM, function thistype.dropItem) 
        call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, function thistype.castAbility) 
        call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, function thistype.unitDies)
    endmethod

    //=====SYSTEM API: You must follow this step by step
    //SECOND thing to do >>> call TR.RegisterItem(YOUR HERO, ITEM RAW CODE)
    //This registers ALL items that are used in the map
    static method RegisterItem takes unit hero, integer itemid returns nothing
        local integer unitID = GetHandleId(hero)
        //childID starts with 0
        call SaveInteger(HT, unitID, LoadInteger(HT, unitID, CHILD_ABIL_ITEM_ID), itemid) 
        //level of the bear ability, childID starts 20000 
        call SaveInteger(HT, unitID, CHILD_ABIL_ITEM_ID, LoadInteger(HT, unitID, CHILD_ABIL_ITEM_ID)+1) 
        //saves all items
        call SaveInteger(HT,itemid,0,0) 
    endmethod

    //FIRST thing to do >>> call TR.RegisterUnit(YOUR HERO, ABILITY RAW CODE)
    //This registers your hero and removes the Transformation(Bear Ability)
    //You MUST call this only once
    static method RegisterUnit takes unit hero, integer abilityid returns nothing
        local integer unitID = GetHandleId(hero)
        if not HaveSavedHandle(HT, unitID, 0x9876) then
            //this is the checking if the hero is registered or not
            call SaveUnitHandle(HT, unitID, 0x9876, hero)
            //saving the ability, loading it when hero acquires a registered item
            call SaveInteger(HT, unitID, CHILD_UNIT_ID, abilityid)
            call UnitRemoveAbility(hero, abilityid)
        else
            debug call BJDebugMsg("ERROR: "+GetUnitName(hero)+" has been registered already!")
        endif
    endmethod
endstruct

endlibrary



  • Demo
    • Events
      • Time - Elapsed game time is 0.10 seconds
    • Conditions
    • Actions
      • -------- ========================== --------
      • -------- WARNING: It is strongly recommended that the number of items being registered EQUALS to the level of the ability --------
      • -------- ========== in this case, the Ability is only level 5, the items should be 5 pcs as well. --------
      • -------- ========================== --------
      • -------- Registering the DEMON HUNTER and the items he will be using for transformation --------
      • Unit Group - Pick every unit in (Units in (Playable map area) matching ((Unit-type of (Matching unit)) Equal to Demon Hunter)) and do (Actions)
        • Loop - Actions
          • -------- Registers the hero and his ability used for transformation, this will be removed after it's registered --------
          • Custom script: call TR.RegisterUnit(GetEnumUnit(), 'A000')
          • -------- The items that a particular hero will be using --------
          • Custom script: call TR.RegisterItem(GetEnumUnit(), 'afac')
          • Custom script: call TR.RegisterItem(GetEnumUnit(), 'spsh')
          • Custom script: call TR.RegisterItem(GetEnumUnit(), 'ajen')
          • Custom script: call TR.RegisterItem(GetEnumUnit(), 'bgst')
          • Custom script: call TR.RegisterItem(GetEnumUnit(), 'belv')
      • -------- Registering the PANDAREN and the items he will be using for transformation --------
      • Unit Group - Pick every unit in (Units in (Playable map area) matching ((Unit-type of (Matching unit)) Equal to Pandaren Brewmaster)) and do (Actions)
        • Loop - Actions
          • -------- Registers the hero and his ability used for transformation, this will be removed after it's registered --------
          • Custom script: call TR.RegisterUnit(GetEnumUnit(), 'A001')
          • -------- The items that a particular hero will be using --------
          • Custom script: call TR.RegisterItem(GetEnumUnit(), 'bspd')
          • Custom script: call TR.RegisterItem(GetEnumUnit(), 'cnob')
          • Custom script: call TR.RegisterItem(GetEnumUnit(), 'ratc')
          • Custom script: call TR.RegisterItem(GetEnumUnit(), 'rat6')
          • Custom script: call TR.RegisterItem(GetEnumUnit(), 'rat9')



167625-albums4053-picture55178.jpg



v1.2
- Functions replaced by struct statics
- Arrays replaced by booleans
- API reduced from 3 to 2
- Code improved

v1.1
- Dummy removed, replaced by arrays.
- Sim Errors are now configurable.


Keywords:
transform, bear, metamorphosis, crow, bear, form, metasis, level, hero, melee, ranged, spell
Contents

Transformations (Map)

Reviews
16 July 2012 Bribe: Seems like a good system. Only problem I see is it's yet another item stacking system. The users will decide for themselves which ones are best for them - variety can't hurt I suppose. Approved 3.4/5.

Moderator

M

Moderator

16 July 2012
Bribe: Seems like a good system. Only problem I see is it's yet another item stacking system. The users will decide for themselves which ones are best for them - variety can't hurt I suppose.

Approved 3.4/5.
 
Tips:

1- You should make AbilityAcquire struct extend an array because the generated code is not being used at all :p (You're not using allocate or deallocate and it wont cost you anything, in fact, it would reduce the amount of generated code ^.^)

2- RegisterItem and RegisterAllItems aren't that good :/
They sound too general and they could conflict with a lot of other systems D:
It's better to name them something like RegisterTransformationItem or something :p

RegisterAllItems -> RegisterTransformationItem
RegisterItem -> RegisterTransformationItemEx
RegisterUnit -> RegisterTransformationUnit

3- The SimError texts should be configurable :eek:

4- Instead of using those DummyCount integers and whatnot, you could simply have one integer that stores the count and when you loop, you could set a local to the amount and subtract by 1 after each iteration and you'd exit when the local is 0

5- The dummy unit is really useless :/
You could use some random integer for the hashtable instead. (like 1337 ;D)
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
1) Im plannin to make it a regular function than structs.

2,3,4 noted

5) I can't do that coz I need to enumerate all items that are registered, the
non-registered heroes can't acquire the items, while registered heroes checks doubled
items or he cant use more than 1 item, so it needs to check the item type...

thanks MAg, :)...

EDIT:
I can however replace the dummy/hashtable into an arrayed integer just to save the itemtype, but arrays have a limit of 8190...
 
Last edited:
Level 29
Joined
Mar 10, 2009
Messages
5,016
Oh dont worry as Im not plannin to use RawCodeIndexer as I dont see whats the difference betweet "1 vs RAW_ID" coz afterall its all integers...

I may however consider the use of Table in the next updates coz the problem I see without using Table is that hashtables are limited per map...but I dont think a map would need more than 8000 registered items...
 
Top