SPELL CONTEST #2 | Theme: Forbidden Arts | Submissions

mr-death

Acolyte
Reaction score
51
The Unforgiven
Just another forbidden blade-striking technique

Type: GUI, some leak removal scripts
Instances: MUI, capability: 500 units.
Leaks: Checking,
Lags: Depends on your extremeness using 0.00 cooldown and more than 3 Punisher.
Levels: Works for n levels.
Configurable: target, smoothness, damage, and timing-delay.

The Idea:
Cripple, Mark an area, check if still within the area, jump, strike, damage.

Tooltip Learn Extended:
"I learn to forgive others, by slashing them deeply through their heart."
Cripples the target, and then creates a circle of forbidden mark at the target's location.
If within the next 3 seconds the target is still found inside the circle, the spell will succeed, immobilizes the target, then in a second, the Punisher will gain invulnerability, and starts to fly throughout any debris from any location, to the position of the marked victim and slash right through its heart, forgiving one's fault by dealing an intense pain.
If the victim manage to leave the circle, he'll be forgiven after 10 seconds.

Screenshots:
Cast.jpg

Hmmm...
Strike.jpg


Well, poor abomination. Found out what's next here:
View attachment demomap_contest_mr-death_TheUnforgiven.w3x
View attachment demomap_contest_mr-death_TheUnforgiven2.w3x Fixed effects, fixed instance and stacks.
View attachment demomap_contest_mr-death_TheUnforgiven3.w3x Fixed Animation, Animation timing, Animation stacks. Lesser light Effects.

will be upgraded later on, maybe.
Currently finding some better purple eye-candy.

You might want to check, if the unit goes out from the circle: Use the ability on the second hero and move him off.

#3 is counted as well-done for the thread-closing.

If there's a plenty of time left, I'll give the finishing off at #4.
 

Genkora

Frog blast the vent core!
Reaction score
92
Divine Mission

Description: Divine mission can only be cast on friendly units. What it does is turns that unit into a living time bomb (30 seconds) with an added "blow up now" button. When a unit with Divine Mission detonates (either by activating the suicidal bombing button that the unit will have or by killing it with other means) it deals damage to all units nearby. Now there are 2 different amounts it can deal, and it depends on which method is used to kill said unit.

method 1 You manually detonate the unit: It will deal 100% of the units current life if Divine Mission is lvl 1. 110% if Divine Mission is lvl 2. 120% if it's lvl 3.

method 2The unit is killed by other means: If the unit's max health is lower than 500, it will deal 200 damage. If the unit's health is higher than 500, but lower than 700, it will deal 500 damage. If the unit's health is higher than 700, it will deal 700 damage. This stays the same regardless of Divine Mission's lvl. In most cases it is a lot weaker than detonating the unit yourself.

either way, that unit is going to blow up.

There is one more effect to this ability. When a unit detonates (using either of the 2 methods), any units still alive will run in terror, the distance increasing with the level of Divine Mission.

lvl 1: 1000 WC3 units (whatever they are)

lvl 2: 1600

lvl 3: 2200

The explosion and fear will affect any unit, friendly or enemy.

GUI? yes

MUI/MPI? I am pretty sure it is

Leakfree? I don't think I missed any leaks

Fun ability? This ability is VERY fun.

Too lazy to upload pics, but it looks pretty good.

Changed some titles that were messed up with ability names.
 

No_exit

Regular User (What is Custom User Title?)
Reaction score
40
Shadow Walk

2q0vqxf.jpg


General
GUI/Jass/vJass? Jass.
MUI? Up to 372 simultanious shadow walks with default settings.
Forbidden Arts? sneak, abduction, imprison, torture.
Designed for? (Player vs Player) Melee.
Well commented code? Yes.

How it works
  • You start your shadow walk by creating a prison (preferably not in sight of any enemies or even better: in your base).
  • You walk towards your target and imprison him.
  • This will cause you and your target to be teleported back to where you started to shadow walk. Your target will however be trapped in the prison and get tortured to death.
