Spell Wall of Replica

Reaction score
456
Wall of Replica

Raises a wall out of pure mana across the landscape. Heroes who attemp to pass through it will have images of themselves emerge from the wall to serve under the Dark Seer until the wall's duration is up. Images take 250% damage and deal 35%.

Level 1: Lasts for 15 seconds.
Level 2: Lasts for 30 seconds.
Level 3: Lasts for 45 seconds.


Information:

Code type: vJass (NewGen required)
MUI: Absolutely!
Leaks: Nope, it never does..
Really?: Look through the code by yourself..

Code:
JASS:
scope WallOfReplica

//Made by: Überplayer
//Credits: Cohadar - for ABC

//Instructions:
//
// 1. Export the icon files from Import Editor (not needed).
// 2. Copy the "Wall of Replica" buff from Object Editor to your map.
// 3. Copy the "[Dummy Spell] - Wall of Replica" spell from Object Editor to your map.
// 4. Copy the "Wall of Replica" spell from Object Editor to your map.
// 5. Copy the "[Dummy Wall] - Wall of Replica" unit to your map.
// 6. Copy the "[Dummy Caster] - Wall of Replica" unit to your map.
// 7. If you don't already have ABC v5.1 implemented in your map, then
//    copy the "ABC" trigger to your map.
// 8. Copy this trigger into your map.
// 9. Make sure that the rawcodes inside this spells Configuration Menu
//    match the rawcodes of your previously copied units and spells rawcodes.

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//CONFIGURATION MENU
    globals
        //Rawcode of the spell
        private constant integer spellId = 'A000'
        //Rawcode of the wall dummy unit
        private constant integer wallDummyId = 'h001'
        //Rawcode of the caster dummy unit
        private constant integer casterDummyId = 'h002'
        //Rawcode of the dummy spell
        private constant integer dummySpellId = 'A001'
        //Integer order of the dummy spell
        private constant integer dummySpellOrder = 852274
        //Interval of the timer
        private constant real timerInterval = 0.08
    endglobals
    
    private constant function WallDuration takes integer level returns real
        //Duration of the wall
        return level * 15.00
    endfunction

    private constant function WallLength takes integer level returns real
        //Length of the wall
        return 768.00
    endfunction
    
    private constant function WallWidth takes integer level returns real
        //Width of the wall
        return 32.00
    endfunction
    
    private constant function TimerInterval takes integer level returns real
        //Interval of the timer
        return 0.08
    endfunction
    
    private function ValidReplicaBasedUnits takes unit caster, unit enterer returns boolean
        //Modify this function only if you know what you're doing.
        //caster  = the caster of this spell
        //enterer = the unit who is checked, if it is valid for replication
        return (IsUnitType(enterer, UNIT_TYPE_HERO))
    endfunction
    
    private constant function EffectPath takes integer level returns string
        //This is the effect which is shown on the replicated unit.
        return "Abilities\\Spells\\Orc\\MirrorImage\\MirrorImageCaster.mdl"
    endfunction
    
    private constant function ImageLimit takes integer level returns integer
        //Maximum limit of the replications created per hero from a wall.
        return 1
    endfunction
