System Attribute Increase

T

Twyddli

Guest
I have created a system that allows each player to increase their heroes Strength, Intelligence and Agility manually, so that they can choose what type of hero they want, a strong one a smart one, or a quick one.

Here is how it works.
When your hero levels, it will gain one skill point, and then it adds 3 more. You can use these 4 Skill points to level abilities or stats, I think if you level just abilities with these then when you get to level 10 you will still have many skill points left, that you can put into stats.

When you learn a skill it checks if you have 1 skill point or less, if so it disables the three stat abilities. making it so that you can only put up 3 stat levels per hero level.
I will put up some the triggers and what ever is Red can be changed.

There is one Unit Variable array in this map. Heroes[1-12] You change the array to how many players you have. You will have to set the variable in the game when you get your hero.

This trigger increases your agility when you increase the skill change the green 1 to any number, this is the amount of Agi your hero gets when it levels agility (agi +1) ability. Agility (Agi +1) is a custom ability, based on attribute point, i nulled all its effects though.
Code:
Agi
    Events
        Unit - A unit Learns a skill
    Conditions
        (Learned Hero Skill) Equal to Agility (Agi +1)
    Actions
        Hero - Modify Agility of (Triggering unit): Add [COLOR="Red"]1[/COLOR]
        Unit - Decrease level of Agility (Agi +1) for (Triggering unit)
        Unit - Remove Agility (Agi +1) from (Triggering unit)

This trigger does the exct same as the first one, only for strength
Code:
Str
    Events
        Unit - A unit Learns a skill
    Conditions
        (Learned Hero Skill) Equal to Strength (Str +1)
    Actions
        Hero - Modify Strength of (Triggering unit): Add [COLOR="Red"]1[/COLOR]
        Unit - Decrease level of Strength (Str +1) for (Triggering unit)
        Unit - Remove Strength (Str +1) from (Triggering unit)

Same as this one, but for Intelligence.
Code:
Int
    Events
        Unit - A unit Learns a skill
    Conditions
        (Learned Hero Skill) Equal to Intelligence (Int +1)
    Actions
        Hero - Modify Intelligence of (Triggering unit): Add [COLOR="Red"]1[/COLOR]
        Unit - Decrease level of Intelligence (Int +1) for (Triggering unit)
        Unit - Remove Intelligence (Int +1) from (Triggering unit)

This one is how many attribute points you get when you level. Change the green 3 to what ever you want.
Code:
Hero Levels
    Events
        Unit - A unit Gains a level
    Conditions
    Actions
        Hero - Modify unspent skill points of (Triggering unit): Add [COLOR="Red"]3[/COLOR] points
        Player - Enable Agility (Agi +1) for (Owner of (Triggering unit))
        Player - Enable Intelligence (Int +1) for (Owner of (Triggering unit))
        Player - Enable Strength (Str +1) for (Owner of (Triggering unit))

When you make your unit, and you want it to have these abilities, you have to put them in the hero abilities part of the object editor and then after .01 seconds has passed, it will disable them, until you level.

To test this map, while in the game, type -level and it will increase the level of the hero by 1.

There is only one problem i have found with this system... You can then only have 2 hero abilities.

I would love to hear your feedback, and ideas on how to improve it.
Good luck! Have fun! ;)
Edit: I fixed something in the map, should be better now.
 

Attachments

  • [System] Attribute Increaser.w3x
    19.4 KB · Views: 315

Ghan

Administrator - Servers are fun
Staff member
Reaction score
888
Code:
Unit - Remove Agility (Agi +1) from (Triggering unit)

Won't this prevent you from adding any more agility to the unit? You can't re-add the ability, you know. ;)

> I will put up some the triggers and what ever is Green can be changed.

That's pretty unnoticeable. I would change it to a different color. :D
 

DuckieKing

Elitist Through and Through
Reaction score
51
Code:
        Unit - Decrease level of Agility (Agi +1) for (Triggering unit)
        Unit - Remove Agility (Agi +1) from (Triggering unit)
