• 🏆 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!

Door System & Modify Camera Ingame System

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
Door System & Manipulate Camera Ingame System

These are 2 Systems made by me that will make your RPG life much better ;)

The Door System
There are some great door models here and in many RPGs but to create triggers to open and close them when the hero comes close takes a lot of time...
This system does this job fully automatic!
You have to register a door type and once you did every door on the map, and every door created anew ingame will open when a unit matching some conditions you can specify comes close, and will close when there are no more units in range!
simple and effecitve ;)

Manipulate Camera Ingame System
Well this is a very basic and simple system.
You can specifiy camera fields for the left/right and for the up/down arrow keys and on press ingame they will be increased/decreased by a adjustable value.
Enabling a maximum and minimum value is of course possible, too!
This system requires my Keyboard system (included)

Both Systems can be used seperatly! They are not bound together!

YOU NEED JNGP TO GET THIS WORKING!!!

Comment, rate, and give constructive critism please ;)

The_Witcher

About the Imports
The imports are necessary to show how this system works, because blizzard has no casual doors! Credits to the Framework!


v.2.0: Thanks to baassee for pointing out some smaller things i simply forgot :D:D added support for CreateDestructableZ


JASS:
library DoorSystem initializer Init
    // Door system by The_Witcher
    //
    // this system opens every instance of the registered doortypes when a units comes close
    // if the unit moves away from the door it will close again

    globals
        //if this is true doors will only close on leave if there are no units in their range
        public boolean CLOSE_ONLY_WHEN_EMPTY = true
        // These are the standart animations for the doors in your map
        private constant string STANDART_OPEN_ANIMATION = "Death Alternate"
        private constant string STANDART_STAND_OPEN_ANIMATION = "Stand Alternate"
        private constant string STANDART_CLOSE_ANIMATION = "Birth"
        private constant string STANDART_STAND_CLOSE_ANIMATION = "stand"
    endglobals

    //Doors will only be triggered when the entering unit matches these conditions
    private function DoorEventConditions takes nothing returns boolean
        return not (IsUnitType(GetFilterUnit(),UNIT_TYPE_DEAD) or GetUnitTypeId(GetFilterUnit()) == 0 )
    endfunction

    //-----------Don't modify anything below this line---------

    globals
        private integer array doors
        private real array range
        private integer total
        private hashtable h
        private boolexpr filt
        private boolexpr enter
        private integer i
        private group g
        private timer tim
    endglobals

    private function FilterFunc takes nothing returns boolean
        return GetDestructableTypeId(GetFilterDestructable()) == doors[i] and LoadBoolean(h,GetHandleId(GetFilterDestructable()),1) != true and LoadBoolean(h,GetHandleId(GetFilterDestructable()),2) != true
    endfunction

    private function DoorActions takes nothing returns nothing
        local destructable d = LoadDestructableHandle(h,GetHandleId(GetTriggeringTrigger()),0)  
        if GetTriggerEventId()==EVENT_GAME_ENTER_REGION and not LoadBoolean(h,GetHandleId(d),0) then
            call KillDestructable(d)
            call SaveBoolean(h,GetHandleId(d),0,true)
            call SetDestructableAnimation(d,LoadStr(h,GetDestructableTypeId(d),4))
            call QueueDestructableAnimation(d,LoadStr(h,GetDestructableTypeId(d),5))
        elseif GetTriggerEventId()==EVENT_GAME_LEAVE_REGION and LoadBoolean(h,GetHandleId(d),0) then
            if not CLOSE_ONLY_WHEN_EMPTY then
                call DestructableRestoreLife(d,GetDestructableMaxLife(d),true)
                call SaveBoolean(h,GetHandleId(d),0,false)
                call SetDestructableAnimation(d, LoadStr(h,GetDestructableTypeId(d),6))
                call QueueDestructableAnimation(d, LoadStr(h,GetDestructableTypeId(d),7))
            else
                call GroupClear(g)
                call GroupEnumUnitsInRect(g, LoadRectHandle(h,GetHandleId(d),3), enter)
                if FirstOfGroup(g) == null then
                    call DestructableRestoreLife(d,GetDestructableMaxLife(d),true)
                    call SaveBoolean(h,GetHandleId(d),0,false)
                    call SetDestructableAnimation(d, LoadStr(h,GetDestructableTypeId(d),6))
                    call QueueDestructableAnimation(d, LoadStr(h,GetDestructableTypeId(d),7))
                endif
            endif
        endif
        set d = null
    endfunction

    private function RegisterEvents takes nothing returns nothing
        local destructable d = GetEnumDestructable()
        local trigger t = CreateTrigger()
        local region g = CreateRegion()
        local real x = GetDestructableX(d)
        local real y = GetDestructableY(d)
        local rect r = Rect(x-range[i], y-range[i], x+range[i], y+range[i])
        call RegionAddRect(g,r)
        call SaveBoolean(h,GetHandleId(d),0,false)
        call SaveDestructableHandle(h,GetHandleId(t),0,d)
        call SaveRectHandle(h,GetHandleId(d),3,r)
        call SaveBoolean(h,GetHandleId(d),1,true)
        call SaveStr(h,GetDestructableTypeId(d),4,STANDART_OPEN_ANIMATION)
        call SaveStr(h,GetDestructableTypeId(d),5,STANDART_STAND_OPEN_ANIMATION)
        call SaveStr(h,GetDestructableTypeId(d),6,STANDART_CLOSE_ANIMATION)
        call SaveStr(h,GetDestructableTypeId(d),7,STANDART_STAND_CLOSE_ANIMATION)
        call TriggerRegisterEnterRegion(t,g,enter)
        call TriggerRegisterLeaveRegion(t,g,enter)
        call TriggerAddAction(t,function DoorActions)
        set t = null
        set d = null
        set r = null
        set g = null
    endfunction

    private function RescanAll takes nothing returns nothing
        set i = 0
        loop
            exitwhen i >= total
            call EnumDestructablesInRect(bj_mapInitialPlayableArea, filt, function RegisterEvents)
            set i = i + 1
        endloop
    endfunction

    function OpenDoor takes destructable d, boolean flag returns nothing
        call SaveBoolean(h,GetHandleId(h),0,flag)
    endfunction

    function ExcludeDoor takes destructable d, boolean flag returns nothing
        call SaveBoolean(h,GetHandleId(h),2,flag)
    endfunction
    
    function ChangeDoorTypeAnimations takes integer id, string openAnimation, string standOpenAnimation, string closeAnimation, string standCloseAnimation returns nothing
        call SaveStr(h,id,4,openAnimation)
        call SaveStr(h,id,5,standOpenAnimation)
        call SaveStr(h,id,6,closeAnimation)
        call SaveStr(h,id,7,standCloseAnimation)
    endfunction

    function AddDoorType takes integer id, real enterRange returns nothing
        set doors[total] = id
        set range[total] = enterRange 
        call SaveStr(h,id,4,STANDART_OPEN_ANIMATION)
        call SaveStr(h,id,5,STANDART_STAND_OPEN_ANIMATION)
        call SaveStr(h,id,6,STANDART_CLOSE_ANIMATION)
        call SaveStr(h,id,7,STANDART_STAND_CLOSE_ANIMATION)
        set total = total + 1
        call RescanAll()
    endfunction

    private function Init takes nothing returns nothing
        set h = InitHashtable()
        set total = 0
        set filt = Condition(function FilterFunc)
        set enter = Condition(function DoorEventConditions)
        set g = CreateGroup()
        set tim = CreateTimer()
    endfunction
    
    private function CatchNewDoors takes integer objectid, real x, real y, real face, real scale, integer variation returns nothing
        call TimerStart(tim,0.01,false,function RescanAll)
    endfunction
    
    private function CatchNewDoors2 takes integer objectid, real x, real y, real z, real face, real scale, integer variation returns nothing
        call TimerStart(tim,0.01,false,function RescanAll)
    endfunction
    
    hook CreateDestructable CatchNewDoors
    hook CreateDestructableZ CatchNewDoors2

