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

Bomb

Status
Not open for further replies.
Level 6
Joined
Apr 14, 2017
Messages
134
I want to create an ability that essentially causes a unit to plant a bomb with a short timer on buildings or even other units, what's the easiest way to go about this?
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
gui meaning not in jass or vjass?
Yes.
Using JASS or vJASS you can very easily use timers to make this work.
In GUI it's a lot more complicated because you have to store the data in hashtables or arrays to make it MUI.
You would have to iterate through the units and use some kind of counter to dealy the explosion.

What should happen when the bomb explodes?
Area of effect or only damaging the target?
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
I decided to do it in vJASS, because it's easier to import and easier to write.
JASS:
scope TimeBomb initializer Init
    globals
        //ability that is used to palce bombs (single target)
        private constant integer TRIGGER_SPELL = 'A000'
        //ability the bombed unit has to display the buff (tornado slow aura)
        private constant integer BUFF_SPELL = 'A001'
        private constant attacktype ATTACK_TYPE = ATTACK_TYPE_NORMAL
        private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_MAGIC
    endglobals
   
    private function GetBombDelay takes integer level returns real
        return 5.-1*level
    endfunction
   
    private function GetBombTargetDamage takes integer level returns real
        return 50.*level
    endfunction
   
    private function GetBombAOEDamage takes integer level returns real
        return 50.*level
    endfunction
   
    private function GetBombAOERange takes integer level returns real
        return 150.+50*level
    endfunction
   
    //Return true, if the target should be damaged by the area of effect
    private function AllowedTargets takes unit caster, unit target returns boolean
        return TRUE
    endfunction
   
    /*====================================================================
    ======================= END OF CONFIGURATION =========================
    ====================================================================*/
   
    globals
        private hashtable hash
        private group bombedUnits
    endglobals
   
    private function DeathConditions takes nothing returns boolean
        return IsUnitInGroup(GetTriggerUnit(), bombedUnits)
    endfunction
   
    private function DeathActions takes nothing returns nothing
        local unit target = GetTriggerUnit()
        call UnitRemoveAbility(target, BUFF_SPELL)
        call FlushChildHashtable(hash, GetHandleId(target))
        call GroupRemoveUnit(bombedUnits, target)
        set target = null
    endfunction
   
    private function Conditions takes nothing returns boolean
        return GetSpellAbilityId() == TRIGGER_SPELL
    endfunction

    private function Explode takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local integer h = GetHandleId(t)
        local unit caster = LoadUnitHandle(hash, h, 0)
        local unit target = LoadUnitHandle(hash, h, 1)
        local integer level = LoadInteger(hash, h, 2)
        local group g = CreateGroup()
        local unit u
        local integer bombCount
       
        if(not IsUnitInGroup(target, bombedUnits)) then
            call PauseTimer(t)
            call DestroyTimer(t)
            call DestroyGroup(g)
            set u = null
            set g = null
            set caster = null
            set target = null
            set t = null
            return
        endif
        call UnitDamageTarget(caster, target, GetBombTargetDamage(level), TRUE, FALSE, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE_WHOKNOWS)
        call GroupEnumUnitsInRange(g, GetUnitX(target), GetUnitY(target), GetBombAOERange(level), null)
        loop
            set u = FirstOfGroup(g)
            exitwhen u == null
            call GroupRemoveUnit(g, u)
            if(AllowedTargets(caster, u) )then
                call UnitDamageTarget(caster, u, GetBombAOEDamage(level), TRUE, FALSE, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE_WHOKNOWS)
            endif
        endloop
        call FlushChildHashtable(hash, h)
        set h = GetHandleId(target)
        set bombCount = LoadInteger(hash, h, 0)-1
        call SaveInteger(hash, h, 0, bombCount)
        if(bombCount == 0) then
            call UnitRemoveAbility(target, BUFF_SPELL)
            call FlushChildHashtable(hash, h)
            call GroupRemoveUnit(bombedUnits, target)
        endif
        call PauseTimer(t)
        call DestroyTimer(t)
        call DestroyGroup(g)
        set u = null
        set g = null
        set caster = null
        set target = null
        set t = null
    endfunction
   
    private function Actions takes nothing returns nothing
        local unit caster = GetTriggerUnit()
        local unit target = GetSpellTargetUnit()
        local integer level = GetUnitAbilityLevel(caster, TRIGGER_SPELL)
        local timer t = CreateTimer()
        local integer h = GetHandleId(t)
        call TimerStart(t, GetBombDelay(level), FALSE, function Explode)
        call SaveUnitHandle(hash, h, 0, caster)
        call SaveUnitHandle(hash, h, 1, target)
        call SaveInteger(hash, h, 2, level)
        call UnitAddAbility(target, BUFF_SPELL)
        set h = GetHandleId(target)
        call SaveInteger(hash, h, 0, LoadInteger(hash, h, 0)+1)
        call GroupAddUnit(bombedUnits, target)
        set caster = null
        set target = null
        set t = null
    endfunction

    private function Init takes nothing returns nothing
        local trigger trg = CreateTrigger(  )
        local integer i = 0
        call TriggerRegisterAnyUnitEventBJ( trg, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition( trg, Condition( function Conditions ) )
        call TriggerAddAction( trg, function Actions )
        set trg = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ( trg, EVENT_PLAYER_UNIT_DEATH )
        call TriggerAddCondition( trg, Condition( function DeathConditions ) )
        call TriggerAddAction( trg, function DeathActions )
        set hash = InitHashtable()
        set bombedUnits = CreateGroup()
        set trg = null
    endfunction

endscope
 

Attachments

  • TimeBomb.w3x
    20.7 KB · Views: 38
Level 6
Joined
Apr 14, 2017
Messages
134
So basically replace the A000 with the ability used to place the bomb and A001 with the bomb's buff and it's ready to go?
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
So basically replace the A000 with the ability used to place the bomb and A001 with the bomb's buff and it's ready to go?
A000: yes
A001: you can't directly add buffs to units, so you need to add an ability that adds the buff. Usually you use slow aura (tornado)
You can see it in my uploaded map.

You can also set damage, aoe, delay depending on the level.
You will probably want to modify the function AllowedTargets, so only certain tarets are damaged (enemies, organic for example).
 
Level 6
Joined
Apr 14, 2017
Messages
134
The map does not show up in the game, is it because I'm using version 1.27b rather than the new 1.28?

I'm hesitant to upgrade to version 1.28 because of the many bugs that I've heard of
 
Level 6
Joined
Apr 14, 2017
Messages
134
@Jampion
Are you supposed to have something enabled in order to properly import this into another map?

When I copy and paste the trigger into another map and try to save it, it gives me an error that states
"Trigger 'time bomb' has been disabled due to multiple errors." And then it proceeds to show me a list of errors.
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
You need either JNGP or WEX in order to save maps with vJASS without getting compiler errors.
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
I could convert it into normal JASS, if you prefer it. Normal JASS can be used in the vanilla world editor.
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
In the configuration trigger you can configure some things (should be self-explanatory).
In the targets allowed trigger you can decide whether the target should be damaged.
In the example only enemies of the caster are damaged.
 

Attachments

  • TimeBombJASS.w3x
    21.6 KB · Views: 39

Rem

Rem

Level 7
Joined
Apr 12, 2017
Messages
230
Can't this simply be done using one ability that has a buff plus a simple trigger.

The ability would be cast on a building, it would display an bomb or something similar on the building, the trigger would be set up such that when the ability is cast the trigger will be set to wait a certain amount of time after which it will create an effect (an explosion) at the location of the building, damage the building as well as anything in like 200 range of the building and remove the buff on the building.
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
Can't this simply be done using one ability that has a buff plus a simple trigger.
That's pretty much what I did, but I avoided using waits.
Also in this case Apostle wanted it to be non dispelable and there are only very few spells, that can't be dispelled and most of them have side effects.
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
Let's see, you could use "Doom" since its un-dispell-able or maybe cyclone (it could be made un-dispell-able), there are a few other abilities
Doom silences the target and cyclone cyclones the target. If these effects are not intended, these abilities cannot be used for this.
Shadow Strike could work, but I did not want to limit the user to not use shadow strike on the same unit, so I rather made a code that works for an ability based on Channel.

I personally never use waits in my spells, because of the inaccuracy, but if you don't care that much about accuracy, you can of course use waits.
 
Level 6
Joined
Apr 14, 2017
Messages
134
Would this work?

  • Untitled Trigger 12
    • Events
      • Unit - A unit Begins casting an ability
    • Conditions
      • (Ability being cast) Equal to Shadow Strike (Custom)
    • Actions
      • Set BUnit = (Target unit of ability being cast)
      • Set BCastingUnit = (Casting unit)
      • Wait 10.00 game-time seconds
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (BUnit is alive) Equal to True
        • Then - Actions
          • Unit - Cause BCastingUnit to damage circular area after 0.00 seconds of radius 500.00 at (Position of BUnit), dealing 500.00 damage of attack type Spells and damage type Normal
          • Special Effect - Create a special effect attached to the overhead of BUnit using Abilities\Weapons\FragDriller\FragDriller.mdl
          • Special Effect - Destroy (Last created special effect)
        • Else - Actions
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
It's not MUI, because the global variables will be overwritten, if you cast it multiple times within 10 seconds.
Damaging a circular area damages all units, also allies and buildings.
 
Level 6
Joined
Apr 14, 2017
Messages
134
Ok, but the cooldown will be longer than 10 seconds, also it's more realistic if it damages all units within a small radius
 
Level 11
Joined
Mar 28, 2015
Messages
632
Originally this was meant as an item ability with several charges, then it was planned to be a hero ability, but I suppose it could be a regular ability as long as the damage is reduce to around 350 or 400, that way it wont be too op and thus wont be abused.
 
Level 16
Joined
Mar 24, 2017
Messages
827
This kinda of reminds me of the Crazy Ivan's ability from RA2, they strap a bomb onto anything and it explodes dealing a good amount of damage to the unit or building, however they are not able to destroy most essential structure in one strike, only structures like powerplants and base defenses which have less HP get annihilated with their bombs, was this your intention Blake?
 
Level 11
Joined
Mar 28, 2015
Messages
632
Nope, if you wanna compare this to RA2 or YR, it would be more like the navy seal's ability, it was originally planned to give a hero in certain missions like 10 or so charges of a bomb so that he/she would be able to destroy buildings easier, then I thought of the whole sphere of flames idea (a highly modified acid bomb ability that damages any building it it thrown at for 10 or so seconds), now that works really well but then I began thinking about an actual sapper unit, or a hero with a similar ability, and that's how this idea came up. If its given to a hero it needs to be real powerful...like dealing 3000 or so damage to a structure (thus being able to destroy almost any structure with just a single bomb) but if its a unit ability it could be a lot weaker, 350-500 damage, I think we might include both versions....idk how it will turn out in actual gameplay.
 
Level 16
Joined
Mar 24, 2017
Messages
827
Navy seals in RA2 are extremely powerful, they can eliminate ANY building in the game (including that impenetrable fortress from the last mission) with a single c4 charge, also they have no timer and deal no AOE damage, and the building just explodes, so I think you're thinking more of a mix between an ivan and a seal here. Anyway seals were way too OP in RA2, I mean just think about what it means to destroy a building by just getting close to it. I dont think that's what you want here, you just need to make structures easier to destroy not give one side a overpowered base killer unit (just remember what happened with your little experiment AKA the Crusader unit ;) )
 