But ...
  • You can only shadow step for a maximum of 22 seconds. You will be notified when the time runs low.
  • If you were shadow walking and your prison is destroyed you will get teleported back instantly. (I hope for you that whatever killed that prison wasn't a large force.)
  • When you imprison a unit and teleport back towards your prison, a dust trail will follow your path which can lead that units allies into rescuing that unit ... or into a trap.

Comments
This is my first submitted skill so feedback of any kind (bugs, advice, ...) is greatly appreciated. I only play custom maps like The Black Road so I hope the ability is more or less balanced for melee because I'm a big noob at it. I also hope you all enjoy my entry as much as I enjoyed making it ;)!
 

Attachments

  • demomap_contest_No_exit_Shadow_Walk.w3x
    49.8 KB · Views: 198

emjlr3

Change can be a good thing
Reaction score
395
Balefire - emjlr3

Balefire is a weapon created with the One Power, in the world of the Wheel of Time. Balefire is a weave, that when evoked by a channeler, summons a blindingly bright beam of "liquid light" that can destroy almost any known substance. Balefire, dependent upon is strength, erases the past actions of anyone it encounters. They litterly cease to exist before the moment of their destruction, and only the memories remain for those who saw or experienced the act.

Balefire dates back in its use to the War of Power, when it was used to destroy entire cities. It is implied that the channelers of the age did not entirely understand what they had discovered, but that when they realized they were unraveling entire swathes and days of the Pattern, and in doing so threatening the very fabric of Creation itself, both sides mutually abandoned its use.

Balefire
Conjure a searing beam of liquid light, burning away all enemies it touches.
Their recent actions are erased along with them, omitting damage done and units they may have killed.

  • Level 1 - 700 range, 3 second effect.
  • Level 2 - 900 range, 6 second effect.
  • Level 3 - 1100 range, 9 second effect.

Spell Code:
JASS:
scope Balefire initializer Init

globals
	private constant integer AbilId = 'A000' // Spell rawcode
	private constant integer DummyId = 'h000' // Balefire dummy rawcode
	private constant real DummyTimeScale = .9 // Animation speed of balefire dummy
	private constant real DummyDuration = 5. // Length in time before balefire dummy is removed from the game
    // Effects to create over the length of the beam
    private constant string Sfx1 = "Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl" 
    private constant string Sfx2 = "Objects\\Spawnmodels\\NightElf\\NEDeathMedium\\NEDeath.mdl"
endglobals
// Units to omit from the system
private function UserFilter takes unit u returns boolean
	return IsUnitType(u,UNIT_TYPE_STRUCTURE)==true and IsUnitType(u,UNIT_TYPE_SUMMONED)==true
endfunction
// Units to erase from existance on cast, bj_groupEnumOwningPlayer is the owner of the caster
private function DamageFilter takes nothing returns boolean
	return IsUnitType(GetFilterUnit(),UNIT_TYPE_SUMMONED)==false and IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE)==false and IsUnitEnemy(GetFilterUnit(),bj_groupEnumOwningPlayer) and GetWidgetLife(GetFilterUnit())>.405
endfunction
// Time into the past to erase
private function GetTime takes integer lvl returns real
	return 3.*lvl
endfunction
// AoE for beam
private function GetAoE takes integer lvl returns real
	return 225.
endfunction
// Distance for beam
private function GetDistance takes integer lvl returns real
	return 500.+(200.*lvl)
endfunction
// Size of beam
private function DummySizeScale takes integer lvl returns real
	return 1.00+(.25*lvl)
endfunction

//** No touching past the point!! **\\
private struct data[816000]
	unit u = null
	
	// Lets hope this is enough points to avoid overlap
	real array damage[200]
	real array damagetime[200]
	unit array damaged[200]
	integer dc = 0
	
	unit array killed[200]
	real array killedtime[200]
	real array killedx[200]
	real array killedy[200]
	integer kc = 0
endstruct
globals
	private group G = CreateGroup()
	private trigger Old = null
	private trigger New = CreateTrigger()
	private timer Timer = CreateTimer()
	private timer GameTime = CreateTimer()
	private data array D[4080]
	
	private group g = CreateGroup()
	private boolexpr b = null
endglobals

// --H2I bug, data storage
private function H2I takes handle h returns integer
    return h
    return 0
endfunction
// Get the data stored on a uit
private function GetUnitData takes unit u returns data
    return D[H2I(u)-0x100000]
endfunction
// Store the data to a unit
private function SetUnitData takes unit u, data d returns nothing
    set D[H2I(u)-0x100000] = d
endfunction

