System RPG Framework

Steel

Software Engineer
Reaction score
109
What is this?
Stemming from my Virtual Equipment system... I've created a framework for RPG makers. The goal is to make a set of systems and functions that are easy to use as well as maintaining complete modularity. I hate it when some really cool idea only works a single way, why not make it modular and allow it to work how I want it to?! This is my primary focus. This will also help alleviate many of the basic functions that RPG developers spend on their maps. Functions like save and loading can vex a map maker and they spend a while figuring out how this work, or not at all.

Everything in this map is available for map makers to use in their RPG projects. The other primary intent of this framework is to allow the map maker freedom to focus about innovative, interesting and fun concepts with their map and not about some of the tedious system in a map. If you plan to use all or part of this framework in your map you must not claim it to be your own work.


Requirements
• vJASS
cJASS
Grim Extension Pack Hotfix - Get it from my DropBox or from Wc3c.net (last post) - This is a must in order to get some of external functions working. The last post in that thread on wc3c contains the hotfix.
• A Brain!


Changelog
Version 1.00:
• Added Dependencies Key Timers 2 and GTrigger By Jesus4Lyf. I'll be adding in spells showing people how to use his system in future relases. (All good maps should use Key Timers)
• Overhauled the actual map to give a better demonstration.
• UnitType is not broken up into it's own library. This was causing some confusion between the Unit library and I felt they should be split up.
• Added ability to repick a hero.
• Floating Bars properly remove on first unit passed into the system. Indexation error.
• Changed Hero Selection's radius spawn value from 250 to 350.
• Fixed an error in Hero Selection creating unit at inaccurate spawn point.
• Fixed an operation limit error in Hero Selection.
• Camera pans to selection area on map startup.
• Camera locks onto selection area until a unit is selected.
• Camera pans to spawn area of hero after selection.
• Unit Struct now tracks if the unit has moved from it's original position.
• Unit Struct now has methods to addBar and removeBar. These tie into the FloatingBars library
• Unit System will now automatically index units that a not yet indexed.
• UnitStruct Library added. This library houses the Unit struct and special functions to handle unit death. This change was needed due to circular dependencies from a new FloatingBars feature.
• FloatingBars will now automatically add a bar to an enemy unit that you select and those units that attack you. This feature can be disabled through a boolean in the setup function.



Version 0.09:
• Fixed Unit Library HP and MP calculations - When a unit spawns it set a variable to the unit's current hitpoints as their base hitpoints (Say 1,000). When the unit levels and gets say 4 strength, that is 100 hp increase, it does not recalculate the unit's current base hitpoints. The unit now has 1,100 hp, the variable is still set to 1,000, so when you acquire an item that increases your hitpoints by 100, it uses the variable of 1,000 and adds 100 to that resulting in 100 or a net gain of 0 hitpoints when you should get 100. [Thanks to Dabum]
• Item System Multiboard uses Darthfett's Multiboard wrapper
• Hero Selection Multiboard uses Darthfett's Multiboard wrapper


Known Bugs
• The random item drop system does not disallow for duplicate drops as the boolean in the setup may suggest


Finished Systems / Libraries
• Advanced Player Library
• Advanced Hero Library
• Hero Selection System
• Item System
• Enemy System
• Loot Table System
• Save / Load System
• Floating Bars System
• Random Item Drop System
• Damage Detection System
• Experience System
• Quest System
• Difficulty System
• Zoning System
• Party System


Disclaimers
• This is not meant for use by novice map makers. This systems in this map are very easy, but there are some steps of implementation that basic map makers must know in order to use this system. Some basic knowledge is how to import other systems (Such as Multibars) and modifying RAW ID's based on your map's data.
• I am not responsible for making these systems work in your map! (Although I will help up to a point)
• I will not post the code from the map on the forums as there is too much to post
• The map is not perfect and I'm sure someone will notice little nuances like memory leaks :rolleyes:.
• Complexity is a huge issue for some of these systems and I will be optimizing them later
• Yes, I use Cohadar's ABC and I don't care if you think some struct system is better than another. I really don't care, talk about it elsewhere!






