Converting spell from HandleVars to ABC

Status
Not open for further replies.

Grundy

Ultra Cool Member
Reaction score
35
I originally wrote this spell using handlevars and now i want it in ABC. I don't care about whose system is better or if theres a better one than ABC. I just want this spell in ABC. I want consistency in my map. I want all of the spells to use the same attachment system or whatever.

The spells targets heroes, ally or enemy. The spell creates a permanent lightning effect between caster and target. The only way to break the spell is by the caster dying, the target dying, or putting a certain amount of distance between the caster and target, or by the caster using the spell again but on a different target.

If it is cast on an enemy hero: When ever the caster takes damage a percentage of that damage is transfered to the target. When ever the target takes damage, it recieves a percentage of bonus damage.

If it is cast on an ally hero: When ever the target takes damage a percentage of that damage is transfered to the caster. When ever the target takes damage, it takes reduced damage.

I can't post any code because I've already started trying to convert it over, I don't have the original code any more. The new code is unfinished and doesn't work right.

The problem I'm having is, I used to attach things to the caster using handlevars. Whenever the spell is cast I get the target unit attached to the caster and remove the dummy ability from the target (just a slow aura ability that does nothing other than provides a buff). I get the timer attached to the caster that loops to update the lightning effect positions and destroy that timer. I get the local triggers that are attached to the caster and used to amplify/reduce damage and transfer damage and destroy those triggers. I get the lightning effect attached to the caster and destroy that. Then i create new timer, triggers, and lightning effect for the new cast.

I can't do this in ABC because you can't attach to units. I modified ABC to allow you to attach things to units and i do it like this:
JASS:
local unit uCaster = GetSpellAbilityUnit()
local unit uTarget = GetSpellTargetUnit()
local spelldata sd = GetUnitStructA(uCaster)
//thinking if there is no struct then sd will be null...
//so if there is a struct it won't be null
if sd != null then
    //get rid of the struct so a new one can be attached
    call ClearUnitStructA(uCaster)
endif
set sd = spelldata.create(uCaster,uTarget)
call SetUnitStructA(uCaster)

but now i'm getting errors like:
Error: Hash[A]: get request on unknown handle
Error: Hash[A] attchment overwrite on unit #1046847
when there is no struct attached to the unit and i get:
Error: Hash[A]: clear request on unknown handle
Error: Hash[A] attchment overwrite on unit #1046847
when there is a struct attached to the unit. It doesnt like the GetUnitStructA() if there is no struct attached and it doesnt like ClearUnitStructA() even if there IS a struct attached.

by the way, before anyone claims that ABC cannot be used to attach structs to units, i've already tested it in a different way. I created 2 triggers with 2 regions, when a unit enters 1 region i create a struct that contains a string and a location. the location is the unit's location and the string is the unit's name. then i had a second trigger for when a unit enteres a different region it gets the struct attached to the unit, clears out that attachment, spits out a BJDebugMsg with the string inside the struct and it moves the unit to the location inside the struct. it worked perfectly. so the problem isnt attaching to units, it is detecting wether or not there is something already attached to that unit.

can anyone come up with a better way to make this spell?
 

Flare

Stops copies me!
Reaction score
662
ABC doesn't support unit attachment.
EDIT: I'll quote the information from ABC (you don't realise how long it took me to get this, my internet is going REALLY slow)
JASS:
//       * Currently supported <handle> types are timer, trigger and dialog
//         ABC can NOT be used to attach things to units,
//         Systems that can attach stuff to units require a mission key
//         ABC does not have mission keys, witch is one of the reasons it is so fast.


You can use custom value instead (just SetUnitUserData (whichunit, structvar) then recall it with)
JASS:
local Structdata data = GetUnitUserData (GetTriggerUnit ())
//or any other unit that can be recalled


Easiest way I can see is with 4 triggers excluding the main one (all specific units, one for each unit for death, and one each for damage taken). When damage is taken, recall your struct data with GetUnitUserData (shown above) then do what you want. Then, when either unit dies, destroy your lightning and your struct.

Would probably be much easier for MUI with direct unit attachment (using CSData, HSAS or HAIL) since two units casting on the same target would interrupt an instance (since custom value can only have one value and the data would be f*cked up since you would lose the reference to first struct instance).

IMO, doing it with CSData/HAIL/HSAS would be more effective since it's less likely to bug with MUI-related problems since you're 'attaching' to locals/struct members, so stuff won't be overwritten and it leaves custom value open for other things
 

Gwypaas

hook DoNothing MakeGUIUsersCrash
Reaction score
50
All attachment systems can attach to triggers, it's just that cohadar removed a few of the handles because he thought there was no use for them.

