• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Map Framework System

Level 31
Joined
Jul 10, 2007
Messages
6,306
[vJASS] The Map Framework

The Map Framework
Now With All Working AI Native Declarations!
Current Version- v3.10
Guide Version- (v.02a)


Anyone who creates quick utilities for giving credits with this format and this usage
JASS:
//! textmacro Mfn_BUILD_CREDIT_INTERFACE takes name, title, description

public function createCredit$name$ takes string systemName, string versionNumber, string author, string helpers, string texturePath, string description returns nothing

will have an Mfn version built for them with their credit type and they will be added to the helper list for that version.

Tired of only Quest Credits? Make your own layout and it will be put out : ).

Why don't I just let users define their own layouts? Obvious reasons ; P. They might be the type who "hates" to give credit : ), and I believe it is required ^^. If they want to remove it, they have to remove it from each thing they put into their map.


1. Must use all parameters, including the icon
2. If temporary, it must display it for 6 seconds
3. May use any preset values desired (Mfn (QUEST) uses a left side true/false setting)


Be sure to do all the formatting yourself and the creation works using this-
JASS:
//! textmacro Mfn_BUILD_CREDIT_INTERFACE takes name, title, description



JASS:
//Level 2 design, defined basic types (level 1 is Mfn)
module Module
    public method greet takes integer instance, string greet returns nothing
        call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, .getH(instance) + greet + .getH2(instance))
    endmethod
endmodule

//! textmacro CONTAINER takes name
    scope Mfn$name$ initializer Mfn$name$Mfn
        globals
            Instance $name$
            private integer array MFN$name$AAbbCCddMFN$name$
        endglobals
        
        private struct Mfn_$name$Instance$name$AABB
            public string h
            public string h2
            public integer id
        endstruct
        
        struct Mfn$name$1122 extends Instance
            public method getInstance takes integer id returns integer
                return MFN$name$AAbbCCddMFN$name$[id]
            endmethod

            public method setInstance takes integer id, integer value returns nothing
                set MFN$name$AAbbCCddMFN$name$[id] = value
            endmethod

            public method setIdInstance takes integer instance, integer value returns nothing
                set Mfn_$name$Instance$name$AABB(instance).id = value
            endmethod

            public method getIdInstance takes integer instance returns integer
                return Mfn_$name$Instance$name$AABB(instance).id
            endmethod

            public method getH takes integer instance returns string
                return Mfn_$name$Instance$name$AABB(instance).h
            endmethod

            public method getH2 takes integer instance returns string
                return Mfn_$name$Instance$name$AABB(instance).h2
            endmethod

            public method setH takes integer instance, string x returns nothing
                set Mfn_$name$Instance$name$AABB(instance).h = x
            endmethod

            public method setH2 takes integer instance, string x returns nothing
                set Mfn_$name$Instance$name$AABB(instance).h2 = x
            endmethod

            public method createInstance takes nothing returns integer
                return Mfn_$name$Instance$name$AABB.create()
            endmethod

            public method destroyInstance takes integer instance returns nothing
                call Mfn_$name$Instance$name$AABB(instance).destroy()
            endmethod
        endstruct
        
        private function Mfn$name$Mfn takes nothing returns nothing
            set $name$ = Mfn$name$1122.create()
        endfunction
    endscope
//! endtextmacro

//default container ^^
//! runtextmacro CONTAINER("defaultInstance")

interface Instance
    public method getInstance takes integer id returns integer defaults 0
    public method setInstance takes integer id, integer value returns nothing defaults nothing
    public method setIdInstance takes integer instance, integer value returns nothing defaults nothing
    public method getIdInstance takes integer instance returns integer defaults 0
    public method getH takes integer instance returns string defaults null
    public method getH2 takes integer instance returns string defaults null
    public method setH takes integer instance, string x returns nothing defaults nothing
    public method setH2 takes integer instance, string x returns nothing defaults nothing
    public method createInstance takes nothing returns integer defaults 0
    public method destroyInstance takes integer instance returns nothing defaults nothing
endinterface

interface Data
    public string h = "you "
    public string h2 =" are a loser"

    public integer index = 0
    
    public delegate Instance instance = defaultInstance
    
    public method makeInstance takes nothing returns integer defaults 0
    public method unmakeInstance takes integer instance returns nothing defaults nothing

    public method addInstance takes integer instance returns nothing defaults nothing
    public method removeInstance takes integer instance returns nothing defaults nothing

    public method greet takes integer instance, string greet returns nothing defaults nothing
endinterface

struct Prototype extends Data
    implement Module
    
    public method makeInstance takes nothing returns integer
        //! runtextmacro Mfn_MAKE("instance", "Instance")
        call .setH(instance, .h)
        call .setH2(instance, .h2)
        return instance
    endmethod

    public method unmakeInstance takes integer instance returns nothing
        //! runtextmacro Mfn_UNMAKE("instance", "Instance")
    endmethod

    public method addInstance takes integer instance returns nothing
        //! runtextmacro Mfn_ADD_INDEX("this", "Instance", "index", "instance")
    endmethod

    public method removeInstance takes integer instance returns nothing
        //! runtextmacro Mfn_REMOVE_INDEX("this", "instance", "Instance", "index")
    endmethod
endstruct

JASS:
//Level 3 design, defined types

//make a container
//! runtextmacro CONTAINER("instance1")

struct Type1 extends Prototype
    public string h = "hi "
    public string h2 = " beep beep"
    
    public delegate Instance instance = instance1
endstruct

struct Type2 extends Prototype
endstruct

JASS:
library a initializer ini requires Mfn
    private function start takes nothing returns nothing
        //for fun, let's create some types through our interface
        local Data a = Type1.create()
        local Data b = Type2.create()

        //Now let's set up some instance variables, just integers ^^
        local integer instance
        local integer instance2
        local integer array instances

        //finally a counter
        local integer x = 1

        //Ok, let's stry setting up a bunch of instances in the array
        loop
            set instances[x] = a.makeInstance()
            call a.setH(instances[x], I2S(x))
            set x = x + 1
            exitwhen x > 10
        endloop
        set x = 0

        //Now let's greet via a loop. The only way to loop through them is via a stack.
        //We can get the stack id of any instance via .getIdInstance(instance) and we can get the instance stored in the
        //stack via the id via .getInstance(id)

        //In this case we are using the id as we want to loop ^^. Instance numbers are useless for looping as some might
        //be empty
        loop
            call a.greet(a.getInstance(x), "Fred")
            set x = x + 1
            exitwhen x == a.index
        endloop

        //Now for fun let's use a specific instance number to greet somebody without setting the instance's properties
        set instance = a.makeInstance()
        call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, I2S(instance))
        call a.greet(instance, "George")
        //This would use the type's default properties ^^

        //What happens when we have a type without defined values??
        set instance2 = b.makeInstance()
        call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, I2S(instance2))
        call b.greet(instance2, "John")

        //this does exactly what you would expect it to. It uses the default values.
    endfunction
    
    private function ini takes nothing returns nothing
        call TriggerAddAction(Mfn_ini, function start)
    endfunction
endlibrary



Utilities-
Virtual Grid and Math (these 2 are now merged)

