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

Eye of Torture v1.0D

This is actualy my first uploaded spell/system. That doesn't mean the coding is pure s**t. Actualy it is well coded according to me.
The spell is MUI.


Target:
Unit Target

Description: Creates an eye that surrounds a target unit for a specific amount of times, each interval the eye damages the target.

Level 1 - deals 80 damage each 2 seconds.
Level 2 - deals 120 damage each 1.50 seconds.
Level 3 - deals 160 damage each second.


BJs = 1 //The unit detection event.
It is vJass.

Credits: inico - for an eye model. I find it necesarry as an importet resource since there doesn't exist any eye model in the Warcraft III mpqs.


JASS:
library bloodeyeQQQL initializer init
native UnitAlive takes unit id returns boolean //Easy and fast way to check if a unit is alive.
globals
    private     integer       SPELL_ID                          = 'XXX1' //|The ability rawcode of the bloodeye.|\\
    
    private     integer       EYE_ID                            = 'h000' //|The unit rawcode of the eye.|\\
    
    private     integer       CROW_FORM                         = 'Arav' //|The Crow Form rawcode, actually it should be this in any map.|\\
    
    private     boolean       DESTROY_ON_WALL                   = true   //|If true then it will destroy when reaching a cliff wall.|\\
    
    private     real          MOVE_INTERVAL                     = 0.02   //|The eye moves DEGREES_PER_MOVE_INTERVAL degree each 0.02 second.|\\
    
    private     real          DEGREES_PER_MOVE_INTERVAL         = 4.     //|The eye moves 4. degrees each 0.02 seconds.|\\
    
    private     integer       DURATION                          = 6      //|The maximum loop number, the loop number raises each MOVE_INTERVAL|\\
    
    private     real          DISTANCE_BETWEEN_CASTER_AND_EYE   = 300.   //|The distance between the eye and the target.|\\
    
    private     real          HEIGHT                            = 300.   //|The constant height of the eye.|\\
    
    private     string        DAMAGE_EFFECT                     = "Objects\\Spawnmodels\\Human\\HumanBlood\\BloodElfSpellThiefBlood.mdl" //|The effect each time the target get damaged.|\\
    
    private     attacktype    ATTACK_TYPE                       = ATTACK_TYPE_CHAOS //|The attack type of the damage dealt.|\\
    
    private     damagetype    DAMAGE_TYPE                       = DAMAGE_TYPE_UNKNOWN //|The damage type of the damage dealt.|\\
    
    private     weapontype    WEAPON_TYPE                       = null //|The weapon type of the damage dealt.|\\
    
    private     real   array  Damage
    
    private     real   array  TBDamage
endglobals
//Time for setting Damage and time between each damage.
private function SetDamage takes nothing returns nothing
set Damage[1] = 80
set Damage[2] = 120
set Damage[3] = 160
//Now time between damage.
set TBDamage[1] = 2.
set TBDamage[2] = 1.5
set TBDamage[3] = 1.
endfunction

//////////////////////////////////////////||||||||||||||||||||\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
//////////////////////////////////////////|DO NOT TOUCH BELOW|\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
//////////////////////////////////////////||||||||||||||||||||\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
globals
    private     timer         T                               = CreateTimer()
    
    private     integer array Data
    
    private     integer       Total                           = 0
    
    private     constant      location      loc               = Location(0.,0.)
endglobals

struct bloodeye
    integer     c          //|Counter, it counts +1 every rotate step when it reaches ROTATIONS * 360 it stops.|\\
    real        max_c      //|The maximum number of c.|\\
    real        i          //|Time for damage|\\
    unit        u          //|Caster.|\\
    unit        tt         //|Target.|\\
    unit        e          //|The eye.|\\
    real        h           //h
    real        f          //|The eye rotating degree.|\\
    real        x          //|The target x coordinate.|\\
    real        y          //|The target y coordinate.|\\
    real        ex         //|The eye's x coordinate|\\
    real        ey         //|The eye's y coordinate|\\
    real        d          //|Distance between target and eye.|\\
static method Create takes unit c, unit t returns bloodeye
local bloodeye this = bloodeye.allocate()
local integer l
call MoveLocation(loc, GetSpellTargetX(),GetSpellTargetY())
set .u = c
set .f = 0.
set .tt = t
set l = GetUnitAbilityLevel(.u, SPELL_ID)
set .i = TBDamage[l] //Storing the time between each damage so I can subtract it from that variable (.i)
set .d = DISTANCE_BETWEEN_CASTER_AND_EYE
set .c = 0
set .e = CreateUnit(GetOwningPlayer(.u), EYE_ID, 0.0, 0.0, 0.0)
set .h = GetLocationZ(loc) + HEIGHT
call UnitAddAbility(.e, CROW_FORM)
call UnitRemoveAbility(.e, CROW_FORM)
set .max_c = DURATION * (MOVE_INTERVAL * 2500.)
set Data[Total] = this
if Total == 0 then
    call TimerStart(T, MOVE_INTERVAL, true, function bloodeye.OnRotate)
