| 03-28-2007, 03:52 AM | #1 | |
Version History:
A simple attribute system which enables players the chance to manually choose what attributes to increase when their hero levels up. Why use this as opposed to other attribute systems? Well as far as I know there is only one, Weaaddars. I used the same concept he did, however I wrote all these triggers from scratch. In comparison, this is more optimized, has no leaks(that I am aware of), is far easier to import(far as in a couple hundred miles), and has a far better read me(far as in in few thousand parsecs). In anycase, download, try it out, you may find it useful, and please comment. Credits to Dusk for his LastOrder library. system code:library AttributeSystem initializer Init needs LastOrder //*************************************************************************** //* * //* Attribute System v5 by: emjlr3 * //* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ **URL in the works * //* Requires: * //* ¯¯¯¯¯¯¯¯¯ * //* * //* - A vJASS Preprocessor * //* - LastOrder library by RisingDusk * //* - The custom items and abilities found in this map * //* - Updated globals in the configuration section * //* * //*************************************************************************** // Configuration Section: globals // Attribute(Attribute System) ability rawcode private constant integer Abil = 'A001' // Blank item rawcode private constant integer Blank = 'I000' // Cancel item rawcode private constant integer Cancel = 'I001' // Number of Stat Points Remaining item rawcode private constant integer At = 'I005' // Increment Strength item rawcode private constant integer Str = 'I004' // Increment Agility item rawcode private constant integer Agi = 'I002' // Increment Intelligence item rawcode private constant integer Int = 'I003' // Max handles in your map, each 8191 interval decreases speed :( private constant integer Max_Handles = 50000 endglobals //**Do not touch past here unless you pain for death!!**\\ private keyword Data globals private trigger Level = CreateTrigger() private trigger Inven = CreateTrigger() private trigger Att = CreateTrigger() private group Enabled = CreateGroup() private timer Timer = CreateTimer() private unit Hero = null private Data array D[Max_Handles] endglobals private struct Data item array it[6] integer points_per_level integer last_level integer points = 0 boolean on = false endstruct //-- Utilities // Return bug, data storage private function H2I takes handle h returns integer return h return 0 endfunction private function GetUnitData takes unit u returns Data return D[H2I(u)-0x100000] endfunction private function SetUnitData takes unit u, Data d returns nothing set D[H2I(u)-0x100000] = d endfunction // Swap the inventory private function SwapInv takes unit u returns nothing local Data d = GetUnitData(u) local integer i local item it if not d.on then set i = 0 else set i = 5 endif loop set it = UnitRemoveItemFromSlot(u,i) if d.it[i]!=null then call SetItemVisible(d.it[i],true) call SetItemInvulnerable(d.it[i],false) if GetItemTypeId(d.it[i])==At then // Points remaining item, update charges call SetItemCharges(d.it[i],d.points) endif call UnitAddItem(u,d.it[i]) endif if it!=null then call SetItemVisible(it,false) call SetItemInvulnerable(it,true) endif set d.it[i] = it if d.on then exitwhen i==0 set i = i - 1 else exitwhen i==5 set i = i + 1 endif endloop set d.on = not d.on // Swap between in and out of point inventory set it = null endfunction // Returns what slot the item is in private function GetItemSlot takes unit hero, item it returns integer local integer i = 0 loop exitwhen i==6 if UnitItemInSlot(hero,i)==it then return i endif set i = i + 1 endloop return -1 endfunction //-- Trigger functions // Universal condition checker private function Conditions takes nothing returns boolean return IsUnitInGroup(GetTriggerUnit(),Enabled) endfunction // When the hero levels up private function Level_Actions takes nothing returns nothing local unit u = GetTriggerUnit() local integer points local Data d = GetUnitData(u) local boolean b = not IsLastOrderFinished(u) set points = ((GetHeroLevel(u)-d.last_level)*d.points_per_level)+d.points set d.last_level = GetHeroLevel(u) if GetUnitAbilityLevel(u,Abil)<1 and not d.on then // No stat points previously call UnitAddAbility(u,Abil) call UnitMakeAbilityPermanent(u,true,Abil) endif if d.on then // In point inventory call SetItemCharges(UnitItemInSlot(u,1),points) endif set d.points = points call IssueImmediateOrder(u,"replenishon") if b then // If the heroes last order was not complete, re-order it call IssueSecondLastOrder(u) endif set u = null endfunction // Unit issued order to view inventory, or player tries to stop our blinking private function Blink takes nothing returns nothing call IssueImmediateOrder(Hero,"replenishon") call IssueImmediateOrder(Hero,"replenishlifeoff") call PauseTimer(Timer) endfunction private function Inven_Actions takes nothing returns nothing local unit hero = GetTriggerUnit() local integer order = GetIssuedOrderId() if order==OrderId("replenish") then // Go to selection items call UnitRemoveAbility(hero,Abil) call SwapInv(hero) elseif order==OrderId("replenishoff") then // Player tries to stop blinking set Hero = hero call TimerStart(Timer,0.0,false,function Blink) endif set hero = null endfunction // Correct path based on the selected item private function Att_Actions takes nothing returns nothing local unit hero = GetManipulatingUnit() local item used = GetManipulatedItem() local Data d = GetUnitData(hero) local integer array temp if not d.on then // Not in point inventory, some in game item was used set hero = null set used = null return endif set temp[0] = GetItemSlot(hero,used) set temp[1] = d.points-1 if temp[0]!=5 then // Not cancel call ModifyHeroStat( temp[0]/2,hero,bj_MODIFYMETHOD_ADD,1) set d.points = temp[1] if temp[1]<=0 then // No more points left call SwapInv(hero) else call SetItemCharges(UnitItemInSlot(hero,1),temp[1]) // Positive points remaining endif else // Cancel call SwapInv(hero) call UnitAddAbility(hero,Abil) call UnitMakeAbilityPermanent(hero,true,Abil) call IssueImmediateOrder(hero,"replenishon") // Re-add and flash points indicator endif set hero = null set used = null endfunction //-- User functions // Change stat gain for given hero public function UpdatePointsGain takes unit u, integer i returns nothing local Data d = GetUnitData(u) if i<=0 then set i = 1 endif set d.points_per_level = i endfunction // Change current points for given hero public function SetCurrentPoints takes unit u, integer i returns nothing local Data d = GetUnitData(u) if i<0 then set i = 0 endif set d.points = i if d.on then call SetItemCharges(UnitItemInSlot(u,1),d.points) endif if i==0 then call SwapInv(u) endif endfunction // Disable the system for the given hero public function UnRegister takes unit u returns boolean local Data d local integer i = 0 // Not enabled or dead check if not IsUnitInGroup(u,Enabled) then call BJDebugMsg("AttributeSystem_UnRegister Error: "+GetUnitName(u)+" has not previously been registered.") return false elseif GetWidgetLife(u)<.405 then call BJDebugMsg("AttributeSystem_UnRegister Error: "+GetUnitName(u)+" is currently dead and cannot be unregistered.") return false endif set d = GetUnitData(u) if d.on then call SwapInv(u) endif loop exitwhen i>5 call SetItemInvulnerable(d.it[i],false) call SetWidgetLife(d.it[i],0.) set i = i + 1 endloop call UnitRemoveAbility(u,Abil) call d.destroy() call SetUnitData(u,0) call GroupRemoveUnit(Enabled,u) return true endfunction // Enable the system for the given hero public function Register takes unit u, integer i returns boolean local Data d // Already enabled check if IsUnitInGroup(u,Enabled) then call BJDebugMsg("AttributeSystem_Register Error: "+GetUnitName(u)+" has already been registered.") return false endif call GroupAddUnit(Enabled,u) // Setup items and struct set d = Data.create() if i<=0 then set i = 1 endif set d.points_per_level = i set d.last_level = GetHeroLevel(u) set d.it[0] = CreateItem(Str,0,0) call SetItemVisible(d.it[0],false) call SetItemInvulnerable(d.it[0],true) set d.it[1] = CreateItem(At,0,0) call SetItemVisible(d.it[1],false) call SetItemInvulnerable(d.it[1],true) set d.it[2] = CreateItem(Agi,0,0) call SetItemVisible(d.it[2],false) call SetItemInvulnerable(d.it[2],true) set d.it[3] = CreateItem(Blank,0,0) call SetItemVisible(d.it[3],false) call SetItemInvulnerable(d.it[3],true) set d.it[4] = CreateItem(Int,0,0) call SetItemVisible(d.it[4],false) call SetItemInvulnerable(d.it[4],true) set d.it[5] = CreateItem(Cancel,0,0) call SetItemVisible(d.it[5],false) call SetItemDroppable(d.it[5],false) call SetItemInvulnerable(d.it[5],true) // Store struct to unit call SetUnitData(u,d) return true endfunction //=========================================================================== private function Init takes nothing returns nothing call TriggerAddAction( Level, function Level_Actions ) call TriggerAddCondition(Level,Condition(function Conditions)) call TriggerRegisterAnyUnitEventBJ( Level, EVENT_PLAYER_HERO_LEVEL ) call TriggerAddAction( Inven, function Inven_Actions ) call TriggerAddCondition(Inven,Condition(function Conditions)) call TriggerRegisterAnyUnitEventBJ( Inven, EVENT_PLAYER_UNIT_ISSUED_ORDER ) call TriggerRegisterAnyUnitEventBJ( Inven, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER ) call TriggerRegisterAnyUnitEventBJ( Inven, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER ) call TriggerAddAction( Att, function Att_Actions ) call TriggerAddCondition(Att,Condition(function Conditions)) call TriggerRegisterAnyUnitEventBJ( Att, EVENT_PLAYER_UNIT_USE_ITEM ) endfunction endlibrary
-emjlr3 |
| 03-28-2007, 03:56 AM | #2 |
hmmm you won't get friendly replies for saying your stuff is more optimized than weaaddar's ... But on a more serious note, I don't see much application on this system unless it actually keeps the item's bonuses, will take a look at it, if it doesn't then it will have to go to samples... |
| 03-28-2007, 04:02 AM | #3 |
take a look at this, then take a look at his system, with the zillion of fluff functions everywhere, and you will see what I mean, however on top of that, i still think this is more optimized, even taking that out of the picture it does not keep bonuses, impossible with this method IMO, however mentioning that would have been a good idea systems or samples, who cares, if someone gets use out of it then that is good |
| 03-28-2007, 11:35 AM | #4 |
Ah, i see what you mean when you say "less clunky". Yours is based on an item style system. nice, although, i still prefer mine for the context its supposed to be used in. |
| 03-29-2007, 02:17 PM | #6 | |
Quote:
Would this have anything to do with the stat-choosing ability being removed from the unit when morphing? If so, make the ability permanent. |
| 03-29-2007, 03:04 PM | #7 |
Yes, blu. Because of the removal of bonuses this is suitable for samples. So just fix the bug with permanent abilities and the preprocessor stuff then it should go. |
| 03-29-2007, 06:23 PM | #8 |
new version uploaded fixed the problem of ability permanency, as well as a bug where it would add the ability to the hero even if the system was not setup for that hero, even though you could not learn any abilities added documentation about items being removed, thus having bonus loss, as well as the need for Preprocessors (however I feel this is unnecessary, since CSCache and CSSafety both require a preprocessor, and your map needs those for this system to work at all) **btw can someone change the thread title to v2 from v1, thnx |
| 03-29-2007, 06:54 PM | #9 |
I'll check your system this night. Title modified. |
| 04-01-2007, 09:36 PM | #10 |
Sampilified. |
| 04-17-2007, 01:24 AM | #11 |
can i ask how to change attribute gain from 5 per lvl to 2 per lvl |
| 04-23-2007, 01:35 AM | #12 |
did you read the readme? |
| 12-14-2007, 03:49 PM | #13 |
pass level stop spell casting, just a note ^^ |
| 04-15-2008, 11:19 PM | #14 |
Hi after a long long time... this is my first post :P Anyway... I am currently using your Attribute System. I like it alot and somehow I know how to use it. My only problem is when calling the function AS_Enable. As I have read the "read me", you said there that you must call AS_Enable once because it might cause problems when it is called more than once. But it cannot be done in Initialization because the heroes that will use the system are not preplaced or created instantly upon Initialization(I'm using your system in an AoS map btw). The selection system that I'm using is Vexorian's Hero Selection System. To make the system work, the function is called after the hero is created. This works fine if the game is played by only one player. My only concern is that everytime a hero is created, the function is called. I haven't played the game with my friends so I can't tell if it will work fine or will cause problems. So what can I use as an alternative on calling the function once, whereby upon calling it, all heroes that will be created will be able to use the system? More Info: This is one of the triggers of Vexorian's Hero Selection System. This is the part where the AS_Enable is called: |
| 04-16-2008, 12:54 PM | #15 |
I really need to upload my vJASS version of this..... enabling this once for all heroes is fine, its sort of the purpose... |