Systems-
Graphic Effects (contorts stuff using math. Really specialized for 2D and 3D shapes created with math and structures of those shapes (things rotating around other things, etc)

Data Effects (effects data, can be like upgrades and can apply to any system ^_^)

Model (unsure about doing this)

Spawn + 3 lvl 2 Spawns (one class style spawning, one charge type, and another trainer type o-o)

Spell + lvl 2 spell (lvl 2 defines a type of spell system ^^, which uses nodes to create spells, very interesting and I find it to be an incredible model for spell creation)

Melee
Ranged

Frameworks-
Footmen Wars Framework
Starcraft Zone Control Framework




Level 1 defines basic types such as complex relationships (link between 3 thinks all sharing one thing, etc), combat types (spell- melee+ranged, bow- ranged, etc), etc.



Level 2 defines basic objects that plug into lvl 1's types.



Level 3 defines objects that extend upon lvl 2's basic objects.



Level 4 instantiates things and adds controls and events for them in the map.



Manipulation for a specific map



JASS:
//! textmacro Mfn_SETTINGS
    public constant boolean creditLeftSide = false
//! endtextmacro

//! textmacro Mfn_GET_HANDLE_ID
    //function GetHandleId takes handle h returns integer
    //    return h
    //    return 0
    //endfunction
//! endtextmacro

JASS:
library Mfn initializer create
    globals
        //Version Information
        private constant string SYSTEM = "Mfn"
        private constant string VERSION_THIS = "4.0"
        private constant string AUTHOR = "Nestharus"
        private constant string HELPERS = "Jesus4Lyf- Hash"
        private constant string TEXTURE_PATH = "ReplaceableTextures\\CommandButtons\\BTNPeriapt1.blp"
        private constant string DESCRIPTION = "The Map Framework"

        //Ini trigger
        public trigger ini = CreateTrigger()

        //Map Properties
        public real Map_centerX
        public real Map_centerY
        public real Map_minX
        public real Map_minY
        public real Map_maxX
        public real Map_maxY
        public rect Map_map

        //Player Properties
        public player array players[12]
        public integer array playerID[12]
        public integer playerCount = 0
        public constant force playerForce = CreateForce()

        public player array computers[12]
        public integer array computerID[12]
        public integer computerCount = 0
        public constant force computerForce = CreateForce()

        public player array all[12]
        public integer array allID[12]
        public integer allCount = 0
        public constant force allForce = CreateForce()
        
        public player host
        
        private constant timer runGameTime = CreateTimer()
        
        public integer gameTime = 0

        //Hash Categories
        public key ABILITY
        public key AI_DIFFICULTY
        public key ALLIANCE_TYPE
        public key ATTACK_TYPE
        public key BLEND_MODE
        public key BOOL_EXPR
        public key BUFF
        public key BUTTON
        public key CAMERA_FIELD
        public key CAMERA_SETUP
        public key CONDITION_FUNC
        public key DAMAGE_TYPE
        public key DEFEAT_CONDITION
        public key DESTRUCTABLE
        public key DIALOG
        public key DIALOG_EVENT
        public key EFFECT
        public key EFFECT_TYPE
        public key EVENT
        public key EVENT_ID
        public key F_GAME_STATE
        public key FILTER_FUNC
        public key FOG_MODIFIER
        public key FOG_STATE
        public key FORCE
        public key GAMECACHE
        public key GAME_DIFFICULTY
        public key GAME_EVENT
        public key GAME_SPEED
        public key GAME_STATE
        public key GAME_TYPE
        public key GROUP
        public key HANDLE
        public key HASHTABLE
        public key I_GAME_STATE
        public key IMAGE
        public key ITEM
        public key ITEM_POOL
        public key ITEM_TYPE
        public key LEADERBOARD
        public key LIGHTNING
        public key LIMIT_OP
        public key LOCATION
        public key MAP_CONTROL
        public key MAP_DENSITY
        public key MAP_FLAG
        public key MAP_SETTING
        public key MAP_VISIBILITY
        public key MULTIBOARD
        public key MULTIBOARD_ITEM
        public key PATHING_TYPE
        public key PLACEMENT
        public key PLAYER
        public key PLAYER_COLOR
        public key PLAYER_EVENT
        public key PLAYER_GAME_RESULT
        public key PLAYER_SCORE
        public key PLAYER_SLOT_STATE
        public key PLAYER_STATE
        public key PLAYER_UNIT_EVENT
        public key QUEST
        public key QUEST_ITEM
        public key RACE
        public key RACE_PREFERENCE
        public key RARITY_CONTROL
        public key RECT
        public key REGION
        public key SOUND
        public key SOUND_TYPE
        public key START_LOC_PRIO
        public key TERRAIN_DEFORMATION
        public key TEX_MAP_FLAGS
        public key TEXT_TAG
        public key TIMER
        public key TIMER_DIALOG
        public key TRACKABLE
        public key TRIGGER
        public key TRIGGER_ACTION
        public key TRIGGER_CONDITION
        public key UBERSPLAT
        public key UNIT
        public key UNIT_EVENT
        public key UNIT_POOL
        public key UNIT_STATE
        public key UNIT_TYPE
        public key VERSION
        public key VOLUME_GROUP
        public key WEAPON_TYPE
        public key WEATHER_EFFECT
        public key WIDGET
        public key WIDGET_EVENT

        public key INTEGER
        public key REAL
        public key STRING
        public key CODE

        public key X
        public key Y
        public key Z
        public key INDEX
        
        private gamecache getTheHost

//! runtextmacro Mfn_SETTINGS()
    endglobals

    //! runtextmacro Mfn_GET_HANDLE_ID()

    //Working AI Natives
    constant native GetPlayerUnitTypeCount takes player p, integer unitid returns integer
    constant native GetUnitGoldCost takes integer unitid returns integer
    constant native GetUnitWoodCost takes integer unitid returns integer
    constant native GetUnitBuildTime takes integer unitid returns integer

    constant native CreepsOnMap takes nothing returns boolean
    constant native UnitAlive takes unit id returns boolean
    
    private function getHost takes nothing returns player
        call StoreInteger(getTheHost, "missionKey", "key", GetPlayerId(GetLocalPlayer()) + 1)
        call TriggerSyncStart()
        call SyncStoredInteger(getTheHost, "missionKey", "key")
        call TriggerSyncReady()
        return Player(GetStoredInteger(getTheHost, "missionKey", "key") - 1)
    endfunction

    //Text Macros
    //! textmacro Mfn_CREATE_CONTAINER takes id, type
        public struct $id$
            public $type$ h

            public static method create takes $type$ x returns thistype
                local thistype h = thistype.allocate()
                set h.h = x
                return h
            endmethod
        endstruct
    //! endtextmacro

    //! textmacro Mfn_MAKE takes var, type
        local integer $var$ = .create$type$()
        call .add$type$($var$)
    //! endtextmacro

    //! textmacro Mfn_UNMAKE takes var, type
        call .remove$type$($var$)
        call .destroy$type$($var$)
    //! endtextmacro

    //! textmacro Mfn_REMOVE_INDEX takes owner, parameter, type, index
        local integer Mfn_id = .getId$type$($parameter$)
        local integer Mfn_recycled = .get$type$($owner$.$index$)
        set $owner$.$index$ = $owner$.$index$ - 1
        if Mfn_id < $owner$.$index$ then
            call .setId$type$(Mfn_recycled, Mfn_id)
            call .set$type$(Mfn_id, Mfn_recycled)
        endif
        call .setId$type$($parameter$, -1)
    //! endtextmacro

    //! textmacro Mfn_ADD_INDEX takes owner, type, index, instance
        call .setId$type$($instance$, $owner$.$index$)
        call .set$type$($owner$.$index$, $instance$)
        set $owner$.$index$ = $owner$.$index$ + 1
    //! endtextmacro

    //! textmacro Mfn_CREATE_LOOP1_1 takes index, timeout
        local integer timeout = $index$ + $timeout$
    //! endtextmacro

    //! textmacro Mfn_CREATE_LOOP1_2 takes index, params, condition, function
        exitwhen ($condition$) or $index$ >= timeout
        endloop
        if not ($condition$) then
            return $function$.evaluate($params$)
        else
    //! endtextmacro

    //! textmacro Mfn_BUILD_CREDIT_INTERFACE takes name, title, description
        public function createCredit$name$ takes string systemName, string versionNumber, string author, string helpers, string texturePath, string description returns nothing
            call credit($title$, $description$, texturePath)
        endfunction
    //! endtextmacro

    public constant function STOP_THREAD takes nothing returns integer
        return 1/0
    endfunction

    //System functions
    public function credit takes string title, string description, string texturePath returns nothing
        local quest credits = CreateQuest()
        call QuestSetTitle(credits, title)
        call QuestSetDescription(credits, description)
        call QuestSetIconPath(credits, texturePath)
        call QuestSetDiscovered(credits, true)
        call QuestSetCompleted(credits, false)
        call QuestSetEnabled(credits, true)
        call QuestSetRequired(credits, creditLeftSide)
        set credits = null
    endfunction

    //! runtextmacro Mfn_BUILD_CREDIT_INTERFACE("1", "systemName + \" v\" + versionNumber", "\"Author of this System- |n\" + author + \"|n|nPeople who helped design this system- |n\" + helpers + \"|n|nDescription- |n\" + description")

    private function playerLeave takes nothing returns nothing
        local player p = GetTriggerPlayer()
        local integer pID = GetPlayerId(p)
        if p == host then
            set host = getHost()
        endif
        set playerCount = playerCount - 1
        set allCount = allCount - 1
        call ForceRemovePlayer(playerForce, p)
        call ForceRemovePlayer(allForce, p)
        if playerID[pID] < playerCount then
            set players[playerID[pID]] = players[playerCount]
            set playerID[allCount] = allID[pID]
        endif
        if allID[pID] < allCount then
            set all[allID[pID]] = all[allCount]
            set allID[allCount] = allID[pID]
        endif
        set playerID[pID] = -1
        set players[playerCount] = null
        set allID[pID] = -1
        set all[allCount] = null
        set p = null
    endfunction

    private function removeAllUnits takes nothing returns nothing
        call RemoveUnit(GetEnumUnit())
    endfunction
    
    private function addToGameTime takes nothing returns nothing
        set gameTime = gameTime + 10000
    endfunction
    
    public function getElapsedGameTime takes nothing returns real
        return gameTime + TimerGetElapsed(runGameTime)
    endfunction
    
    private function mapSetup takes nothing returns nothing
        local integer x = 0
        local rect r = GetWorldBounds()
        local trigger playerLeaves = CreateTrigger()
        local group g = CreateGroup()
        call TimerStart(runGameTime, 10000, true, function addToGameTime)
        
        //Setup Map
        set Map_minX = GetRectMinX(r) + GetCameraMargin(CAMERA_MARGIN_LEFT)
        set Map_minY = GetRectMinY(r) + GetCameraMargin(CAMERA_MARGIN_BOTTOM)
        set Map_maxX = GetRectMaxX(r) - GetCameraMargin(CAMERA_MARGIN_RIGHT)
        set Map_maxY = GetRectMaxY(r) - GetCameraMargin(CAMERA_MARGIN_TOP)
        set Map_centerX = (Map_minX+Map_maxX)/2
        set Map_centerY = (Map_minY+Map_maxY)/2
        call RemoveRect(r)
        set r = null
        set Map_map = Rect(Map_minX, Map_minY, Map_maxX, Map_maxY)

        //Setup Players
        loop
            if (GetPlayerController(Player(x)) == MAP_CONTROL_USER and GetPlayerSlotState(Player(x)) == PLAYER_SLOT_STATE_PLAYING) then
                set players[playerCount] = Player(x)
                set playerID[x] = playerCount
                set playerCount = playerCount + 1
                call ForceAddPlayer(playerForce, Player(x))
                call TriggerRegisterPlayerEvent(playerLeaves, Player(x), EVENT_PLAYER_LEAVE)
            elseif (GetPlayerController(Player(x)) == MAP_CONTROL_COMPUTER and GetPlayerSlotState(Player(x)) == PLAYER_SLOT_STATE_PLAYING) then
                set computers[computerCount] = Player(x)
                set computerID[x] = computerCount
                set computerCount = computerCount + 1
                call ForceAddPlayer(computerForce, Player(x))
            else
                call GroupEnumUnitsOfPlayer(g, Player(x), null)
                call ForGroup(g, function removeAllUnits)
                call GroupClear(g)
            endif
            if (GetPlayerSlotState(Player(x)) == PLAYER_SLOT_STATE_PLAYING) then
                if (GetPlayerController(Player(x)) == MAP_CONTROL_COMPUTER or GetPlayerController(Player(x)) == MAP_CONTROL_USER) then
                    set all[allCount] = Player(x)
                    set allID[x] = allCount
                    set allCount = allCount + 1
                    call ForceAddPlayer(allForce, Player(x))
                endif
            endif
            set x = x + 1
            exitwhen x > 11
        endloop
        if playerCount > 1 then
            set getTheHost = InitGameCache("Mfn")
            set host = getHost()
        endif
        call DestroyGroup(g)
        call TriggerAddAction(playerLeaves, function playerLeave)
    endfunction
    
    private struct HashIndex
        thistype next=0
        integer hashedInt
    endstruct
    globals
        private constant integer MAX_HASH_VALUE=8191
        private HashIndex array ListOnHash
    endglobals
    public function Hash takes integer int returns integer
        local HashIndex hash=HashIndex(int-(int/MAX_HASH_VALUE)*MAX_HASH_VALUE)
        if ListOnHash[hash]==0 then
            set ListOnHash[hash]=HashIndex.create()
            set hash=ListOnHash[hash]
            set hash.hashedInt=int
        else
            set hash=ListOnHash[hash]
            loop
                exitwhen hash.hashedInt==int
                if hash.next==0 then
                    set hash.next=HashIndex.create()
                    set hash=hash.next
                    set hash.hashedInt=int
                    return hash
                endif
                set hash=hash.next
            endloop
        endif
        return hash
    endfunction
    public function HashFree takes integer int returns nothing
        local HashIndex hash=HashIndex(int-(int/MAX_HASH_VALUE)*MAX_HASH_VALUE)
        local HashIndex last=ListOnHash[hash]
        if last.hashedInt==int then
            set ListOnHash[hash]=last.next
            call last.destroy()
        else
            loop
                set hash=last.next
                exitwhen hash==0
                if hash.hashedInt==int then
                    set last.next=hash.next
                    call hash.destroy()
                    return
                endif
                set last=hash
            endloop
        endif
    endfunction

    private function create takes nothing returns nothing
        call Mfn_createCredit1(SYSTEM, VERSION_THIS, AUTHOR, HELPERS, TEXTURE_PATH, DESCRIPTION)
        call mapSetup()
        call TriggerRegisterTimerEvent(ini, .01, false)
    endfunction
endlibrary

library Hash initializer ini requires Mfn
    globals
        private constant string SYSTEM = "Hash"
        private constant string VERSION_THIS = "2.0"
        private constant string AUTHOR = "Jesus4Lyf"
        private constant string HELPERS = "None"
        private constant string TEXTURE_PATH = "ReplaceableTextures\\CommandButtons\\BTNOrcCar.blp"
        private constant string DESCRIPTION = "Rawcode Hashing"
    endglobals
    
    //! textmacro Hash_CREATE takes new
        private struct HashIndex
            thistype next=0
            integer hashedInt
        endstruct
        globals
            private constant integer MAX_HASH_VALUE=8191
            private HashIndex array ListOnHash
        endglobals
        public function Hash takes integer int returns integer
            local HashIndex hash=HashIndex(int-(int/MAX_HASH_VALUE)*MAX_HASH_VALUE)
            if ListOnHash[hash]==0 then
                set ListOnHash[hash]=HashIndex.create()
                set hash=ListOnHash[hash]
                set hash.hashedInt=int
                $new$
            else
                set hash=ListOnHash[hash]
                loop
                    exitwhen hash.hashedInt==int
                    if hash.next==0 then
                        set hash.next=HashIndex.create()
                        set hash=hash.next
                        set hash.hashedInt=int
                        $new$
                        return hash
                    endif
                    set hash=hash.next
                endloop
            endif
            return hash
        endfunction
        public function HashFree takes integer int returns nothing
            local HashIndex hash=HashIndex(int-(int/MAX_HASH_VALUE)*MAX_HASH_VALUE)
            local HashIndex last=ListOnHash[hash]
            if last.hashedInt==int then
                set ListOnHash[hash]=last.next
                call last.destroy()
            else
                loop
                    set hash=last.next
                    exitwhen hash==0
                    if hash.hashedInt==int then
                        set last.next=hash.next
                        call hash.destroy()
                        return
                    endif
                    set last=hash
                endloop
            endif
        endfunction
    //! endtextmacro
    
    private function ini takes nothing returns nothing
        call Mfn_createCredit1(SYSTEM, VERSION_THIS, AUTHOR, HELPERS, TEXTURE_PATH, DESCRIPTION)
    endfunction
endlibrary

library RequiresMfn requires Mfn, Hash
endlibrary
 

Attachments

  • Mfn Library Template.w3m
    11.5 KB · Views: 75
  • Mfn Utility and System Template.w3m
    11.7 KB · Views: 89
  • Mfn Framework Template.w3m
    11.7 KB · Views: 69
  • Mfn Guide.zip
    1,020.3 KB · Views: 79
Last edited:
Level 14
Joined
Nov 18, 2007
Messages
816
JASS:
function MFN_main takes nothing returns nothing
    call NewSoundEnvironment( "Default" )
    call SetMapMusic( "Music", true, 0 )
    call InitGlobals()
    //call InitSounds(  )
    //call CreateRegions(  )
    //call CreateAllUnits(  )
endfunction

function MFN_gui takes nothing returns nothing
    //call InitCustomTriggers(  )
    //call RunInitializationTriggers(  )
endfunction

function MFN_system_ini takes nothing returns nothing
endfunction

function MFN_game_ini takes nothing returns nothing
endfunction

function MFN_ingame_ini takes nothing returns nothing
endfunction

globals 
    MFNStructure MFN
endglobals

struct MFNStructure
    private string System = "MFN"
    private string Version = ".01b"
    private integer CompatibilityNumber = 7
    
    private trigger ini = CreateTrigger()
    
    public real MinX
    public real MinY
    public real MaxX
    public real MaxY
    public rect Map
    
    public player array PlayerID[20]
    public integer Players = 0
    
    private string array Systems[500]
    private integer array SystemsCompatibilityNumber[500]
    private string array ReqSystems[500]
    private integer array ReqSystemsCompatibilityNumber[500]
    private integer array MissingSystem[500]
    private integer MissingSystemCount = 0
    private integer IndexSys = 0
    private integer IndexReq = 0
    
    public boolean Diagnostics = false
    
    public method RegisterINI takes code ini returns nothing
        call TriggerAddAction(.ini, ini)
    endmethod
    
    private method SystemCheck takes nothing returns integer
    local integer x = 0
    local integer y = 0
    local integer check = -1
    local boolean end = false
        loop
            set x = x + 1
            set y = 0
            loop
                set y = y + 1
                if .Systems[y] == .ReqSystems[x] and .SystemsCompatibilityNumber[y] == .ReqSystemsCompatibilityNumber[x] then
                    set end = true
                elseif y >= .IndexSys then
                    set end = true
                endif
                exitwhen end == true
            endloop
            if .Systems[y] == .ReqSystems[x] and .SystemsCompatibilityNumber[y] == .ReqSystemsCompatibilityNumber[x] then
                if x == .IndexReq and check == -1 then
                    set check = 1
                endif
            else
                set check = 0
                set .MissingSystemCount = .MissingSystemCount + 1
                set .MissingSystem[.MissingSystemCount] = x
            endif
            exitwhen x == .IndexReq
        endloop
    return check
    endmethod
    
    private static method ingameini takes nothing returns nothing
    local integer x = 1
        if MFN.SystemCheck() == 0 then
            loop
                call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "Missing System: " + MFN.ReqSystems[MFN.MissingSystem[x]])
                call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "Compatibility Number: " + I2S(MFN.ReqSystemsCompatibilityNumber[MFN.MissingSystem[x]]))
                set x = x + 1
                exitwhen x > MFN.MissingSystemCount
            endloop
        else
            if MFN.Diagnostics == true then
                call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "Map Compliant")
            endif
        endif
    endmethod
    
    public method Credit takes string SystemName, string VersionNumber, string Author, string Helpers, string TexturePath, string Description returns nothing
        local quest Credits = CreateQuest()
        call QuestSetTitle(Credits,SystemName +" v" + VersionNumber)
        call QuestSetDescription(Credits,"Author of this System- |n" + Author + "|n|nPeople who helped design this system- |n" + Helpers + "|n|nDescription- |n" + Description)
        call QuestSetIconPath(Credits, TexturePath)
        call QuestSetRequired(Credits, false)
        call QuestSetDiscovered(Credits, true)
        call QuestSetCompleted(Credits, false)
        call QuestSetEnabled(Credits, true)
        set Credits = null
    endmethod
    
    public method RegisterSystem takes string SystemID, integer CompatibilityNumber returns nothing
    local integer x = 0
    local boolean end = false
        loop
            set x = x + 1
            if x >= .IndexSys then
                set end = true
            elseif .Systems[x] == SystemID and .SystemsCompatibilityNumber[x] == CompatibilityNumber then
                set end = true
            endif
            exitwhen end == true
        endloop
        if .Systems[x] != SystemID and .SystemsCompatibilityNumber[x] != CompatibilityNumber then
            set .IndexSys = .IndexSys + 1
            set .Systems[.IndexSys] = SystemID
            set .SystemsCompatibilityNumber[.IndexSys] = CompatibilityNumber
        endif
        set SystemID = null
    endmethod
    
    public method RequireSystem takes string SystemID, integer CompatibilityNumber returns nothing
    local integer x = 0
    local boolean end = false
        loop
            set x = x + 1
            if x >= .IndexReq then
                set end = true
            elseif .ReqSystems[x] == SystemID and .ReqSystemsCompatibilityNumber[x] == CompatibilityNumber then
                set end = true
            endif
            exitwhen end == true
        endloop
        if .ReqSystems[x] != SystemID and .ReqSystemsCompatibilityNumber[x] != CompatibilityNumber then
            set .IndexReq = .IndexReq + 1
            set .ReqSystems[.IndexReq] = SystemID
            set .ReqSystemsCompatibilityNumber[.IndexReq] = CompatibilityNumber
        endif
        set SystemID = null
    endmethod

    private method MapSetup takes nothing returns nothing
    local integer x = 0
        set .MinX = GetRectMinX(GetWorldBounds()) + GetCameraMargin(CAMERA_MARGIN_LEFT)
        set .MaxX = GetRectMaxX(GetWorldBounds()) - GetCameraMargin(CAMERA_MARGIN_RIGHT)
        set .MinY = GetRectMinY(GetWorldBounds()) + GetCameraMargin(CAMERA_MARGIN_BOTTOM)
        set .MaxY = GetRectMaxY(GetWorldBounds()) - GetCameraMargin(CAMERA_MARGIN_TOP)
        set .Map= Rect(.MinX, .MinY, .MaxX, .MaxY)
        call SetCameraBoundsToRect(.Map)
        loop
            if GetPlayerController(Player(x)) == MAP_CONTROL_USER then
                set .Players = .Players + 1
                set .PlayerID[.Players] = Player(x)
            endif
            set x = x + 1
            exitwhen x > 11
        endloop
    endmethod
    
    private method IniSetup takes nothing returns nothing
        call TriggerRegisterTimerEvent(.ini, .01, false)
        
        call .RegisterINI(function MFNStructure.ingameini)
        call .RegisterINI(function MFN_ingame_ini)
    endmethod
    
    private method MapRegistration takes nothing returns nothing
        call .RegisterSystem(.System, .CompatibilityNumber)
    endmethod
    
    static method Create takes nothing returns MFNStructure
        local MFNStructure ini = MFNStructure.allocate()
        
        call ini.MapSetup()
        call ini.IniSetup()
        call ini.MapRegistration()
        
        call ini.Credit(ini.System, ini.Version, "Nestharus", "None", "ReplaceableTextures\\CommandButtons\\BTNStaffOfPreservation.blp", "The Map Framework System!.")
        
        return ini
    endmethod