// --Spell cast
// Main function for when the spell is cast
private function Go takes nothing returns nothing
	local unit u = GetTriggerUnit()
	local integer lvl = GetUnitAbilityLevel(u,AbilId)
	local real dist = 50.
	local real maxdist = GetDistance(lvl)
	local real aoe = GetAoE(lvl)
	local real x
	local real y
	local real ux = GetUnitX(u)
	local real uy = GetUnitY(u)
	local location l = GetSpellTargetLoc()
	local real ang = Atan2(GetLocationY(l)-uy,GetLocationX(l)-ux)
	local real cos = Cos(ang)
	local real sin = Sin(ang)
	local unit targ
	local data d
	local real time = TimerGetElapsed(GameTime)-GetTime(lvl)
	local integer i
    local integer j
	local unit dummy 
    local group newg = CreateGroup()
    local real scale = DummySizeScale(lvl)
    	
	// Create and setup dummy
    set x = ux+dist*cos
    set y = uy+dist*sin
    set dummy = CreateUnit(GetOwningPlayer(u),DummyId,x,y,ang*bj_RADTODEG)
	call SetUnitScale(dummy,scale,scale,scale)
	call SetUnitTimeScale(dummy,DummyTimeScale)
	call UnitApplyTimedLife(dummy,'BTLF',DummyDuration)
    
    // Get all units to effect in a line extending out from caster
	call GroupClear(g)
	set bj_groupEnumOwningPlayer = GetOwningPlayer(u)
	loop
		exitwhen dist>maxdist
        
		call GroupEnumUnitsInRange(g,x,y,aoe,b)
        call GroupAddGroup(g,newg)
        call DestroyEffect(AddSpecialEffect(Sfx1,x,y))
        call DestroyEffect(AddSpecialEffect(Sfx2,x,y))
        
        call GroupClear(g)
		set dist = dist + 50.
        set x = ux+dist*cos
		set y = uy+dist*sin
	endloop
	
	// Loop through effected targets
	loop
		set targ = FirstOfGroup(newg)
		exitwhen targ==null
		
		set d = GetUnitData(targ)
		
		// Erase all kills they made
        if d.kc==0 then
            set i = 200
        else
            set i = d.kc-1
        endif
		loop
			exitwhen d.killedtime<i>&lt;time
            
			if GetWidgetLife(d.killed<i>)&lt;.405 and d.killed<i>!=null then
				if IsUnitType(d.killed<i>,UNIT_TYPE_HERO)==true then
					call ReviveHero(d.killed<i>,d.killedx,d.killedy,true)
				else
					set dummy = CreateUnit(GetOwningPlayer(d.killed<i>),GetUnitTypeId(d.killed<i>),d.killedx<i>,d.killedy<i>,bj_UNIT_FACING )
				endif
                
                // Restore hp to amount of last damage
                if d.dc==0 then
                    set j = 200
                else
                    set j = d.dc-1
                endif
                loop
                    exitwhen d.damaged[j]==d.killed<i>
                    if j==0 then
                        set j = 200
                    else
                        set j = j - 1
                    endif
                endloop
                call SetWidgetLife(dummy,d.damage[j])
			endif
			
			if i==0 then
				set i = 200
			else
				set i = i - 1
			endif
			
			// Just incase
			if i==d.kc then
				call BJDebugMsg(&quot;Balefire Error:  Kills storage overlap, reduce your Erase Duration.&quot;)
				exitwhen true
			endif
		endloop
		
		// Erase all damage they did
		if d.dc==0 then
            set i = 200
        else
            set i = d.dc-1
        endif
		loop
			exitwhen d.damagetime<i>&lt;time
			
			if GetWidgetLife(d.damaged<i>)&gt;.405 and d.damaged<i>!=null then
				call SetWidgetLife(d.damaged<i>,GetWidgetLife(d.damaged<i>)+d.damage<i>)
			endif
			
			if i==0 then
				set i = 200
			else
				set i = i - 1
			endif
			
			// Just incase
			if i==d.dc then
				call BJDebugMsg(&quot;Balefire Error:  Damage storage overlap, reduce your Erase Duration.&quot;)
				exitwhen true
			endif
		endloop
		
		// Obliterate them
		call UnitDamageTarget(u,targ,99999.,false,false,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_UNIVERSAL,null)
		
		call GroupRemoveUnit(newg,targ)
	endloop
	
	call RemoveLocation(l)
    call DestroyGroup(newg)
    set newg = null
	set l = null
	set u = null
	set dummy = null
endfunction
// Run our effects if its the correct spell cast
private function Cast takes nothing returns boolean
	if GetSpellAbilityId()==AbilId then
		call Go()
	endif
	return false
endfunction