The following documentation about each of these will increase greatly. The best way to learn is to open the map and read what is in there and try figuring some things out.
RPG Framework - The Entire API - This is the API file containing all of the map's function. To use this with Jass NewGen Editor, open the folder "tesh", open the folder "includes" and then paste this file into there. The next time you open the editor the TESH addon will show the functions for you to use. Some of the functions need large documentation to understand but most are self explanatory.
JASS:
	//***********************************************************************************
	//****************************cPlayer API****************************************	
	//***********************************************************************************    
	function cPlayer_CreateAllPlayers takes nothing returns nothing
	//Name:         CreateAllPlayers
	//Param:        None
	//Purpose:      Setup function for creating all of the cPlayer library information.  This must be run in order for things to work.
	//Use:          call CreateAllPlayers()
	//Complexity:   N/A
	//Return:       Nothing
	//Error:        Nothing	
		local integer i = 0
		local player p
		loop
			exitwhen i > 12
			set p = Player(i)
			if (GetLocalPlayer()==p) then
				call cPlayer.create(GetPlayerName(p),p, i )
			endif
			set i = i + 1
		endloop
		set p = null    
    endfunction

    function cPlayer_getPlayerInt takes integer index returns cPlayer
	//Name:         getPlayerInt
    //Param:        Integer index - The index value for one of the players.
    //Purpose:      This function will retrieve the cPlayer data for a specific user.
    //Use:          call getPlayerInt(5)
    //Complexity:   N/A
    //Return:       cPlayer
    //Error:        Attempting to reference an inactive player.
        if CPLAYER<i>.getActivity() then
            return CPLAYER<i>
        else
            debug call BJDebugMsg(&quot;System Error: 105&quot;)
        endif
        return -1
    endfunction

    function cPlayer_getPlayerPlayer takes player p returns cPlayer
	//Name:         getPlayerPlayer
    //Param:        Player p - A single player variable
    //Purpose:      This function will retrieve the cPlayer data for a specific user.
    //Use:          call getPlayerPlayer()
    //Complexity:   N/A
    //Return:       Nothing
    //Error:        Attempting to reference an inactive player.
        return getPlayerInt(GetPlayerId(p))
    endfunction

    function cPlayer_CreateUnit takes cPlayer customPlayer, integer unitID, real x, real y, real face returns unit
	//Name:         CreateUnit
    //Param:        cPlayer customePlayer 	- The cPlayer information for a specific player
	//              Integer unitID			- The RAW ID for a unit that is going to be created
	//              Real x 					- The x coordinate where you wish the unit to be created
	//              Real y 					- The y coordinate where you wish the unit to be created	
	//              Real face				- The facing angle for the newly created unit
    //Purpose:      This function creates a unit for the cPlayer that is passed in
    //Use:          call CreateUnit(cPlayer_getPlayerPlayer(GetTriggerPlayer()), &#039;H000&#039;, 47, 182, 28)
    //Complexity:   N/A
    //Return:       Unit u 
    //Error:        Nothing		
        return customPlayer.createUnit(unitID,x,y,face)
    endfunction

    function cPlayer_Setup takes integer maximumPlayers returns nothing
	//Simple function that takes in the maximum number of players in the map.
        set PLAYER_MAX = maximumPlayers
    endfunction
	
	
	//***********************************************************************************
	//******************************Hero API*****************************************	
	//***********************************************************************************	
    function Hero_FindByIndex takes integer index returns herotype
        return heroes[index]
    endfunction
    
    function Hero_FindByID takes integer id returns herotype
        local integer i = 0 
        loop
            exitwhen i&gt;count
            if heroes<i>.unitid==id then
                return heroes<i>
            endif
        set i = i + 1
        endloop
        debug call BJDebugMsg(&quot;FindByID == -1&quot;)
        return -1
    endfunction
    
    function Hero_FindByUnit takes unit u returns herotype
        return FindByID(GetUnitTypeId(u))
    endfunction
    
    function Hero_AddTypeAdvanced takes integer unitID, string unitDescription, boolean dualWield returns nothing
    //Name:         AddClassAdvanced
    //Param:        Integer unitID - Raw ID of unit to be added as a herotype
    //              String unitDescription - The description of the herotype you will be adding
	//              Boolean dualWield - Allows this herotype to dual wield weapons
    //Purpose:      Dynamically allocate any unit as a herotype.  This adds in the Raw ID to our database of herotypes
    //Use:          call AddClass(&#039;H000&#039;, &quot;This is a short description of our hero&quot;, true)
    //Complexity:   O(1)
    //Return:       Nothing - Function modifies the heroes array database.
    //Error:        Adding more classes than allowed

        if count &gt; max then
            call BJDebugMsg(&quot;System Error: 101&quot;)
            return
        endif
        
        if count == 0 then
            set heroes[count] = herotype.create(&#039;RNDM&#039;, &quot;          Selecting this will give you a randomly chosen hero&quot;, true)
            set count = count + 1
        endif
        set heroes[count] = herotype.create(unitID, unitDescription, dualWield)
        set count = count + 1
        
    endfunction

    function Hero_AddType takes integer unitID returns nothing
    //Name:         AddClass
    //Reference:    See function AddClassAdvanced
        call AddTypeAdvanced(unitID, &quot;No Description Available&quot;, false)
    endfunction  

    function Hero_AddAbilityAdvanced takes integer unitID, string abilityName, string abilityDescription, string abilityIcon returns nothing
	//Name:         AddAbilityAdvanced
    //Param:        Integer unitID - Raw ID of the unit we wish to add an ability for into our database. 
    //              String abilityName - The name of the ability you would like to add for the aforementioned unit
	//              String abilityDescription - The description of the ability you have presented to the above
	//              String abilityicon - This will display an icon of the ability on the multiboard for hero selection.  If left blank the icon will be omitted.
    //Purpose:      This function is for displaying the ability a unit has on a multiboard for hero selection.  It has no bearing on the actual abilities a unit has.
    //Use:          call AddClass(&#039;H000&#039;, &quot;Holy Light&quot;, &quot;Heals a friendly target&quot;, &quot;&quot;)
    //Complexity:   N/A
    //Return:       Nothing
    //Error:        Nothing
        call FindByID(unitID).addAbility(abilityName, abilityDescription, abilityIcon)
    endfunction    
    
    function Hero_AddAbility takes integer unitID, string abilityName, string abilityDescription returns nothing
	//Name: AddAbility
	//Reference: See function AddAbilityAdvanced
        call AddAbilityAdvanced(unitID, abilityName, abilityDescription, &quot;&quot;)
    endfunction
	
	
    function Hero_SelectionSetupAdvanced takes real xSelect, real ySelect, real distance, real xSpawn, real ySpawn returns nothing
	//Name:         SelectionSetupAdvanced
    //Param:        Real xSelect 	- The x coordinate for the selection area where heroes will be placed [Default is -1]
	//              Real ySelect 	- The y coordinate for the selection area where heroes will be placed [Default is -1]
	//              Real distance 	- The distance between the center of our (x,y) location to where our unit&#039;s will be placed [Default is 250]
	//              Real xSpawn 	- The x coordinate for where your selected hero will spawn.
	//              Real ySpawn 	- The y coordinate for where your selected hero will spawn.
    //Purpose:      This is the advanced selection setup function.  The xSelect and ySelect denote where the heroes will be placed, the heroes will be placed in a circle around this location.  The distance variable tells how far the units are place, in other words the circle&#039;s radius.  The xSpawn and ySpawn are used when you select a hero, the unit is placed there.
    //Use:          call AddClass(0,0, 250, 750, -200)
    //Complexity:   N/A
    //Return:       Nothing
    //Error:        No herotypes added to the system.

        set xselect = xSelect
        set yselect = ySelect
        set d = distance
        set xspawn = xSpawn
        set yspawn = ySpawn
        
        if count == 0 then
            call BJDebugMsg(&quot;System Error: 130&quot;)
            return
        endif
        
        call SelectionCreateHeroes()
    endfunction
        
    function Hero_Setup takes integer maxLevel, rect selectAreaRect, rect spawnAreaRect returns nothing
	//Name:         Setup
    //Param:        Integer maxLevel - The maximum level of heroes in your map.  
	//              Rect selectAreaRect - The rect where the hero selection system will create the unit&#039;s for selecting
	//              Rect spawnAreaRect - The rect where the hero selection system will spawn a unit when you pick a hero
    //Purpose:      This function must be called last for the setup purposes.  The above parameters should yield enough information about this function
    //Use:          call AddClass(50,gg_rct_select, gg_rct_spawn)
    //Complexity:   N/A
    //Return:       Nothing
    //Error:        Nothing
	
        set MAX_LEVEL = maxLevel
        
		//This is a private function
		call SelectionSetup(selectAreaRect, spawnAreaRect)
    endfunction

    public function getMaxLevel takes nothing returns integer
        return MAX_LEVEL
    endfunction
	
	
	//***********************************************************************************
	//******************************Unit API*****************************************	
	//***********************************************************************************
	
	function Unit_CreateNew takes integer unitID, player whichPlayer, real x, real y, real face returns Unit
        local unit u = CreateUnit(whichPlayer, unitID, x,y,face)
        local Unit temp = Unit.create(u,count)
        set count = count + 1
        //call Unit.create(u, p, getUnitTypeId(id), x, y, face)
        //set enemy_unit[enemy_unit_count] = Enemy.create(u, p, getEnemyTypeId(id), x, y, face)
        //set enemy_unit_count = enemy_unit_count + 1
        set u = null
        return temp
    endfunction
    
    function Unit_AddExisting takes unit whichUnit returns Unit
	//Adds a preplaced unit to the database
        local Unit temp     = Unit.create(whichUnit, count)
        set count = count + 1
        return temp
    endfunction

    function Unit_AddAllExisting takes player whichPlayer returns nothing
        local group g = CreateGroup()
        local unit u
        call GroupEnumUnitsOfPlayer(g, whichPlayer, null)

        loop
            set u = FirstOfGroup(g)
            exitwhen u == null
            call AddExisting(u)
            call GroupRemoveUnit(g, u)
        endloop   

        call DestroyGroup(g)
        set g = null
        set u = null
    endfunction

    //Adds a special unit type to the database
     function Unit_AddType takes integer unitID, string unitName, string lootTable, real baseMovespeed, integer hitpointBase, integer manapointBase, real respawnTime, real experienceYield, real goldYield returns nothing
        if (getUnitTypeId(unitID) == -1) then 
            set unittypes[counttypes] = UnitType.create(unitID, unitName, lootTable, baseMovespeed, hitpointBase, manapointBase, respawnTime, experienceYield, goldYield)
            set counttypes = counttypes + 1
        else
            call BJDebugMsg(&quot;System Error: 110&quot;)
        endif
    endfunction
    
    function Unit_getCount takes nothing returns integer
        return count
    endfunction

    function Unit_Find takes unit whichUnit returns Unit
		local integer index = GetUnitUserData(whichUnit)
		if index == 0 then
		call BJDebugMsg(&quot;System Error: 127&quot;)
		return -1
		endif   
		return units[index]
    endfunction
    
    function Unit_FindIndex takes unit whichUnit returns integer
        local integer i = 0
        loop
            exitwhen i &gt; count
            if (whichUnit == units<i>.u) then
                return i
            endif
            set i = i + 1
        endloop
        return -1
    endfunction	
	
	//***********************************************************************************
	//****************************Floating Bars API**************************************	
	//***********************************************************************************
    function FloatingBars_Enabled takes nothing returns boolean
        return enabled
    endfunction
    
    function FloatingBars_RemoveBar takes unit whichUnit returns boolean
        local integer i = FindUnitIndex(whichUnit)
        if (i==-1) then
            debug call BJDebugMsg(&quot;Error unit not in index&quot;)
            return false
        else
            call RemoveBarInt(i)
        endif
        return true
    endfunction

    function FloatingBars_AddBar takes unit whichUnit, boolean showLife, boolean showMana returns FloatingStruct
        local FloatingStruct fs = 0
        debug call BJDebugMsg(&quot;AddBar called: &quot;+GetUnitName(whichUnit))
        
        if (not(FindUnitIndex(whichUnit)==-1)) then
            debug call BJDebugMsg(&quot;Error: Duplicate Floating Bar Creation Called&quot;)
            return -1
        endif

        if ((not(showLife)) and (not(showMana))) then
            debug call BJDebugMsg(&quot;System Error: 112&quot;)
            return -1
        endif
        
        set fs = FloatingStruct.create(whichUnit, showLife, showMana)
        set structlink[FS_COUNT] = fs
        set FS_COUNT=FS_COUNT+1
        return fs
    endfunction

    function FloatingBars_Setup takes boolean enableSystem, boolean createBarAutomatically, boolean addHeroesOnly, boolean showLife, boolean showMana returns nothing
    local integer i  = 0

        set enabled  = enableSystem
        if (createBarAutomatically) then
            
            loop
                exitwhen i&gt;10
                //Player selects a unit
                call TriggerRegisterPlayerUnitEvent(select, Player(i), EVENT_PLAYER_UNIT_SELECTED, null)
                call TriggerAddAction(select, function SelectActions)
                call TriggerAddCondition(select, Condition(function SelectConditions))

                //Player deselects a unit
                call TriggerRegisterPlayerUnitEvent(deselect, Player(i), EVENT_PLAYER_UNIT_DESELECTED, null)
                call TriggerAddAction(deselect, function DeselectActions)
                call TriggerAddCondition(deselect, Condition(function DeselectConditions))
                set i = i + 1
            endloop
            
        else
            call DestroyTrigger(select)
            call DestroyTrigger(deselect)
            set select      = null          
            set deselect    = null
        endif        
        set fb_heroes       = addHeroesOnly
        set fb_life         = showLife
        set fb_mana         = showMana
    endfunction

    function FloatingBars_AdvancedSetup takes boolean enableSystem, boolean createBarAutomatically, boolean addHeroesOnly, boolean showLife, boolean showMana, string displayCharacter, integer barLength, real barSize, real X_OffSet_Life, real Y_OffSet_Life, real X_OffSet_Mana, real Y_OffSet_Mana, real frequency returns nothing
        call Setup(enableSystem, createBarAutomatically, addHeroesOnly, showLife, showMana)
        set DisplayCharacter    = displayCharacter
        set BarLength           = barLength
        set BarSize             = barSize
        set XOffSet             = X_OffSet_Life
        set YOffSet             = Y_OffSet_Life
        set XOffSetM            = X_OffSet_Mana
        set YOffSetM            = Y_OffSet_Mana
        set Frequency           = frequency
    endfunction
	
	
	//***********************************************************************************
	//******************************Item System API**************************************	
	//***********************************************************************************
	function ItemSystem_Setup takes nothing returns nothing
	//Required function to enable the system
        if Regeneration_Enabled() then
            set columns = columns + 2
        endif
    endfunction
	
	function ItemSystem_Multiboard_DisplayByPlayer takes player whichPlayer returns nothing
	//DisplayByPlayer - Takes in a player, example: Player(0) can be passed into the function to display that multiboard
            if (GetLocalPlayer()==whichPlayer) then
                call MultiboardDisplay(cPlayer_getPlayerPlayer(whichPlayer).item_system_multiboard, true)
            endif
	endfunction


	function ItemSystem_Multiboard_DisplayByInt takes integer whichIndex returns nothing
	//DisplayByInt - Takes in a player&#039;s id.  For example, the person in the Player Slot 1 is referenced by integer 0
	//Passing in 0 to this function is the same as using the DisplayByPlayer function with Player(0)
	//Note: Index starts at 0
	
		if (whichIndex&gt;11 or whichIndex&lt;0) then
			call BJDebugMsg(&quot;System Error: 104&quot;)
		endif
		call DisplayByPlayer(Player(whichIndex))
	endfunction
	
	function ItemSystem_Multiboard_DisplayAll takes nothing returns nothing
	//DisplayAll - This function forces all players to view their inventory multiboard
		local integer i = 0
		loop   
			exitwhen i &gt; 9        
			call DisplayByInt(i)//Call by int to force integer check
			set i = i + 1
		endloop
	endfunction
            
			
	function ItemSystem_Multiboard_Create takes integer whichIndex returns nothing
	//This function requires a player&#039;s index to create a multiboard for them
		local multiboarditem mbi = null
		local integer k = 0
		local integer rows = SLOT_COUNT+1
		local integer curr = 0
		local real icon_width = 1.5


		//Create the whole thing
		call MultiboardSetRowCount(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, rows+1)
		call MultiboardSetColumnCount(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, columns)
		call MultiboardSetTitleText(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, cPlayer_getPlayerInt(whichIndex).name)
		call MultiboardDisplay( cPlayer_getPlayerInt(whichIndex).item_system_multiboard,true )
			
			

		//Column 0 -- Icons
		loop
			set mbi = MultiboardGetItem(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, k,curr)
			call MultiboardSetItemStyle(mbi, false, true)
			call MultiboardSetItemIcon(mbi, &quot;UI\\Widgets\\Console\\Human\\human-inventory-slotfiller.blp&quot;)
			call MultiboardSetItemWidth(mbi, icon_width/100)
			call MultiboardReleaseItem(mbi)
			set k = k + 1    
			exitwhen k&gt;rows
		endloop
		
		set k = 0
		set mbi = MultiboardGetItem(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, 0,curr)
		call MultiboardSetItemStyle(mbi, false, false)
		set mbi = MultiboardGetItem(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, SLOT_COUNT+1,curr)
		call MultiboardSetItemWidth(mbi, icon_width/100)
		call MultiboardSetItemStyle(mbi, false, false)
		set curr = curr + 1

		//Column 1 -- Slot
		loop
			set mbi = MultiboardGetItem(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, k,curr)
			call MultiboardSetItemStyle(mbi, true, false)
			call MultiboardSetItemValue(mbi, &quot;   |c00808080-&quot;+IS_SLOT[k]+&quot;-|r&quot;)
			call MultiboardSetItemWidth(mbi, 8.0/100)
			call MultiboardReleaseItem(mbi)
			set k = k + 1    
			exitwhen k&gt;rows
		endloop
		set k = 0
		set mbi = MultiboardGetItem(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, 0,curr)
		call MultiboardSetItemValue(mbi, &quot;     Slot&quot;)
		set mbi = MultiboardGetItem(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, SLOT_COUNT+1, curr)
		call MultiboardSetItemWidth(mbi, 8.0/100)
		//call MultiboardSetItemStyle(mbi, true, false)
		call MultiboardSetItemValue(mbi, &quot;     |c00808040Totals|r:&quot;)

		set curr = curr + 1



		//Column 2 -- Damage
		loop
			set mbi = MultiboardGetItem(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, k,curr)
			call MultiboardSetItemStyle(mbi, true, false)
			call MultiboardSetItemWidth(mbi, icon_width/100)
			call MultiboardReleaseItem(mbi)
			set k = k + 1    
			exitwhen k&gt;rows
		endloop
		set k = 0
		set mbi = MultiboardGetItem(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, 0, curr)
		call MultiboardSetItemStyle(mbi, false, true)
		call MultiboardSetItemIcon(mbi, &quot;UI\\Widgets\\Console\\Human\\infocard-neutral-attack-melee.blp&quot;)
		set curr = curr + 1

		//Column 3 -- Armor
		loop
			set mbi = MultiboardGetItem(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, k,curr)
			call MultiboardSetItemStyle(mbi, true, false)
			call MultiboardSetItemWidth(mbi, icon_width/100)
			call MultiboardReleaseItem(mbi)
			set k = k + 1    
			exitwhen k&gt;rows
		endloop
		set k = 0
		set mbi = MultiboardGetItem(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, 0, curr)
		call MultiboardSetItemStyle(mbi, false, true)
		call MultiboardSetItemIcon(mbi, &quot;UI\\Widgets\\Console\\Human\\infocard-neutral-armor-medium.blp&quot;)
		set curr = curr + 1

		//Column 4 -- Health
		loop
			set mbi = MultiboardGetItem(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, k,curr)
			call MultiboardSetItemStyle(mbi, true, false)
			call MultiboardSetItemWidth(mbi, icon_width/100)
			call MultiboardReleaseItem(mbi)
			set k = k + 1    
			exitwhen k&gt;rows
		endloop
		set k = 0
		set mbi = MultiboardGetItem(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, 0, curr)
		call MultiboardSetItemStyle(mbi, false, true)
		call MultiboardSetItemIcon(mbi, &quot;ReplaceableTextures\\CommandButtons\\BTNHealthStone.blp&quot;)
		set curr = curr + 1


		//Column 5 -- Mana
		loop
			set mbi = MultiboardGetItem(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, k,curr)
			call MultiboardSetItemStyle(mbi, true, false)
			call MultiboardSetItemWidth(mbi, icon_width/100)
			call MultiboardReleaseItem(mbi)
			set k = k + 1    
			exitwhen k&gt;rows
		endloop
		set k = 0
		set mbi = MultiboardGetItem(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, 0, curr)
		call MultiboardSetItemStyle(mbi, false, true)
		call MultiboardSetItemIcon(mbi, &quot;ReplaceableTextures\\CommandButtons\\BTNManaStone.blp&quot;)
		set curr = curr + 1


		//Column 6 -- Strength
		loop
			set mbi = MultiboardGetItem(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, k,curr)
			call MultiboardSetItemStyle(mbi, true, false)
			call MultiboardSetItemWidth(mbi, icon_width/100)
			call MultiboardReleaseItem(mbi)
			set k = k + 1    
			exitwhen k&gt;rows
		endloop
		set k = 0
		set mbi = MultiboardGetItem(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, 0, curr)
		call MultiboardSetItemStyle(mbi, false, true)
		call MultiboardSetItemIcon(mbi, &quot;UI\\Widgets\\Console\\Human\\infocard-heroattributes-str.blp&quot;)
		set curr = curr + 1


		//Column 7 -- Agility
		loop
			set mbi = MultiboardGetItem(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, k,curr)
			call MultiboardSetItemStyle(mbi, true, false)
			call MultiboardSetItemWidth(mbi, icon_width/100)
			call MultiboardReleaseItem(mbi)
			set k = k + 1    
			exitwhen k&gt;rows
		endloop
		set k = 0
		set mbi = MultiboardGetItem(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, 0, curr)
		call MultiboardSetItemStyle(mbi, false, true)
		call MultiboardSetItemIcon(mbi, &quot;UI\\Widgets\\Console\\Human\\infocard-heroattributes-agi.blp&quot;)
		set curr = curr + 1

		//Column 8 -- Intelligence
		loop
			set mbi = MultiboardGetItem(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, k,curr)
			call MultiboardSetItemStyle(mbi, true, false)
			call MultiboardSetItemWidth(mbi, icon_width/100)
			call MultiboardReleaseItem(mbi)
			set k = k + 1    
			exitwhen k&gt;rows
		endloop
		set k = 0
		set mbi = MultiboardGetItem(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, 0, curr)
		call MultiboardSetItemStyle(mbi, false, true)
		call MultiboardSetItemIcon(mbi, &quot;UI\\Widgets\\Console\\Human\\infocard-heroattributes-int.blp&quot;)
		set curr = curr + 1
		
	   //Column 9 -- Movespeed
		loop
			set mbi = MultiboardGetItem(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, k,curr)
			call MultiboardSetItemStyle(mbi, true, false)
			call MultiboardSetItemWidth(mbi, icon_width/100)
			call MultiboardReleaseItem(mbi)
			set k = k + 1    
			exitwhen k&gt;rows
		endloop
		set k = 0
		set mbi = MultiboardGetItem(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, 0, curr)
		call MultiboardSetItemStyle(mbi, false, true)
		call MultiboardSetItemIcon(mbi, &quot;ReplaceableTextures\\CommandButtons\\BTNBootsOfSpeed.blp&quot;)
		set curr = curr + 1
		
		if Regeneration_Enabled() then
		   //Column 10 -- Health Regen
			loop
				set mbi = MultiboardGetItem(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, k,curr)
				call MultiboardSetItemStyle(mbi, true, false)
				call MultiboardSetItemWidth(mbi, icon_width/100)
				call MultiboardReleaseItem(mbi)
				set k = k + 1    
				exitwhen k&gt;rows
			endloop
			set k = 0
			set mbi = MultiboardGetItem(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, 0, curr)
			call MultiboardSetItemStyle(mbi, false, true)
			call MultiboardSetItemIcon(mbi, &quot;ReplaceableTextures\\CommandButtons\\BTNReplenishHealth.blp&quot;)
			set curr = curr + 1
		endif

		if Regeneration_Enabled() then
		   //Column 11 -- Mana Regen
			loop
				set mbi = MultiboardGetItem(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, k,curr)
				call MultiboardSetItemStyle(mbi, true, false)
				call MultiboardSetItemWidth(mbi, icon_width/100)
				call MultiboardReleaseItem(mbi)
				set k = k + 1    
				exitwhen k&gt;rows
			endloop
			set k = 0
			set mbi = MultiboardGetItem(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, 0, curr)
			call MultiboardSetItemStyle(mbi, false, true)
			call MultiboardSetItemIcon(mbi, &quot;ReplaceableTextures\\CommandButtons\\BTNReplenishMana.blp&quot;)
			set curr = curr + 1   
		endif

		//Last Row (totals)
		set k = 2
		loop
			set mbi = MultiboardGetItem(cPlayer_getPlayerInt(whichIndex).item_system_multiboard, SLOT_COUNT+1,k)
			call MultiboardSetItemStyle(mbi, true, false)
			call MultiboardSetItemWidth(mbi, icon_width/100)
			call MultiboardReleaseItem(mbi)
			set k = k + 1    
			exitwhen k&gt;rows
		endloop
		set k = 0

		call DisplayByInt(whichIndex)
	endfunction

		//ItemSystem_Multiboard_CreateAll
	function ItemSystem_Multiboard_CreateAll takes nothing returns nothing
		local integer i = 0
		local integer j = 1
			loop
				exitwhen i &gt; 10
				call Create(i)
				set i = i + 1
			endloop   
	endfunction
	//End Multiboard Scope
	
    function ItemSystem_getItemDatabaseID takes integer databaseIndex returns ItemStruct
        return ITEM_DATABASE[databaseIndex]
    endfunction

    function ItemSystem_setItemDatabase takes ItemStruct whichItemStruct returns nothing
        set ITEM_DATABASE[count] = whichItemStruct
    endfunction

    function ItemSystem_incrementCount takes nothing returns nothing
        set count = count + 1
    endfunction

    function ItemSystem_getItemCount takes nothing returns integer
        return count
    endfunction

    function ItemSystem_setItemCount takes integer value returns nothing
        set count = value
    endfunction	
	
    function ItemSystem_CreateItemStruct takes nothing returns ItemStruct
        set bj_lastCreatedItemStruct = ItemStruct.create(0,0,&quot;e&quot;, 0,0,0,0,0,0,0,0,0,0,0,0.,0,0.,0,0,&quot;UI\\Widgets\\Console\\Human\\human-inventory-slotfiller.blp&quot;)
        return bj_lastCreatedItemStruct
    endfunction

	function ItemSystem_CreateCustomItem takes integer itemID, integer whichSlot, string itemType, integer whichHeroes, integer levelRequirement, integer strengthRequirement, integer agilityRequirement,integer intelligentRequirement, integer strengthBonus, integer agilityBonus, integer intelligentBonus, integer damageBonus, integer armorBonus, integer hitpointBonus, integer manapointBonus, string modelPath returns nothing
        call ItemStruct.create(itemID, whichSlot, itemType, whichHeroes, levelRequirement, strengthRequirement, agilityRequirement, intelligentRequirement, strengthBonus, agilityBonus, intelligentBonus, damageBonus, armorBonus, hitpointBonus, 0., manapointBonus, 0., 0, 0, modelPath)
    endfunction


    function ItemSystem_CreateCustomItemAdvanced takes integer itemID, integer whichSlot, string itemType, integer whichHeroes, integer levelRequirement, integer strengthRequirement, integer agilityRequirement,integer intelligentRequirement, integer strengthBonus, integer agilityBonus, integer intelligentBonus, integer damageBonus, integer armorBonus, integer hitpointBonus, real hitpointRegen, integer manapointBonus, real manapointRegen, integer abilityID, integer movespeedBonus, string modelPath returns nothing
        call ItemStruct.create(itemID, whichSlot, itemType, whichHeroes, levelRequirement, strengthRequirement, agilityRequirement, intelligentRequirement, strengthBonus, agilityBonus, intelligentBonus, damageBonus, armorBonus, hitpointBonus, hitpointRegen, manapointBonus, manapointRegen, abilityID, movespeedBonus, modelPath)
    endfunction
	
    function ItemSystem_FindItem takes integer itemID returns ItemStruct
	//Name:         FindItem
    //Param:        Integer itemid - Item&#039;s RAW ID value
    //Purpose:      Check database of items for itemid.  
    //              If item exists in database it returns the data
    //Use:          set itemstruct = FindItem(&#039;I000&#039;)
    //Complexity:   O(n)
    //Return:       ItemStruct   - Two cases
    //              Successful   - Returns ItemStruct for given Item&#039;s RAW ID
    //              Unsuccessful - Returns the integer -1
    //Error:        Item does not exist in database
        local integer i = 0
        loop
            exitwhen i&gt;count
            if i&lt;5 then
            endif
            if itemID==ITEM_DATABASE<i>.item_id then
                return getItemDatabaseID(i)
            endif
            set i = i + 1
        endloop
        call BJDebugMsg(&quot;System Error: 100&quot;)
        return -1
    endfunction	
	
    function ItemSystem_AddSlot takes string slotName returns nothing
        if SLOT_COUNT &gt; SLOT_MAX then
            call BJDebugMsg(&quot;System Error: 102&quot;)
            return
        endif
        
        set SLOT_COUNT = SLOT_COUNT + 1
        set IS_SLOT[SLOT_COUNT] = slotName
    endfunction

    function ItemSystem_GetSlotName takes integer slotIndex returns string
        return IS_SLOT[slotIndex]
    endfunction
	
	function ItemSystem_DestroyItem takes unit whichUnit, integer whichSlot returns nothing
	//This function removes an item from the given unit of the respective slot
		local integer idx   = GetPlayerId(GetOwningPlayer(whichUnit))
        local ItemStruct is = cPlayer_getPlayerInt(idx).hero.equipment.itemstruct[whichSlot]

        //If there is no item
        if is.item_id&lt;1 then
        call Misc_SimError(GetOwningPlayer(whichUnit), &quot;There is no item in that slot.&quot;)
        return 
        endif

        call ItemUpdateChar(whichUnit,is,-1)
        call UpdateMultiboard(idx,whichSlot, is, false)
        call CreateItem(is.item_id, GetUnitX(whichUnit), GetUnitY(whichUnit))
        call Misc_SimError(GetOwningPlayer(whichUnit), &quot;Dropping: &quot;+is.item_name)

        //Deconstruction
        //We cannot call the .destroy() because it removes the item from the database
        set cPlayer_getPlayerInt(idx).hero.equipment.itemstruct[whichSlot] = 0

    endfunction
	
    function ItemSystem_ForceEquipItem takes unit whichUnit, integer itemID returns boolean
	//ForceEquip without restrictions
    //This function is used for the loading system
    //Some item may have no requirements to wear it but provide +50 to all stats
    //if that item is not equip, some other items may depend upon those stats
    //Thus disallowing other items to be equip.
        local item i = CreateItem(itemID, 0,0)
        local ItemStruct is = FindItem(itemID)
        local string str = &quot;&quot;
        local integer temp

        if (is == -1) then
            return false
        endif

        set temp = ItemSlotCheck(is,whichUnit)

        //Checks slot avaliability
        if temp == -1 then
            call ItemFinish(whichUnit, &quot;Equipment slot unavailable.&quot;)
        else
            call ItemUpdateChar(whichUnit, is, 1)
            call ItemAddToChar(whichUnit,i, is, temp)
            return true
        endif

        return false
    endfunction

    function ItemSystem_EquipItemItem takes unit whichUnit, item whichItem returns boolean
        local integer it  = GetItemTypeId(whichItem)
        local ItemStruct is = FindItem(it)
        local string str = &quot;&quot;
        local integer temp

        if (is == -1) then
            return false
        endif

        if not(CheckPermissions(R2I(Pow(2, FindClassIndex(GetUnitTypeId(whichUnit)))), is.who)) then
            call ItemFinish(whichUnit, &quot;Your class cannot use that.&quot;)
            return false
        endif

        set str = ItemStatCheck(whichUnit, is)
        
        if not(str==&quot;&quot;) then
            call BJDebugMsg(&quot;str=&#039; &#039;&quot;)
            call ItemFinish(whichUnit, str)
            return false
        endif

        debug call BJDebugMsg(&quot;Dependencies met&quot;)

        set temp = ItemSlotCheck(is,whichUnit)

        //Checks slot avaliability
        if temp == -1 then
            call ItemFinish(whichUnit, &quot;Equipment slot unavailable.&quot;)
        else
            call ItemUpdateChar(whichUnit, is, 1)
            call ItemAddToChar(whichUnit,whichItem, is, temp)
            return true
        endif

        return false
    endfunction

    function ItemSystem_EquipItemId takes unit whichUnit, integer itemID returns boolean
        local item i = CreateItem(itemID, 0,0)

        if not(EquipItemItem(whichUnit, i)) then
            call RemoveItem(i)
            set i = null
            return false
        endif
        
        set i = null
        return true
    endfunction
	
	
	
	
	
	//***********************************************************************************
	//****************************Save/Load System API***********************************	
	//***********************************************************************************	
	function SaveLoad_Setup takes boolean disableSinglePlayer, boolean saveHero, boolean saveLevel, boolean saveExperience, boolean saveStrength, boolean saveAgility, boolean saveIntelligence, boolean saveInventory, boolean saveEquipment, boolean saveGold, boolean saveLumber returns nothing
    local integer index = 2
    local integer temp
    set nosingleplayer  = disableSinglePlayer
    set save_hero       = saveHero
    set save_level      = saveLevel
    set save_exp        = saveExperience
    set save_str        = saveStrength
    set save_agi        = saveAgility
    set save_int        = saveIntelligence
    set save_inventory  = saveInventory
    set save_equipment  = saveEquipment
    set save_gold       = saveGold
    set save_lumber     = saveLumber


    //Map Version initial
    set total_save = total_save+1



    if save_hero then
    set total_save = total_save+1
    endif

    if save_level then
    set total_save = total_save+1
    endif

    if save_exp then
    set total_save = total_save+1
    endif

    if save_str then
    set total_save = total_save+1
    endif

    if save_agi then
    set total_save = total_save+1
    endif

    if save_int then
    set total_save = total_save+1
    endif

    if save_inventory then
    set total_save = total_save+6 //6 inventory slots
    endif

    if save_equipment then
    set total_save = total_save+SLOT_COUNT
    endif

    if save_gold then
    set total_save = total_save+1
    endif

    if save_lumber then
    set total_save = total_save+1
    endif

    debug call BJDebugMsg(&quot;Total Save = &quot;+I2S(total_save))

    set codemaker_vals[0] = total_save
    set codemaker_size[1] = 2 //2^2, 4 different map versions

    if save_hero then
        set codemaker_size[index] = BinPow(Hero_Count())
        set index = index + 1
    endif

    if save_level then
        set codemaker_size[index] = BinPow(Hero_getMaxLevel())
        set index = index + 1
    endif

       
    if save_exp then
        set codemaker_size[index] = BinPow(100)
        set index = index + 1
    endif

    if save_str then
        set codemaker_size[index] = BinPow(200)
        set index = index + 1
    endif

    if save_agi then
        set codemaker_size[index] = BinPow(200)
        set index = index + 1
    endif

    if save_int then
        set codemaker_size[index] = BinPow(200)
        set index = index + 1
    endif


    set temp = 0
    if save_inventory then
        loop
            exitwhen temp &gt; 5
            set codemaker_size[index] = BinPow(ItemSystem_getItemCount())
            set temp = temp + 1
            set index = index + 1
        endloop
    endif
     
    set temp = 1//Slot count index starts on 1
    if save_equipment then
        loop
            exitwhen temp&gt;SLOT_COUNT
            set codemaker_size[index] = BinPow(ItemSystem_getItemCount())
            set temp = temp + 1
            set index = index + 1
        endloop
    endif

    if save_gold then
        set codemaker_size[index] = BinPow(MAX_GOLD)
        set index = index + 1
    endif

    if save_lumber then
        set codemaker_size[index] = BinPow(MAX_LUMBER)
        set index = index + 1
    endif
	endfunction
	
	//***********************************************************************************
	//****************************LootTable System API***********************************	
	//***********************************************************************************		
    function LootTable_Create takes string nameOfTable, integer numerOfDrops, boolean allowDuplicate returns nothing
		set loot_table[loot_table_count] = LootTable.create(nameOfTable, numerOfDrops, allowDuplicate)
		set loot_table_count = loot_table_count + 1
    endfunction

    function LootTable_Find takes string nameOfTable returns LootTable
    local integer i = 0
    //call BJDebugMsg(&quot;Finding....&quot;+name)
    loop
        exitwhen i &gt; loot_table_count
        //call BJDebugMsg(&quot;loot_table[&quot;+I2S(i)+&quot;]&quot;+loot_table<i>.name)
        if (loot_table<i>.name == nameOfTable) then
        return loot_table<i>
        endif
        set i = i + 1
    endloop
    return -1
    endfunction

    function LootTable_addItem takes string nameOfTable, integer itemID, integer chanceToDrop returns nothing
    local LootTable lt = Find(nameOfTable)
    local integer sum = lt.sumChance()

    if (chanceToDrop &lt;= 0) then
        call BJDebugMsg(&quot;System Error: 109&quot;)
        return
    endif

    if (lt == -1) then
        call BJDebugMsg(&quot;System Error: 107&quot;)
        return
    endif

    if (sum&gt;100) then 
        call BJDebugMsg(&quot;System Error: 108&quot;)
        return
    endif

    call lt.add_Item(itemID, chanceToDrop)
    endfunction
	
	
	
	//***********************************************************************************
	//****************************Experience System API**********************************
	//***********************************************************************************
	function Experience_Enabled takes nothing returns boolean
        return enable
    endfunction

    function Experience_Fancy takes nothing returns boolean
        return fancy
    endfunction

    function Experience_Share takes nothing returns boolean
        return share
    endfunction

    function Experience_Split takes nothing returns boolean
        return split and share //Split true..share false...returns false. Split ok, share false so its only for one unit
    endfunction

    function Experience_Range takes nothing returns real
        return range
    endfunction

    function Experience_Trigger takes nothing returns trigger
        return experience
    endfunction

    function Experience_Setup takes boolean enableSystem, boolean fancyDisplay, boolean shareExperience, boolean splitExperience, real maxRange returns nothing
        set enable = enableSystem
        set fancy = fancyDisplay
        set share = shareExperience
        set split = splitExperience
        set range = maxRange
    endfunction
	
	//***********************************************************************************
	//******************************Damage System API************************************	
	//***********************************************************************************			
	function Damage_AddType takes string damageName returns nothing
		set DamageTypes[count] = damageName
		set count = count + 1
	endfunction

	function Damage_Setup takes boolean enableSystem,boolean ShowFloatingText, boolean customArmor returns nothing
		set enabled = enableSystem
		set floatingtext = ShowFloatingText
		set armor = customArmor
	endfunction
	
	
	//***********************************************************************************
	//******************************Zoning System API************************************	
	//***********************************************************************************				
	function Zoning_AddRegion takes region whichRegion, string zoneName returns nothing
		set trig[count] = CreateTrigger()
		set zone[count] = whichRegion
		set name[count] = zoneName

		call TriggerRegisterEnterRegion(trig[count], whichRegion, null)
		call TriggerAddCondition(trig[count], Condition( function Conditions ) )
		call TriggerAddAction(trig[count], function Actions)
		set count = count + 1
	endfunction

	function Zoning_AddRect takes rect whichRect, string zoneName returns nothing
		local region r = CreateRegion()
		call RegionAddRect(r, whichRect)
		call AddRegion(r, zoneName)
	endfunction	

	//***********************************************************************************
	//*******************************Quest System API************************************	
	//***********************************************************************************		
	function Quest_Create_Kill takes integer startUnitID, real startUnitX, real startUnitY, real startUnitFace, integer levelRequirementMinimum, integer levelRequirementMaximum, boolean repeatable, integer unitToKillID, integer howMany, string questTitle, string questDescription, string questIcon, integer rewardItemID, integer rewardExp, integer rewardGold, integer rewardLumber returns nothing
		call Create(&quot;Kill&quot;,  startUnitID,  startUnitX,  startUnitY,  startUnitFace,  levelRequirementMinimum,  levelRequirementMaximum,  repeatable,  unitToKillID,  howMany,  -1,  -1,  null,  -1,  questTitle,  questDescription,  questIcon,  rewardItemID,  rewardExp,  rewardGold,  rewardLumber)
	endfunction

	//***********************************************************************************
	//*****************************Difficulty System API*********************************	
	//***********************************************************************************			
	function Difficulty_Get takes nothing returns DifficultySetting
		return current_difficulty_setting
	endfunction

	function Difficulty_Enabled takes nothing returns boolean
		return enabled
	endfunction	
	
	public function Choose takes nothing returns nothing returns nothing
	local Dialog d 
	local player p 
	local integer i = 0
	local integer j = 0
	local timer t = CreateTimer()

	if not (enabled) then
		call BJDebugMsg(&quot;System Error: 120&quot;)
		call DestroyTimer(t)
		set t = null
		set p = null
		return
	endif

	if custom and count &gt; 1 then
		loop
			exitwhen j&gt;10 or (choice and j==1)
				set p = Player(j)
				set d = Dialog.create()
				call d.SetMessage(&quot;Select A Difficulty&quot;)
				loop
					exitwhen i == count
					call d.AddButton(&quot;[|c00FFFFFF&quot;+I2S(i+1)+&quot;|r] - &quot;+setting<i>.name+&quot; - |c0000FF00&quot;+I2S(R2I(setting<i>.hp*100))+&quot;% HP|r / |c00808040&quot;+I2S(R2I(setting<i>.exp*100))+&quot;% XP|r / |c00FF0000&quot;+I2S(R2I(setting<i>.dmg*100))+&quot;% DMG|r&quot;, 49+i)
					set i = i + 1
				endloop
				set i = 0
				call d.AddAction( function Callback )
				call d.Show(p) 
				set j = j + 1
		endloop
	endif

	call BJDebugMsg(&quot;You have &quot;+I2S(time)+&quot; seconds to choose the difficulty&quot;)
	call TriggerSleepAction(5)
	if choice then
	call BJDebugMsg(&quot;|c00FF0000Player 1|r is deciding the difficulty&quot;)
	else
	call BJDebugMsg(&quot;Deciding Difficulty...&quot;)
	endif
	call TimerStart(t, time, false, function Timer)
	set t = null
	set p = null
	endfunction


	function Difficulty_Add takes string name_of_difficulty, real enemy_hp_percentage, real experience_yield_percentage, real enemy_damage_percentage returns nothing
	local DifficultySetting ds = DifficultySetting.create(name_of_difficulty,enemy_hp_percentage,experience_yield_percentage,enemy_damage_percentage)

	if not (enabled) then
		call BJDebugMsg(&quot;System Error: 120&quot;)
		return
	endif

	if count == 7 then
	call BJDebugMsg(&quot;System Error: 118&quot;)
	return
	endif

	set setting[count] = ds
	set count = count + 1
	endfunction

	function Difficulty_Setup takes boolean enableSystem, boolean useCustomDifficulties, boolean playerOneChooses, integer timeToChoose returns nothing
	set enabled = enableSystem
	set custom = useCustomDifficulties
	set choice = playerOneChooses
	set time = timeToChoose
	set count = 0
	endfunction	
	
	//***********************************************************************************
	//*******************************Party System API************************************	
	//***********************************************************************************	
	function Party_Enabled takes nothing returns boolean
	return enabled
	endfunction

	function Party_ExpBonus takes nothing returns real
	return expBonus
	endfunction

	function Party_shareExp takes nothing returns boolean
	return shareExpExclusive
	endfunction
	
	function Party_FindPlayerParty takes player whichPlayer returns Party
	
		local integer i = 0
		local integer j = 0
		local Party party = 0
		loop
			exitwhen i&gt;count_party_list
			set party = partylist<i>
			loop
				exitwhen j &gt;party.count
				if party.members[j].p == whichPlayer then
					return party.members[j]
				endif
				set j = j + 1
			endloop
			set j = 0
			set i = i + 1
		endloop
		return -1    
	endfunction
	
	function Party_Setup takes boolean enableSystem, boolean show_Name, boolean show_HP, boolean show_MP, boolean show_EXP, boolean ShareExperienceOnlyWithPartyMembers, real experienceBonus returns nothing
    set display_count = 0
    
    if enableSystem then
        set enabled = true
    endif
    
    if enabled then
        if show_Name then
            set showName = show_Name
            set display_count = display_count+1
        endif

        if show_HP then
            set showHP = show_HP
            set display_count = display_count+1
        endif

        if show_MP then
            set showMP = show_MP
            set display_count = display_count+1
        endif

        if show_EXP then
            set showEXP = show_EXP
            set display_count = display_count+1
        endif
        
       if experienceBonus &gt; expBonus then
            set expBonus = experienceBonus
        endif        
        
        if ShareExperienceOnlyWithPartyMembers then
            set shareExpExclusive = true
        endif
    endif
	endfunction	
	
	
	
	//***********************************************************************************
	//***************************Regeneration System API*********************************	
	//***********************************************************************************
	function Regeneration_Enabled takes nothing returns boolean
		return enabled
	endfunction

	function Regeneration_Setup takes boolean enableSystem, real UpdateTime returns nothing
		set enabled = enableSystem
		set updateTime = UpdateTime

		if enabled then
			set t = NewTimer()
			call TimerStart(t, updateTime, true, function Regen_Timer)
		endif
	endfunction</i></i></i></i></i></i></i></i></i></i></i></i></i></i>





API Explanation
If you need more information abotu the API's and some example, click right here or scroll down to my next post and you will see all of the information. I cannot post it here in a single post since there is a 60,000 character limit. Adding this in brings everything to 73,000 characters.

Hero Selection Screenshot
HeroSelection.jpg

Hero Equipment Screenshot
ItemSystem.jpg


Downloads
Changelog - This file holds all of the information of previous releases of the map, it catalogs all of the changes.

RPG Framework v1.00

Enjoy

-Steel
 

wellwish3r

wishes wells.
Reaction score
52
Maybe I'm just stupid, but neither in your post, nor the demo map, you describe how to make an item actually drop from a certain unit once you have created the loot table, and added items to it. So how do you do that?
 

Steel

Software Engineer
Reaction score
109
Hero System
Hero System API
JASS:
public function AddTypeAdvanced takes integer unitID, string unitDescription, string baseAttribute, boolean dualWield returns nothing
public function AddType takes integer unitID returns nothing

These functions will add in a specific unitID to treat as a hero. If you look at the map you will see Hamg or Hpal passed in, these tell the system to add those as heros to the system. The required input of the advanced function speak for themselves.

Demo Map Example:
JASS:
call Hero_AddType(&#039;Hamg&#039;)
call Hero_AddTypeAdvanced(&#039;Hpal&#039;, &quot;Paladin&quot;, &quot;A user of holy and divine light that purges the lands of evil&quot;, true )

This adds the 'Hpal' under the name of Paladin and the description above. The boolean passed in as true, is used by the itemsystem that tells us this herotype can wield two weapons at once. The advanced function's Name and Description fields are not required yet but will be used in the .08 release for a hero selection system.


Regeneration System
Regeneration System API
JASS:
public function Setup takes boolean enableSystem, real UpdateTime returns nothing

This is rather simple, you enable the system and you tell it how frequent you want to go through the regeneration. For example if you want to recreate the MP5 feel of World of Warcraft, you set the UpdateTime to 5. The system does something else a bit differently too. When you set a unit's HPS (Hitpoints Per Second) regeneration to say 100, that is saying you are giving it 100 hitpoints back every second. If the update frequency is set to 5, then every 5 seconds the unit will get 500 hitpoints. If you have the update frequency set to 1, it will give 100 hitpoints back every second. If it is set to .1, the unit will get 10 hitpoints back every .1 seconds.


Party System
Party System API
JASS:
public function Setup takes boolean enableSystem, boolean show_Name, boolean show_HP, boolean show_MP, boolean show_EXP, boolean ShareExperienceOnlyWithPartyMembers, real experienceBonus returns nothing

This is quite simple, pass true or false into which fields you want displayed on the party system multiboard. The last 2 may be confusing. ShareExperienceOnlyWithPartyMembers relates to how experience is handled while in a party. If this is set to true, only members of your party can benefit from your experience while killing an enemy.

The last value experienceBonus allows for bonus experiend yield while in a group, the default setting is 1.0 (100% normal experience) and in the demo map it is set to 1.5 (150% which is 50% more experience). The experience yield value is applied after the Difficulty System's experience gain.

Note I: This experience value is here and not in the Experience System because this value is only calculated if the Party System is enabled which must be done through the same setup trigger. If users want them in both places I can make this happen.
Note II: When you create a party you are the only person in the party. To prevent the experience bonus from being exploited you must have a minimum of 2 people in a party AND when you kill a unit, 2 members of the party must be present. This also disallows for a player to invite someone at random to get the benefit while they sit AFK. This is a feature, not a bug.

The setup function is the only function that should be used, the rest of the system is controlled by either abilities or chat commands. Each chat command has a counterpart ability to cater to both player's liking. The chat commands are:
"-createparty" - Creates a party with you as the leader, automatically shows the party multiboard.
"-invite" - Brings up a dialog window of other players you can invite. When you select a player to invite it will prompt that player to Accept or Decline, if they decline you will be notified.
"-leave" - Leaves your current party
"-showparty" - Shows your party's multiboard

(The abilities can be found in the Commands spellbook)

I know this was requested and it is something I've thought of in the past; the ability to have your group's hero on the side to heal, buff, etc... While I know how to do this, it is an immense amount of work. I will get this done for a future release.

Zoning System
Zoning System API
JASS:
public function AddRegion takes region whichRegion, string zoneName returns nothing

This is very simple, say you create a rect on using the World Editor, which I did in the Demo map. You simply pass a region into the map and then the name of that zone.

Demo Map Example:
JASS:
call Zoning_AddRect(gg_rct_ogreboss, &quot;Ogre&#039;s Hill&quot;)



Quest System
Quest System API
JASS:
public function Create_Kill takes integer startUnitID, real startUnitX, real startUnitY, real startUnitFace, integer levelRequirementMinimum, integer levelRequirementMaximum, boolean repeatable, integer unitToKillID, integer howMany, string questTitle, string questDescription, string questIcon, integer rewardItemID, integer rewardExp, integer rewardGold, integer rewardLumber returns nothing

This is very self explanatory. You give the system the RAW ID of the unit you which to declare as the starting unit. You give the system the X,Y coordinates with the facing direction. You then feed the system in a minimum level your unit must be to start the quest and a maximum level. The option repeatable is there, figure that one out. Since this is kill quest we take the RAW ID of the unit to kill next, then how many. We give the quest a title and a description finally a quest icon. Now you are onto the rewards for the; the RAW ID for the item, experience, gold and lumber rewards.

Demo Map Example:
JASS:
call Quest_Create_Kill(&#039;hkni&#039;, -900,-1300, 30, 1,3, true, &#039;n000&#039;, 3, &quot;Slay Wolves&quot;, &quot;Wolves up north have killed the transporters of our food supply, kill them to restore order!&quot;, &quot;ReplaceableTextures\\CommandButtons\\BTNTimberWolf.blp&quot;,0,10,10,10)


This system will be expanded to handle more than just kill quests. You can always create quests the manual way in your map if you choose. This system just greatly simplifies the process.


Difficulty System
Difficulty System API
JASS:
public function Setup takes boolean enableSystem, boolean useCustomDifficulties, boolean playerOneChooses, integer timeToChoose returns nothing
public function Add takes string name_of_difficulty, real enemy_hp_percentage, real experience_yield_percentage, real enemy_damage_percentage returns nothing
public function Choose takes nothing returns nothing returns nothing

The Setup function is very simple. You must first tell the system to be on or not with the first boolean. The second boolean tells our system to use custom difficulties. The next boolean if true lets player 1 select the difficulty and the integer is how long players have to select a difficulty
The Add function is how to setup and create a custom difficulty. It takes in the name of the difficulty, the modification of the enemy unit HP. The next value takes in the experience yield per difficulty. Finally the value is used to scale the damage of enemy units. These take in any value, 1.0 represents 100%, 1.5 represents 150%. .75 is 75% and so forth.
The Choose function actually brings up a dialog for players to select what difficulty. This function must follow after the Add function.

Demo Map Example:
JASS:
call Difficulty_Setup(true,true, true, 10)
call Difficulty_Add(&quot;Easy&quot;, .75,1.25,.75)
...
call Difficulty_Choose()



Advanced Player Library:
This should only be used by advanced users who know what they are doing with vJASS. Standard users should never open this

The Player library redefines the simple "player" and allows for much more complex usage of data manipulation. I hated always dealing with MUI systems needing arrays for everything I did, an array of multiboards... 1 for each player...an array of this or that, it gets annoying. This alleviates those problems and localizes everything within the cPlayer struct. The game uses various triggers to store data to a player such as gold and lumber. Other things can be associated with a player such as unit ownership. Some of these features however need to be extended or rather offer better usage. With the example of gold and lumber a user could manipulate these stats by third party programs or by hacking and altering the map. If the game is recording a player's gold at 1,000 and this system is recording it at 1,000 then suddenly there is an increase to 1,500 while the system sees it still at 1,000 something is wrong.

The Player library here serves other purposes than security, it ties many of my systems together. The Player library stores the data of the player's item system multiboard as well as dialogs and the player's hero unit. There are other various features that will be added in the future.

Example of the Player library in action. Lets say you want to reference a player first off. To do this you simply call cPlayer_getPlayerInt or cPlayer_getPlayerPlayer, these 2 functions will retrieve the struct for a specific player. PlayerInt takes an integer, this values is associated with the index of that player. Player 1 is index slot 0, Player 5 is index slot 4. Using PlayerPlayer you can pass in a variable 'player' to the function to retrieve that 'player' struct.

Once you have that cPlayer struct you can reference the data in it without any problems at all.

At present this system is just a backbone to all the other systems currently at work here (Mainly the Hero library (which tracks a players primary hero and only one), and the item system).

Advanced Hero Library:
This should only be used by advanced users who know what they are doing with vJASS. Standard users should never open this

This system stems from the Player library, it functions in much the same way. Instead of a player, think of this as focusing upon a single unit. The unit we focus upon here is the hero, mainly in an RPG you have a single unit that is you "character" that you control and level up with. You can gain various stats, items and other such features in an RPG. This library is here to encapsulate the data for quick and easy reference.

The quick and dirty example I can give is the use of movement speed that I have recorded here. While doing the Item System I wanted to allow a user to increase movement speed by a straight value, which can be done very easily. You retrieve the unit's current movement speed and add whatever you like to it. Say our movement speed is 270, if you add 50 to that you get 320, but if you have an aura that increases your movement speed by a percentage you can run into mathematical issues when calculating back down. Thus you need the movement speed of the unit tracked.


Item System
Item System API
There is now a new way to add items to the system that is much more user friendly.

JASS:
            method setID takes integer id returns nothing
                set .item_id = id
            endmethod                
            method setName takes string str returns nothing
                set .item_name = str
            endmethod
            method setType takes string str returns nothing
                set .item_type = str
            endmethod
            method setSlot takes integer slot returns nothing
                set .slot = slot
            endmethod
            method setSlotByName takes string str returns nothing
                local integer i = FindSlotSpecial(str)
                if (i==-1)
                    call BJDebugMsg(&quot;Error: Method on ItemStruct - setSlotByName&quot;)
                    set .slot = -1
                else
                    set .slot = i
                endif
            endmethod
            method setPermissions takes integer who returns nothing
                set .who = who
            endmethod
            method setLvlReq takes integer i returns nothing
                set .level = i
            endmethod
            method setStrReq takes integer req returns nothing
                set .str_r = req
            endmethod
            method setAgiReq takes integer req returns nothing
                set .agi_r = req
            endmethod
            method setIntReq takes integer req returns nothing
                set .int_r = req
            endmethod
            method setBonusStr takes integer val returns nothing
                set .bonus.str = val
            endmethod
            method setBonusAgi takes integer val returns nothing
                set .bonus.agi = val
            endmethod
            method setBonusInt takes integer val returns nothing
                set .bonus.int = val
            endmethod
            method setBonusDmg takes integer val returns nothing
                set .bonus.dmg = val
            endmethod
            method setBonusArmor takes integer val returns nothing
                set .bonus.armor = val
            endmethod
            method setBonusHP takes integer val returns nothing
                set .bonus.hp = val
            endmethod
            method setBonusHPR takes integer val returns nothing
                set .bonus.hpr = val
            endmethod
            method setBonusMP takes integer val returns nothing
                set .bonus.mp = val
            endmethod
            method setBonusMPR takes integer val returns nothing
                set .bonus.mpr = val
            endmethod
            method setAbilityID takes integer id returns nothing
                set .ability_id = id
            endmethod
            method setMovespeed takes integer val returns nothing
                set .movespeed = val
            endmethod
            method setModel takes string str returns nothing
                set .model = str
            endmethod


Example, only use what you're going to add. If you aren't going to have a strength requirement, why fill it out?
JASS:
    //Demonstration
    call ItemSystem_CreateItemStruct()
    call GetLastCreatedItemStruct().setID(&#039;H000&#039;)
    call GetLastCreatedItemStruct().setName(&quot;Cloth Hood&quot;)
    call GetLastCreatedItemStruct().setSlotByName(&quot;Helm&quot;)
    call GetLastCreatedItemStruct().setPermissions(16383)
    call GetLastCreatedItemStruct().setLvlReq(1)
    call GetLastCreatedItemStruct().setIntReq(18)
    call GetLastCreatedItemStruct().setBonusInt(5)
    call GetLastCreatedItemStruct().setBonusArmor(2)
    call GetLastCreatedItemStruct().setModel(&quot;ReplaceableTextures\\CommandButtons\\BTNCloak.blp&quot;)


Look below for details on how to use these functions. There were changes to the multiboard functions in version 0.05. The only difference between this and previous versions is Multiboard_ItemSystem is now ItemSystem_Multiboard
JASS:
function CreateCustomItem takes integer id, integer slot, string itype, integer who, integer level, integer str_r, integer agi_r,integer int_r, integer str, integer agi, integer int, integer dmg, integer armor, integer hp, integer mp, string model returns nothing
function CreateCustomItemAdvanced takes integer id, integer slot, string itype, integer who, integer level, integer str_r, integer agi_r,integer int_r, integer str, integer agi, integer int, integer dmg, integer armor, integer hp, integer mp, integer abilityid, integer movespeed, string model returns nothing
function AddSlot takes string str returns nothing

//ItemSystem Multiboard Functions
function Create takes nothing returns nothing
function DisplayAll takes nothing returns nothing
function DisplayByInt takes integer i returns nothing
function DisplayByPlayer takes player p returns nothing


Demo Map Examples:
Trigger:
  • 1) Custom script: call ItemCreation_CreateCustomItem(&#039;I004&#039;,4,&quot;e&quot;, 16383,3,15,10,5,2,0,0,0,9,20,20, &quot;ReplaceableTextures\\CommandButtons\\BTNBootsOfSpeed.blp&quot;)
    • 2) Custom script: call ItemCreation_CreateCustomItemAdvanced(&#039;I003&#039;,11,&quot;e&quot;,16383,1,0,0,0,1,1,1,1,1,1,1,&#039;A01Y&#039;, 0, &quot;ReplaceableTextures\\CommandButtons\\BTNNatureTouchGrow.blp&quot;)
    • 3) Custom script: call ItemSystem_AddSlot(&quot;Accessory&quot;)
    • 4) Custom script: call ItemSystem_Multiboard_Create()
    • 5) Custom script: call ItemSystem_Multiboard_DisplayAll()
    • 6) Custom script: call ItemSystem_Multiboard_DisplayByInt(0)
    • 7) Custom script: call ItemSystem_Multiboard_DisplayByPlayer(Player(3))


FAQ
Q: What is this?
A: This is a map that allows an extensive addition to the current item system belonging to the Warcraft III game. There have been systems like this before but I wanted people to have a look at mine and see how it works.

Q: What does this do?
A: It extends the basic 6 item slots of our unit and allows for multiple equipment slots such as a helm, accessory, boots, and such.

Q: Can you add more slots?
A: The system is completely modular, you can add and create whatever you want. The system is hardcapped at 37 since the multiboard cannot extend that far and frankly any more than that you should be slapped.

Q: Can the system support multiple slots of the same type?
A: Yes, so long as the slot names are EXACTLY the same. The demo map includes 2 slots titled "Accessory" to show how this works. If you attempt to equip an item with the slot title "Accessory" the system cycles through all the slots created initially by the system for a slot called "Accessory". The system will check the first slot it comes accross, in our example, slot 5. If slot 5 has nothing there, it will use that slot. If slot 5 has something there, the system will recognize this and search for another slot named "Accessory", if no other slot is found, you cannot equip the item.

In the example, we call AddSlot in the order of the 5th and 6th calls to the function. This means if we create an item with the ItemCreation_CreateCustomItem, the slot variable must be either 5 or 6, it does not have to be slot 5 only.

Q: How do I figure out the slot number now to create items?!
A: Very simple, if you call AddSlot 3 times, you will have 3 slots. You add them by calling the following
call AddSlot("Helm")
call AddSlot("Chest")
call AddSlot("Gloves")

Now to create an item for the helm slot, this was the FIRST call to AddSlot, so all items that you want put into the helm slot, are slot 1...call ItemCreation_CreateCustomItem('I000', 1....
If you wanted to create a pair of gloves, gloves are the THIRD call to AddSlot, so they are slot 3....call ItemCreation_CreateCustomItem('I000', 3....

Q: How do you create custom item abilities?
A: There is an advanced user function for creating items that has more features than the normal function. Take a look at this example:
JASS:
call ItemCreation_CreateCustomItemAdvanced(&#039;I00B&#039;,8,&quot;2h&quot;,16383,1,10,17,38,0,0,0,0,3,10,50, &#039;A021&#039;, 0, &quot;ReplaceableTextures\\CommandButtons\\BTNBrilliance.blp&quot;)

This function creates an item like normal. I00B is the item, 8 is the slot, 2h is the type, etc etc...continuing to the 3 for armor, 10 for hp, 50 for mana. The A021 is the custom ability to be added to the unit. The 0 is to indicate movespeed increase. Finally the last is the icon path for the multiboard.

The A021 in this example is the Blizzard spell, it will show up on the hero like normal. If you want to hide a passive ability use the spellbook / disable trick to work that out, or modify the ability any other way you wish. I may change how this works because it uses icons and slots on the player's unit which can be rather annoying for active abilities.


Explanations
1/2) This may look like garbage but lets take a look at what we're passing in:
- I004 is the item's raw ID value
- 4 is the slot we're using (A list of usable slots can be found in the map)
- "e" is passed in to tell the system to equip. (There are only 4 different types used, "e" for normal items, "1h" for one handed items, "2h" for two handed items and "s" for shields (This can also be used for offhand items)
- 16383 tells our system all classes in the system may use the item. This is actually a complex formula...I've included a spreadsheet that will calculate the value for you: http://dl.getdropbox.com/u/517800/Item System.xls
Say for example we have 4 Heroes.
Hero 1 is assigned 1
Hero 2 is assigned 2
Hero 3 is assigned 4
Hero 4 is assigned 8
Now, say we want an item Heroes 1,2 and 4 can use...add their values! 1+2+8 = 11. 11 would be the value to let those 3 use that item and EXCLUDE Hero 3.
- 3 the level requirement
- 15 Strength Requirement
- 10 Agility Requirement
- 5 Intelligence Requirement
- 2 Bonus Strength
- 0 Agility Bonus
- 0 Intelligence Bonus
- 0 Damage Bonus
- 9 Armor Bonus
- 20 HP Bonus
- 20 MP Bonus
- "ReplaceableTextures\\CommandButtons\\BTNBootsOfSpeed.blp" this is the icon associate with the item for multiboard display

Look at the GUI trigger in the Item_System category for more examples.

2) This is the same as above but 2 more values are passed. The first you can see is 'A022' this tells the system to give the unit that special ability. In my demo map the 'A022' is a Spellbook that has an ability inside it that is hidden so the user gains the ability and does not gain visibility of it.
The second additional value passed into the function is an increase to the unit's movement speed.

3) To add a class to the system all you have to do is pass in the unit's rawID. Maximum number of classes you can add is 16. You should never need any more than that unless you are making an AOS.

Look at the GUI trigger in the Item_System category for more examples.

4) This is the same as above but it takes in a boolean. Passing in true means you want to allow the unit you're passing in to dual wield weapons.

5) This function allows you to add any type of slot you want to the system. You can have absolutely anything you want, 10 finger slots, leggings, eyelash, whatever. Simply just call this function with the string you want. If you want multiple slots of the same type you must use the EXACT same string name (NOTE: System is case sensitive). The system can only create 37 item slots, this limitation is hardcoded because the multiboard can only display a certain number of rows properly.

6) Initially creates the multiboards for all players to allow the display of our equipment