endstruct

//! inject main
    //! dovjassinit
    call InitBlizzard()
    call MFN_main()
    set MFN = MFNStructure.Create()
    call MFN_system_ini()
    call MFN_gui()
    call MFN_game_ini()
//! endinject

Okay:
First off, you leak four rects, whenever you create a new MFNStructure (GetWorldBounds()).
Secondly, i dont like the way you initialize your system. inject main is not the correct way to do this. Use a library initializer for that.

But i think this is well made nonetheless, it does what its meant to do. Although i think the usefulness of it can be disputed.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Updates on Documentation Stuff:
I decided to change the design around again : ). At the moment, this allows for various classes and layers of classes. It also allows you to dynamically create containers ^_-.

Right now it only allows one container per object and only deals with XHTML code : D.

The current code is riddled with stuff at the moment, so I gotta clear it out and save it as a template or sumtin ^^, but i'll be using this model for awhile until the better one is ready to go : D. I actually quite like this model cuz it's easy to use ; D.
 
Last edited:
Level 31
Joined
Jul 10, 2007
Messages
6,306
Updates-
CN 9 Emergency Release!!

CN 10 will be released soon

Version v.01c (not sure what CN number it will be) will be released at some point : O.

Virtual Gridding utility will be released soon

Colorizer is actually done, so I don't know why I have yet to release it : |.

