| 11-22-2010, 01:13 PM | #1 |
I'm trying to learn some Jass, but I think this system is currently beyond my capabilities. More specifically, I'm trying to make a system in which: -Each of three characters has 4 custom attributes (the same four for all characters) -Each attribute gives bonus damage, defense etc. based on a different formula depending on the character. -Armor absorbs an integer amount of damage (Damage = Damage - (Armor/2)). If anyone is interested in helping me, I can fill you in on more details. |
| 11-22-2010, 05:40 PM | #2 |
Note: the following code is in vJass, I hope that is all right for you because you will find it difficult to find anyone still working in plain JASS. Let's start with the attributes themselves. This is a fairly simple task, we just need to store a few integer values on a per-unit basis. AutoIndex is useful for this sort of thing: JASS:library Attribute requires AutoIndex //! textmacro Attribute takes ATTRIBUTE globals private integer array $ATTRIBUTE$ endglobals private function GetUnit$ATTRIBUTE$ takes unit u returns integer return $ATTRIBUTE$[GetUnitId(u)] endfunction private function SetUnit$ATTRIBUTE$ takes unit u, integer a returns nothing set $ATTRIBUTE$[GetUnitId(u)] = a endfunction //! endtextmacro // This is an example using WC3 attributes, you will declare your four attributes here isntead. //! runtextmacro Attribute("Strength") //! runtextmacro Attribute("Agility") //! runtextmacro Attribute("Intelligence") endlibrary Now, we could also add functions that get and set default attributes for each unit type and then automatically initialize those attributes whenever a unit enters the map, but since you have only three units you want to use this for we might as well hardcode it instead: JASS:library DefaultAttribute initializer Init requires Attribute, AutoIndex private function InitAttributes takes unit u returns nothing local integer i = GetUnitTypeId(u) if i=='u000' then // replace 'u000' with your character unit's rawcode. call SetUnitStrength(u, 15) // This is a function from the attribute system. // Repeat the above line for all four attributes. elseif i=='u001' then // Repeat for all units that use attributes. endif endfunction private function Init takes nothing returns nothing call OnUnitIndexed( InitAttributes ) endfunction endlibrary For the actual damage/armour/life bonuses, we will use BonusMod. You didn't specify whether an attribute can modify multiple bonuses or if multiple attributes can affect the same bonus, so I will make the code as open as possible to allow for such things. Whenever any of the attributes changes, we need to update all the unit's bonuses accordingly, so we will need to add support for that to the Attribute library: JASS:library Attribute requires AutoIndex public function interface Update takes unit u returns nothing globals private Update array U private integer N=0 endglobals private function AttributeUpdate takes unit u returns nothing local integer i=0 loop exitwhen i==N call U[i].execute(u) endloop endfunction function OnAttributeUpdate takes Update u returns nothing set U[N]=u set N=N+1 endfunction //! textmacro Attribute takes ATTRIBUTE globals private integer array $ATTRIBUTE$ endglobals private function GetUnit$ATTRIBUTE$ takes unit u returns integer return $ATTRIBUTE$[GetUnitId(u)] endfunction private function SetUnit$ATTRIBUTE$ takes unit u, integer a returns nothing set $ATTRIBUTE$[GetUnitId(u)] = a call AttributeUpdate(u) endfunction //! endtextmacro // This is an example using WC3 attributes, you will declare your four attributes here isntead. //! runtextmacro Attribute("Strength") //! runtextmacro Attribute("Agility") //! runtextmacro Attribute("Intelligence") endlibrary And now, the AttributeBonus library: JASS:library AttributeBonus requires Attribute, AutoIndex, BonusMod globals // I will use 2D arrays to store attribute bonus data for each unit. // We must set the 2D array size big enough to avoid bugs. // The values set here should be sufficient, while still being small enough to not require multiple arrays. private constant integer MAX_UNIT_ID=400 private constant integer MAX_BONUS_ID=20 private integer array bonus [MAX_UNIT_ID][MAX_BONUS_ID] endglobals function SetUnitAttributeBonus takes unit u, Bonus bonusType, integer amount returns nothing local integer id=GetUnitId(u) if bonus[id][integer(bonusType)] != amount then // Using AddUnitBonus instead of SetUnitBonus allows the attribute bonuses to stack with bonuses from other sources: call AddUnitBonus(u, bonusType, amount-bonus[id][integer(bonusType)]) set bonus[id][integer(bonusType)]=amount endif endfunction endlibrary The last thing we need is to actually calculate the bonuses based on attributes, I will add this functionality to the DefaultAttribute library: JASS:library DefaultAttribute initializer Init requires Attribute, AttributeBonus, AutoIndex private function InitAttributes takes unit u returns nothing local integer i = GetUnitTypeId(u) if i=='u000' then // replace 'u000' with your character unit's rawcode. call SetUnitStrength(u, 15) // This is a function from the attribute system. // Repeat the above line for all four attributes. elseif i=='u001' then // Repeat for all units that use attributes. endif endfunction private function UpdateAttributeBonus takes unit u returns nothing local integer i = GetUnitTypeId(u) local integer damage local integer armor // I added local variables for bonuses to make the code more readable. if i=='u000' then // replace 'u000' with your character unit's rawcode. set armor = R2I(GetUnitStrength(u)*0.1+GetUnitAgility(u)*0.25) set damage = R2I(GetUnitAgility(u)*0.2+GetUnitIntelligence(u)*0.5) elseif i=='u001' then // Repeat for all units that use attributes. endif call SetUnitAttributeBonus(u, BONUS_ARMOR, armor) call SetUnitAttributeBonus(u, BONUS_DAMAGE, damage) endfunction private function Init takes nothing returns nothing call OnUnitIndexed( InitAttributes ) call OnAttributeUpdate( UpdateAttributeBonus ) endfunction endlibrary That should cover your attributes. Now, to make armour function differently, we must first disable the default armour functionality in the gameplay constants. Then, we need to write our own armour library using damage modifiers. I'll leave that for another post, though, try to first get the attribute system to work. If there are any errors in the code I posted, post about it here or you can also find me on the wc3c irc channel. |
| 11-23-2010, 09:00 PM | #3 |
Wow, I didn't expect to get a reply so soon! Thanks a lot, but I'm afraid it'll take until next friday until I have some spare time to code. I'll try to make the system work and then I'll post it here when I'm done (or completely bugging it). |