endlibrary

JASS:
library ModifyCamIngame initializer Init requires KeyboardSystem 

// Modify Camera Ingame System
//                        by The_Witcher
//
//  to activate this system for a specific player
//
//         set  ModifyCamIngame_active[  << id of player >>   ] = true
//
// pretty easy huh? ;)
    
    globals 
        // the timer interval, increase if laggy
        private constant real INTERVAL = 0.01
        
        //The camera field you manipualte with the left and right arrow key
        private constant camerafield LEFT_RIGHT_MANIPULATE = CAMERA_FIELD_ROTATION
        //The value the field gets changed each interval (right is + value, left is - value)
        private constant real LEFT_RIGHT_STEP = 1
        //The initial value of the field for left and right
        private constant real LEFT_RIGHT_START = bj_CAMERA_DEFAULT_ROTATION
        //The max value of the field for left and right     (Set min and max to the same value to disable min and max)
        private constant real LEFT_RIGHT_MAX = 0
        //The min value of the field for left and right     (Set min and max to the same value to disable min and max)
        private constant real LEFT_RIGHT_MIN = 0
        
        //The camera field you manipualte with the up and down arrow key
        private constant camerafield UP_DOWN_MANIPULATE = CAMERA_FIELD_ANGLE_OF_ATTACK
        //The value the field gets changed each interval (up is + value, down is - value)
        private constant real UP_DOWN_STEP = -1
        //The initial value of the field for up and down
        private constant real UP_DOWN_START = bj_CAMERA_DEFAULT_AOA
        //The max value of the field for up and down     (Set min and max to the same value to disable min and max)
        private constant real UP_DOWN_MAX = 340
        //The min value of the field for up and down     (Set min and max to the same value to disable min and max)
        private constant real UP_DOWN_MIN = 270
    endglobals

    // DON'T MODIFY ANYTHING BELOW THIS LINE

    globals 
        public boolean array active[12]
        private real array lr[12]
        private real array ud[12]
    endglobals

    private function process takes nothing returns nothing
        local integer i = 0
        local real x
        local real y
        loop
            exitwhen i > bj_MAX_PLAYERS
            if active[i] and (IsKeyDown(KEY_LEFT,Player(i)) or IsKeyDown(KEY_RIGHT,Player(i)) or IsKeyDown(KEY_UP,Player(i)) or IsKeyDown(KEY_DOWN,Player(i))) then
                if GetLocalPlayer() == Player(i) then
                    set x = GetCameraTargetPositionX()
                    set y = GetCameraTargetPositionY()
                endif
                if IsKeyDown(KEY_LEFT,Player(i)) then
                    set lr[i] = lr[i] - LEFT_RIGHT_STEP
                endif
                if IsKeyDown(KEY_RIGHT,Player(i)) then
                    set lr[i] = lr[i] + LEFT_RIGHT_STEP
                endif
                if IsKeyDown(KEY_UP,Player(i)) then
                    set ud[i] = ud[i] + UP_DOWN_STEP
                endif
                if IsKeyDown(KEY_DOWN,Player(i)) then
                    set ud[i] = ud[i] - UP_DOWN_STEP
                endif
                if LEFT_RIGHT_MAX != LEFT_RIGHT_MIN then
                    set lr[i] = RMinBJ(LEFT_RIGHT_MAX, lr[i])
                    set lr[i] = RMaxBJ(LEFT_RIGHT_MIN, lr[i])
                endif
                if UP_DOWN_MAX != UP_DOWN_MIN then
                    set ud[i] = RMinBJ(UP_DOWN_MAX, ud[i])
                    set ud[i] = RMaxBJ(UP_DOWN_MIN, ud[i])
                endif
                if GetLocalPlayer() == Player(i) then
                    call SetCameraPosition(x,y)
                    call SetCameraField(LEFT_RIGHT_MANIPULATE,lr[i],0)
                    call SetCameraField(UP_DOWN_MANIPULATE,ud[i],0)
                endif
            endif
            set i = i + 1
        endloop
    endfunction

    private function Init takes nothing returns nothing
        local integer i = 0
        loop
            exitwhen i > 12 //= bj_MAX_PLAYERS
            set ud[i] = UP_DOWN_START
            set lr[i] = LEFT_RIGHT_START
            set i = i + 1
        endloop
        call TimerStart(CreateTimer(), INTERVAL, true, function process)
    endfunction 