Pondering a new thing for automatically building things in a specific order and adding things to a stack o_O so that the map makers don't have to worry about build order.

hf all and Happy Mapping! : D
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Ok well.. more updates


I'm unsure how to work extensions into this... so I think registering systems will be fine :\.

Unsure how to get systems to build themselves without library INI stuff or building them as the game starts (which isn't good :p), soooo... i'll just let mappers build the systems themselves :\.

Uhm... that being said, CN10 (on another computer) only has 1 fix in it, lol, but otherwise CN9 works =). The fix is really tiny, so, you guys can play with CN9 if you like.

The documentation, as I said before, isn't really updated, but... you just do SysetmID.Create to create the various systems in the various load areas : D.

I understand that many people don't really see a point to this, but it'll help keep your map organized ^^. Also, it'll allow people to build systems that depend on other systems : P (without messy errors). This will mean that systems will become more efficient, smaller, and well, better : D. Uhm... yea..

Oh well, documentation framework still isn't done because I haven't had too much time for it : p. I'll release CN10 with the one tiny fix as soon as documentation is done : D.

Also, I'm still debating about how to work extensions into MFN. The only idea I can think of is code snippets (copying/pasting into MFN). But that wouldn't be good (updating MFN will be a hassle), so I suppose that I'll just keep it as it is (low-level systems, medium tier systems, and high level systems ^^).

