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

Item Fuse/Disassemble 2.1 (GUI & vJass)

This system's setup is made in GUI, but code is in vJass. This system can combine and disassemble items.




Update to my previous system 1.4

-------------------------------------------------------
Version 1.5
- Mirror image sound now can be configurable, once can delay it, shut it down or use it and disable effect sound. If do not want to use MirrIm sound then just use effect from comments. If you want to play both just delay MirrIm sound.

- The "return" line of code was there to eliminate extra loops and simply end the code
so i just added "u = null" to fix the leak
-------------------------------------------------------

-------------------------------------------------------
Version 1.6
- Added option for array increase
- Fixed hex array id
- Fixed timer leak
- Added compatibility with 'Table'
-------------------------------------------------------

-------------------------------------------------------
Version 1.7
- Added support for item disassemble
- Fixed bug with wrong flush of 'Table'
-------------------------------------------------------

-------------------------------------------------------
Version 1.7b
- Replaced multiple instances of "6" by bj_MAX_INVENTORY, for easier readability
- Changed trigger action with condition
- Added some more comments
- Fixed sound bug (when 2 recipes are fused faster than "fuse" sound ends, sound would not play)
-------------------------------------------------------

-------------------------------------------------------
Version 2
- Optimized code
-------------------------------------------------------


-------------------------------------------------------
Version 2.1
- Fixed sound bug with desync
-------------------------------------------------------






Why use this recipe system?

It is vJass and GUI, very simple to use (using GUI globals)
You do not use say different functions such as CreateRecipe1,2,3,....
just use global vars instead of rawcodes, it is easier to click directly on icons and then just call recipecreate function.




  • Load Items
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- ----------------------------------------------------------------- --------
      • -------- Item Group 1 --------
      • Set CItemType[1] = Claws of Attack +6
      • Set CItemType[2] = Claws of Attack +9
      • Set CItemType[0] = Claws of Attack +15
      • Set CItemDisassemble = True
      • Custom script: call NewItemGroup()
      • -------- ----------------------------------------------------------------- --------
      • -------- Item Group 2 --------
      • Set CItemType[1] = Circlet of Nobility
      • Set CItemType[2] = Circlet of Nobility
      • Set CItemType[3] = Circlet of Nobility
      • Set CItemType[0] = Crown of Kings +5
      • Set CItemDisassemble = True
      • Custom script: call NewItemGroup()
      • -------- ----------------------------------------------------------------- --------
      • -------- Item Group 3 --------
      • Set CItemType[1] = Mantle of Intelligence +3
      • Set CItemType[2] = Slippers of Agility +3
      • Set CItemType[0] = Hood of Cunning
      • Set CItemDisassemble = True
      • Custom script: call NewItemGroup()
      • -------- ----------------------------------------------------------------- --------
      • -------- Item Group 4 --------
      • Set CItemType[1] = Boots of Quel'Thalas +6
      • Set CItemType[2] = Slippers of Agility +3
      • Set CItemType[0] = Bloodfeather's Heart
      • Set CItemDisassemble = True
      • Custom script: call NewItemGroup()
      • -------- ----------------------------------------------------------------- --------
      • -------- Item Group 5 --------
      • Set CItemType[1] = Claws of Attack +15
      • Set CItemType[2] = Claws of Attack +6
      • Set CItemType[0] = Divine Rapier
      • Set CItemDisassemble = False
      • Custom script: call NewItemGroup()
      • -------- ----------------------------------------------------------------- --------
      • Custom script: call DestroyTrigger( GetTriggeringTrigger() )
  • Item Disassemble
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Disassemble
    • Actions
      • -------- Set the slot from which you want item to be dissasembled --------
      • Set CItemDisassembleSlot = 1
      • -------- The unit which will be casting disassemble ability, in case you have different way of disassembling, --------
      • -------- change that unit variable to mach that unit, for example Circle of Power... --------
      • Set CItemUnit = (Triggering unit)
      • Custom script: call SlotItemDisassemble(udg_CItemUnit, udg_CItemDisassembleSlot)



JASS:
//==========================================================================
//                  Dark Dragon Library Code v1.3
//
//      * Made on Warcraft III v1.30.4
//
//  Installation:
//                  
//                  1) Export instantdummy.mdx from this map and import it to your map, leave path at "war3mapImported/instantdummy.mdx"
//                  2) Copy this trigger to your map, save your map and then change below line "// external ... " or copy "DD Dummy" and paste it in your map
//     3) Copy and paste "Unit Chill" ability from this map to your map
//     4) Match the rawcodes below to your map or use same ones as below
//
// Credits:
//          ('Vexorian' - dummy.mdx)
//============================================================================

// *** Change "// external" to "//! external", save your map, close map, change back from "//!" to "//" and save map again.
// *** This will create dummy in your map
//
// ==================================
// external ObjectMerger w3u ushd dumy uabi "Aloc,Amrf" uble 0 ucbs 0 ucpt 0 umxp 0 umxr 0 umdl "war3mapImported\instantdummy.mdx" ushu "None" umvh 0 umvs 1 umas 1 umis 1 ucol 0 ufoo 0 uhom 1 umpi 10000 umpm 10000 usid 1 usin 1 unam "DD Dummy"
// ==================================


//! zinc

