- 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 = 039;A000039;
//Rawcode of the wall dummy unit
private constant integer wallDummyId = 039;h001039;
//Rawcode of the caster dummy unit
private constant integer casterDummyId = 039;h002039;
//Rawcode of the dummy spell
private constant integer dummySpellId = 039;A001039;
//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:
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.
-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):