7) Forces ALL players to view their equipment multiboard

8) Displays the equipment multiboard for the Player's ID you pass in to the function (Note, Player ID values start at the array base of ZERO (0))

9) Displays the equipment multiboard for the Player you pass in to the function



Enemy System: This library allows a user to create 2 databases of enemy information. The first is EnemyType which is very simple: you have a single unit that you place or use multiple times in your map. The second is Enemy which is each individual enemy unit placed on the map.
Enemy System API
JASS:
public function AddUnitType takes integer id, string str, string loot_table, real base_ms, integer hp_base, integer mp_base, real respawn_time, real experience, real gold returns nothing
public function AddAllExistingUnits takes player p returns nothing
public function AddUnit takes integer id, player p, real x, real y, real face returns nothing



The purpose of these functions and this system is to allow units to "respawn" in a certain amount of time as well as provide a Loot Table of items for that unit to drop randomly.

Lets take a deeper look into the API. The function to create a new EnemyType follows as such:
public function AddUnitType takes integer id, string str, string loot_table, real base_ms, integer hp_base, integer mp_base, real respawn_time, real experience, real gold returns nothing

Demo Map Example:
JASS:
call cEnemy_AddUnitType(&#039;n000&#039;, &quot;Frost Wolf&quot;,&quot;Table 1&quot;, 320, 210,0,30,25, 9)


This tells the system to add the unit type 'n000' with the name "Frost Wolf" using the Loot Table "Table 1". The unit's base movespeed is going to be 320, the unit's base HP is going to be 210. The unit's base MP is going to be 0. The respawn time will be 30 seconds. The experience given is 25. The golden yield is 9. All of this information is just generic data for the Frost Wolf enemy with the RAW ID of n000.

Please note: If you already set the unit's movespeed, hitpoints and mana in the Object Editor you need to pass 0 through those values so the system will omit any modifications

Next we add the actual enemy to the system and into a different database. There are 2 types of units we have to handle, preplaced units and spawned units.
The system already handles any and all preplaced units. If you specify a unit's hitpoints to be 1,000 but in the Object Editor you give it only 1 hitpoint the system will force the unit's hitpoint to 1,000 as the data you input suggests. If you have triggers that spawn units later you need to offset when the preplacement trigger runs.

call cEnemy_AddAllExistingUnits(Player(PLAYER_NEUTRAL_AGGRESSIVE))
Handles all exist units owned by PLAYER_NEUTRAL_AGGRESSIVE

public function AddUnit takes integer id, player p, real x, real y, real face returns nothing
call cEnemy_AddUnit('n000', Player(PLAYER_NEUTRAL_AGGRESSIVE), -800, 200, 37)
The following function above actually tells to create the unit of id n000 for player_neutral_aggressive at the X,Y location of -800, 200 facing 37º



Loot Table System
This system establishes loot tables for the individual units or specific groups of units. Please look at the system above for adding a loot table to an item. Looking at the Loot Table Data trigger you can see how things are created. The first function is LootTable_Create("Table 1", 1, false) and what this tells the system is to create a new loot table with the name of "Table 1". The 1 indicates that when we go to drop an item from this loot table only a single (1) item can be picked. This is particularly useful if you want a boss table loot with many items and multiple items to drop. The boolean false tells the system that it cannot allow duplicate items from this system to drop. If you have 10 items in a loot table and set the boolean to true, you cannot see 2 of the same item drop at once.

After we have our Loot Table created we can now add items to it.
call LootTable_addItem("Table 1", 'I003', 30) this tells our system to look at the "Table 1" Loot Table and add the item (via RAW ID) 'I003' to the system with a 30% chance of drop. The trick here with adding chances to drop is these are percentage based. The percentages of items added to these tables must be less than or equal to 100%. So for example you have 5 items each with 10% chance to drop, that leaves 50% chance of no item dropping. On the contrary here you cannot have 5 items with a 50% chance to drop, that would equal 250% total and thus result in an error.

Each loot table can hold a maximum of 50 items, I figured that would be plenty large enough since each item would be nearly 2% drop at that point. If you want this increase let me know.

Save / Load System
Save / Load System API
JASS:
function Setup takes boolean disableSinglePlayer, boolean saveHero, boolean saveLevel, boolean saveExperience, boolean saveStrength, boolean saveAgility, boolean saveIntelligence, boolean saveInventory, boolean saveEquipment, boolean saveGold, boolean saveLumber returns nothing

Probably the biggest and hardest feature for people to work into a map. Currently the save / load system handles your hero, hero's level, hero's exp, hero's equipment (however many slots you have designed with the Item System, it doesn't matter if you make 40 equipment slots, it handles ALL of them), gold and lumber. If you look at the SaveLoad Setup trigger, inside this you will find a function SaveLoad_Setup, this function takes in what you want and do not want to save. If you want to save the hero, his level, NOT his exp you can certainly do that.
Take a look at the setup function and what it takes in. The only one that may be confusing is the first boolean, disableSinglePlayer if set to true will disallow the ability to use the save / load system in Single Player WC3.
Demo Map Example:
JASS:
call SaveLoad_Setup(false,true, true, false, false, false, false, true, true, true, false)