library DDLib requires optional TimerUtils, optional GroupUtils
{
    
    // -----------------------------------------------------------------------
    // -----------------------------------------------------------------------
    // *** Lib constants ***
    public {
        
  // ----------------------------------------------------------------------
  // * Start modify/match rawcodes to your map
        constant        integer     DD_DUMMYCODE       = 'dumy';
        constant        integer     DD_ABILITY_CROWN_FORM     = 'Amrf';
  constant   integer  DD_CHILL     = 'Achl';
  constant   integer  DD_CHILL_BUFF    = 'Bfro';
  // * End modify
  // ----------------------------------------------------------------------
  
  
  constant        integer     p_null             = (0x0);
        constant        real        DD_INTERVAL       = .017;
        
                        // map min and max coords
                        real        DDMinX             = 0.;
                        real        DDMinY             = 0.;
                        real        DDMaxX             = 0.;
                        real        DDMaxY             = 0.;
    }
 
 private {
  constant   integer  HARVEST_ID     = 'Ahrl';
  constant  real  TRIGGER_REFRESH_RATE  = (60.)*3.; /// damage detection trigger
                        
                        unit   TreeChecker              = null;
      trigger  TempTrig      = null;
      integer  NTrig       = 0;
      trigger  DmgTrig[];
      p_real   EnumVec      = p_null;
      boolexpr  EnumFilter      = null;
      sound  ErrorSound     = null;
      timer  GameElapsedTimer   = null;
  constant   integer  RND_INT_MAX_ARRAY_N   = 100;
      integer  RndInt[], RndIntWriteN = 00, RndIntReadN = 00;
      trigger  TrigMouseEvent     = null;
      force   RndGenForce     = null;
      real   RndElapsedTime     = 0.;
 }
    // -----------------------------------------------------------------------
    // -----------------------------------------------------------------------
    // -----------------------------------------------------------------------
    
    // * types
    public {
        
        // *** pointer to list of data ***
        type    p_integer           extends     integer[8];
        type    p_real              extends     real[8];
        type    p_unit              extends     unit[8];
        
  function H2ID(handle h) -> integer {
   return GetHandleId(h) - 0x100000;
  }
  
        function New_pInteger(integer i) -> p_integer
        { p_integer p = p_integer.create(); p[0] = i; return p; }
        function New_pReal(real r) -> p_real
  { p_real p = p_real.create(); p[0] = r; return p; }
        function New_pUnit(unit u) -> p_unit
  { p_unit p = p_unit.create(); p[0] = u; return p; }
        
  function pVector(real x, real y, real z) -> p_real {
   p_real v = p_real.create();
   v[0] = x; v[1] = y; v[2] = z;
   return v;
  }
  
  // --------------------------------------------------------------------------------------
 
  function DDMsg(string str) {
   DisplayTimedTextFromPlayer(GetLocalPlayer(), 0., 0., 30., str);
  }
  
  // --------------------------------------------------------------------------------------
  
  function DisplayErrorMsgPlayer(player p, real dur, string msg) {
   if (GetLocalPlayer() == p) {
    StartSound(ErrorSound);
    DisplayTimedTextFromPlayer(p, 0., 0., dur, "|cffffcc00"+ msg +"|r");
   }
  }

    }
    
    // -----------------------------------------------------------------------
    // ->           ***** private globals *****
    // -----------------------------------------------------------------------
    private {
        location    TempLoc         = Location(0., 0.);
        timer       TimerStack[];
        integer     TimN            = 0;
        group       GroupStack[];
        integer     GrpN            = 0;
        unit        DummyStack[];
        integer     DumN            = 0;
  integer  TimTicks[];
  integer  TimData[];
  timer  TimTim1[];
  timer  TimTim2[];
  
  
  integer  UnitStackData = 0;
  unit  UnitStack[];
  integer  US_N   = 0;
        
        public hashtable   DDHT            = InitHashtable();
    }
    // -----------------------------------------------------------------------
    
   public {
   
        // *** Global funcs
        
        function Pw_2(real x) -> real {
            return x*x;
        }
  
  function DDHypot(real x, real y) -> real {
   return (x*x) + (y*y);
  }
        
        function DDTerrZ(real x, real y) -> real {
            MoveLocation(TempLoc, x, y);
            return GetLocationZ(TempLoc);
        }
        
        function DDWidgetTerrZ(widget w) -> real {
   MoveLocation(TempLoc, GetWidgetX(w), GetWidgetY(w));
            return GetLocationZ(TempLoc);
        }
  
  function DDEffectTerrZ(effect e) -> real {
   MoveLocation(TempLoc, BlzGetLocalSpecialEffectX(e), BlzGetLocalSpecialEffectY(e));
            return GetLocationZ(TempLoc);
  }
  
  function DDGetUnitZ(unit u) -> real {
   return BlzGetUnitZ(u) + GetUnitFlyHeight(u);
  }
        
        // =================================================================
        //              *** Save Handle data ****
        // =================================================================
        
        function DDSet(handle h, integer id, integer val) {
            SaveInteger(DDHT, id+1, GetHandleId(h), val);
        }
        
        function DDGet(handle h, integer id) -> integer {
            return LoadInteger(DDHT, id+1, GetHandleId(h));
        }
  
  function DDHas(handle h, integer id) -> boolean {
   return HaveSavedInteger(DDHT, id+1, GetHandleId(h));
  }
  
  function DDFlush(integer id) {
   FlushChildHashtable(DDHT, id+1);
  }
        
        // =================================================================
        //              *** Timer Handling ****
        // =================================================================
  
  // -> check if timer is recycled
  function DDIsTimRecycled(timer t) -> boolean {
   integer i;
   for(i=TimN-01; i >= 00; i-=01)
    if (TimerStack[i] == t)
     return true;
   return false;
  }
  
        // -> Load timer for recycling
        function DDLoadTim() -> timer {
            static if (LIBRARY_TimerUtils) { return NewTimer(); }
            else {
                if (TimN > 0) {
                    TimN -= 1;
                    return TimerStack[TimN];
                }
                return CreateTimer();
            }
        }
        
        // -> recycle loaded timer
        function DDRecycleTim(timer t) {
            static if (LIBRARY_TimerUtils) { ReleaseTimer(t); }
            else {
    static if (DEBUG_MODE)
     if (DDIsTimRecycled(t)) {
      DDMsg("Multiple recycle of timer!");
      return;
     }
                TimerStack[TimN] = t;
                TimN += 1;
            }
        }
        
        // ** Get data stored on expired timer
        function DDTimData() -> integer {
            return TimData[H2ID(GetExpiredTimer())];
        }
  
  // *** Custom timer tick
        function DDCTimTick(timer t) -> integer {
            return TimTicks[H2ID(t)];
        }
  
  // *** Gets current tick and adds next one ***
        function DDTimTick() -> integer {
   integer id = H2ID(GetExpiredTimer());
   TimTicks[id] += 01;
            return TimTicks[id];
        }
        
        // ** start timer with data storage
        function DDStartTim(real secs, boolean looping, integer pdata, code func) -> timer {
            timer t = DDLoadTim();
   
   TimData[H2ID(t)] = pdata;
            TimerStart(t, secs, looping, func);
            return t;
        }
        
        // ** start timer with data storage, and launches it instantly
        function DDStartTimInst(real secs, boolean looping, integer pdata, code func) -> timer {
            timer t1 = DDLoadTim(), t2 = DDLoadTim(), t3 = DDLoadTim();
            
   TimData[H2ID(t2)] = pdata;
            TimerStart(t2, 0., false, func);
   
   TimTim1[H2ID(t3)] = t1;
   TimTim2[H2ID(t3)] = t2;
   TimerStart(t3, .005, false, function() {
    timer t = GetExpiredTimer();
    integer id = H2ID(t);
    
    PauseTimer(t);
    static if (LIBRARY_TimerUtils)
     ReleaseTimer(t);
    else {
     TimerStack[TimN] = t;
     TimN += 1;
    }
    
    t = TimTim2[id];
    if (DDIsTimRecycled(t))
     t = TimTim1[id];
    TimTicks[H2ID(t)] = 00;
    PauseTimer(t);
    static if (LIBRARY_TimerUtils)
     ReleaseTimer(t);
    else {
     TimerStack[TimN] = t;
     TimN += 1;
    }
   });
   
   TimData[H2ID(t1)] = pdata;
            TimerStart(t1, secs, looping, func);
            
            return t1;
        }
        
        // *** Quit expired timer ***
        function DDQuitTim() {
   timer t = GetExpiredTimer();
   TimTicks[H2ID(t)] = 00;
            PauseTimer(t);
   static if (LIBRARY_TimerUtils)
    ReleaseTimer(t);
            else {
                TimerStack[TimN] = t;
                TimN += 1;
            }
        }
  
  function DDQuitTimEx(timer t) {
   TimTicks[H2ID(t)] = 00;
            PauseTimer(t);
   static if (LIBRARY_TimerUtils)
    ReleaseTimer(t);
            else {
                TimerStack[TimN] = t;
                TimN += 1;
            }
        }
        
        // =================================================================
        //              *** Group Handling ****
        // =================================================================
        
        // -> Load timer for recycling
        function DDLoadGroup() -> group {
            static if (LIBRARY_GroupUtils) { return NewGroup(); }
            else {
                if (GrpN > 0) {
                    GrpN -= 1;
                    return GroupStack[GrpN];
                }
                return CreateGroup();
            }
        }
        
        // -> Recycle group
        function DDRecycleGroup(group g) {
            static if (LIBRARY_GroupUtils) { ReleaseGroup(g); }
            else {
    GroupClear(g);
                GroupStack[GrpN] = g;
                GrpN += 1;
            }
        }
        
        // --------------------------------------------------------
        // -- Quick filter area
  private integer GroupFilterData = 00;
  
        function DDGroupFilterArea(real x, real y, real radius, integer data, code func) {
            group g = DDLoadGroup();
   GroupFilterData = data;
            GroupEnumUnitsInRange(g, x, y, radius, Filter(func));
            DDRecycleGroup(g);
        }
        
        // --------------------------------------------------------
        // -- Quick filter rect
        function DDGroupFilterRect(rect r, integer data, code func) {
            group g = DDLoadGroup();
   GroupFilterData = data;
            GroupEnumUnitsInRect(g, r, Filter(func));
            DDRecycleGroup(g);
        }
        
  function DDGFilterData() -> integer {
   return GroupFilterData;
  }
  
  function DDGFilterDataSet(integer data) {
   GroupFilterData = data;
  }
  
  // --------------------------------------------------------
        // *** Filtrates and fills units in to memory
        function DDGroupFillMemArea(real x, real y, real radius, integer data, code filter) {
   group g = DDLoadGroup();
   boolexpr exp = And(Filter(filter), Filter(function() -> boolean {
    UnitStack[US_N] = GetFilterUnit();
    US_N += 1;
    return false;
   }));
   US_N = 0;
   UnitStack[0] = null;
   UnitStackData = data;
   GroupEnumUnitsInRange(g, x, y, radius, exp);
   DDRecycleGroup(g);
   DestroyBoolExpr(exp);
   exp = null;
  }
  
  function DDGroupFillMemRect(rect r, integer data, code filter) {
   group g = DDLoadGroup();
   boolexpr exp = And(Filter(filter), Filter(function() -> boolean {
    UnitStack[US_N] = GetFilterUnit();
    US_N += 1;
    return false;
   }));
   US_N = 0;
   UnitStack[0] = null;
   UnitStackData = data;
   GroupEnumUnitsInRect(g, r, exp);
   DDRecycleGroup(g);
   DestroyBoolExpr(exp);
   exp = null;
  }
  
  function DDMemUnitN() -> integer { return US_N; }
  function DDMemUnitData() -> integer { return UnitStackData; }
  
  function DDMemUnit(integer index) -> unit {
   if (US_N == 0) return null;
   debug {
    if (index < 0) {
     BJDebugMsg("DDMemUnit: index less than 0");
     index = 0;
    } else if (index >= US_N) {
     BJDebugMsg("DDMemUnit: index greater than units alloc size");
     index = 0;
    }
   }
   return UnitStack[index];
  }
  // --------------------------------------------------------
  
  // --------------------------------------------------------
  // *** 
        
        // =================================================================
        //              *** Dummy Handling ****
        // =================================================================
        
        // -> Load dummy for recycling
        function DDLoadDummy() -> unit {
            if (DumN > 0) {
                DumN -= 1;
                PauseUnit(DummyStack[DumN], false);
                return DummyStack[DumN];
            }
            return CreateUnit(Player(0xF), DD_DUMMYCODE, DDMaxX, DDMaxY, 0.);
        }
        
        // *** prepares/setups dummy for spell casting
        function DDLoadSpellDummy(player owner, real x, real y, integer abil, integer abilLevel) -> unit {
            unit dummy = DDLoadDummy();
            SetUnitOwner(dummy, owner, false);
            SetUnitX(dummy, x);
            SetUnitY(dummy, y);
            if (abil != p_null) {
                UnitAddAbility(dummy, abil);
                SetUnitAbilityLevel(dummy, abil, abilLevel);
            }
            return dummy;
        }
        
        // -> Recycle dummy
        function DDRecycleDummy(unit u) {
            PauseUnit(u, true);
            DummyStack[DumN] = u;
            DumN += 1;
        }
        
        // -> Recycle dummy timed
        function DDRecycleDummyTimed(unit u, real secs) {
            DDStartTim(secs, false, New_pUnit(u), function() {
                DDRecycleDummy(p_unit(DDTimData())[0]);
                p_unit(DDTimData()).destroy();
                DDQuitTim();
            });
        }
        
        // *** shares vision for timed amount, usually for dummy casting
        function DDUnitShareVisionTimed(unit u, player toP, real secs) {
            p_integer pi = p_integer.create();
            
            pi[0] = New_pUnit(u);
            pi[1] = GetPlayerId(toP);
            UnitShareVision(u, toP, true);
            DDStartTim(secs, false, pi, function() {
                p_integer pi = DDTimData();
                
                UnitShareVision(p_unit(pi[0])[0], Player(pi[1]), false);
                p_unit(pi[0])[0] = null;
                p_unit(pi[0]).destroy();
                pi.destroy();
                DDQuitTim();
            });
            
        }
  
        // *** Remove ability timed ***
        private struct uratimed {
            private {
                unit u;
                integer abil;
            }
            
            static method create(unit whichUnit, integer id, real time) -> uratimed {
                thistype this = allocate();
                
                u = whichUnit;
                abil = id;
                DDStartTim(time, false, this, function() {
                    thistype this = DDTimData();
                    UnitRemoveAbility(u, abil);
                    DDQuitTim();
                    deallocate();
                });
                
                return 0;
            }
        }
        function DDRemoveAbilityTimed(unit u, integer abil, real secs) { uratimed.create(u, abil, secs); }
        
  function DDSpellDamage(unit u, unit v, real dmg) {
   real life = GetWidgetLife(v);
   real dmgfactor = 1.;
   
   if (IsUnitType(v, UNIT_TYPE_HERO)) {
    if (UnitHasItemOfTypeBJ(v, 'brac'))
     dmgfactor = .5;
    else
     dmgfactor = .75;
   }
   
   if (life > dmg*dmgfactor) {
    SetWidgetLife(v, life-(dmg*dmgfactor));
   } else
    UnitDamageTarget(u, v, 99999., false, true, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS);
  }
  
  // -------------------------------------------------------------------------------------
  // *** Chills target unit
  private struct chill {
   unit u, dmy;
   real dur;
   
   static chill Data[];
   //static key CHILL_KEY;
  }
  
  function DDUnitChill(player p, unit u, real dur) -> boolean {
   //chill c = DDGet(u, chill.CHILL_KEY);
   chill c = chill.Data[H2ID(u)];
   unit d;
   real rad;
   
   
   if (c == p_null) {
    c = chill.create();
    c.u = u; c.dur = dur;
    chill.Data[H2ID(u)] = c;
    //DDSet(u, chill.CHILL_KEY, c);
    
    d = DDLoadDummy();
    c.dmy = d;
    rad = GetUnitFacing(d) * bj_DEGTORAD;
    SetUnitOwner(d, p, false);
    UnitAddAbility(d, DD_CHILL);
    SetUnitX(d, GetUnitX(u) - 20.*Cos(rad));
    SetUnitY(d, GetUnitY(u) - 20.*Sin(rad));
    
    if (IssueTargetOrder(d, "frostnova", u)) {
     DDStartTim(.1, true, c, function() {
      chill c = DDTimData();
      
      c.dur -= .1;
      if (c.dur <= 0. || GetUnitAbilityLevel(c.u, DD_CHILL_BUFF) == 00) {
       UnitRemoveAbility(c.u, DD_CHILL_BUFF);
       UnitRemoveAbility(c.dmy, DD_CHILL);
       DDRecycleDummy(c.dmy);
       chill.Data[H2ID(c.u)] = p_null;
       //DDSet(c.u, chill.CHILL_KEY, p_null);
       c.u = null;
       c.destroy();
       DDQuitTim();
      }
     });
     return true;
    }
    
    return false;
   }
   
   c.dur = dur;
   
   return true;
  }
  
  // ------------------------------------------------------------------------------------------------
  
  struct fade {
   unit u;
   real trans;
   real rate, e_trans, dur;
   
   static constant real INTERVAL = .1;
   
   static method create(unit u, real dur, real s_trans, real e_trans) -> fade {
    fade this = allocate();
    
    this.u = u;
    this.trans = s_trans;
    this.rate = ((e_trans-s_trans)/dur)*fade.INTERVAL;
    this.e_trans = e_trans;
    this.dur = dur;
    
    return this;
   }
  }
  
  // *** Fades unit over time ***
  public function DDFadeUnit(unit u, integer from_alpha, integer to_alpha, real duration) {
   fade f = fade.create(u,
         duration,
         from_alpha/2.55,
         to_alpha/2.55);
   
   SetUnitVertexColor(u, 255, 255, 255, from_alpha);
   // --- Start thread ---
   DDStartTim(fade.INTERVAL, true, f, function() {
    fade f = DDTimData();
    
    f.trans += f.rate;
    f.dur -= fade.INTERVAL;
    SetUnitVertexColor(f.u, 255, 255, 255, R2I(f.trans*2.55));
    
    if (f.dur < 0.) {
     SetUnitVertexColor(f.u, 255, 255, 255, R2I(f.e_trans*2.55));
     f.u = null;
     f.destroy();
     DDQuitTim();
    }
   });
        
  }
  
  // ------------------------------------------------------------------------------------------------
  
        // Check if unit is invulnerable
        function DDIsUnitInvulnerable(unit u) -> boolean {
            unit d = DDLoadDummy();
            real hp = GetWidgetLife(u);
            boolean flag;
            
            UnitDamageTarget(d, u, 1., true, false, null, null, null);
            flag = GetWidgetLife(u) == hp;
            SetWidgetLife(u, hp);
            DDRecycleDummy(d);
            
            return flag;
        }
        
        // *** check if unit is ward
        function DDIsUnitWard(unit whichUnit) -> boolean {
            return GetUnitDefaultMoveSpeed(whichUnit) == 0.;
        }
  
        // =================================================================
        //              *** Effect Handling ****
        // =================================================================
        
        // -----------------------------------------------
        // *** Define movable effect
        struct ddeffect {
            private {
                effect e;
                real fac; // facing angle in radians
                real effZ; // pitch in radians
                real decay;
    real stepTrans, cTrans, eTrans;
                
                static constant real        EFFECT_DECAY        = 5.;
            }
            
            // =========================================================================================
            // =========================================================================================
            static method create(string mdl, real x, real y, real facRad, real size) -> ddeffect {
                ddeffect this = allocate();
                
                this.e   = AddSpecialEffect(mdl, x, y);
    this.fac  = facRad;
    this.effZ = 0.;
                BlzSetSpecialEffectRoll(this.e, facRad);
    BlzSetSpecialEffectScale(this.e, size);
                
                return this;
            }
   
   static method createZ(string mdl, real x, real y, real z, real facRad, real size) -> ddeffect {
                ddeffect this = allocate();
                
                this.e   = AddSpecialEffect(mdl, x, y);
    this.fac  = facRad;
    this.effZ = z-DDTerrZ(x, y);
                BlzSetSpecialEffectRoll(this.e, facRad);
    BlzSetSpecialEffectScale(this.e, size);
    BlzSetSpecialEffectZ(this.e, z);
                
                return this;
            }
            
            // -----------------
            method destroy() {
                DestroyEffect(this.e);
                this.e = null;
                deallocate();
            }
            
            // *** destroys effect timed
            method destroyx(real decayTime) {
                DDStartTim(decayTime, false, this, function() {
     ddeffect se = DDTimData();
     BlzSetSpecialEffectPosition(se.e, DDMaxX, DDMaxY, 0.);
                    DestroyEffect(se.e);
     se.e = null;
     se.deallocate();
                    DDQuitTim();
                });
            }
            // =========================================================================================
            // =========================================================================================
            
   
            
   method operator Z=(real z)     { BlzSetSpecialEffectZ(this.e, z); }
   
            method operator X() -> real                 { return BlzGetLocalSpecialEffectX(this.e); }
            method operator Y() -> real                 { return BlzGetLocalSpecialEffectY(this.e); }
            method operator Z() -> real                 { return BlzGetLocalSpecialEffectZ(this.e); }
            method operator WZ() -> real                { return DDEffectTerrZ(this.e); }
            method operator Height() -> real            { return this.Z-this.WZ; }
            
            method operator Facing=(real facRad)        { BlzSetSpecialEffectRoll(this.e, facRad); this.fac = facRad; }
            method operator Facing() -> real            { return this.fac; }
   
   method Position(real x, real y)    { BlzSetSpecialEffectPosition(this.e, x, y, this.effZ+this.WZ); }
   method PositionZ(real x, real y, real z) { BlzSetSpecialEffectPosition(this.e, x, y, z); }
   method Animation(animtype at)    { BlzPlaySpecialEffect(this.e, at); }
   method AnimationSpeed(real animSpeed)  { BlzSetSpecialEffectTimeScale(this.e, animSpeed/100.); }
   
   //method operator Pitch=(integer pitch)  { SetUnitAnimationByIndex(u, pitch); }
            
            //method Face(widget w) { Facing = Atan2(GetWidgetY(w)-Y, GetWidgetX(w)-X)*bj_RADTODEG; }
   
   method Fade(real startTransparency, real endTransparency, real duration) {
    this.cTrans = startTransparency;
    this.eTrans = endTransparency;
    this.stepTrans = .1*(endTransparency-startTransparency) / duration;
    
    BlzSetSpecialEffectAlpha(this.e, R2I(startTransparency*2.55));
    
    DDStartTim(.1, true, this, function() {
     ddeffect dde = DDTimData();
     
     dde.cTrans += dde.stepTrans;
     if (dde.stepTrans > 0.)
      if (dde.cTrans >= dde.eTrans) {
       BlzSetSpecialEffectAlpha(dde.e, R2I(dde.eTrans*2.55));
       DDQuitTim();
       return;
      }
     else
      if (dde.cTrans <= dde.eTrans) {
       BlzSetSpecialEffectAlpha(dde.e, R2I(dde.eTrans*2.55));
       DDQuitTim();
       return;
      }
     BlzSetSpecialEffectAlpha(dde.e, R2I(dde.cTrans*2.55));
    });
   }
   
        }
        
  private type timedeffect extends effect[01];
  
  function DDDestroyEffectTimed(effect e, real secs) {
   timedeffect te = timedeffect.create();
   te[00] = e;
   DDStartTim(secs, true, te, function() {
    timedeffect te = DDTimData();
    DestroyEffect(te[00]);
    te.destroy();
    DDQuitTim();
   });
  }
    }
 
 // ----------------------------------------------------------------------------
    // *** Main damage detection function, registers any damage dealt to units ***
    public function DDTriggerRegisterAnyUnitDamaged(trigger t) {
        DmgTrig[NTrig] = t;
        NTrig += 1;
    }
    
    function InitDamageDetection() {
  code c = function() {
   if (TempTrig != null)
    DestroyTrigger(TempTrig);
   
   TempTrig = CreateTrigger();
   TriggerRegisterEnterRectSimple(TempTrig, bj_mapInitialPlayableArea);
   TriggerAddCondition(TempTrig, function() -> boolean {
    integer i;
    
    // *** Check if we need to exec triggers or register an unit ***
    if (GetTriggerEventId() == EVENT_UNIT_DAMAGED) {
     for(i=0; i < NTrig; i+=1)
      if (IsTriggerEnabled(DmgTrig[i]))
       if (TriggerEvaluate(DmgTrig[i]))
        TriggerExecute(DmgTrig[i]);
    }
    else
     // *** Register new unit ***
     TriggerRegisterUnitEvent(GetTriggeringTrigger(),
            GetTriggerUnit(),
            EVENT_UNIT_DAMAGED);
    
    return false;
   });
   
   DDGroupFilterRect(bj_mapInitialPlayableArea, 00, function() -> boolean {
    TriggerRegisterUnitEvent(TempTrig, GetFilterUnit(), EVENT_UNIT_DAMAGED);
    return false;
   });
  };
  trigger t = CreateTrigger();
  
  TriggerAddAction(t, c);
  TriggerExecute(t);
  DestroyTrigger(t);
  TimerStart(CreateTimer(), TRIGGER_REFRESH_RATE, true, c);
  t = null;
    }
 
 // ---------------------------------------------------------------------------------
 
 // *** Main enum dests in range function ***
    public function DDEnumDestsInRange(p_real vec, real radius, boolexpr filter, code pfunc) {
        rect r = Rect(vec[0]-radius, vec[1]-radius, vec[0]+radius, vec[1]+radius);
  
   EnumVec[0] = vec[0];
   EnumVec[1] = vec[1];
   EnumVec[2] = radius;
            
        if (filter != null) filter = And(EnumFilter, filter);
        else filter = EnumFilter;
        EnumDestructablesInRect(r, filter, pfunc);
  
        if (filter != EnumFilter) { DestroyBoolExpr(filter); filter = null; }
  RemoveRect(r);
  r = null;
    }
        
    function InitEnumDests() {
        EnumVec = p_real.create();
        EnumFilter = Filter(function() -> boolean {
            return Pw_2(EnumVec[0]-GetDestructableX(GetFilterDestructable())) + Pw_2(EnumVec[1]-GetDestructableY(GetFilterDestructable())) < Pw_2(EnumVec[2]);
        });
    }
    
 // --------------------------------------------------------------------------------------
 
 // *** checks is destruct tree ***
    public function DDIsDestructableTree(destructable d) -> boolean {
        if (d != null) {
            PauseUnit(TreeChecker, false);
            if (IssueTargetOrder(TreeChecker, "harvest", d)) {
                PauseUnit(TreeChecker, true);
                return true;
            }
            PauseUnit(TreeChecker, true);
        }
        return false;
    }

    function InitDestTreeCheck() {
        TreeChecker = CreateUnit(Player(bj_PLAYER_NEUTRAL_EXTRA), DD_DUMMYCODE, DDMaxX, DDMaxY, 0.);
        UnitAddAbility(TreeChecker, HARVEST_ID);
        PauseUnit(TreeChecker, true);
    }
 
 // --------------------------------------------------------------------------------------
    
 public function DDNewTextTagUnit(unit whichUnit, string text, real dur, real red, real green, real blue, real transparency) {
  CreateTextTagUnitBJ( text, whichUnit, 0., 11.00, red, green, blue, transparency );
  SetTextTagPermanentBJ( bj_lastCreatedTextTag, false );
  SetTextTagVelocityBJ( bj_lastCreatedTextTag, 48.00, 90 );
  SetTextTagFadepointBJ( bj_lastCreatedTextTag, dur-1.25 );
  SetTextTagLifespanBJ( bj_lastCreatedTextTag, dur );
 }
 
 // --------------------------------------------------------------------------------------
 
 struct cameranoisedata {
  player p[12];
  integer n=00;
 }
 
 public function DDCameraSetSourceNoiseForPlayers(real x, real y, real mag, real vel, real maxDist, real duration) {
  integer i;
  real d;
  cameranoisedata cnd = cameranoisedata.create();
  
  for (i=00; i < bj_MAX_PLAYERS; i+=01) {
   if (GetLocalPlayer() == Player(i)) {
    d = SquareRoot( Pw_2(GetCameraTargetPositionX()-x) + Pw_2(GetCameraTargetPositionY()-y) );
    if (d < maxDist) {
     cnd.p[cnd.n] = Player(i);
     CameraSetSourceNoise(mag-(d*(mag/maxDist)), vel-(d*(vel/maxDist)));
     CameraSetTargetNoise(mag-(d*(mag/maxDist)), vel-(d*(vel/maxDist)));
     cnd.n += 01;
    }
   }
  }
  
  DDStartTim(duration, false, cnd, function() {
   cameranoisedata cnd = DDTimData();
   
   while(cnd.n != 00) {
    cnd.n -= 01;
    if (GetLocalPlayer() == cnd.p[cnd.n])
     CameraSetSourceNoise(0., 0.);
     CameraSetTargetNoise(0., 0.);
   }
   
   cnd.destroy();
   DDQuitTim();
  });
 }
 
 // --------------------------------------------------------------------------------------
    
 hashtable GenSndTable = null;
 
    public function DDGenericSound(string file, real vol, real x, real y, real mxDist, real pitch) {
  integer sh = StringHash(file),
    snd_n = LoadInteger(GenSndTable, sh, 04);
  sound s = LoadSoundHandle(GenSndTable, sh, snd_n);
  real d;
  integer i;
        
  if (s == null) {
   s = CreateSound(file, false, false, false, 10, 10, "");
   SaveSoundHandle(GenSndTable, sh, snd_n, s);
  } else if (GetSoundIsPlaying(s)) {
   StopSound(s, false, false);
  }
  SetSoundPitch(s, pitch);
  snd_n += 01;
  if (snd_n == 04)
   snd_n = 00;
  SaveInteger(GenSndTable, sh, 04, snd_n);
  
  // Play sound and shake camera for players within spell cast range
  for (i=00; i < bj_MAX_PLAYERS; i+=01) {
   if (GetLocalPlayer() == Player(i)) {
    d = SquareRoot( DDHypot(GetCameraTargetPositionX()-x, GetCameraTargetPositionY()-y) );
    if (d < mxDist) {
     SetSoundVolume(s, R2I((vol-d*(vol/mxDist))*1.27));
     StartSound(s);
    }
   }
  }
    }
 
 public function DDGetGameElapsedTime() -> real {
  return TimerGetElapsed(GameElapsedTimer);
 }
 
 public function DDGetRndReal(real min, real max) -> real {
  real rnd = ((max-min)/1000000.)*I2R(RndInt[RndIntReadN]);
  debug if (max > 1000000.)
   DDMsg("ERROR: \"DDGetRndNumber\" - 'max' variable is greater than 1000000!");
  RndIntReadN += 01; if (RndIntReadN == RND_INT_MAX_ARRAY_N) RndIntReadN = 00;
  return min + rnd;
 }
 
 public function DDGetRndInt(integer min, integer max) -> integer {
  return R2I( DDGetRndReal(I2R(min), I2R(max)) );
 }
 
 // ====================================================================
    function onInit() {
  InitDamageDetection();
  InitDestTreeCheck();
  InitEnumDests();
  
        DDMinX = GetRectMinX(bj_mapInitialPlayableArea);
        DDMinY = GetRectMinY(bj_mapInitialPlayableArea);
        DDMaxX = GetRectMaxX(bj_mapInitialPlayableArea);
        DDMaxY = GetRectMaxY(bj_mapInitialPlayableArea);
  
  GenSndTable = InitHashtable();
  
  ErrorSound = CreateSound( "Sound\\Interface\\Error.wav", false, false, false, 10, 10, "" );
  SetSoundParamsFromLabel( ErrorSound, "InterfaceError" );
  SetSoundDuration( ErrorSound, 614 );
  SetSoundVolume(ErrorSound, 127);
  
  GameElapsedTimer = CreateTimer();
  TimerStart(GameElapsedTimer, 10800., false, null);
  
  for(RndIntWriteN=00; RndIntWriteN < RND_INT_MAX_ARRAY_N; RndIntWriteN+=01)
   RndInt[RndIntWriteN] = GetRandomInt(00, 1000000);
  
  RndIntWriteN = 00;
  RndGenForce = CreateForce();
  TrigMouseEvent = CreateTrigger();
  ForForce(bj_FORCE_ALL_PLAYERS, function() {
   if (GetPlayerController(GetEnumPlayer()) == MAP_CONTROL_USER)
    TriggerRegisterPlayerEvent(TrigMouseEvent, GetEnumPlayer(), EVENT_PLAYER_MOUSE_MOVE);
  });
  TriggerAddCondition(TrigMouseEvent, Condition(function() -> boolean {
   real mouseN;
   boolean xFirst = GetRandomInt(00, 01) == 01;
   
   if (!IsPlayerInForce(GetTriggerPlayer(), RndGenForce)) {
    // example: input x = 578.4571496
    //   output rnd n = 4571498
    if (xFirst)
     mouseN = RAbsBJ(BlzGetTriggerPlayerMouseX()) * 100.;
    else
     mouseN = RAbsBJ(BlzGetTriggerPlayerMouseY()) * 100.;
    if (mouseN == 0.)
     return false;
    //mouseN *= 100.;
    RndInt[RndIntWriteN] = R2I((mouseN - I2R(R2I(mouseN))) * 1000.);
    //DDMsg(I2S(RndInt[RndIntWriteN]));
    //RndIntWriteN += 01; if (RndIntWriteN == RND_INT_MAX_ARRAY_N) RndIntWriteN = 00;
    
    if (xFirst)
     mouseN = RAbsBJ(BlzGetTriggerPlayerMouseY()) * 100.;
    else
     mouseN = RAbsBJ(BlzGetTriggerPlayerMouseX()) * 100.;
    RndInt[RndIntWriteN] += R2I((mouseN - I2R(R2I(mouseN))) * 1000.)*1000;
    //DDMsg(I2S(RndInt[RndIntWriteN]));
    RndIntWriteN += 01; if (RndIntWriteN == RND_INT_MAX_ARRAY_N) RndIntWriteN = 00;
    ForceAddPlayer(RndGenForce, GetTriggerPlayer());
   }
   
   if (DDGetGameElapsedTime()-RndElapsedTime > .125) {
    ForceClear(RndGenForce);
    RndElapsedTime = DDGetGameElapsedTime();
   }
   
   return false;
  }));
    }
    
}