Level 11
Joined
Mar 28, 2015
Messages
632
Well I fixed that problem, remember I completely removed the unit from the campaign, anyway what if it takes several seconds to plant the bomb and it only deals heavy damage to the structure it's placed on and relatively light (~150-100) AOE damage to surrounding units?
 
  • Like
Reactions: Rem
Level 6
Joined
Apr 14, 2017
Messages
134
Is this what you had in mind?
your_gif_from_mp4togif_com_1496040680036.gif
 
Level 11
Joined
Mar 9, 2017
Messages
506
@colonelaster here's what I was talking about
Yuri Prime (Red Alert 2)

fyi - the range that the wikia specifies is wrong, its real range is 30, I know because I tried tweaking the unit, take it into consideration that long range units in ra2 usually have a range of 8-10, grand cannons have a range of 15, and V3s whose missiles can be shut down have a range of 18.

Now that is truly OP
 
Last edited by a moderator:
Level 16
Joined
Mar 24, 2017
Messages
827
wtf? I never knew there was such a unit, range of 30? I know those fearsome dreadnoughts have a range of like 25 according to the wikia, 30 is just crazy.
 
Level 11
Joined
Mar 28, 2015
Messages
632
From the wikia
In Red Alert 2, Yuri Prime is a stolen-tech unit which can be unlocked when a Soviet-controlled spy (either by mind-controlling a spy or by obtaining access to the Allied techtree) infiltrates a Soviet battle lab. An Allied spy infiltrating Soviet battle lab and having an access to Soviet barracks (also built or captured) will have the same effect.

Yuri Prime himself is simply a much more powerful version of the Psi-Corps trooper. In Yuri's Revenge, the unit was changed and given the role of the standard commando unit of Yuri's Army.

It's a stolen tech unit, very hard to get, not a normal unit, that's why its so op
 
Level 10
Joined
Jan 31, 2017
Messages
377
Damn, you could probably cause all kinda of havoc with just one of those, imagine a mission where you're given one of those and a few simply infantry units and you have to wreck several enemy bases::that would be awesome
 
Status
Not open for further replies.
Top