Do NOT disable single player saving. Save our hero, save the level. Do not save the experience, strength, agility or intelligence. Save our inventory, equipment gold. Finally do NOT save lumber.

You will notice 2 other functions in the SaveLoad Setup trigger. I think the SetMapVersion speaks for itself. If you make a major change to your map and you want to disallow any and all old save / load codes working on your map, you can change this value. Currently it only supports the numbers 1-4, I will change this later.

In the demo map I have it set to save everything except for experience and lumber. (Standard Experience is disabled in the map currently anyway)

Floating Bars System
Floating Bars API
JASS:
public function Setup takes boolean all_units, boolean heroes_only, boolean life, boolean mana returns nothing
public function AdvancedSetup takes boolean all_units, boolean heroes_only, boolean life, boolean mana, string Display_Character, integer Bar_Length, real Bar_Size, real X_OffSet_Life, real Y_OffSet_Life, real X_OffSet_Mana, real Y_OffSet_Mana, real frequency returns nothing

Currently this is only configured to work with heroes. It will later be adapted with the Damage System to automatically add a bar to any unit that is taking damage. This system has a single setup function:
JASS:
function Setup takes boolean all_units, boolean heroes_only, boolean life, boolean mana returns nothing

It may look redundant to have it take all_units and heroes_only, but I will work on changing this. Essentially you can tell the Floating Bars system to allow all units the ability to have a bar on their head. If you enable Heroes only, this will create a floating bar above their head for the entire duration. The boolean of life and mana speak for themselves, do you want life to show? do you want mana to show?