// --Store kills
// When a unit dies, store who killed them, when, and where
private function Death takes nothing returns boolean
	local data d
	
	if not IsUnitInGroup(GetTriggerUnit(),G) or not IsUnitInGroup(GetKillingUnit(),G) then
		return false
	endif
	
	set d = GetUnitData(GetKillingUnit())
	set d.killed[d.kc] = GetTriggerUnit()
	set d.killedtime[d.kc] = TimerGetElapsed(GameTime)
	set d.killedx[d.kc] = GetUnitX(d.killed[d.kc])
	set d.killedy[d.kc] = GetUnitY(d.killed[d.kc])
    if d.kc==200 then
		set d.kc = 0
	else
		set d.kc = d.kc + 1
	endif
    
    return false
endfunction

// --Lite damage detection system
// When units take damage, store the damage, who did the damage and the time at which it was done
private function Damaged takes nothing returns boolean
	local data d 
	
	if GetEventDamage()&lt;.1 or not IsUnitInGroup(GetEventDamageSource(),G) then
		return false
	endif
	set d = GetUnitData(GetEventDamageSource())

	set d.damage[d.dc] = GetEventDamage()
	set d.damaged[d.dc] = GetTriggerUnit()
	set d.damagetime[d.dc] = TimerGetElapsed(GameTime)	
    if d.dc==200 then
		set d.dc = 0
	else
		set d.dc = d.dc + 1
	endif
	
	return false
endfunction
private function Add takes nothing returns boolean
	if UserFilter(GetEnumUnit()) then
		return false
	endif
	call TriggerRegisterUnitEvent(New,GetEnumUnit(),EVENT_UNIT_DAMAGED)
	return true
endfunction
// Units enter the map, register them taking damage, give them a struct if needed, clean old uneeded structs
private function EnterMap takes nothing returns boolean
	local data d
	local unit u = GetTriggerUnit()
	
	if IsUnitInGroup(u,G) or UserFilter(u) then
		set u = null
		return false
	endif
	call TriggerRegisterUnitEvent(New,u,EVENT_UNIT_DAMAGED)
	call GroupAddUnit(G,u)
	
	set d = GetUnitData(u)
	if d==0 then
		set d = data.create()
		set d.u = u
		call SetUnitData(u,d)
	elseif d.u!=u then
		call d.destroy()
		set d = data.create()
		set d.u = u
		call SetUnitData(u,d)
	endif
	
	set u = null
	return false
endfunction
// Constantly keep our damage detection up to date, this method should remove DestroyTrigger() bugs
private function Update takes nothing returns nothing
	call DisableTrigger(New)
    if Old != null then
        call DestroyTrigger(Old)
    endif
    set Old = New
    set New = CreateTrigger()      
	call GroupClear(G)
    call GroupEnumUnitsInRect(G,bj_mapInitialPlayableArea,Condition(function Add))
endfunction

//======================
private function Init takes nothing returns nothing
	local trigger t = CreateTrigger()	
	call TriggerRegisterEnterRectSimple(t,bj_mapInitialPlayableArea)
	call TriggerAddCondition(t,Condition(function EnterMap))
										 
	set t = CreateTrigger()
	call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_DEATH)
	call TriggerAddCondition(t,Condition(function Death))
										 
	set t = CreateTrigger()
	call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
	call TriggerAddCondition(t,Condition(function Cast))
		
	call TriggerAddCondition(New,Condition(function Damaged))
	call GroupEnumUnitsInRect(G,bj_mapInitialPlayableArea,Condition(function Add))
	call TimerStart(Timer,600.,true,function Update)
	call TimerStart(GameTime,99999.,false,null)
	
	set b = Condition(function DamageFilter)
endfunction

endscope</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>


The way I had to code this was by using a struct per registered unit, which keeps track of data points into the past for damage and kills.
Because of this method, a limitation of 4,080 is imposed on the total number of handles in your map at any given time, which requires a rather
inflated 816,000 member struct array.

It would be smart to avoid dealing damage very quickly through triggers. Limiting periodic triggered damage to once every .25s or so should suffice, baring
any massive values of erasing duration you may desire. If a unit deals damage no more often then once every .1s, at a max erase duration of 10s, only
100 members of my struct member arrays are in use at a given time, which is half their maximum value.

-emjlr3
 

Attachments

  • Spell Contest 2 Balefire emjlr3.w3x
    166.7 KB · Views: 224
  • Balefire.jpg
    Balefire.jpg
    60.2 KB · Views: 277
General chit-chat
Help Users
  • No one is chatting at the moment.

      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