A tip would be using HSAS, HAIL or CSData since they are faster and is able to attach to everything.
 

Grundy

Ultra Cool Member
Reaction score
35
if youadd these lines to the ABC trigger
JASS:
//! runtextmacro ABC("A","Unit","unit")

call InitUnitHashA()
then ABC can be used to attach structs to units.

I don't care if yo believe me or not. If you're so subborn to say that it can't be done then do you know of another way to make this spell work?

No matter what system I use there will always be somebody telling me to use something different so I'm not going to use all these different systems in my map - everone would still tell me that I'm using the wrong one. So, f*** it I'm just going to use the one that I already have and know how to use.
 
Reaction score
333
if youadd these lines to the ABC trigger
JASS:
//! runtextmacro ABC("A","Unit","unit")

call InitUnitHashA()

You could use //! runtextmacro ABC("A","Handle","handle") and attach to any handle type, without the needless duplication of code.

I use there will always be somebody telling me to use something different so I'm not going to use all these different systems in my map - everone would still tell me that I'm using the wrong one. So, f*** it I'm just going to use the one that I already have and know how to use.

I love this philosophy that progress is bad.
 

Flare

Stops copies me!
Reaction score
662
Even if you add that line Grundy, it's probably still not very useful since (1) ABC was originally designed only to take triggers, timers and dialogs so I can't see it being so easy to incorporate unit attachment (the ABC documentation said something about not using mission keys which prevented unit attachment, but allowed for greater speed) and (2) if you are getting errors with it, it can't be working, now can it :p

And I'm curious, why give the textmacro two unit arguments? Aren't you trying to attach a struct to a unit, not a unit to a unit?

No matter what system I use there will always be somebody telling me to use something different so I'm not going to use all these different systems in my map - everone would still tell me that I'm using the wrong one. So, f*** it I'm just going to use the one that I already have and know how to use.

There's no 'right' and 'wrong' system to use (apart from Handle Vars since it's old :p) and learning a new system like CSData/HAIL/HSAS now is beneficial since they are designed for attaching to practically any handle-type, without any modification (CSData has a few limitations, of about 6 handle-types).

I've never used HSAS/CSData, but I can say that HAIL is easy as f*** to use. Just call the textmacro with 3 arguments, and it generates 3 functions for you to use. Stick with ABC if you want, I'm just pointing out a good alternative (simple to use, faster and more versatile)

JASS:
library Test requires HAIL
//! runtextmacro HAIL_CreateProperty ("Data", "integer", "public")

//This will generate the 3 functions that are used for attaching/retrieving/clearing data
//1st argument: The name allocated to your function calls (in this instance, we will have SetData, GetData, and ResetData)
//2nd argument: The type of data taken (in the case of attaching structs, this'll be integer)
//3rd argument: Whether the functions are public/private members of your scope/library. This argument can be set to "" if you want to leave it as a normal function
endlibrary

function TestFunc takes nothing returns nothing
local integer i = 15
local integer i2
local trigger t = GetTriggeringTrigger ()
//And your 3 HAIL functions
call Test_SetData (t, i)
set i2 = Test_GetData (t)
call Test_ResetData (t)
set t = null
endfunction
 

Gwypaas

hook DoNothing MakeGUIUsersCrash
Reaction score
50
HSAS is like HAIL but it goes to GameCache when to many things gets attached and the text macro only takes 1 argument.

(Atleast older versions did.)
 

Flare

Stops copies me!
Reaction score
662
HAIL doesn't go to GC after exceeding the dedicated low bound value? I thought it did :\ And even if HSAS only takes 1 argument (what argument would that be? HSAS always confused me :p), the HAIL textmacro does give alot of flexibility with creating the functions :)

EDIT: I see nothing related to GC in HAIL's code, so I guess it doesn't use GC after the dedicated index is exceeded :)
 

Cohadar

master of fugue
Reaction score
209
All attachment systems can attach to triggers, it's just that cohadar removed a few of the handles because he thought there was no use for them.
A tip would be using HSAS, HAIL or CSData since they are faster and is able to attach to everything.

Nope, cohadar did not include a few of the handles because he knew there was a better way for them.

Ok Grundy a friendly advice: never translate a raw gamecache spell to anything.
It never works. It is too complicated and it will actually take you less time to make it from scratch.

Trust me I have lot experience in converting gamecache spells and every time I did it I was sorry for it.

Now check this out: You don't need unit attaching to make spell that you just described. (did I mention hacking ABC like you did was bad?)
You need simple timer and pair struct that is all.
JASS:

private struct Pair
    unit caster
    unit target
    // some other data
endstruct


Then you make an array of those structs
JASS:

globals
    private integer n = 0
    private Pair array Pairz