In the map I have it set to do only heroes and display both life and mana.
 

FhelZone

Have a drink of a nice cold mellowberry juice!
Reaction score
103
I'm actually counting on you to implement a good save and load system, which is well demonstrated on this framework. One with the following I guess.

• Stash System (Multiple Inventory) - Load code to load items in stash. Has more than one inventory
• Save Point - When you load your character, it will spawn on the point where it saved.
• Abilities - Well, some save load does not save the abilities the hero has.
• Items - The items weilded by the hero (including the charges)
• EXP - Of course the total XP of the hero shouldn't be gone
• Gold - Yep the money
• Booleans - Well, I guess it would be useful to store some variables. Lets say you have one variable with unli arrays that can store up booleans. Lets say for example, unit has already taken quest or not
• Integer - It would be nice to save some integer. Kill counts is a good reason for having this. (Variable with unli arrays)
• Player Name Based Codes - Yep bases on player name and secures the code with a random character.

Some more suggestions:

• Fancy Text - Like in Diablo II there are fancy texts if you've entered a specific region.

• Damage System - Yep, I remember someone making one, and more or less its you :D

• Floating Health and Mana Bars - Yeah, it would rock with these, though having the selection scale of a unit to 0 would bug off its life bar and go some unit elses.

• Spell Combo - The damage system and spell combo is connected. Combos have a sum up of total damage dealt with other color than the normal damage.