endlibrary

JASS:
library KeyboardSystem initializer Init

// Keyboard System by The_Witcher

// This System helps you to get rid of all the triggers
// you would need for creating an effective arrow key
// system.
// This system has aditionally the power to add a key twice press event to a trigger
// you just need to adjust this little variable:
globals
    // this is the time the player has to "double press" a key
    // if a key is pressed twice in this time the registered triggers are executed
    private constant real DELAY = 0.2
endglobals
// Use this function to see which keys are hold down:
//
//  IsKeyDown( key,   pl)   returns boolean
//           string player
//
//   key can be KEY_LEFT, KEY_RIGHT, KEY_UP or KEY_DOWN
//   pl is the player who is checked
//   if the function returns true the key is hold down by player pl
//
// And this 2 functions to register a double press event to a trigger
//
//   TriggerRegisterKeyDoublePressEvent(t, key)
//
//   TriggerRegisterPlayerKeyDoublePressEvent(t, key, pl)
//
//   TriggerRegisterKeyDoubleInterruptEvent(t, key)
//
//   TriggerRegisterPlayerKeyDoubleInterruptEvent(t, key, pl)
//
//   t is the trigger you want to register that event to
//   key is the pressed key (again can be KEY_LEFT, KEY_RIGHT, KEY_UP or KEY_DOWN)
//   pl is in the second function the player who has to press 
//      the keys to fire the trigger
//   the first function fires the trigger regardless of which player pressed the key
//
//
//--------------Don't edit anything below---------------------------
globals
    private timer array time[13]
    private trigger array TRIGGERS
    private trigger array TRIGGERS2
    private integer total = 0
    private integer total2 = 0
    private integer array PLAYER
    private integer array PLAYER2
    private string array KEY
    private string array KEY2
    constant string KEY_LEFT = "left"
    constant string KEY_RIGHT = "right"
    constant string KEY_UP = "up"
    constant string KEY_DOWN = "down"
    private hashtable h = InitHashtable()