//END OF CONFIGURATION MENU
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
    
    private struct tempStruct
        integer tempInteger
    endstruct
    
    private struct replicaStruct
        unit array replica[200]
        unit array baseUnit[200]
        integer totalReplicas = 0
        boolean isDestroying = false
    endstruct
    
    private struct WORstruct
        unit casterUnit
        unit wallDummy
        
        real wallDuration
        real wallLength
        real wallWidth
        string effectPath
        integer imageLimit
        
        real x1
        real y1
        real x2
        real y2

        real currentTime
        
        static method create takes unit casterUnit, unit wallDummy, real wallDuration, real wallLength, real wallWidth, string effectPath, integer imageLimit returns WORstruct
            local WORstruct dat = WORstruct.allocate()
            
            set dat.casterUnit = casterUnit
            set dat.wallDummy = wallDummy
            
            set dat.wallDuration = wallDuration
            set dat.wallLength = wallLength
            set dat.wallWidth = wallWidth
            set dat.effectPath = effectPath
            set dat.imageLimit = imageLimit
            
            set dat.x1 = GetUnitX(dat.wallDummy) + dat.wallLength / 2 * Cos((GetUnitFacing(dat.casterUnit) + 90.00) * bj_DEGTORAD) 
            set dat.y1 = GetUnitY(dat.wallDummy) + dat.wallLength / 2 * Sin((GetUnitFacing(dat.casterUnit) + 90.00) * bj_DEGTORAD) 
            set dat.x2 = GetUnitX(dat.wallDummy) + dat.wallLength / 2 * Cos((GetUnitFacing(dat.casterUnit) - 90.00) * bj_DEGTORAD) 
            set dat.y2 = GetUnitY(dat.wallDummy) + dat.wallLength / 2 * Sin((GetUnitFacing(dat.casterUnit) - 90.00) * bj_DEGTORAD) 
            
            set dat.currentTime = timerInterval
            
            return dat
        endmethod
    endstruct
    
    private function GroupEnumUnitsInLine takes group g, real x1, real y1, real x2, real y2, real width returns nothing
        local real angle = Atan2(y2 - y1, x2 - x1)
        local real dist = SquareRoot((x2-x1) * (x2 - x1) + (y2 - y1) * (y2 - y1))
        local real cdist = 0
        local group temp
        loop
            exitwhen (cdist > dist)
            set temp = CreateGroup()
            call GroupEnumUnitsInRange(temp, x1, y1, width / 2, null)
            set bj_wantDestroyGroup = true
            call GroupAddGroup(temp, g)
            set x1 = x1 + ((width / 4) * Cos(angle))
            set y1 = y1 + ((width / 4) * Sin(angle))
            set cdist = cdist + (width / 4)
        endloop
        set temp = null
    endfunction
    
    private function OnDeath takes nothing returns nothing
        local WORstruct dat
        local replicaStruct dat2
        local trigger trig = GetTriggeringTrigger()
        local integer index = -1
        local integer index2
        local unit deadReplica = GetTriggerUnit()
        
        set dat = GetTriggerStructA(trig)  
        set dat2 = GetTriggerStructB(trig)
        
        if (dat2.isDestroying == false) then
            loop
                exitwhen (index == dat2.totalReplicas)
                if (deadReplica == dat2.replica[index]) then
                    set dat2.baseUnit[index] = null
                    set index2 = index
                    loop
                        exitwhen (index2 == dat2.totalReplicas)
                        set dat2.baseUnit[index2] = dat2.baseUnit[index2 - 1]
                        set dat2.replica[index2] = dat2.replica[index2 - 1]
                        set dat2.baseUnit[index2] = null
                        set dat2.replica[index2] = null
                        set index2 = index2 + 1
                    endloop
                    set dat2.totalReplicas = dat2.totalReplicas - 1
                    exitwhen (true)
                endif
                set index = index + 1
            endloop
        endif
        
        call ClearTriggerStructA(trig)
        call ClearTriggerStructB(trig)
        call DestroyTrigger(trig)
        set trig = null
        set deadReplica = null 
    endfunction
    
    private function GetReplica takes nothing returns nothing
        local WORstruct dat
        local replicaStruct dat2
        local tempStruct dat3
        local trigger trig = GetTriggeringTrigger()
        local unit summoner = GetTriggerUnit()
        local unit summoned = GetSummonedUnit()
        local trigger trig2 = CreateTrigger()
        
        set dat = GetTriggerStructA(trig)
        set dat2 = GetTriggerStructB(trig)
        set dat3 = GetTriggerStructC(trig)
        
        call SetUnitX(summoned, GetUnitX(summoner))
        call SetUnitY(summoned, GetUnitY(summoner))
        set dat2.replica[dat3.tempInteger] = summoned
        call SetTriggerStructA(trig2, dat)
        call SetTriggerStructB(trig2, dat2)
        call TriggerRegisterUnitEvent(trig2, dat2.replica[dat3.tempInteger], EVENT_UNIT_DEATH)
        call TriggerAddAction(trig2, function OnDeath)
        
        call RemoveUnit(summoner)
        call dat3.destroy()
        call ClearTriggerStructA(trig)
        call ClearTriggerStructB(trig)
        call ClearTriggerStructC(trig)
        call DestroyTrigger(trig)
        set trig = null
        set summoner = null
        set summoned = null
        set trig2 = null
    endfunction
    
    private function WallOfReplicaHandler_Actions takes nothing returns nothing
        local WORstruct dat
        local replicaStruct dat2
        local tempStruct dat3
        local timer watch = GetExpiredTimer()
        local integer index = 0
        local group g
        local unit f
        local integer found = 0
        local unit d
        local trigger trig
        
        set dat = GetTimerStructA(watch)
        set dat2 = GetTimerStructB(watch)
        
        if (dat.currentTime >= dat.wallDuration) then
            set index = 0
            set found = dat2.totalReplicas
            set dat2.isDestroying = true
            loop
                exitwhen (index == found)
                call KillUnit(dat2.replica[index])
                set index = index + 1
            endloop
            call KillUnit(dat.wallDummy)
            call dat.destroy()
            call dat2.destroy()
            call ClearTimerStructA(watch)
            call ClearTimerStructB(watch)
            call PauseTimer(watch)
            call DestroyTimer(watch)
            set watch = null
        else
            set dat.currentTime = dat.currentTime + timerInterval
            set g = CreateGroup()
            call GroupEnumUnitsInLine(g, dat.x1, dat.y1, dat.x2, dat.y2, dat.wallWidth)
            loop
                set f = FirstOfGroup(g)
                exitwhen (f == null)
                call GroupRemoveUnit(g, f)
                if (ValidReplicaBasedUnits(dat.casterUnit, f)) then
                    set index = 0
                    set found = 0
                    loop
                        exitwhen (index == dat2.totalReplicas)
                        if (dat2.baseUnit[index] == f) then
                            set found = found + 1
                        endif
                        set index = index + 1
                    endloop
                    if (found < dat.imageLimit) then
                        set dat3 = tempStruct.create()
                        set dat3.tempInteger = dat2.totalReplicas
                        set dat2.totalReplicas = dat2.totalReplicas + 1
                        set dat2.baseUnit[dat3.tempInteger] = f
                        call DestroyEffect(AddSpecialEffect(dat.effectPath, GetUnitX(f), GetUnitY(f)))
                        set d = CreateUnit(GetOwningPlayer(dat.casterUnit), casterDummyId, GetUnitX(f), GetUnitY(f), 0.00)    
                        call UnitAddAbility(d, dummySpellId)
                        call IssueTargetOrderById(d, dummySpellOrder, f)
                        set trig = CreateTrigger()
                        call SetTriggerStructA(trig, dat)
                        call SetTriggerStructB(trig, dat2)
                        call SetTriggerStructC(trig, dat3)
                        call TriggerRegisterUnitEvent(trig, d, EVENT_UNIT_SUMMON)
                        call TriggerAddAction(trig, function GetReplica)
                        set d = null
                        set trig = null
                    endif
                endif
                set f = null
            endloop
            set watch = null
        endif
    endfunction

    private function WallOfReplica_Conditions takes nothing returns boolean
        return (GetSpellAbilityId() == spellId)
    endfunction

    private function WallOfReplica_Actions takes nothing returns nothing
        local unit caster = GetTriggerUnit()
        local integer level = GetUnitAbilityLevel(caster, spellId)
        local location loc = GetSpellTargetLoc()
        local unit wall = CreateUnit(GetOwningPlayer(caster), wallDummyId, GetLocationX(loc), GetLocationY(loc), GetUnitFacing(caster))
        local WORstruct dat = WORstruct.create(caster, wall, WallDuration(level), WallLength(level), WallWidth(level), EffectPath(level), ImageLimit(level))
        local replicaStruct dat2 = replicaStruct.create()
        local timer watch = CreateTimer()
        
        call SetTimerStructA(watch, dat)
        call SetTimerStructB(watch, dat2)
        call TimerStart(watch, timerInterval, true, function WallOfReplicaHandler_Actions)
        
        set caster = null
        call RemoveLocation(loc)
        set loc = null
        set wall = null
        set watch = null
    endfunction

    function InitTrig_Wall_of_Replica takes nothing returns nothing
        local trigger trig = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(trig, EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddAction(trig, function WallOfReplica_Actions)
        call TriggerAddCondition(trig, Filter(function WallOfReplica_Conditions))
        set trig = null
    endfunction
endscope

Screenshot:
worscreenshot.png

Updates:
Version 2:
-Reduced timer interval from 0.035 to 0.16
-Added a constant function ImageLimit, which enables user to change the maximum limit of the images per hero from a wall.
-Fixed InitTrig.
-Minor change to ValidReplicaBasedUnits function.

Version 3:
-Can't remember.. maybe nothing?

Version 4:
-Made the code to use ABC (much faster now).
-Replicas of a wall will die when the wall's duration is up.
-If replica dies, unit can copy itself again from the wall.

Map ("lol", ABC increased the file size a bit):
 

Attachments

  • [DotA Spell] - Wall of Replica.w3x
    64.8 KB · Views: 1,020
Nice, i understood jass before newgen now it looks like jibbersh when i read it, but for the screenshot does it like create the unit beside him not like angled? like how it looks
 
There is still a thing.. I'd like the illusion to be created on the units position, as it goes quite random right now.

*waiting for CA (Cohadar's Attack) :shades:.. I'm all cool.. aaaaaall cool*
 
heh i was surprised when he didnt flame me when i post my shitty ass jass codes for dota spells
 
JASS:
    private function ValidReplicaBasedUnits takes unit caster, unit enterer returns boolean
        //Modify this function only if you know what you're doing.
        //caster  = the caster of this spell
        //enterer = the unit who is checked, if it is valid for replication
        local boolean b1 = (IsUnitType(enterer, UNIT_TYPE_HERO))
        return b1
    endfunction


looooooooooooooooooooooooooooooooool

How about:
JASS:
    private function ValidReplicaBasedUnits takes unit enterer returns boolean
        //Modify this function only if you know what you're doing.
        //caster  = the caster of this spell
        //enterer = the unit who is checked, if it is valid for replication
        return IsUnitType(enterer, UNIT_TYPE_HERO)
    endfunction



--------------------------------------------------
JASS:
    private constant function WallLength takes integer level returns real
        return 768.00 //Length of the wall
    endfunction
    
    private constant function WallWidth takes integer level returns real
        return 32.00 //Width of the wall
    endfunction
    
    private constant function TimerInterval takes integer level returns real
        return 0.035 //Interval of the timer
    endfunction

These function are not using level, therefore they are constants:
JASS:
    private constant real WallLength = 768.00
    private constant real WallLength = 32.00
    private constant real TimerInterval = 0.035


--------------------------------------------------
JASS:
    private constant function EffectPath takes integer level returns string
        //This is the effect which is shown on the replicated unit.
        return "Abilities\\Spells\\Orc\\MirrorImage\\MirrorImageCaster.mdl"
    endfunction

OMG WTF DID YOU THINK WHEN YOU MADE THIS?
JASS:
    private constant string EffectPath = "Abilities\\Spells\\Orc\\MirrorImage\\MirrorImageCaster.mdl"


--------------------------------------------------
JASS:
    private struct usedUnits
        unit array usedToReplicate[100] //This line needs fixing.
        integer totalReplicates = 0
    endstruct

Just reduce 100 to maximum number of heroes in game.

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

JASS:
    function InitTrig_Wall_of_Replica takes nothing returns nothing
        local trigger trig = CreateTrigger()
        local boolexpr b = Filter(function WallOfReplica_Conditions)
        local integer index = 0
        loop
            exitwhen (index == 15)
            call TriggerRegisterPlayerUnitEvent(trig, Player(index), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
            set index = index + 1
        endloop
        call TriggerAddAction(trig, function WallOfReplica_Actions)
        call TriggerAddCondition(trig, b)
        set b = null
        set trig = null
    endfunction
endscope


OMG do NOT inline event registration BJ's , who ever invented that was a total jackass. And you used boolexpr for condition aaaaaaaaaaaaaaaaaaaa

There is a big difference between optimizing code and being stupid.
Just leave trigger stuff as they normally are.

JASS:
    function InitTrig_Wall_of_Replica takes nothing returns nothing
        local trigger trig = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ( trig, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddAction(trig, function WallOfReplica_Actions)
        call TriggerAddCondition(trig, Condition( function WallOfReplica_Conditions))
        set trig = null
    endfunction


--------------------------------------------------
I will bash you some more when I get time to look at the spell in detail.
 
Configuration menu shall be left as it is. I made those values constant functions for purpose.. some users may want to change value for different levels.

JASS:
    private function ValidReplicaBasedUnits takes unit caster, unit enterer returns boolean
        //Modify this function only if you know what you're doing.
        //caster  = the caster of this spell
        //enterer = the unit who is checked, if it is valid for replication
        local boolean b1 = (IsUnitType(enterer, UNIT_TYPE_HERO))
        return b1
    endfunction

I left it like that by an accident as I had 2 booleans, and I didn't want to make a long line for the condition.

>Just reduce 100 to maximum number of heroes in game.
I never know how many heroes a player wants there to be.

>There is a big difference between optimizing code and being stupid.
Just leave trigger stuff as they normally are.

Okay, I change that back :). I've just used to it.. as I write all triggers from a scratch.

>I will bash you some more when I get time to look at the spell in detail.
I'll look forward into it ^^


I think I survived from the first attack quite well. Now I just need some sleepy sleeeeep..
 
nice spell just one question:
what's the point of the shield if they hero enemies can go around it?
i mean don't you think it should be defending from every corner?
 
Grrr... nice :D I hope it makes illusion if the Hero passes the wall again?
+rep if i can
 
Actually, the hero doesn't pass through the wall. It's just picked from the line. And in DotA, if I remember right, only 1 illusion can be created from one hero per wall, but I can change that.

>what's the point of the shield if they hero enemies can go around it?
Read the description and you know why.

EDIT:// Update!
 
> And in DotA, if I remember right, only 1 illusion can be created from one hero per wall, but I can change that.
Well, In the newest version after a Hero passes the wall it creates an image. If the image dies and the Hero passes again, another image spawns (something like 1 image per hero limit)...
Good job anyway I learned a few stuff from ur code ^_^

EDIT: Not sure about the images! But that's what I remember from the last time I played with Ish'kafel in 6.49
 
Oh.. I haven't still figured out how to get last created illusion.. I fix it as soon as I figure out.

The images also should be killed when the wall is gone.

>I learned a few stuff from ur code ^_^
Glad to hear that you did =)
 
Just create a trigger to dectect when a unit is summoned, i guess that the ilussion is just another summoned unit i am 70% sure =P
 
>Just create a trigger to dectect when a unit is summoned, i guess that the ilussion is just another summoned unit i am 70% sure =P
Dunno how the get the replicated hero in the trigger then.. It's not so tip top.

Is this spell approved / dotaspellindexed?
 
Approved/Disapproved?

At last, the new version is out:

Updates:
Version 4:
-Made the code to use ABC (much faster now).
-Replicas of a wall will die when the wall's duration is up.
-If replica dies, unit can copy itself again from the wall.

This is now completely DotA spell.
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Varine Varine:
    +1
  • Varine Varine:
    I've been really into this
  • Varine Varine:
    It's a musical retelling of The Odyssey
  • Varine Varine:
    Also if you want mixed drinks without alcohol, there's a handful of non-alcoholic 'spirits'. Ritual Zero and Free Spirit are the two brands I've tried and they are alright. They don't have a TON of options, but they have some gin and whiskey alternatives that are fun to play with.
  • Varine Varine:
    I got a couple bottles to make some mixy drinks around holidays when I mostly want to drink, they aren't exact replacements but they are surprisingly close.
  • Varine Varine:
    I ended up with some hop water things that I really like instead for when I want to feel like I'm participating
  • Varine Varine:
    I just got moved to unsupervised probation, so I can get away with drinking a bit now. I technically am not supposed to, but I don't think I get checked anymore. I really want to smoke weed but it scares me
  • The Helper The Helper:
    Happy Wednesday! I am not feeling it today, my teeth are bothering me, or the fragments that were left behind are coming up and it is extra painful today. Don't ever let them tell you that getting full dental implants is easy. They have to pull all your teeth to do those and apparently they are not very good at getting all the teeth out all the time.
    +1
  • The Helper The Helper:
    That is true with Dentures too. I am taking the day off and working from home. The big difference is though, I am not drinking anymore so I have a nice tea and coffee regimen set up :)
  • Varine Varine:
    I wish i had a 3D scanner
  • Varine Varine:
    That would make what I'm doing SO much easier
  • Varine Varine:
    I guess I could just take a picture of it and then use that as a reference. I have a circuit board with some weird holes I can't get measured right
  • Varine Varine:
    Oh I got a Klipper mod for my big printer! It comes with a bunch of parts and I don't totally understand what it does but apparently it's way better than Marlin, which is I think what it currently runs
    +1
  • The Helper The Helper:
    Nice!
  • Varine Varine:
    You're people in Florida safe? The only couple I know are safe but I think they evacuated.
  • The Helper The Helper:
    They are without power but safe. Flood damage and stuff alot of tornados hit east Florida. No fatalities or injuries to any of my people that I know of
  • The Helper The Helper:
    They have been through all the Florida hurricanes they are like me I have been through every texas hurricane for the last 50 years.
  • The Helper The Helper:
    Never evacuated.
  • The Helper The Helper:
    Check out this bad ass Chicken Noodle soup recipe - https://www.thehelper.net/threads/crack-chicken-noodle-soup.196687/
  • The Helper The Helper:
    Happy Saturday!
    +1

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top