Thats all I could think of as of now. More power to you. Hope you finish this in no time.
 

Steel

Software Engineer
Reaction score
109
I'm actually counting on you to implement a good save and load system, which is well demonstrated on this framework. One with the following I guess.

• Stash System (Multiple Inventory) - Load code to load items in stash. Has more than one inventory
• Save Point - When you load your character, it will spawn on the point where it saved.
• Abilities - Well, some save load does not save the abilities the hero has.
• Items - The items weilded by the hero (including the charges)
• EXP - Of course the total XP of the hero shouldn't be gone
• Gold - Yep the money
• Booleans - Well, I guess it would be useful to store some variables. Lets say you have one variable with unli arrays that can store up booleans. Lets say for example, unit has already taken quest or not
• Integer - It would be nice to save some integer. Kill counts is a good reason for having this. (Variable with unli arrays)
• Player Name Based Codes - Yep bases on player name and secures the code with a random character.

Some more suggestions:

• Fancy Text - Like in Diablo II there are fancy texts if you've entered a specific region.

• Damage System - Yep, I remember someone making one, and more or less its you :D

• Floating Health and Mana Bars - Yeah, it would rock with these, though having the selection scale of a unit to 0 would bug off its life bar and go some unit elses.

• Spell Combo - The damage system and spell combo is connected. Combos have a sum up of total damage dealt with other color than the normal damage.