Did you try doing this without the "Decrease level..."? I'm fairly (100%) sure you don't need it.

edit: A way to get around having only two hero abilities would be to use a spellbook with dummy spells for raising stats. That way you can even disable the spellbook and hide the stat bonus feature when there are no bonus stats to be had. Cons might be either a variable to hold the number of stats a unit has or limiting the system to newgen jass, if you use structs + custom value.

anotheredit: Gonna post a test map? Not that I intend on downloading it. I never download test maps. I'm just too lazy to open WC3/WE.
 
T

Twyddli

Guest
Ghan, I will change the green to red i think, and also I have tested it and it works, even when you remove the ability, all it does is remove it from your learnt skills, but you can still increase it.

DuckieKing, I didn't know that i didn't need that, thanks for telling me though.

Edit: Yeah i just relized it wasn't up, so i put it up then i tested it again to check if Ghan was right, but it doesn't disable the abilities when you have only 1 Attribute point.. Ill see if i can fix it.

Edit2: Ok i think i have fixt up the problem, ill put the fixed one up.
 

Ghan

Administrator - Servers are fun
Staff member
Reaction score
888
> also I have tested it and it works, even when you remove the ability, all it does is remove it from your learnt skills

Interesting. As this is a system, a demo map would help for clarification. And yes, it would help greatly if you could get the system to work without taking up 3 hero abilities.
 
T

Twyddli

Guest
> As this is a system, a demo map would help for clarification.

I accadentally forgot to click uplode, :eek:

Its up there now, and i had to fix it up a tiny bit so that you can only get 3 attributes per hero level, and not 4 ;) it should work now.
 

DuckieKing

Elitist Through and Through
Reaction score
51
AHA! I remembered how to attach a struct to a unit. I didn't think of it's because it's so hilariously simple.
Code:
  call SetUnitUserData(theUnit, unitData)
If you need help with this I'll gladly give it, but basically what I'm suggesting you do is create a new variable type that can hold as many integers, reals, units, etc. that you want to attach to a unit or item. You'd be using this initially to store the number of bonus stats a hero has to apply. The reason you'd need structs to do this, though, is because it's infinitely multiinstanceable, and intuitive, if you understand the language. That might be problem, though, since it's a bit more complex than Jass. :p
 
T

Twyddli

Guest
:eek: I don't even really know JASS, I don't even understand properly what you are suggesting. :O if you can expain it in even more detail, for a really newbie, then maybe ill understand ;)
 

DuckieKing

Elitist Through and Through
Reaction score
51
Crash course in Jass/C! Though technically a struct contains only member data (variables) and no member functions (methods).
JASS:
struct unitData //this is a new variable and is declared like any other: "local real currentHP" turns into "local unitData uD"
  unit subject
  real currentHP
  real maxHP //these are the variables created when you create the struct unitData, and any unitData you create is the combined size of all its variables

  method DamageUnit takes real damage returns nothing  //a method is like the Actions part of a trigger; it "takes" variables like a real or integer so that it does something different every time, otherwise it'd be worthless; returns is not important right now
    call SetUnitState(this.subject, UNIT_STATE_LIFE, GetUnitState(this.subject, UNIT_STATE_LIFE)-damage) //"SetUnitState" is used to change a unit's current life or mana without firing damage triggers; this.subject refers to the unit variable in the struct, named "subject"; "this." is just a pointer to the struct; "GetUnitState" to get the unit's current life, "-damage" to get the unit's current life minus the damage being taken
  endmethod
endstruct

Read it, let it soak in, type in your question but don't hit submit, read it again, then post your questions. It's a lot to take in at once. You might wanna try some of the Jass tutorials floating around in this section to learn the syntax.

edit: You know about custom values, right? You can give a unit an integer, and then you can get the integer from a trigger. It's better than a global.

To make it even BETTER, you can set the unit's custom value to be a struct, which is a user-created variable that can contain other variable types.