//! endzinc


JASS:
//TESH.scrollpos=0
//TESH.alwaysfold=0
// ===============================================================================
//                  * System: Item Combine v2
//
// * Installation:
// 
// 1) Copy "DD Library" "Load Items", "Item Disassemble" and "Item Combine Core" triggers to your map
//  note: dummy unit and other stuff for "DD Library" trigger is not in this map because this system does not need dummies...
// 2) Copy ability "Disassemble" and paste it in your map, unless you use different method of item disassemble
// 3) Export and import "ItemFuse.mdx", "Item_Disassembly.wav" and "Item_Disassemble.mdx" to your map
//    Import path: Same as in this map
//    If you want to change path or use different effect, change that below
// 4) Make your own recipes in "Load Items" trigger
// 5) Enjoy!
//
// Credits: Magos, Audacity team, Notepad++ team, Vexorian, Blizzard
// ===============================================================================

//! zinc
library DDItemCombineBasic requires DDLib
{

    // -------------------------------------------------------
    // *** Edit to your own will ***
        
    // * This is effect that will be displayed when items combine/disassemble and attachment point
 constant string         ITEM_COMBINE_EFFECT         = "Custom\\Models\\ItemFuse.mdx"; //"Abilities\\Spells\\Items\\AIlm\\AIlmTarget.mdl"
 constant string   ITEM_DISASSAMBLE_EFFECT  = "Custom\\Models\\Item_Disassemble.mdx";
 constant string         ATTACH_POINT          = "origin";
        
    // * If you want to use custom sound, setup it below
    // * "Sound path", "time in second to play sound after combine is done", "volume" and "pitch" of sound
    constant boolean        USE_CUSTOM_SOUND            = true;
 constant real           SOUND_MAX_DISTANCE          = 3500.;
    constant string         SOUND_FILE            = "Abilities\\Spells\\Orc\\MirrorImage\\MirrorImage.wav";
    constant real           SOUND_VOL                   = 90.;
    constant real           SOUND_PITCH                 = 1.2;
    
  
 // * This is disassemble sound
 constant string         SOUND_FILE_2            = "Custom\\Sounds\\Item_Disassembly.wav";
 constant real           SOUND_VOL_2                 = 90.;
 constant real           SOUND_PITCH_2               = 1.;
    // *** End edit ***
    // -------------------------------------------------------
    
    //private keyword Table
    // ===========================================================================
    // ===========================================================================
    sound               ItemCombineSound        = null;
 sound    ItemDisassembleSound = null;
    integer          CType[];
 boolean      CTypeDisassemble[];
 integer             ItemN                   = 0;
 
    // ===========================================================================
    
 // -----------------------------------------------------------------------
 // ** Items in CItemType from 1-6 are user items that we need to shift to next memory locations, that is why for this recipe system
 //    slots lower than 6 are not used, we store items in higher slots
    public function NewItemGroup() {
        integer i = ItemN*bj_MAX_INVENTORY + 07;
        integer h = 01;
  
  if (bj_gameStarted || udg_CItemType[00] == 00)
   return;
  
        while(h != 07) {
            udg_CItemType[i] = udg_CItemType[h];
            udg_CItemType[h] = 00;
            h += 01;
            i += 01;
        }
        CType[ItemN] = udg_CItemType[00];
  CTypeDisassemble[ItemN] = udg_CItemDisassemble;
        udg_CItemType[00] = 00;
  ItemN += 01;
  //udg_CItemDisassemble = false;
    }
    
 // -----------------------------------------------------------------------
 // ** Primary public function for item disassemble
    public function SlotItemDisassemble(unit u, integer slot) {
  item it = UnitItemInSlot(u, slot-01);
  integer it_id = GetItemTypeId(it);
  real x = GetUnitX(u);
  real y = GetUnitY(u);
  
  // *** is slot empty? ***
  if (it != null) {
   // *** search for registerd item recipe ***
   for(slot=00; slot < ItemN; slot+=01) {
    // *** found the item ***
    if (CType[slot] == it_id) {
     // *** Check if allow disassemble by user? ***
     if (!CTypeDisassemble[slot]) {
      // *** Disassembly not allowed, but null the item
      it = null;
      return;
     }
     
     // *** Do remove and creation jobs ***
     RemoveItem(it);
     slot = slot*bj_MAX_INVENTORY + 07; // get to first item id of this recipe
     while(udg_CItemType[slot] != 00) {
      CreateItem(udg_CItemType[slot], x, y);
      slot += 01;
     }
     
     // -------------------------------------------------------------------------------------
     // *** play custom sound and effect ***
     // *** If items are disassembled too fast, sound might be playing, so first we have to stop it
     DDGenericSound(SOUND_FILE_2, SOUND_VOL_2, x, y, SOUND_MAX_DISTANCE, SOUND_PITCH_2);
     DestroyEffect( AddSpecialEffectTarget(ITEM_DISASSAMBLE_EFFECT, u, ATTACH_POINT) );
     // *** Item is removed, now null
     it = null;
     return;
    }
   }
   // *** invalid item, do null anyway ***
   it = null;
  }
 }
 
 // ====================================================================================

    function UnitRemoveItemById(unit whichUnit, integer itemId) {
        integer i = 00;
        item it;
        
        for(i=00; i < bj_MAX_INVENTORY; i+=01) {
            it = UnitItemInSlot(whichUnit, i);
            if (GetItemTypeId(it) == itemId) {
                RemoveItem(it);
                break;
            }
        }
        it = null;
    }

    //===========================================================================
    function onInit() {
        trigger t = CreateTrigger();
        TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_PICKUP_ITEM);
        TriggerAddCondition(t, function() -> boolean {
   unit  u = GetTriggerUnit();
   integer it[];
   integer n, i = 07;
   integer h;
   integer x, y, z;
   
   boolean b = true;
   integer hero_item_type[];
   
   static if (USE_CUSTOM_SOUND)
    timer t;

   // Get hero items
   for(x=00; x < bj_MAX_INVENTORY; x+=01)
    hero_item_type[x] = GetItemTypeId(UnitItemInSlot(u, x));

   for(n=00; n < ItemN; n+=01) {
    h = i + bj_MAX_INVENTORY;
    
    x = 00;
    it[x] = hero_item_type[x]; x = 01;
    it[x] = hero_item_type[x]; x = 02;
    it[x] = hero_item_type[x]; x = 03;
    it[x] = hero_item_type[x]; x = 04;
    it[x] = hero_item_type[x]; x = 05;
    it[x] = hero_item_type[x]; x = 06;
    
    //y = 00; // N of items that hero has ()
    //z = 00; // N of items needed ()
    for(y=00, z=00; i < h; i+=01) {
     if (udg_CItemType[i] == 0)
      break;
     
     z += 01;
     // Does unit contain item n
     for(x=00; x < bj_MAX_INVENTORY; x+=01) {
      if (it[x] == udg_CItemType[i]) {
       // Kick out the item
       it[x] = 00;
       y += 01;
       // And increase by 1
       break;
      }
     }
    }
    
    i = h;
    
    if (y == z) {
     i -= bj_MAX_INVENTORY;
     while(i <= h && udg_CItemType[i] != 00) {
      UnitRemoveItemById(u, udg_CItemType[i]);
      i += 01;
     }
     UnitAddItemById(u, CType[n]);
     
     static if (USE_CUSTOM_SOUND)
      DDGenericSound(SOUND_FILE, SOUND_VOL, GetWidgetX(u), GetWidgetY(u), SOUND_MAX_DISTANCE, SOUND_PITCH);
     DestroyEffect(AddSpecialEffectTarget(ITEM_COMBINE_EFFECT, u, ATTACH_POINT));
     u = null;
     return false;
    }
   }
   
   u = null;
   return false;
  });

    }

}
//! endzinc

