First attempt at making a struct spell.

chovynz

We are all noobs! in different states of Noobism!
Reaction score
130
I'm converting this into a struct'ed spell. This works as is but could be better.
Heads up from the first post. I'll probably end up doing alot of double posts.

Edit: I'm going to convert the below into structs. I haven't done so yet.
JASS:
//-------Mine Spells Integer Block
constant function ProxRawCode takes nothing returns integer
    return 'A00Z' //Proximity Mine Spell
endfunction
constant function FoFRawCode takes nothing returns integer
    return 'A011' //FoF Mine Spell
endfunction
constant function HomeRawCode takes nothing returns integer
    return 'A012' //Homing Mine Spell
endfunction
constant function StealthRawCode takes nothing returns integer
    return 'A014' //Stealth Mine Spell
endfunction
constant function AcidRawCode takes nothing returns integer
    return 'A015' //Acid Mine Spell
endfunction

function Trig_CreateProximityMineJass2_Conditions takes nothing returns boolean
    if ((GetSpellAbilityId()==ProxRawCode())) then
        set udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))] = 1
        return GetSpellAbilityId()==ProxRawCode()
    endif
    if ((GetSpellAbilityId()==FoFRawCode())) then
        set udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))] = 2
        return GetSpellAbilityId() == FoFRawCode()
    endif
    if ((GetSpellAbilityId()==HomeRawCode())) then
        set udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))] = 3
        return GetSpellAbilityId()==HomeRawCode()
    endif
    if ((GetSpellAbilityId()==StealthRawCode())) then
        set udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))] = 4
        return GetSpellAbilityId()==StealthRawCode()
    endif
    if ((GetSpellAbilityId()==AcidRawCode())) then
        set udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))] = 5
        return GetSpellAbilityId()==AcidRawCode()
    endif
    return false
endfunction

//--------Mine Units 
function MineID takes nothing returns integer
    if (udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))]) == 1 then
        return 'n003'  //Proximity Mine Spell
    endif
    if (udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))]) == 2 then
        return 'n005'  //FoF Mine Spell
    endif
    if (udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))]) == 3 then
        return 'n002'  //Homing Mine Spell
    endif
    if (udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))]) == 4 then
        return 'n000'  //Stealth Mine Spell
    endif
    if (udg_LastMine[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))]) == 5 then
        return 'n004'  //Acid Mine Spell
    endif
return 0
endfunction

//-------Generic Mine stuff
constant function MineFuse takes nothing returns real
    return 6.
endfunction

constant function MineBlastRadius takes nothing returns real
    return 200. //Mine Blast Radius
endfunction

constant function MineDamage takes nothing returns real
    return 300. //Proximity Mine Damage
endfunction

function Trig_CreateProximityMineJass2_Actions takes nothing returns nothing
   local unit Caster = GetTriggerUnit()
   local real CasterX = GetUnitX(Caster)
   local real CasterY = GetUnitY(Caster)
   local real CasterFace = GetUnitFacing(Caster)
   local unit Mine
   local unit Explosion

   set Mine = CreateUnit(GetOwningPlayer(Caster), MineID(), CasterX, CasterY, bj_UNIT_FACING)
   call UnitApplyTimedLife(Mine ,'BTLF', MineFuse())
   call TriggerSleepAction(MineFuse())

   set Explosion = CreateUnit(GetOwningPlayer(Caster),'h00Q',GetUnitX(Mine),GetUnitY(Mine),bj_UNIT_FACING)
   call UnitDamagePoint(Mine, 0, MineBlastRadius(), GetUnitX(Mine), GetUnitY(Mine), MineDamage(), true, false, ATTACK_TYPE_MELEE, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
   call UnitApplyTimedLife(Explosion, 'BTLF', 2)
   
   set Caster            = null
   set Mine              = null
   set Explosion         = null
   
endfunction

//===========================================================================
function InitTrig_CreateProximityMineJass2 takes nothing returns nothing
    set gg_trg_CreateProximityMineJass2 = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_CreateProximityMineJass2, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_CreateProximityMineJass2, Condition( function Trig_CreateProximityMineJass2_Conditions ) )
    call TriggerAddAction( gg_trg_CreateProximityMineJass2, function Trig_CreateProximityMineJass2_Actions )
endfunction

I will start by analyzing the spell that I want. The intention is to create a mine that blows up based on the ability clicked. I have 5 different mines. Any player can use it so it needs to be fully MUI and PUI.

All mines have the same actions with some slight differences that can be allowed for with "if/thens" or some other way. The action is as follows:

1. player clicks 1 of 5 mine abilities
2. Mine is created
2a. Mine is activated after a few seconds to allow the triggering unit to move away.
3. Mine will blow up after a certain amount of time - irrespective of type.
3a. Mine can be destroyed and will blow up.
3b. If a hero comes near the mine it will blow up.
4a. Mine Options. Proximity blows up at any hero approach. Homing mine will move slowly towards the nearest hero(including self). Friend or Foe will not blow up at Friendly approach (beware of enemy coming close at this time.) Stealth will be invisible. Acid has extreme damage.
5. Kills need to be counted from Mine kills, but not when a mine destroys another mine. Kills only get counted on heros, so this might not come into the equation.

First Question: Am I being too complicated?
 

Doom-Angel

Jass User (Just started using NewGen)
Reaction score
167
i didn't get it where are the structs? (did i miss them in your trigger or something?)
 

chovynz

We are all noobs! in different states of Noobism!
Reaction score
130
I haven't done them yet. This is an open journey. :) I'll be posting them up and asking if im doing it right. The first post is what I'm converting from.

My first thought is that I need to make structs for each type of mine. So...