For example, the base types in C, the language WC3 was written in, are in short float (real), int (integer), and char (string). From that, Blizzard made the other variable types containing their own variables, or member data: a unit contains max life (real), current life (real), max mana (real), current mana (real), move speed (integer), attack range (integer), attack damage (a whole bunch of integers), etc.

In short, a struct is a variable that holds the values for other variables. This can be used by you to hold custom unit data such as extra stat points, extra spell damage, number of xx ability that has been stacked on a unit, and hold it all by using a unit's custom value, allowing you to do many things to many units without needing massive unit and player arrays.

I did not mean to type a term paper. Oops.
 
T

Twyddli

Guest
Ok i have read it a few times, And i think im gettin gbits of it. I see how this.subject is a unit. But do you have to set unit subject? do you have to set the real values current HP and max HP? Im also not entirely sure on what the struct UnitData is. Like is it kinda like floating information that you can grab just like a variable? And do does your trigger put subject, maxHP and CurrentHP into UnitData?

I can see what is going on in this triggers method i think.
It takes a real (Please Explain, im a little fuzzy what this meens.)
Then it sets the life of Subject(Thats a unit) to its current life - damage.

Also, Does the Struct contain its variables AND the Method? is that why you end struct after the method has happened? And not when the Struct has done every thing.

What exactly does the Struct do in this trigger? is it stting everything up to say that these three things are in this Struct?

and lastly, I will look at some tutorials.
Thanks ;)
 

DuckieKing

Elitist Through and Through
Reaction score
51
You picked it up quite fast. I shall now tower-quote.
What exactly does the Struct do in this trigger? is it stting everything up to say that these three things are in this Struct?
I put the end of your post up here for a reason: This is not a trigger. It has no events and the only action has to be called inside a function. A function is just like a method, except methods are exclusive to structs. Functions are how everything is done in Jass, and I'll show how structs work in functions...

do you have to set unit subject? do you have to set the real values current HP and max HP?
Yes. This is done in a Jass trigger with the following calls:
JASS:
local unit u=CreateUnit(Player(0), 'hfoo', 0, 0, 0) //"native CreateUnit takes player whichPlayer, integer unitTypeId, real x, real y, real facing returns unit"...I assign a newly created unit to "u"; "u" is assigned the "returned" value of "CreateUnit"
local unitData uD=unitData.create() //the struct is created and given the name uD
set uD.subject=u
set uD.maxHP=GetUnitState(uD.subject, UNIT_STATE_MAX_LIFE)
set uD.currentHP=uD.maxHP //you use "uD.", the name of the struct created and a period, to point to the struct, and currentHP/maxHP to point to the specific variables
call uD.DamageUnit(50)
I want it clear, though, that doing this will not actually modify the unit's health as perceived by the health bar or numbers under its icon. The struct's member data and method are only meant to supply an analogy.

It takes a real (Please Explain, im a little fuzzy what this meens.)
Fuzzy on what a real is or what the method does? The method modifies the struct's reals, which are numbers that can be fractional (2.5, 0.75) as opposed to integers, which are whole numbers (2, 0).

Also, Does the Struct contain its variables AND the Method? is that why you end struct after the method has happened? And not when the Struct has done every thing.
Not exactly. Everything between struct and endstruct is the struct declaration. It tells the game engine what to create when create.<structname>() and <structname>.<methodname>() are called.

Im also not entirely sure on what the struct UnitData is. Like is it kinda like floating information that you can grab just like a variable? And do does your trigger put subject, maxHP and CurrentHP into UnitData?
Have these been answered yet?

The struct is your own variable type. It is in essence a variable, which is a block of memory set aside by the program to contain a series of 1's and 0's. The difference between a struct/unit and an integer is purely one of style and implementation. When an integer is created, 4 bytes are set aside. When a struct containing two integers is created, 8 bytes are set aside.
 
T

Twyddli