[/B]

[B]


If you have any more questions, please ask in comments.
Enjoy!

~Dark Dragon



Keywords:
System, recipe, items, combine
Contents

System - Recipe/Disassemble v2.1 (Map)

Reviews
12:37, 3st Feb 2016 BPower: Criticism: The code is short and does exacly what it was made for. Good job. In my opinion the sound files fit to the mechanics. Approved as good alternative to Diablo-dk's recipe system.

Moderator

M

Moderator

12:37, 3st Feb 2016
BPower:

Criticism:

The code is short and does exacly what it was made for. Good job.
In my opinion the sound files fit to the mechanics.

Approved as good alternative to Diablo-dk's recipe system.
 
Level 15
Joined
Jul 19, 2007
Messages
618
Hi, here you go:


  • Load Items
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- ----------------------------------------------------------------- --------
      • -------- Item Group 1 --------
      • Set CItemType[1] = Claws of Attack +6
      • Set CItemType[2] = Claws of Attack +9
      • Set CItemType[0] = Claws of Attack +15
      • Set CItemDisassemble = True
      • Custom script: call NewItemGroup()
      • -------- ----------------------------------------------------------------- --------
      • -------- Item Group 2 --------
      • Set CItemType[1] = Circlet of Nobility
      • Set CItemType[2] = Circlet of Nobility
      • Set CItemType[3] = Circlet of Nobility
      • Set CItemType[0] = Crown of Kings +5
      • Set CItemDisassemble = True
      • Custom script: call NewItemGroup()
      • -------- ----------------------------------------------------------------- --------
      • -------- Item Group 3 --------
      • Set CItemType[1] = Mantle of Intelligence +3
      • Set CItemType[2] = Slippers of Agility +3
      • Set CItemType[0] = Hood of Cunning
      • Set CItemDisassemble = True
      • Custom script: call NewItemGroup()
      • -------- ----------------------------------------------------------------- --------
      • -------- Item Group 4 --------
      • Set CItemType[1] = Boots of Quel'Thalas +6
      • Set CItemType[2] = Slippers of Agility +3
      • Set CItemType[0] = Bloodfeather's Heart
      • Set CItemDisassemble = True
      • Custom script: call NewItemGroup()
      • -------- ----------------------------------------------------------------- --------
      • -------- Item Group 5 --------
      • Set CItemType[1] = Claws of Attack +15
      • Set CItemType[2] = Claws of Attack +6
      • Set CItemType[0] = Divine Rapier
      • Set CItemDisassemble = False
      • Custom script: call NewItemGroup()
      • -------- ----------------------------------------------------------------- --------
      • Custom script: call DestroyTrigger( GetTriggeringTrigger() )


  • Item Disassemble
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Disassemble
    • Actions
      • -------- Set the slot from which you want item to be dissasembled --------
      • Set CItemDisassembleSlot = 1
      • -------- The unit which will be casting disassemble ability, in case you have different way of disassembling, --------
      • -------- change that unit variable to mach that unit, for example Circle of Power... --------
      • Set CItemUnit = (Triggering unit)
      • Custom script: call SlotItemDisassemble(udg_CItemUnit, udg_CItemDisassembleSlot)