endglobals

function IsKeyDown takes string key, player pl returns boolean
    return LoadBoolean(h,GetPlayerId(pl),StringHash(key))
endfunction

function TriggerRegisterKeyDoublePressEvent takes trigger t, string key returns nothing
    set TRIGGERS[total] = t
    set KEY[total] = key
    set PLAYER[total] = 100
    set total = total + 1
endfunction

function TriggerRegisterPlayerKeyDoublePressEvent takes trigger t, string key, player pl returns nothing
    set TRIGGERS[total] = t
    set KEY[total] = key
    set PLAYER[total] = GetPlayerId(pl)
    set total = total + 1
endfunction

function TriggerRegisterKeyDoubleInterruptEvent takes trigger t, string key returns nothing
    set TRIGGERS2[total2] = t
    set KEY2[total2] = key
    set PLAYER2[total2] = 100
    set total2 = total2 + 1
endfunction

function TriggerRegisterPlayerKeyDoubleInterruptEvent takes trigger t, string key, player pl returns nothing
    set TRIGGERS2[total2] = t
    set KEY2[total2] = key
    set PLAYER2[total2] = GetPlayerId(pl)
    set total2 = total2 + 1
endfunction

//! textmacro TriggerActions takes NAME, VarTrue, VarFalse
private function $NAME$press takes nothing returns nothing
    local integer i = GetPlayerId(GetTriggerPlayer())
    local integer x = 0
    call SaveBoolean(h,i,StringHash("$VarTrue$"),true)
    call SaveBoolean(h,i,StringHash("$VarFalse$"),false)
    if LoadStr(h,i,StringHash("LastKey")) != "$VarTrue$" then
        call TimerStart(time[i],0,false,null)
    endif
    if TimerGetRemaining(time[i]) > 0 and LoadStr(h,i,StringHash("LastKey")) == "$VarTrue$" then
        call SaveInteger(h,i,StringHash("Debug"),0)
        call SaveBoolean(h,i,StringHash("$VarTrue$Double"),true)
        loop
            exitwhen x >= total
            if TriggerEvaluate(TRIGGERS[x]) and KEY[x] == "$VarTrue$" and (PLAYER[x] == 100 or PLAYER[x] == i) then
                call TriggerExecute(TRIGGERS[x])
            endif
            set x = x + 1
        endloop
    endif
    if LoadInteger(h,i,StringHash("Debug")) == 1 then
        call TimerStart(time[i],DELAY,false,null)
    else
        call SaveInteger(h,i,StringHash("Debug"),1)
    endif
    call SaveStr(h,i,StringHash("LastKey"),"$VarTrue$")