Guest
Ok, i think i got some more of it. You need one trigger that fires off the Struct like a unit takes damage, then it does everything. But before the Struct is fired, you need to have already set the three (i forgot what they are called) Unit, Real and Real, or it wont work? is that right?

I want it clear, though, that doing this will not actually modify the unit's health as perceived by the health bar or numbers under its icon. The struct's member data and method are only meant to supply an analogy.
What exactly would you use this for? Like could you give me some examples? ;) Thanks heaps for helping
me.

Let me have a quick go at some free hand JASSing, so i can ask if i got it right.

Code:
function Test actions takes nothing returns nothing
    call set subject = Attacked unit
    call set maxHP = max HP of attacked unit
    call set currentHP = current HP of attacked unit
    call uD.DamageUnit(50)
endfunction
//======================
The event stuff create trigger blah blah
the event that says a unit is attacked
So this one up here ^ would set everything, then run this one down bottom.(Your one)
Code:
struct unitData //this is a new variable and is declared like any other: "local real currentHP" turns into "local unitData uD"
  unit subject
  real currentHP
  real maxHP //these are the variables created when you create the struct unitData, and any unitData you create is the combined size of all its variables

  method DamageUnit takes real damage returns nothing //a method is like the Actions part of a trigger; it "takes" variables like a real or integer so that it does something different every time, otherwise it'd be worthless; returns is not important right now
  call SetUnitState(this.subject, UNIT_STATE_LIFE, GetUnitState(this.subject, UNIT_STATE_LIFE)-damage) //"SetUnitState" is used to change a unit's current life or mana without firing damage triggers; this.subject refers to the unit variable in the struct, named "subject"; "this." is just a pointer to the struct; "GetUnitState" to get the unit's current life, "-damage" to get the unit's current life minus the damage being taken

  endmethod
 endstruct

Is that what it basically is? If it isn't please tell me ;)
Thanks a billion! :D :D :D :D
 

DuckieKing

Elitist Through and Through
Reaction score
51
In real programming, the member data are private, meaning they cannot be modified except by member functions, which would be the methods.

It is BAD practice to "set uD.currentHP". Instead, you would have seperate methods to do this, like "call uD.DamageUnit".

The purpose of structs and classes in real programming is encapsulation. Encapsulation is the idea that tasks should be as seperate as possible to make configuration and maintenance of code simpler and clearer.