------------------------------------------------------------------------

Jass code is now in description!

Regards!
~DD
 
Last edited:
Level 19
Joined
Mar 18, 2012
Messages
1,716
set TUnit[GetHandleId(t)-0x10000] = u is incorrect. The minimum possible handle id is 0x100000.

Also not very safe, as handle ids are shared over different type of objects.
They can go above 8910 during a game season.

You leak a timer handle.

I don't think the system is more advanced than dk-diablo system.

The API is nice and straight foreward.
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
I still think this is a great system for all the GUI users who are way too scared to look at vJass. The API on this is so simple, I don't see how any newbie can be confused by it. On a side note, I really think you should put a warning somewhere that this still requires JNGP to use. The "GUI / Triggers" is a bit misleading.
 
Level 17
Joined
Dec 11, 2014
Messages
2,004
JASS:
            set x = 0
            set it[x] = hero_item_type[x]
            set x = x + 1
            set it[x] = hero_item_type[x]
            set x = x + 1
            set it[x] = hero_item_type[x]
            set x = x + 1
            set it[x] = hero_item_type[x]
            set x = x + 1
            set it[x] = hero_item_type[x]
            set x = x + 1
            set it[x] = hero_item_type[x]
            set x = x + 1

You can put this in a loop as well. Shortens the code and improves readability.
 