Thats all I could think of as of now. More power to you. Hope you finish this in no time.

I will update my main page to reflect some of the points I am about to make but here goes.

First: The Save / Load code system I am implementing is by Vexorian, it is his Codemaker system. The reason I am using this is that I have experience using it, it provides everything I need to and it is fairly difficult to crack. Although with the upcoming changes in the 1.23b patch (or whatever it is) the system could break as it is older.

Second: The more things you add to a save / load system the longer the code will be. There are many trade offs you have to take. So if you want save POINTS I can do that, but it will be something you the designer must choose to enable for the system. The way I am implementing the Save / Load right now is, as all my system wills be, completely modular. You pick what to save with a simple function call and my system does the rest.

Third: I will never do saving and loading of abilities. Yes I can do it, but I don't find it practical so unless someone makes a very convincing argument my stance on the matter will not change.


On all of your other saving / loading comments...Saving very specific information is not something I will do. If you really need something added I can show you how, but I will not implement how to track your special variable BANANA_TEAM_SCORE or whatever, that's an arbitrary variable in a very structured environment.

• Items - The items weilded by the hero (including the charges)
As I stated in my main post this is a graphics issue, I will not do this. There are 3 reasons for this:
1) It requires importing of many models and understanding attachment points.
2) All units do not have the same attachment points and there are no functions that can retrieve data about a model's information on these matters.
3) It cannot be done in a modular sense. Some models already have a sword equip, so unless you are going to use the same bland character model there is no point.