Finally, for system etiquette, there should be an objects area for objects that your system instantiates (structs area) ^^. These should be private structs (put them in a scope with a big name o_O) and should be accessed via the interface and the methods within the system code area ^^ (make documentation on the methods that can be used and the interface ^^).

Happy mapping/programming : D.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Rather than trying to get people to post at other sites, why don't you support each site you're on ^_-. I have my reasons for never posting at thehelper or wc3campaigns ^_-. Also, I believe that would count as advertising other sites? Oh well, I'll let a mod deal with it ^^.

I believe a solved the issue of how to implement integrated extensions for MFN : |.

I suppose we shall see if this works or not : P

Version Check has been reworked so that its loop is split among various threads. This will remove all possibility of a thread crash from a large amount of systems ^^.

The start up stack was reworked a bit to include some new things in the interface.

Credit Feature has finally been taken out of the system code and placed into a customization area so that people can format their credits however they like. They can only edit the formatting for the title and the description.

At the moment it is possible to make it so no text appears, but I'll be doing checks here. If they end up doing that, I'll override it with internal formatting >: (. Originally, I was planning on doing a massive sleep action during their load up, but eh... I really do believe that credits should be given to people for their work.

At this time, the only way to fully remove credits is by going through the MFN System Code >: ). The only thing you can modify, as I said, is the title and the description. You can also modify whether it will show up on the left side or the right side : P. Be sure to create your own categories so that it doesn't conflict with future releases of MFN if you want custom formatting.

I'll release v.01c CN10 soon : ). First I need to finish the documentation and then I need to finish the credit system so that it overrides formatting and uses default formatting if the map maker is trying to remove the credits or the custom formatting is screwed up >: P.

Quite a bit of the internal design has changed, but overall use hasn't : ).

H2I was also added in because it's just such a useful function and it's only 3 lines of code : P. I wasn't about to add it into its own utility since it's so small... that's why I just added it into the system code.
 
Last edited:
Level 31
Joined
Jul 10, 2007
Messages
6,306
Ok, sry that it's taking so long to update this thing.

I tried to pass it on to someone else, but it doesn't seem like they are interested in working it, so I'm back on it. I'm also working on an actual commercial game, so I'm really doing this on *hobby* time now : |. Shhhhhhhhh

Well... I'm doing some massive updates to it. You can check out the pastebin to see what's going on.

I updated the create variable and destroy variable stuff to make it a bit faster.

I added a roundUp and roundDown function since I was shocked*****, and let me emphasize *SHOCKED* to find out that wc3 didn't have that >: O.

The round up and round down function still needs to be fixed up. I also added a displayText and displayTimedText function cuz I was tired of using the absolutely crappy BJDebug stuffs. Yes, it is faster.

Added a getInternalPlayerID function because I found a need for it. I needed to get the MFN Player ID given the regular Player ID : P.

Changed around styling for systems to use create instead of Create. Changed around over-all styling to make it more compliant with standard coding practices. I optimized a few things, changed a load around, and I'm adding lots more in.

Was going to add in slots for the virtual memory address stuff, but I decided not to. Virtual Memory allows easy attatchment systems for non-handle variables and what not. It also allows for handle variables if you plan on having more handles than an array allows... considering you can have 40800, i really doubt u need it. My little virtual memory thing takes 120,000, but yea...

So yea, pretty much it allows for like structs to use memory addresses to attach structs together... or something like that : P. You have to store the memory address of so said value somewhere =).

The virtual memory address only takes integers, but there are a bundle of conversion functions in there to convert stuff into integers and back. I realize I still need to add a few more things, but eh : P.

There are still being things added in. I also created a create unit utility thing that runs off of the special MFN set variable stuffs : ). It'll create the unit, put it in a variable, etc. I found a need for it : P.

I'm also doing terrain stuff.

From here, I'm going to be doing a unit properties thingie that'll be handling the memory for you and what not using that utility and MFN's default stuff. I'll also be doing a terrain properties thingie that'll be handling the memory for you and using the terrain utility and MFN's default stuff : O.

Why am I really working on this right now? Because I can't work on the commercial game atm because my internet connection's going wacky with MSN Messenger... but I'll hardly be working on this in a month or so, so lucky you ^_^.

So here's what I'm working on atm:
MFN
UN (unit utility)
TN (terrain utility)
VGN (virtual grids utility)
String Utilities (encryption, etc)
TSN (the saver system)
UPN (unit properties mid-system)
TPN (terrain properties mid-system)
UPMN (unit properties for mazes)
TPMN (terrain properties for mazes)
TN (trackables utility... will make it so you only need one trackable per area or w/e for all players and will be able to track what players does what. Will require VGN).
GUIN (GUI using VGN, TN, and various string utilities ^^)
SN (shapes in wc3, useful for doing combat systems and so on, will also contain filters and what not (filters through the shape given a range from a point).
S3DN (3D shapes)
VG3DN (3D virtual grids)
PN (projectiles by me. It will be a mid-level system)
CN (combat system by me ^_-, using shapes and what not)

All i can say is omg at that wishlist... yes, i want all of those systems o_O. Yes, I'll probably be doing them for the commercial game as well : |. Why not design them for the commercial game now? Because the engine isn't out yet and uhm... I should really be working on the website now that I think about it. o_O

Will I finish all of the above? I'm not sure... probably not.. lol

Will you guys? probably not, but I can always hope : P

and omg o-o, adding support C2TriggerAction (code to trigger action), TriggerAction2C, uhm... and a few other things, hehehehehe. soooo tired, need more diet mtn dew ;o

*New*
Heavily optimized the roundUp, roundDown, and round methods o-o
 
Last edited:
Level 11
Joined
Nov 4, 2007
Messages
337
OMG?
JASS:
        public static method round takes real r returns integer
            if (RAbsBJ(r) - IAbsBJ(R2I(r)) >= .5) then
                return R2I(r) + 1
            endif
            return R2I(r)
        endmethod
Worst round function i've ever seen!
Do it like this:
JASS:
function round takes real r returns integer
     return R2I(r+0.5)
endfunction

public static method roundDown takes real r returns integer
return R2I(r)
endmethod

==> Not necessary.



And don't use that:

public function S2I takes string s returns integer
return s
return 0
endfunction

==> Slow!
You should better loop through strings and chekc if a == b.
 
Last edited:
Level 31
Joined
Jul 10, 2007
Messages
6,306
Oo at round. Actually, roundDown and RoundUp aren't really needed : ), nor is round, but eh.

S2I does something different from what you think it does.... the thing you said would not work for strings..

*updates*
final change to virtual memory address management network underway, so don't talk about that

round is fixed ;p....

the over-all MFN structure will probably be moved to a library to keep things faster. I've come to learn that structs = bad for functions but fine for variables =). I also decided that if your system requires another system, just make it require it in the library. Don't use library inits though !!

So yea, over-all model for designing systems will change to keep things faster =).
 