Level 15
Joined
Jul 19, 2007
Messages
618
JASS:
            set x = 0
            set it[x] = hero_item_type[x]
            set x = x + 1
            set it[x] = hero_item_type[x]
            set x = x + 1
            set it[x] = hero_item_type[x]
            set x = x + 1
            set it[x] = hero_item_type[x]
            set x = x + 1
            set it[x] = hero_item_type[x]
            set x = x + 1
            set it[x] = hero_item_type[x]
            set x = x + 1

You can put this in a loop as well. Shortens the code and improves readability.

I know, but it is faster to directly code then to use loop.
if i where to code this now, i would use loop, but at the time i was coding this, i did it this way coz i thought i had to do it as fast as possible...

Your code will not compile in DEBUG_MODE = true.

Why does ARRAY_SIZE influence the array space of CType.
It should increases the size of TUnit.
I would recommend to use a table instance from library Table instead of the array.

Ops sorry about debug mode, did this in zinc, but forgot to change to vjass...
ARRAY_SIZE changed to TUnit... sorry i rushed the update and miss the variable :xxd:

About table, i never used it, but i could learn to... its just that for system i am not using much of data for this so i think this array_size var should do...

EDIT: I added support for Table, for thous who already have it/use it in there maps and it is part of 1.6 update

Regards!
~DD
 