endfunction

private function $NAME$release takes nothing returns nothing
    local integer i = GetPlayerId(GetTriggerPlayer())
    local integer x = 0
    call SaveBoolean(h,i,StringHash("$VarTrue$"),false)
    if LoadBoolean(h,i,StringHash("$VarTrue$Double")) then
        call SaveBoolean(h,i,StringHash("$VarTrue$Double"),false)
        loop
            exitwhen x >= total2
            if TriggerEvaluate(TRIGGERS2[x]) and KEY2[x] == "$VarTrue$" and (PLAYER2[x] == 100 or PLAYER2[x] == i) then
                call TriggerExecute(TRIGGERS2[x])
            endif
            set x = x + 1
        endloop
    endif    
endfunction
//! endtextmacro

//! runtextmacro TriggerActions("LEFT","left","right")
//! runtextmacro TriggerActions("RIGHT","right","left")
//! runtextmacro TriggerActions("UP","up","down")
//! runtextmacro TriggerActions("DOWN","down","up")

//! textmacro Initiate takes NAME
    set i = 0
    set t = CreateTrigger()
    set tt = CreateTrigger()
    call TriggerAddAction(t,function $NAME$press)
    call TriggerAddAction(tt,function $NAME$release)
    loop
        exitwhen i > 12
        call TriggerRegisterPlayerEvent(t,Player(i),EVENT_PLAYER_ARROW_$NAME$_DOWN)
        call TriggerRegisterPlayerEvent(tt,Player(i),EVENT_PLAYER_ARROW_$NAME$_UP)
        set i = i + 1
    endloop
//! endtextmacro

private function Init takes nothing returns nothing
    local trigger t
    local trigger tt
    local integer i
    //! runtextmacro Initiate("LEFT")
    //! runtextmacro Initiate("RIGHT")
    //! runtextmacro Initiate("UP")
    //! runtextmacro Initiate("DOWN")
    set i = 0
    loop
        exitwhen i > 12
        set time[i] = CreateTimer()
        set i = i + 1
    endloop
endfunction

endlibrary

Keywords:
doors, open, close, doodad, destructable, system, enter, leave, house, room, cam, control, change, field
Contents

Door & Manipulate Camera Ingame Sys (Map)

Reviews
11:31, 9th Feb 2011 Bribe: Please submit each of these things as individual resources to: http://www.hiveworkshop.com/forums/jass-functions-413/ As it stands, this absolutely cannot be a single resource.

Moderator

M

Moderator

11:31, 9th Feb 2011
Bribe: Please submit each of these things as individual resources to: http://www.hiveworkshop.com/forums/jass-functions-413/

As it stands, this absolutely cannot be a single resource.
 
Because many people don't read the description here once again:

I WON'T TRANSFORM THIS TO GUI CAUSE VJASS TO GUI IS IMPOSSIBLE

YOU NEED JNGP TO USE THESE SYSTEMS IN YOUR MAP

