• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[Mapping] Spell as basic attack

Spell as basic attack
Spell as basic attack
by -Kobas-


Requirements

* Basic knowledge of the Object Editor
* Basic knowledge of the Trigger Editor
* Poor knowledge in variables.
* A moment of your time :) (Around 5 min).

Introduction

This new cool way to create hash and slash games without removing units attack from UI :)
Yes hero will still have displayed attack damage and any bonuses that goes with it (Items, abilities etc...)

Let's start!

Usually this kind of games just removed attack damage from hero and used large number of all kind of array variables to store data (damage, damage type and such things).

How to do it easier way.

  • 1st of all do next, pick your hero (Paladin for example) and just remove the attack icon - the only one you can remove; go to Combat - Attack 1 - Show UI and set it to False. If your unit uses both attack types, then do the same for the Combat - Attack 2 - Show UI field.
  • 2nd. Create new ability (example: Channel, set it to unit ability, make it visible and set path x,y(3,0), rename it to attack and set cooldown to dunno, 1 sec, also edit spell animation to attack)
  • 3rd. Create this like trigger:
    • Attack
      • Events
        • Unit - A unit Starts the effect of an ability
      • Conditions
        • (Ability being cast) Equal to Attack
      • Actions
        • Wait 0.00 seconds
        • Set p = (Position of (Triggering unit))
        • Unit - Order (Triggering unit) to Attack Once (Random unit from (Units within 128.00 of p))
        • Custom script: call RemoveLocation (udg_p)
    Variable [(Random unit from (Units within 128.00 of p))] can be edited to anything you want :)


Good:
You can use mouse to target enemy units
Bad: Small delay before attack (because of wait, but it won't work without it.)

How to do it more professional
.

  • 1st. Once again hide attack UI.
  • 2nd. Duplicate your unit
  • 3rd. Set targets for real one to "wards" or anything you don't use!
  • 4th. Open Game Interface panel and instead of message text (Can't attack target or whatever you set for attack target) set " " (space).
  • 5th. Create your duplicate unit somewhere on map, add locust ability to it and change owner. Each time when you pick/drop item, learn spell or whatever, do same with dummy unit, then order that unit to attack once another dummy unit (10000 hp and regeneration, 0 armor, for armor and damage type try to use some unused type in your map, just edit values in gameplay constant so this damage actually deal 100% to target unit) and then just save damage taken into variable.
  • 6th. Create new trigger that will deal this new saved damage to random unit/s when you cast spell.
    • Attack
      • Events
        • Unit - A unit Starts the effect of an ability
      • Conditions
        • (Ability being cast) Equal to Attack
      • Actions
        • Wait 0.00 seconds
        • Set p = (Position of (Triggering unit))
        • Unit - Cause (Triggering unit) to damage (Random unit from (Units within128 .00 of p)), dealing X damage of attack type Normal and damage type Normal
        • Custom script: call RemoveLocation (udg_p)
    Variable [(Random unit from (Units within 128.00 of p))] can be edited to anything you want :)
    Variable [X] is your hero saved damage.
    You can use variables to change attack and damage type as well.

Good: Unit won't attack nearby enemy units without order.
Bad: Small delay

Author's notes:

Don't forget special effects, floating text and such things.
I will try to finish test map, this is so far tested idea only, it works I just need to polish it a little.
 
Last edited:
Would a 0 second timer work for this? If so, the delay could be nearly eliminated if you use that instead of a wait. ;) Although, keep the wait method there, because some people might prefer it over timers.

Otherwise, good job. :thumbs_up:

Didn't tried that, but it won't work without wait action.
 
You would need a 0.27 second timer here :p
Anyway, although that trigger uses waits, it's still MUI and good for GUIers.
Here's a vJass version:

JASS:
library AttackSpell requires TimerUtils
    globals
        private constant integer ABIL_CODE = 'A000'
    endglobals
    
    private function GetDamage takes integer level returns real
        return I2R(level * 80)
    endfunction
    
    private module Init
        private static method onInit takes nothing returns nothing
            local trigger t = CreateTrigger()
            call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
            call TriggerAddCondition(t,Condition(function thistype.run))
            set t = null
        endmethod
    endmodule
    
    private struct Data
        unit caster
        unit target
        real damage
        method destroy takes nothing returns nothing
            set .caster = null
            set .target = null
            call .deallocate()
        endmethod
        static method attack takes nothing returns nothing
            local timer t = GetExpiredTimer()
            local thistype this = GetTimerData(t)
            call UnitDamageTarget(.caster,.target,.damage,true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,null)
            call .destroy()
            call ReleaseTimer(t)
            set t = null
        endmethod
        static method create takes unit u, unit v returns thistype
            local thistype this = thistype.allocate()
            local timer t = NewTimer()
            set .caster = u
            set .target = v
            set .damage = GetDamage(GetUnitAbilityLevel(u,ABIL_CODE))
            call SetTimerData(t,this)
            call TimerStart(t,0.3,false,function thistype.attack)
            return this
        endmethod
        static method run takes nothing returns boolean
            if GetSpellAbilityId()==ABIL_CODE then
                call thistype.create(GetTriggerUnit(),GetSpellTargetUnit())
            endif
            return false
        endmethod
        implement Init
    endstruct
endlibrary

It requires TimerUtils
 
Top