Last edited:
Level 19
Joined
Mar 18, 2012
Messages
1,716
You have an item handle leak in UnitRemoveItemById, if the item type id has been found.
Fix that please.
Edit: My mistake. There is no leak in the code.

Trigger conditions are favored over trigger actions to run on as trigger action/condition function.
Simply because they evaluate faster than trigger actions.
---
Actually it's not a big performance difference, but that issue is mentioned hundred times accross our forums.
Trigger conditions also have other advantages when it comes
to dynamically created triggers, but that is not important for this resource.

Good resource. Approved.

Edit:
As there is a link from your to Diablo-dk's system in your review,
I also added a link backwards to this resource in his submission review.
 
Last edited:
Level 15
Joined
Jul 19, 2007
Messages
618
You have an item handle leak in UnitRemoveItemById, if the item type id has been found.
Fix that please.
Edit: My mistake. There is no leak in the code.

Trigger conditions are favored over trigger actions to run on as trigger action/condition function.
Simply because they evaluate faster than trigger actions.
---
Actually it's not a big performance difference, but that issue is mentioned hundred times accross our forums.
Trigger conditions also have other advantages when it comes
to dynamically created triggers, but that is not important for this resource.

Good resource. Approved.

Edit:
As there is a link from your to Diablo-dk's system in your review,
I also added a link backwards to this resource in his submission review.

Ok thanks, i updated the system, hope its good now.

Regards!
~DD
 
Level 4
Joined
Jan 7, 2014
Messages
69
what need to change for modify this system for possible to create items with full inventory if you take an dummy item wich is last needed for create the item? its little hard to improve not your own systems. i added recipe with dummy item, but it doesnt works. another recipes with 1-6 items works perfect, but with 7th items have no idea how.
 