IF IT DOESN'T WORK WITH JNGP PLEASE SAVE YOUR MAP TWICE AND TRY AGAIN!

feel free to pm me if you find any bugs or have questions or requests ;)

The_Witcher

p.s: the camera manipulate sys takes always some time to turn on because of the delay of the arrow key pressing...
if you know a workaround to fix this please tell me ;)
 
Level 12
Joined
Apr 16, 2010
Messages
584
I really like the camera system, but i guess you should add option where while pressing arrow keys camera won't move just rotate. And the door system is great, love it, to bad i have no use for it(
So the point is that you should that option to camera system, this would be better i guess.
5/5
 
The door system could be done extremely simply in GUI (just store the types into an array, pick every destructible of type loop, create actions, loop, la-de-da) and so could the camera system. Flood has already created a GUI camera system like yours that is much more complex.

Well then be happy and code your own system in GUI! I wish you good luck :p
 
Level 22
Joined
Nov 14, 2008
Messages
3,256
Nice unique work as always, just a few points.

The constants, shouldn't they be private?

Why are you using a timer when you are going to fire the rescan, just call the function instead? :p

Also that could cause a bit heavy job if you have triggers that creates dests, lots of hooking. Maybe have an option to use a CreateDestEx instead of using hooks (I know some people dislike hooks dunno why). Also it doesn't detect CreateDestZ should be mentioned so people can create dests without lagging the map with scanning calls :D

In the camera system

Shouldn't the boolean active be sized to [bj_MAX_PLAYERS] or just [12]?

Same hero, the constants should be private

Keyboard system is fine. Good job.
 
Nice unique work as always, just a few points.

The constants, shouldn't they be private?

Why are you using a timer when you are going to fire the rescan, just call the function instead? :p

Also that could cause a bit heavy job if you have triggers that creates dests, lots of hooking. Maybe have an option to use a CreateDestEx instead of using hooks (I know some people dislike hooks dunno why). Also it doesn't detect CreateDestZ should be mentioned so people can create dests without lagging the map with scanning calls :D

In the camera system

Shouldn't the boolean active be sized to [bj_MAX_PLAYERS] or just [12]?

Same hero, the constants should be private

Keyboard system is fine. Good job.


Thats what I call a helpfull reply ;)
thanks!! I fixed all the things you mentioned but you can't set an array size to bj_MAX_PLAYERS for some reasons... so I simply set it to 12 :D

hooks are necessary to make this work for GUI users too!

and when will you ever have a loop creating a massive amount of doors :D

UPDATE v.2.0 released!
 
Level 15
Joined
Jul 6, 2009
Messages
889
call TimerStart(tim,0.01,false,function RescanAll) - Wai 0.01? Doesn't 0.00 work fine?

Wouldn't having a timer per person work better? That way you don't need to loop through each of the players, and only have timers run for players who are using the thingy actively, thus improving the performance!! Or so that is my theory. struct camera extends array ~ ? I dunno T__T.
 
call TimerStart(tim,0.01,false,function RescanAll) - Wai 0.01? Doesn't 0.00 work fine?

Wouldn't having a timer per person work better? That way you don't need to loop through each of the players, and only have timers run for players who are using the thingy actively, thus improving the performance!! Or so that is my theory. struct camera extends array ~ ? I dunno T__T.

Its good that you reply! please explain the extends array thing to me (by PM please) cause i never understood that!

a timer per player wouldnt help because the delay the timer creates is just to make sure that the objects are really created cause hooks are not perfect;) in addition it scans destructables and so the player doesnt make a difference!!
i experienced problems with a timer running 0.00 before so i use 0.01!

hope that everythings clear now!
 
Level 2
Joined
Dec 24, 2009
Messages
34
Awsome system :) i like alot of ur system , just that i don't got jnpg or know where 2 DL it :/ + my pc just make erorr when i try us custom script or jass :(. well any ways good system ^^ 5/5 (if u can tell me where 2 dl jnpg ^^ just write it in comment , it would be great)
 
Top