Last edited:
Level 31
Joined
Jul 10, 2007
Messages
6,306
Well, I've decided to give you guys some news on the latest developments-

Current, Virtual Grids are still being worked on, but here's what is being played around with right now-
getCameraMin (x ,y) (if ur vertical it'd be using z in the background)
getCameraMax (x, y) (if ur vertical it'd be using z in the background)

With this, I tried out making a grid and a UI that followed the screen around. Worked perfectly : ).

After that, I decided to see how single player arrow keys would work with this. It was amazing... 0 delay on the arrows ^_^. I moved the unit based on the screen rather than listening for an arrow key. I let the camera do all the work.

Those are just some of the many things in store for you guys : D. Yes, you can make incredible 0 lag arrow movement maps now ^_^. I'm still working on figuring out a way to slow down the camera tho : ).

However, this won't be released until I get the needed models for Mouse Properties. Sry guys : |, but nobody wants to do the needed models, so this may never ever get released : (.

http://www.hiveworkshop.com/forums/f341/really-easy-model-request-_-125045/

Oh well, some RTC functionality done in plain wc3 : D.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
which one? current round function in MFN is this
JASS:
function round takes real r returns integer
     return R2I(r+0.5)
endfunction

Oh doh, I see, rofl ;o. yea..... i should fix that : o


Oh by the way... the next release is going to include a lot more than just virtual grids.... I'm doing all the math stuff as well for next release because virtual grids needs the math stuff o_O.
 
Last edited:
Level 31
Joined
Jul 10, 2007
Messages
6,306
Latest News-
Working on 3 projects for college due this week... after that, I'll have 1 month to work on w/e, then I'll be in Europe a couple of weeks, then a month and a half to work on stuff.

What will I be working on?
Well, Torque 3D will be out, so I'll be working on an actual game.

How much time will I have for this?
I'll still have time, and I really want to finish this... sooo.

What exactly is being worked on with for this at the moment?
Right now, the current thing is working with player screens (getting the min x, min y, max x, max y in a 2D environment or getting min x, min y, min z, max x, max y, max z in a 3D environment). In short, to keep everything fast I'll be doing a lot of matrix math : p.

Why would I want to be able to access the actual player's screen?
Well, for one you could create a virtual grid for each player and put a UI on it that follows the player's screen around (keep menus and what not on the edges)... you could see if a unit is on the player's actual screen, try out new movement things that will make it so there is 0 delay for players (uses transformations of the player's screen to move units about via arrow keys, which may cause desyncs, well, it will probably cause desyncs, lol).

So, what exactly are these virtual grids you keep talking about?
Well, you know what a rect is right? if you don't, a rect is a 2D rectangle you can place and move about on a map. Rects have various events with them. Regions are a network of rects (you can add rects from anywhere on the map to a region).

Virtual grids is like a network of rects that can not only be placed in a 2D environment, but a 3D environment as well. These grids also have more event properties than rects to (clicking, mouse over, and the traditional rect events as well as a few others).

What else can be done with virtual grids?
Well, you can create them in any shape... squares, cubes, 2D triangles, 3D triangles, etc, etc, etc, even other grids cells within grids.

From here, you can manipulate the walls of cells within grids (cells are always cubes), meaning you can paint textures on to them, add events for actual cell walls, attach functions or data to them, and so on.

Why would I ever want to paint a cell wall?
well, let's say you want to make a spiffy 3D structure with a collection of textures. All you'd have to do is paint the walls of various cells, angle the painting, and so on, and from there make it so units can't pass through them. This means you have an instant 3D structure. Imagine building a house via JASS, or a dungeon with traps via JASS. Cool? You can also easily have infinite tilesets of various sizes by painting tiles on to cell floors or cell ceilings : ).

Well, that's pretty cool I suppose... so could I make like 3D shapes and whatever I want with grids?

Yup.

Could I like attach a function to a cell and enable like a unit event for that cell?

Yup

What about adding structs to cells or even entire grids?

Easy

That's actually pretty cool...

I know ^_^.

So could I have a 3D space shooter fighter game with like space ships flying about. Could I even define the density of a given space within a cell?

You can do anything you want pretty easily with them.

But I'd still have to do the mathematics for all of this stuff right?

Nop, that's where the math utilities come in. Want a 3D triangle, just define where you want it, the altitude, etc and you've got it. From here, you can fill it up with a grid with an easy function call, and then you can outline it's vertexes via the grid with bolts or w/e to see it.

That's actually pretty awesome... and I can create grids in any space? Even a player's screen?

Yup.

Any shape? Even like a 458439589 sided polygon?

if you define it, sure, rofl.

accessing cells within a grid must be hard though...

No... Let's say you had a 3D grid called pie. To access a cell within it, all you'd do is this

MFN_getCell(pie, positionX, positionY, positionZ)

The coordinates aren't coordinates on the actual map. They are the coordinates of the cell within the grid... so if you want cell 1, 1, 1, you'd do this

Cell cell = MFN_getCell(pie, 1, 1, 1)

From here, you could get min x coords, max x coords, etc, all the regular stuff you can do with rects including z coords. You can also enable properties on them, get cell walls within them, and use various paint and modifying functions on the cell walls you got to add effects or w/e you like.

So, what if I wanted to create a unit in every cell in the entire grid at like 50% of the cell's width and 50% of the cell's height...

Well, you can apply things to not just single cells, but ranges of cells and entire grids.

Wouldn't these grids take up a LOAD of memory?

Not at all. When you define a grid, none of the cells within it are actually activated. Stuff is activated as you use it and it clears up when you are done using it. If you destroy a grid, the entire grid clears up. If you destroy a cell, it clears out everything in the cell.

If you define a grid like 1000, 1000, 1000 (1000 across, 1000 up, 1000 z), none of the cells within it will be in memory. The only thing in memory will be the grid. After you declare it, you can access various cells within it and add information. Accessing cells will still not activate the cell. The only way to activate a given cell is by actually enabling stuff within it. You can access cells individually, or with a range (meaning you could even access every cell in the entire grid).

So with a virtual grid, you can pretty much make any game you want in wc3?

Yup... and considering MFN already has stuff for converting any given handle to an integer and back, you can do w/e you want.

So are virtual grids done?
Not at all... I need some invisible models, and nobody is willing to do them.

What would they be for?
Trackable events for cells =).

Can I help out?
You sure can. Just reply to this thread saying you're interested in helping out and say what you do (vjass, modeling, texturing, javascript, xhtml, etc). This is meant to be a community project, but I've been soloing at the moment because hardly anyone sees any use for this stuff =).

What's next after this framework?
Some string utilities, and then more specific frameworks that are built on top of this one like a maze framework, RPG framework, etc.

So like, if I wanted to make an RPG and used the RPG framework, what would it be like?
In short, you wouldn't have to do hardly any system design because everything you'd need would already be in it. All you'd have to worry about is the content in your map ^_^.

--------------------------------------------------
Fact-
Most of the time spent working on a high quality maps is actually spent making the systems for running it. Hardly any time is spent on actual content.
--------------------------------------------------

By the way, what's this actual game project you've been talking about?

Me and a small team of people are making an MMORPG using Torque 3D-http://www.garagegames.com/products/torque-3d/preorder

We're using pro fantasy map making software for initial designs so everyone on the team can get involved with making the actual game. Our team is really made up of people who aren't really experienced in this but really want to make a game ^_^.

Could I join up or w/e?

You sure can : D. If you know vjass or have any graphics design skills or really innovative concepts, just shoot me a PM : D.

Why would I event want to join?
Because if you wanted to do this on your own you'd have to spend about $2,000.00 to get the stuff : P, and I mean, many people on wc3 really want to make games ^_-.

Is this an advertisement for your project?

Nope... just letting people know because I keep bringing it up. The game project the small team and I are doing is more important to me than MFN for obvious reasons : P.

Oh... so should I help with MFN or should I join the team for that game?