Level 15
Joined
Jul 19, 2007
Messages
618
what need to change for modify this system for possible to create items with full inventory if you take an dummy item wich is last needed for create the item? its little hard to improve not your own systems. i added recipe with dummy item, but it doesnt works. another recipes with 1-6 items works perfect, but with 7th items have no idea how.

Hi,

Could you modify this "map/system" so that i can see what does not work.

Regards!
~DD
 
Level 4
Joined
Jan 7, 2014
Messages
69
good system, but still does not support +7 items :), for support need to implement few lines in code
 
Last edited:
Hey, this is a good system, but I've had desync when I try to combine items with sound enabled. Without custom sound, the combination happens normally.

Edit: Further testing and looking at the script reveals that the problem might be in one of your GetLocalPlayer() blocks:
JASS:
function DDGenericSound takes string file,real vol,real x,real y,real mxDist,real pitch returns nothing
        local sound s
        local real d
        local integer i
        local integer snd_n
        local integer sh
        set i=00 // Play sound and shake camera for players within spell cast range
        loop
        exitwhen i >= bj_MAX_PLAYERS
            if ( GetLocalPlayer() == Player(i) ) then
                set d=SquareRoot(Pw_2(GetCameraTargetPositionX() - x) + Pw_2(GetCameraTargetPositionY() - y))
                if ( d < mxDist ) then
                    set sh=StringHash(file)
                    set snd_n=LoadInteger(DDLib___GenSndTable, sh, 04)
                    set s=LoadSoundHandle(DDLib___GenSndTable, sh, snd_n)
                    if ( s == null ) then
                        set s=CreateSound(file, false, false, false, 10, 10, "")
                        call SaveSoundHandle(DDLib___GenSndTable, sh, snd_n, s)
                    elseif ( GetSoundIsPlaying(s) ) then
                        call StopSound(s, false, false)
                    endif
                    call SetSoundVolume(s, R2I(vol - d * ( vol / mxDist )))
                    call StartSound(s)
                    set snd_n=snd_n + 01
                    if ( snd_n == 04 ) then
                        set snd_n=00
                    endif
                    call SaveInteger(DDLib___GenSndTable, sh, 04, snd_n)
                endif
            endif
        set i=i + 01
        endloop
    endfunction
Specifically, the
JASS:
set s=CreateSound(file, false, false, false, 10, 10, "")
line is unsafe.
 
Last edited:
Level 15
Joined
Jul 19, 2007
Messages
618
Hey, this is a good system, but I've had desync when I try to combine items with sound enabled. Without custom sound, the combination happens normally.

Edit: Further testing and looking at the script reveals that the problem might be in one of your GetLocalPlayer() blocks:
JASS:
function DDGenericSound takes string file,real vol,real x,real y,real mxDist,real pitch returns nothing
        local sound s
        local real d
        local integer i
        local integer snd_n
        local integer sh
        set i=00 // Play sound and shake camera for players within spell cast range
        loop
        exitwhen i >= bj_MAX_PLAYERS
            if ( GetLocalPlayer() == Player(i) ) then
                set d=SquareRoot(Pw_2(GetCameraTargetPositionX() - x) + Pw_2(GetCameraTargetPositionY() - y))
                if ( d < mxDist ) then
                    set sh=StringHash(file)
                    set snd_n=LoadInteger(DDLib___GenSndTable, sh, 04)
                    set s=LoadSoundHandle(DDLib___GenSndTable, sh, snd_n)
                    if ( s == null ) then
                        set s=CreateSound(file, false, false, false, 10, 10, "")
                        call SaveSoundHandle(DDLib___GenSndTable, sh, snd_n, s)
                    elseif ( GetSoundIsPlaying(s) ) then
                        call StopSound(s, false, false)
                    endif
                    call SetSoundVolume(s, R2I(vol - d * ( vol / mxDist )))
                    call StartSound(s)
                    set snd_n=snd_n + 01
                    if ( snd_n == 04 ) then
                        set snd_n=00
                    endif
                    call SaveInteger(DDLib___GenSndTable, sh, 04, snd_n)
                endif
            endif
        set i=i + 01
        endloop
    endfunction
Specifically, the
JASS:
set s=CreateSound(file, false, false, false, 10, 10, "")
line is unsafe.

Hi,

thanks for reporting the bug.
Here is new code, hope it works now.

JASS:
hashtable GenSndTable = null;
    public function DDGenericSound(string file, real vol, real x, real y, real mxDist, real pitch) {
  integer sh = StringHash(file),
    snd_n = LoadInteger(GenSndTable, sh, 04);
  sound s = LoadSoundHandle(GenSndTable, sh, snd_n);
  real d;
  integer i;
      
  if (s == null) {
   s = CreateSound(file, false, false, false, 10, 10, "");
   SaveSoundHandle(GenSndTable, sh, snd_n, s);
  } else if (GetSoundIsPlaying(s)) {
   StopSound(s, false, false);
  }
  SetSoundPitch(s, pitch);
  snd_n += 01;
  if (snd_n == 04)
   snd_n = 00;
  SaveInteger(GenSndTable, sh, 04, snd_n);
 
  // Play sound and shake camera for players within spell cast range
  for (i=00; i < bj_MAX_PLAYERS; i+=01) {
   if (GetLocalPlayer() == Player(i)) {
    d = SquareRoot( DDHypot(GetCameraTargetPositionX()-x, GetCameraTargetPositionY()-y) );
    if (d < mxDist) {
     SetSoundVolume(s, R2I((vol-d*(vol/mxDist))*1.27));
     StartSound(s);
    }
   }
  }
    }

Regards!
~DD
 
Level 15
Joined
Jul 19, 2007
Messages
618
Hey, this is a good system, but I've had desync when I try to combine items with sound enabled. Without custom sound, the combination happens normally.

Edit: Further testing and looking at the script reveals that the problem might be in one of your GetLocalPlayer() blocks:
JASS:
function DDGenericSound takes string file,real vol,real x,real y,real mxDist,real pitch returns nothing
        local sound s
        local real d
        local integer i
        local integer snd_n
        local integer sh
        set i=00 // Play sound and shake camera for players within spell cast range
        loop
        exitwhen i >= bj_MAX_PLAYERS
            if ( GetLocalPlayer() == Player(i) ) then
                set d=SquareRoot(Pw_2(GetCameraTargetPositionX() - x) + Pw_2(GetCameraTargetPositionY() - y))
                if ( d < mxDist ) then
                    set sh=StringHash(file)
                    set snd_n=LoadInteger(DDLib___GenSndTable, sh, 04)
                    set s=LoadSoundHandle(DDLib___GenSndTable, sh, snd_n)
                    if ( s == null ) then
                        set s=CreateSound(file, false, false, false, 10, 10, "")
                        call SaveSoundHandle(DDLib___GenSndTable, sh, snd_n, s)
                    elseif ( GetSoundIsPlaying(s) ) then
                        call StopSound(s, false, false)
                    endif
                    call SetSoundVolume(s, R2I(vol - d * ( vol / mxDist )))
                    call StartSound(s)
                    set snd_n=snd_n + 01
                    if ( snd_n == 04 ) then
                        set snd_n=00
                    endif
                    call SaveInteger(DDLib___GenSndTable, sh, 04, snd_n)
                endif
            endif
        set i=i + 01
        endloop
    endfunction
Specifically, the
JASS:
set s=CreateSound(file, false, false, false, 10, 10, "")
line is unsafe.

Hi,

i have modified sound/model sounds a bit and they have to be imported now. You need to export and import fuse and disassamble files from my map to your map. Modified models with sounds and one custom sound should work now.

Hello,does someone have a older version of this so it can work on patch 1.28.5? It looks great ! Thanks.

This version of recipe system (2.1) should work with warcraft 3 1.28.5, does it report some error?

Regards!
~Dark Dragon
 
Top