endglobals


And some periodic function to do the spell stuff for you:
JASS:

private function Periodic takes nothing returns nothing
    local integer i=0
    loop
        exitwhen i>=n
        call DoSomethingWithStruct(pairz<i>)
        set i = i + 1
    endloop
endfunction
</i>


As for the rest of you people I suggest you inform yourself here
 

Grundy

Ultra Cool Member
Reaction score
35
that wouldnt work. I need to get the struct when the unit casts's the spell - there's no timer to get the struct from. I can't get the struct from the trigger because then it wouldnt be MUI every time the spell is cast it would cancel out the previous instance.

...maybe an array of structs - but then I wouldn't know what to use for the index. converting the handle of the unit to integer, that would be too big for the index of the array.
 
Reaction score
333
...maybe an array of structs - but then I wouldn't know what to use for the index. converting the handle of the unit to integer, that would be too big for the index of the array.

JASS:
set MyArray[H2I(MyUnit)-0x100000] = MyValue
 
C

Chindril

Guest
Are you kidding me ? You're doing -0x100000 everytime you want to access the index of a unit ?

I agress with Cohadar that translating a game cache spell to ABC is a waste of time (was a sad experience). Recode it all, it will pratice you with JASS.

- Chindril
 
C

Chindril

Guest
Yes, it's totally horrible and bad coding practice. At LEAST make a function that does the H2I(MyUnit)-0x100000.

Oh no wait, you guys are speed-freak and ready to do any kind of awful code to get the tiny bit of speed bonus.

Let's take a situation. Tomorrow, blizzard releases patch 1.22 and suddently, the unit handles doesn't start at 0x100000 anymore, but 0x050000 (just an exemple). What you doing if you used that code at 834 places in your map ?

This is not a rant aimed to you TheDamien, but for some reason, most people doing Jass are soooooo minded to get every bit of possible speed ever. I'm pretty sure if we could code in ASM most of you would.

- Chindril
 

Flare

Stops copies me!
Reaction score
662
Let's take a situation. Tomorrow, blizzard releases patch 1.22 and suddently, the unit handles doesn't start at 0x100000 anymore, but 0x050000 (just an exemple). What you doing if you used that code at 834 places in your map ?

1) How likely is that situation? That example doesn't really help your argument :p
2) NewGen does have a Find & Replace function.
3) What's wrong with trying to achieve best possible speed in your code? How someone else codes doesn't necessarily affect you in a bad way (unless it's really bad coding and screws up the map, but if it's good coding that makes everything faster?)
 
C

Chindril

Guest
1) That's how you get screwed up, something changes that you did not anticipated and you have to waste hours changing it. Yes, my exemple is unlikely, but you get the point.
2) Ok, it helps you do it faster, but you still have to check them one by one to make sure you have to change it. Doesn't help you if your constant is a common number.
3) It's wrong when you give up code readability and cleaness for speed. It IS worth it in some cases, but most often it isn't. When I get home, I'll grab you a whole bunch of BJ's that you should keep in your code as an exemple. (I read WAY too much "Avoid all BJs" all over the Jass forum)

- Chindril
 
Reaction score
333
Yes, it's totally horrible and bad coding practice. At LEAST make a function that does the H2I(MyUnit)-0x100000.

-0x100000 is absolutely fine unless you're leaking (which actually is bad practice). It was given as an example and didn't need to be put into a function to accomplish this.

Oh no wait, you guys are speed-freak and ready to do any kind of awful code to get the tiny bit of speed bonus.

You realize that inlined 0x100000 attachment is roughly 4 times faster than ABC? That isn't a "tiny" bit of speed bonus, that is a hell of a lot.

Let's take a situation. Tomorrow, blizzard releases patch 1.22 and suddently, the unit handles doesn't start at 0x100000 anymore, but 0x050000 (just an exemple). What you doing if you used that code at 834 places in your map ?

What if Blizzard released a patch tomorrow that changed the name of every single native. What would do you if you used those natives 834 times in your map without individual wrapper functions? What if Blizzard released a patch tomorrow that replaced Jass with a Warcraft-specific Lisp dialect? What if Blizzard released a patch that stole all your socks? Blah blah blah.

Even if I hadn't put the -0x100000 in a constant or function, the scenario is so unlikely that I would be comfortable having to use find+replace in the event that it actually occurred.

This is not a rant aimed to you TheDamien, but for some reason, most people doing Jass are soooooo minded to get every bit of possible speed ever. I'm pretty sure if we could code in ASM most of you would.

It's because speed difference is actually important in Jass if you want to make lots of cool things that run smoothly.
 
Status
Not open for further replies.
General chit-chat
Help Users

      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