JASS:
struct prox
    integer delay = 2
    integer fuse = 6     
    integer damage = 300
    real x
    real y

    method rawcode takes nothing returns integer
       return 'A00Z' //Proximity Mine Spell
    endmethod

endstruct


Is this a good start?
 

SFilip

Gone but not forgotten
Reaction score
634
Why do you want to use structs here in the first place? You don't seem to have the need for attaching anything and there is overall no place where they're really needed.

But anyway...don't use methods that way. They are quite slow compared to standard functions, only use them if you need to do something with the parent struct's members or need something that can be called from anywhere (or both).
Some other things you should consider about the spell the way it is now:
-TriggerSleepAction should always be avoided when it comes to spells, especially with longer waits, if you must then use PolledWait
-you have a lot of calls in some functions such as Trig_CreateProximityMineJass2_Conditions, it's a much better idea to store GetSpellAbilityId and GetTriggerUnit to variables so that you only need to call them once in that function
-another example is MineID where the whole GetPlayerId(GetOwningPlayer(GetTriggerUnit())) can be one variable
-you can use constant globals instead of constant functions for raw codes and similar setup
 

chovynz

We are all noobs! in different states of Noobism!
Reaction score
130
Ok. Answer me this then. Why would I use structs? Maybe this is my problem. What is attachment?
I need to move my homing mine (like a slide but using x,y to target). Is that where I would attach?
 

Andrewgosu

The Silent Pandaren Helper
Reaction score
716
For instance, you might want to use a struct where you need to move a unit with a periodic timer and
attach its starting coordinates, facing etc. to the timer and retrieve the data in the "move" function.
 

SFilip

Gone but not forgotten
Reaction score
634
You use structs when you need to put more than one value in one variable (there are other purposes, but this is the most notable).
Say you need to attach three variables using some system. You can just put them all in one struct and then attach the struct itself as an integer - almost three times faster than attaching each of the variables separately.
Yes, using it for sliding is a good idea.
 

chovynz

We are all noobs! in different states of Noobism!
Reaction score
130
Well... when you think about it, ideally all mines should have periodic timer dont you think?

TriggerSleepAction has been causing me some problems. That's why i want to move to structs or something else. I'm going to be having a LOT of movement on my map. I'm going to need things as optimized as possible.

I understood structs would help me do that. Handle Vars feels clunky.
What do you think i should do? I can make 5 different spells for each mine if thats what it takes, but i dont see the point when i can do one or two functions with conditions instead of 10+ functions.
 

Arkan

Nobody rides for free
Reaction score
92
if you want something to be accurate, then yes, use a timer, alternative a periodic trigger.
 

chovynz

We are all noobs! in different states of Noobism!
Reaction score
130
Then that is why I need to use structs. All the mines are having two timers (one for action delay and one for death time). At the moment TriggerSleepAction is the only way I know of doing a wait (except for HandleVars which I want to move away from. It is going to be too slow for what I have in mind.)
 

Cohadar

master of fugue
Reaction score
209
If you are looking for how to use structs to move objects there is a really nice example spell in ABC demo map for that.
 

chovynz

We are all noobs! in different states of Noobism!
Reaction score
130
I know. I saw that. That was cool and very good to see that its possible to do that sort of thing. I didn't understand it enough to be able to use it though. Thats what these last two threads have been about. Heading down that struct path.

Is there a problem in my thinking?

I thinking from create unit --timedelay--> damage area --->destroy unit
Do I need to think a different way with structs / attachment?
 

Cohadar

master of fugue
Reaction score
209
Actually the best way to make a proximity mine is to register area event trigger for that mine, and then to attach struct to that trigger.
 

chovynz

We are all noobs! in different states of Noobism!
Reaction score
130
. . .

elucidate please.

Is that unit comes in range? And how would I attach to that trigger?

SetTriggerStructA(trigger, struct)?
 

Cohadar

master of fugue
Reaction score
209
exactly like that.

call TriggerRegisterUnitInRangeSimple( trigger, range, unit )

For range you put 200 for example,
unit is your mine of course.

If it is a tracking mine (spider mine from starcraft) you can order unit to kaboom on unit that enters region.

I would love to make an example of this, but I have to go now.
Maybe tomorrow.

EDIT:
starcraft heh.
Well if noone beats me to it I will submit a starcraft spider mine spell tomorrow.
 

chovynz

We are all noobs! in different states of Noobism!
Reaction score
130
Is this the spell data I need? And is it correct syntax?
JASS:
scope ProximitySpell
    struct Proxdata
       unit caster
       unit target
       integer minetype = 'n003'
       integer ID = 'A00Z'
       real delay = 2.
       real fuse = 6.  
       real blast = 200.
       real damage = 300.
    endstruct
endscope
 

Cohadar

master of fugue
Reaction score
209
unit types and ability ID's should be constant globals, not struct variables

JASS:



scope ProximitySpell

globals
       constant integer minetype = 'n003'
       constant integer ID = 'A00Z'
endglobals

    struct Proxdata
       unit caster
       unit target
       real delay = 2.
       real fuse = 6.  
       real blast = 200.
       real damage = 300.
    endstruct
endscope
 

SFilip

Gone but not forgotten
Reaction score
634
Why exactly do you need any of that inside a struct? If you want movement then you just need two reals for X and Y and a unit you're moving. The rest (delay, fuse, blast, damage) can all be constant globals.

> what's a constant global?
Isn't it self-explanatory? It's a global with a constant value, something that never changes. Kind of like using constant functions.
 

Silvenon

New Member
Reaction score
19
Any constant value in your spell should be put inside a constant global. Constant globals are just a cool way to store a constant value (what you would otherwise store in a constant function, probably).
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top