You can do w/e you like. If you want to stick with wc3 community, helping out on MFN would be a great plus to the community. If you want to make your own game, you're welcome to join the team. If you want to do both, you can do both, lol : D.

Oh cool... will you be making a save/load system?

String Utilities will include things for converting bases. The primary thing holding people back from making their own save/load systems is that they don't understand the base conversion process or don't want to spend their time doing it. With base conversion, you could make your own save/load system pretty easily, but optimization is another issue. The RPG framework will include a heavily optimized and very customizable save/load system. You can even modify the optimization process of it pretty easily =).




-Wow, this is really long post O_O-
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Well some more updates I suppose. I've really hardly worked on this as there has been a lot going on (trying to put a team together, 4 parties, signing up for classes and getting ready for next semester, working on website, and reading a 4580395834098 page book on .net framework 2.0, 3.0, and 3.5).

Yes, I still plan on finishing this. Seeing as I'll probably never use it because I'm pretty much not on wc3 anymore, I'm curious to see who will.

Once again, any help with any of the required resources is much appreciated : ).

I'm posting this to let you all know that I'm not dead and that I'm still doing this : O.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Working on documentation.

I believe the MFN version that is currently released is probably going to be the final version : ).


If anyone wants to help out with some new designs on the current MFN or some new and better ways of doing things (eccho already provided some great insight), then feel free to reply or pm me.

If anyone wants to help out with some of the utilities that are being worked on or anyone has some interest in some of them and is already working on similar, once again, feel free to reply or pm me : ).
 
Last edited:
Level 31
Joined
Jul 10, 2007
Messages
6,306
Done

Also, it's not a system, and I'm really unsure of where to put it o-o. I followed Forum Guidelines and put it here as it helps with coding for map makers ^_-.


Oh, and if you could please change the thread title to:
[vJASS][Framework]MFN- The Map Framework

I'd really appreciate it, ty. It's just not a system, so the title is misleading =).
 
Level 11
Joined
Feb 22, 2006
Messages
752
Wow, that's some serious textmacro abuse. Anyway, I only had time to give it a quick look over, here's what I have so far:

JASS:
MFN_timers[GetHandleId(MFNLoopTimer)-0x100000]

That can bug if your handle ids climb higher than 0x100000 + 8191

JASS:
call DestroyTimer(MFNLoopTimer)

If the timer isn't paused this causes handle stack corruption.

JASS:
call DestroyTrigger(ini)

Shouldn't do that. Possibility of handle stack corruption not worth one less handle object.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Wow, that's some serious textmacro abuse
Proper use of them, I wouldn't call that abuse.

That can bug if your handle ids climb higher than 0x100000 + 8191
Impossible... go over the op limit before that happens unless the user messes with the code

If the timer isn't paused this causes handle stack corruption.
Timer is expired (no need to be paused as it isn't running). Impossible for a timer to not be expired unless a user messes with the code or rummages through the code and accesses the private variables within their function that there is no documentation on.

Shouldn't do that. Possibility of handle stack corruption not worth one less handle object.
Impossible... only time you have handle stack corruption is when a handle is destroyed while it is still being used or when a handle is created from nothing and set to null (which isn't possible anymore as return bug was fixed).

However, there are still protocols for destroying a trigger properly even when it is destroyed and set to null during use. You have to put it to sleep to get some good corruption going.
 
Level 11
Joined
Feb 22, 2006
Messages
752
Requires 8191 timers to be going to reach that, so I believe that is safe. If that many timers were going, the map would crash from going over op limit.

No, requires 8191 total handle objects to reach that, which happens more often than people think.

There is no possibility of handle stack corruption... I'm not noob at destroying triggers.

You can't predict with certainty whether it will cause handle stack corruption. For some reason trigger actions sometimes run even after the action function returns, and if this is happening while you destroy the trigger...handle stack corruption.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
You can't predict with certainty whether it will cause handle stack corruption. For some reason trigger actions sometimes run even after the action function returns, and if this is happening while you destroy the trigger...handle stack corruption.
JASS:
call TimerStart(CreateTimer(), 120, false, function MFN_cleanLeaks)

That is how it cleans the leaks. It's not cleaned until 120 seconds after the map has already started : ).

No, requires 8191 total handle objects to reach that, which happens more often than people think.
For timers, yes that is true o-o. I didn't think about that o-o.

I suppose I should move this over to a hash table o-o.
 
Level 11
Joined
Feb 22, 2006
Messages
752
It's not cleaned until 120 seconds after the map has already started

The thing is, you can't say with certainty that the trigger action isn't still running even after 120 seconds. Seriously, one trigger isn't going to lag up your map, and premature optimization is the root of all evil.

And another thing, InitBlizzard() call isn't needed inside main anymore (with the newer versions of jasshelper).
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Oh, that is good.

I just really see how a trigger with no pauses can still be running 120 seconds into the map, but I will take this in mind : ). I'll remove the destruction of the trigger.

We are now on v.01r CN 24 o-o

Also, another error on my part is that I failed to document on MFN_registerIni() for system automatic further in-game initialization and etc, stuff like starting up the map : ). I also have to update some of the documentation for changes and techniques-

MFN User Area Changing on MFN_Settings
MFN Thread Stack Techniques
MFN Further Initialization Techniques
A required user area for further initialization (unique instances of a system) that lets a user easily set up communication between all the instances

Other than that, I believe everything is ok =). So just documentation updates really ^_^ (3 pages I think, not bad)
 
Level 11
Joined
Feb 22, 2006
Messages
752
Ok, I finally got around to reading the documentation so I know what some of this stuff is actually supposed to do.

Some things:

  • JASS convention is to capitalize the first letter of function names.
  • Common convention is to not capitalize acronyms
  • For MFN_CREATE_LOOP1 and 2, if you just want to create a new thread, setting a timer with a 0 second timeout does the same thing.
  • For both of the loop things, you should probably mention that they are not compatible with trigger events.
  • For both of the loop things, there are situations where people exit loops based on something other than a simple counter.
  • Is there ANY reason why someone would want to freeze wc3? If even if there was, something like that should not be allowed. I'd be really pissed if I found out my custom maps were freezing my game cuz the author CODED it that way. The same goes for desyncing a player.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
JASS convention is to capitalize the first letter of function names.
Documentation on Frameworks covers this for the base frameworks

Also, my reason for choosing this convention for MFN-

When looking at functions not accessible like main and config, they are lowercase =). I believe accessible functions were made uppercase so that beginners would have an easier time using them. If this were not the case, main and config would have not been an exception to this rule ^_-.

Common convention is to not capitalize acronyms

true ^_-, will fix that for v.01s o_O

For MFN_CREATE_LOOP1 and 2, if you just want to create a new thread, setting a timer with a 0 second timeout does the same thing.

Not at all ^_-

1. timeout- how much it iterates before "doing a slight pause" and "starting a new thread"

That is the difference : P. It doesn't start a new thread after each iteration, so it is faster ; ).

For both of the loop things, you should probably mention that they are not compatible with trigger events.

They are compatible... you can put anything you want into the loop, lol.

For both of the loop things, there are situations where people exit loops based on something other than a simple counter.

The condition is whatever is desired??? you don't have to use a counter...

Is there ANY reason why someone would want to freeze wc3? If even if there was, something like that should not be allowed. I'd be really pissed if I found out my custom maps were freezing my game cuz the author CODED it that way. The same goes for desyncing a player.

Just making all of wc3's features available to the user ^_-. I really have no idea why they would use that stuff, but that doesn't mean I'm going to hide it. If they never want to get their map played, or they want to do some practical joke, I guess it would be useful. Maybe they want to add something for the host to deal with those "really" naughty players? Who knows.

Look at don't touch the tauren or w/e =). That one crashes the game ^_-. Just because you don't agree with these features doesn't mean nobody else does, there may be a use. And yes, don't touch the tauren or w/e is still played : ).


Oh, and v.01s of MFN does have some interesting changes. I decided not to inject into the main method and to just use library intializers and what not. This does take away from some of the stuff you can do with it (code in between initalizations and what not), but it does make it easier to use. In this case, I saw a lot of ease of use and only a very small drop in power. I see no need for people to program in between systems and what not because if they needed it, the system would be requiring what they did which would be odd : o.
 