endif
set Total = Total + 1
return this
endmethod

static method OnRotate takes nothing returns nothing
local bloodeye dat
local integer i = 0
local real xx
local real yy
local integer l
loop
    exitwhen i == Total
    set dat = Data[i]
    set l = GetUnitAbilityLevel(dat.u, SPELL_ID)
    set dat.x = GetUnitX(dat.tt)
    set dat.y = GetUnitY(dat.tt)
    set dat.ex = GetUnitX(dat.e)
    set dat.ey = GetUnitY(dat.e)
    if dat.i <= 0. then //If Time for damage less than or equal to 0 then do damage.
        call UnitDamageTarget(dat.u, dat.tt, Damage[l], false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
        call DestroyEffect(AddSpecialEffect(DAMAGE_EFFECT, dat.x, dat.y))
        set dat.i = TBDamage[l]
    else
        set dat.i = dat.i - MOVE_INTERVAL
    endif
    if dat.c > dat.max_c then
        //Eye duration is over, kill the eye.
        call dat.Destroy()
        set Total = Total - 1
        set Data[i] = Data[Total]
        set i = i - 1
    else
        //Moving the eye.
        set xx = dat.x + dat.d * Cos(dat.f * bj_DEGTORAD)
        set yy = dat.y + dat.d * Sin(dat.f * bj_DEGTORAD)
        call SetUnitY(dat.e, yy)
        call SetUnitX(dat.e, xx)
        call SetUnitFacingTimed(dat.e, bj_RADTODEG * Atan2(dat.y - dat.ey, dat.x - dat.ex), 0.)
        call MoveLocation(loc, xx, yy)
        call SetUnitFlyHeight(dat.e, dat.h - GetLocationZ(loc), 0.)
        set dat.f = dat.f + DEGREES_PER_MOVE_INTERVAL
        set dat.c = dat.c + 1
        if DESTROY_ON_WALL then
            if dat.h - GetLocationZ(loc) <= 0 then
                call dat.Destroy()
            endif
        endif
        if not UnitAlive(dat.tt) then
            call dat.Destroy()
            set Total = Total - 1
            set Data[i] = Data[Total]
            set i = i - 1
        endif
    endif
    set i = i + 1
endloop
if Total == 0 then
    call PauseTimer(T)
endif
endmethod

method Destroy takes nothing returns nothing
call KillUnit(.e)
set .u = null
set .tt = null
set .e = null
call .deallocate()
endmethod
endstruct

private function Conditions takes nothing returns boolean
return GetSpellAbilityId() == SPELL_ID
endfunction

private function Actions takes nothing returns nothing
call bloodeye.Create(GetTriggerUnit(), GetSpellTargetUnit())
endfunction

private function init takes nothing returns nothing
local trigger t = CreateTrigger()
call SetDamage()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Condition(function Conditions))
call TriggerAddAction(t, function Actions)
endfunction
endlibrary

Give credits if used.
Have fun.

Update - V1.0D
Changes:
- Used constant global location instead of creating and removing locations each interval.

Update - V1.0B
Changes:
- Made constant height to the eye.
- Added an option to destroy the eye when it hits a too big wall.
- Nulled members in .Destroy()
- Made more configurable globals
- Fixed some other stuff

Keywords:
Eye, Torture, Diablo, Warcraft, Catch_ya, Death, Kill, Unit, Blood, Shaman, Evil, Witch
Contents

Just another Warcraft III map (Map)

Reviews
19:55, 19th Apr 2010 The_Reborn_Devil: The coding looks good now. Status: Approved Rating: Useful

Moderator

M

Moderator

19:55, 19th Apr 2010
The_Reborn_Devil:

The coding looks good now.


Status: Approved
Rating: Useful
 
Level 12
Joined
May 21, 2009
Messages
994
Hmm. The eye is a hero? Gonna fix that. Other than that Reborn, what do you mean with "Also it would be nice if you could take terrain height into account"? Also null some members? I always heard that you shouldn't null handles in structs.
 
Level 12
Joined
May 21, 2009
Messages
994
Uuhhmm, This could be alot simplier. Just create a dummy and add a "invis" spell which deals "Your damage" every " your space between attacks.

What?

But its good coding.

Thanks.


EDIT: Update! - 1.0C - used constant global location instead of creating and removing locations all the time.
 
Last edited:
Top