• Fancy Text - Like in Diablo II there are fancy texts if you've entered a specific region.
I did this in my RPG map, I will port it over and update it accordingly.

• Damage System - Yep, I remember someone making one, and more or less its you :D
I have one planned, but my only problem is that it would be terribly complex and I don't want that in this map.

• Floating Health and Mana Bars - Yeah, it would rock with these, though having the selection scale of a unit to 0 would bug off its life bar and go some unit elses.
I was the original created of the Floating Bars system, I plan to implement this.

• Spell Combo - The damage system and spell combo is connected. Combos have a sum up of total damage dealt with other color than the normal damage.
This is already slated.


Thank you for the feedback, I appreciate it.
 

Steel

Software Engineer
Reaction score
109
Post the code.

Steel said:
-I will not post the code from the map on the forums as there is too much to post.

Also, I don't want to have to break each section of code down into multiple different sections. It is a HUGE pain in the ass when I make minor updates to a single system to optimize something and have to repaste the whole thing.

If you have interest in it then by all means take the 30 seconds to download and open the map.

At the time of writing this, the map is over 6,000 lines of code.
 

wraithseeker

Tired.
Reaction score
122
Took a look at your test map and it uses quite alot of BJs.

Make those functions private....

Learn how to indent your code.

ABC,BonusMod and SetUnitMaxState is outdated. Use TimerUtils and UnitProperties to replace them.
 

Steel

Software Engineer
Reaction score
109
Took a look at your test map and it uses quite alot of BJs.

Make those functions private....

Learn how to indent your code.

ABC,BonusMod and SetUnitMaxState is outdated. Use TimerUtils and UnitProperties to replace them.

If those are your only observations that is actually showing very strongly for my map. You didn't comment on if anything is good or bad in terms of practicality or functionality so I'll assume everything is 100%. So what if all of my code isn't indented? The code isn't meant for people to read unless they know what they're reading, which for most coders, what I have written won't throw them off.

My map uses a lot of Multiboard BJs, thats it. Even the popular system Multibars uses Multiboard BJs... I don't feel like rehashing this:
JASS:
function MultiboardSetItemStyleBJ takes multiboard mb, integer col, integer row, boolean showValue, boolean showIcon returns nothing
    local integer curRow = 0
    local integer curCol = 0
    local integer numRows = MultiboardGetRowCount(mb)
    local integer numCols = MultiboardGetColumnCount(mb)
    local multiboarditem mbitem = null

    // Loop over rows, using 1-based index
    loop
        set curRow = curRow + 1
        exitwhen curRow &gt; numRows

        // Apply setting to the requested row, or all rows (if row is 0)
        if (row == 0 or row == curRow) then
            // Loop over columns, using 1-based index
            set curCol = 0
            loop
                set curCol = curCol + 1
                exitwhen curCol &gt; numCols

                // Apply setting to the requested column, or all columns (if col is 0)
                if (col == 0 or col == curCol) then
                    set mbitem = MultiboardGetItem(mb, curRow - 1, curCol - 1)
                    call MultiboardSetItemStyle(mbitem, showValue, showIcon)
                    call MultiboardReleaseItem(mbitem)
                endif
            endloop
        endif
    endloop
endfunction


Over and over again for a simple multiboard, I dunno maybe I'll do it if I get really bored. I just don't see the reason on this BJ.

What makes any of those systems outdated? They all still do their job and perform very well. I don't like Windows Vista so I stuck with XP because it still works, same thing with these existing systems.
 

Steel

Software Engineer
Reaction score
109
If you want people to look over the code then indent your code else we cannot read it.

I never stated I want people to look at the system code. If you take a look over at my Virtual Equipment Thread you will notice that I post up 9 functions for people to use while the system code is quite long and unintuitive. This is the same thing I want here and as you can already see in my functions for this framework it is following in the same way. There are easy and quick Setup functions and then functions to add onto a system.

Wraithseeker, I don't think you quite understand the purpose of this map.
Steel said:
The goal is to make a set of systems and functions that are easy to use as well as maintaining complete modularity. I hate it when some really cool idea only works a single way, why not make it modular and allow it to work how I want it to?! This is my primary focus. This will also help alleviate many of the basic functions that RPG developers spend on their maps.

This is not for people to go in depth into the code and modify it for their map. The functions I provide do that for you so you never have to modify any core system functions!

The map is of course open so anyone can look at what I have written, but if I wanted that I would properly comment every function and detail what they all do. I did this with important functions of my Virtual Equipment system, but that was it.
 

wraithseeker

Tired.
Reaction score
122
If you even want this to be approved, it has to be reviewed and thus looked over the whole system code.
Do you expect the mods to just say Approved! without looking at the code?

You are submitting this as a resource and people has to look through it, what you are trying to say is like

Bob: Hey Tom I made a cake, don't ask about what the flavour is because you don't have to modify it to your likes!

Tom: :(
 

Steel

Software Engineer
Reaction score
109
If you even want this to be approved, it has to be reviewed and thus looked over the whole system code.
Do you expect the mods to just say Approved! without looking at the code?

You are submitting this as a resource and people has to look through it, what you are trying to say is like

Bob: Hey Tom I made a cake, don't ask about what the flavour is because you don't have to modify it to your likes!

Tom: :(
Here is my own analogy:
Bob: I want to give you this brand new Car!

Tom: I want to inspect the ceramic breaks, the steering column, the engine, the cylinders, the gaskets, the smell of the seats, the taste of the glass before I take it from you.



It doesn't have to be approved for people to use it. I really could care less what the moderators think of my map; I didn't make this map for them, I made it for the general public.
 

FhelZone

Have a drink of a nice cold mellowberry juice!
Reaction score
103
So did you update the map above already with the save/load codes?
I'm quite excited to actually implement a working save and load for my map hahahah.....
 

Steel

Software Engineer
Reaction score
109
Version 0.02 is now up. This update includes: Save / Load System, Floating Bars System. I will add in comments for the Save / Load system to elaborate on how it works. Please remember I use Vexorian's Codemaker here, that is the core of the system that is housed in the trigger "SaveLoad System". For details on how I make that work in an actual sense, look at the triggers "Save" and "Load"

Next version to include damage detection system, floating damage, random item drop, and an experience system
 

FhelZone

Have a drink of a nice cold mellowberry juice!
Reaction score
103
Hmm, save load code is in JASS, and I don't read JASS. It would have been better with some comment line in the code, I'll stick with Acehart's hahahaha.....
 

wellwish3r

wishes wells.
Reaction score
52
Btw since you said you have your own RPG? Can you upload that/give us a link to it? Would be interesting to see those features in action.
 

Steel

Software Engineer
Reaction score
109
Btw since you said you have your own RPG? Can you upload that/give us a link to it? Would be interesting to see those features in action.

The old systems I have would take too long to update now with NewGen additions and such. I'll think about expanding this little demo map to a small area to demo all of the features.
 

xAnaMorphine

Active Member
Reaction score
43
Can you upload those maps to fastshare or ultraupload? (Don't know If I am allowed to use original names, rapid + mega)

Because the site where the downloads are located has a trojan.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top