Last edited:
Level 11
Joined
Feb 22, 2006
Messages
752
Not at all ^_-

1. timeout- how much it iterates before "doing a slight pause" and "starting a new thread"

That is the difference : P. It doesn't start a new thread after each iteration, so it is faster ; ).

Uh, you misunderstand me. In your system, you create a new thread by using a 0.01 second timer. I'm saying you can do the same thing with a 0.00 second timer.

They are compatible... you can put anything you want into the loop, lol.

Trigger event functions stop working after TSA and PW (with the exception of GetTriggerUnit()), so loop method number 1 breaks compatibility with most of the event functions.

ANY trigger event functions stop working after creating a new thread, so loop method number 2 breaks compatibility with ALL event functions.

If you don't get what I'm saying:

JASS:
function callback takes nothing returns nothing
    local unit u = GetTriggerUnit() // this won't work.
endfunction

function actions takes nothing returns nothing
    local unit killer
    call TimerStart(CreateTimer(), false, 0.00, function callback)
    call TriggerSleepAction(0.01)
    set killer = GetKillingUnit() // this won't work.
endfunction

function init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH)
    call TriggerAddAction(t, function actions)
endfunction
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Uh, you misunderstand me. In your system, you create a new thread by using a 0.01 second timer. I'm saying you can do the same thing with a 0.00 second timer.
Yes I did misunderstand u ^_-, but to respond, I use .01 to get a slightly large pause going rather than 0 for op limit stuff =). I've tried 0 before with large threads and it crashed : (.

Trigger event functions stop working after TSA and PW (with the exception of GetTriggerUnit()), so loop method number 1 breaks compatibility with most of the event functions.
What I meant is you could easily attach the trigger information or w/e to the timer and pass it on through : D, but I should probably write something on that point o-o.

The first function/method attaches the trigger data so the looped one can collect it ^_^.

And that is why "i" believe it is compatible, but you can do that with anything really. I do it all the time ^_^, especially with triggers o-o.

What I meant when I said you can put anything you want is that you could attach data or whatever. I am sorry if I wasn't clear ; ). Although, I should probably write something about that : P.
 
Level 5
Joined
Dec 4, 2006
Messages
110
The loops are teh pwn.

And the map properties vars help shorten code.

Haven't used any other vars yet ^_^ And haven't used any utils/systems yet other than MFN Core.

I've never seen such pwnage loops in my life for JASS.

Using it to make my AI for the contest on TH ^_^

(Infinite Loop. With no crash. :))

Can't wait for Spawn ^_^
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
So the system uses structs it does not declare nor require?

EDIT: I hear key is a default type.

Anyhow, you'll still have to convince me of this thing actually being useful for something.

It was made for programming other things. It's not meant to be directly used in a map : ).

It includes basic features that could be useful for all systems within maps : o.

These features are included in the documentation : d, but to convince you as to its use.


As described in the documentation, Mfn is an all-purpose framework for general map making. It's features can both be used in the process of map making and in the process of library, utility, system, and framework design.

Mfn is the groundwork for other things to work off of, meaning it also has very strict conventions and standards, which are again included in the documentation : ).

Mfn includes basic key declarations-
all handles
X, Y, Z

It also includes useful macros-
Loop Creation for *BIG* loops :)
Credit Creation for Designers
Container Creation for ambiguous types

From here, it tracks basic things on the map-
Player tracking
Computer tracking
all tracking (players and computers together)

It will also eventually have force tracking : ).


That is what it does. If it did anything more, it would start becoming too specific and some features would not be usable for all maps : |.


Is it useful by itself?
not really

Is it useful in conjuncture with other things built for it?
Yes

Why?
Because those things can use its basic features rather than do it again for themselves

But it's hardly anything isn't it?
Would you want to make a player tracking thing for every map you ever made? It should be included. Would you want to make credit stuff for everything you did? Naw. I mainly put in things that I had to repeat for every single map ^_^.


Should all maps use it?
I don't think so, no. Extremely basic maps, like melee maps, shouldn't use it as it'd be a waste. Really, it's main purpose is design, not map making. The only reason it's connected with map making are its general features and conventions for designers (the conventions make it so all systems are accessed the same way etc and that all documentation is written the same way).

Isn't it already like that?
No, it's not.

Why are you trying to do this?
Because I'm tired of everyone doing things their own way. If you don't want to use run things off of this, fine. It's one framework, try making your own with your own conventions and stuff, or just do plain vjass with jass like most everyone else. I've met people that really saw potential in what Mfn stands for and they think wow. I've also met people that believe everyone should do w/e their heart tells them to do however their heart tells them to do it.

Mfn's main concept is designing like this

General -> little more specific -> little more specific -> little more specific

etc until you get to as specific as possible for the actual map.

Why does it follow this model and uphold this model? A lot of systems do a lot more than what they let on to... systems have systems built inside of them ><. Look at ToadCop's famous Full Screen Inventory System. Did you know it has an entire grid system inside of it? Why is it in there? Why didn't he split them up so people could use the grid system too and submit both? Most people design like that, and Mfn gets away from that and tells everyone who designs for Mfn to split their stuff up ^_^.

Also, ToadCop's famous Full Screen Inventory System completely manages inventories and what not, but it also has a lot of defined types. What if you don't use those types? Ur stuck with them unless you go thru the code and take them out. What if you want to add ur own? Good luck.

Mfn talks about libraries, utilities, systems, and frameworks.

ToadCop's thing would be split up into one framework, 2 systems (i think), 1 utility, and 1 library.

The framework would be his graphical cosmetic stuff (trackable creation etc).

System 1 would be inventories in general
System 2 would be items

Utility would be the grids

Library would be all of his defined types (effects, etc).

I could name a lot of other systems, but I figure that's one of the most widely known ones ^_^.

If you'd like to learn exactly what libraries, utilities, systems, and frameworks are in the scope of Mfn's conventions, feel free to download the documentation on Mfn and read about them.

If you support the ideals of Mfn, thank you.

If you don't, that's fine too. It's not like I'm trying to force everyone on to my little dinky framework : p. I find it's design, standards, and conventions very good. I also find its concepts on libraries, utilities, systems, and frameworks to be exceptional : ).
 
Level 11
Joined
Feb 22, 2006
Messages
752
Yea, I'm going to have to say I agree with poot. While the code doesn't seem to have any bugs in it, the utility of it is severely limited. The entire thing is a nice idea, but in my opinion, people aren't going to want to adopt a new standard like this when wc3 mapmaking has been around for 9 years.

I'm going to graveyard this (after my usual one day warning period). As for the other things you submitted that require this framework, if you want to edit them to not require this framework and keep them around for review, that's fine. Otherwise, just let me know if you want to withdraw those as well and I'll graveyard them too.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Well, Mfn now hash Jesus4Lyf's rawcode hashing in it with improvements, a 2.0 with FreeHash etc, but w/e ^^. In fact, Jesus4Lyf is probably going to upgrade his hashing into the one I built.

All my stuff will require Mfn as anything that manages memory will either be using hashing or blizzard hashtable and anything that does anything with players will be using Mfn's player tracking to save on memory.

It's too bad if you want to graveyard it, but ok. TheHelper did the same thing, and it looks like they're going to graveyard and recode everything I submit to them without the Mfn stuff (Gcsn is heavily loved there and one guy is thinking of just resubmitting it under his name with a few minor changes: no Mfn reqs). So it's not like what I code is bad in any way.

Guess you'll be graveyarding everything I submit too and people will probably just cnp them, remove Mfn from them, and then make it all their own ^^. I don't really mind, I build everything for the wc3 community to use. However, the stuff won't run as fast and will use up a little extra memory because of the lack of player tracking : |, or the fact that they'll have to recode some of the stuff in Mfn each and every time, which would kinda suck. Oh well, if people want second rate utilities and systems, they can have them I suppose ^_^.

I'll keep submitting for people who do use stuff built for Mfn, but you can just instant graveyard I suppose and they can look through graveyard for anything built for Mfn, like Gcsn (an incredible costs and states utility), Spawn, and other stuff I'll be releasing, and the people who want to convert it to standalone non-Mfn can just steal it I guess.
 
Top