The purpose of structs in WC3 is attaching multiple variables to one. By doing this you easily increase multiinstanceability of almost any triggered effect you can think of, including this stat system. Example...
JASS:
struct unitData
  unit u //a variable is added to reference the unit whose data is held
  integer statCredits=4 //this variable is initialized to 4, so that a new hero has 4 stats to spend

  method ModifyStatCredits takes integer statBonus returns nothing //takes an integer in case you want to add quests that give different bonus stats than leveling does; also allows removal of credits in case it were ever necessary, note that the credits can be negative so that the spellbook won&#039;t be activated at the next level (or they&#039;ll just have fewer stats)
    if this.statCredits &lt;= 0 and this.statCredits+statBonus &gt; 0 then
      call SetPlayerAbilityAvailable(this.u, &#039;A000&#039;, true) //reactivates the spellbook if it wasn&#039;t active and credits are now positive
    endif
    set this.statCredits=this.statCredits+statBonus
  endmethod
    

  method BuyStat takes integer a returns nothing //this method will remove one stat credit and raise the stat
    set this.statCredits=this.statCredits-1
    if a == &#039;A001&#039; then
      call this.RaiseAgi()
    endif
    if a == &#039;A002&#039; then
      call this.RaiseInt()
    endif
    if a == &#039;A003&#039; then
      call this.RaiseStr()
    endif
    if this.statCredits &lt;= 0 then
      call SetPlayerAbilityAvailable(this.u, &#039;A000&#039;, false) //here we disable the spellbook if there are no more stats to buy, this will close the spellbook like if you run out of hero points in the ability selection screen
    endif
  endmethod

  method RaiseAgi takes nothing returns nothing //encapsulation specifies that we let functions do as little as possible on their own
    call SetHeroAgi(this.u, GetHeroAgi(this.u)+1)
  endmethod
  method RaiseInt takes nothing returns nothing //no need for another empty line, all three of these methods do the same thing
    call SetHeroInt(this.u, GetHeroInt(this.u)+1)
  endmethod
  method RaiseStr takes nothing returns nothing
    call SetHeroStr(this.u, GetHeroStr(this.u)+1)
  endmethod
endstruct


Whew, a lot of work went into that. It was mostly in the comments. You should write comprehensive comments for yourself, too, and make use of whitespace. It makes maintaining code easier, as you might forget the purpose of what you've written before.

edit: I forgot to show how structs work with triggers. x_x An example trigger utilizing this struct would be as follows:
JASS:
function HeroLevelsUp takes nothing returns nothing
  local unitData uD=GetUnitUserData(GetTriggerUnit()) //creates a local struct using the &quot;TriggerUnit&quot;&#039;s custom value; &quot;GetUnitUserData&quot; will return the struct which is assumed to have been attached to the triggering hero when it was created, then assigns it to uD; &quot;TriggerRegisterAnyUnitEventBJ&quot; will allow you to use both &quot;GetTriggerUnit&quot; and &quot;GetTriggerPlayer&quot; with all events
  call uD.ModifyStatCredits(4) //calls the ModifyStatCredits method and sets a=4
  call uD.destroy() //this is important; if you don&#039;t destroy a local struct it wastes the memory it occupies as it can&#039;t be used once the function ends
endfunction

function Init_Trig_Hero_Levels_Up takes nothing returns nothing //this function runs at map initialization and creates the trigger
  set gg_trg_Hero_Levels_Up=CreateTrigger() //&quot;gg_trg_Hero_Levels_Up&quot; would be the variable name of the trigger &quot;Hero Levels Up&quot;
  call TriggerRegisterAnyUnitEventBJ(gg_trg_Hero_Levels_Up, EVENT_PLAYER_HERO_LEVEL) //this tells the trigger to fire when a hero of any player levels up
  call TriggerAddAction(gg_trg_Hero_Levels_Up, function HeroLevelsUp) //this tells the trigger to perform this function when it is fired by any hero leveling
endfunction //all in all a standard trigger init function: function init-&gt;set trigger=create trigger-&gt;call triggerregister-&gt;call triggeraddaction

Well gee, I pretty much just wrote your stat system for you if you choose to use structs. You can do the part that raises the stats and attaches the struct though. :)
I'll link some tools you need to use structs and Jass.
Jass NewGen Pack, to use structs without compile errors
 
T

Twyddli

Guest
Ok, so do the Structs kinda check constantly if something is going on, and if one this is going on it changes something, else it cahnges something else? a bit confusing let me try again.

Structs constantly check, in this instance, what an integer is. If the integer is higher than 0 then it shows an ability, if the integer is 0 or less, it hides the ability?

I think i am beginning to see how this all works. They don't use events, they are just constantly running and checking to see if an integer = 0 or greater than 0. Correct me if i am wrong.
When or where do you set the variable statBonus and the variable a.
I don't see anywhere that you set them?

Could you maybe go through your trigger explaining what each part does? and what each bit of each line does? If its not too much trouble.

I find i understand this slightley but then i look at it again and i don't know whats going on. I'm a little confused.
I will +Rep you! ;)
 

DuckieKing

Elitist Through and Through
Reaction score
51
The variables in a struct are just like variables outside a struct; they can be called in any function the struct is created.

The methods are just functions that can only be called in a function that has this struct. They don't run on their own; they need a trigger to call them.

This struct would check the number of stat credits a hero would have whenever you called ModifyStatCredits, and I did the naming conventions wrong. -.- All the methods should be capitalized. Fixing now.
 
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