Name | Type | is_array | initial_value |
//===========================================================================
//
// Screen Mouse v1.1.2
// by loktar
// -------------------------------------------------------------------------
// * Determine direction of mousemovement on screen
// * Get the mouse position on screen, relative to center
// * Get mouse button up/down state
// * Note that coordinates go from right to left (X) and bottom to top (Y)
// * LIMITATIONS:
// * * Cursor must be on map geometry
// * * Results are distorted on non-flat terrain
// * * Relative position is distorted by Field of View (x values are smaller at the top of the screen than at the bottom)
// -------------------------------------------------------------------------
//
// -------
// * API *
// -------
// * boolean SMRegisterPlayerMove(trigger moveTrigger, player plr)
// - Register mouse move functionality
// - Disables moveTrigger
// - Native trigger functions can be used in actions/conditions added to moveTrigger
// - Returns false if trigger/player combination is already registered
//
// * boolean SMEnablePlayerMove(boolean enable, trigger moveTrigger, integer playerId)
// - Enable/disable ScreenMouse move functionality
// - If enable == false, prevents all moveTrigger actions from executing
// - If enable == false, disables moveTrigger
// - Returns false if trigger/player combination doesn't exist
//
// * boolean SMRegisterPlayerButton(trigger buttonTrigger, player plr)
// - Register mouse button functionality
// - Native trigger functions can be used in actions/conditions added to buttonTrigger
// - Returns false if trigger/player combination is already registered
//
// * boolean SMEnablePlayerButton(boolean enable, trigger buttonTrigger, integer playerId)
// - Enable/disable ScreenMouse button functionality
// - If enable == false, prevents all buttonTrigger actions from executing
// - Enables/disables buttonTrigger
// - Returns false if trigger/player combination doesn't exist
//
// * boolean SMRegisterPlayerDrag(trigger buttonTrigger, trigger moveTrigger, player plr, boolean left, boolean right, boolean both)
// - Register mouse drag functionality: enable/disable moveTrigger while holding down mouse button(s)
// - Register for left button, right button and/or both together
// - Calls SMRegisterPlayerMove() and SMRegisterPlayerButton()
// - Returns false if buttonTrigger/player combination already has a moveTrigger associated
//
// * boolean SMEnablePlayerDrag(boolean left, boolean right, boolean both, trigger buttonTrigger, integer playerId)
// - Enable/disable ScreenMouse drag functionality
// - If any flag == true, enables buttonTrigger
// - If all flags == false, disables buttonTrigger and associated moveTrigger
// - Returns false if buttonTrigger/player combination doesn't exist or has no associated moveTrigger
//
// * boolean SMIsLeftDown(integer playerId), SMIsRightDown(integer playerId)
// - Mouse button up/down state
// - Set with buttonTriggers
//
// * real SMGetDifX(integer playerId), SMGetDifY(integer playerId)
// - Difference with previous mouse position on screen
// - Set with moveTriggers
//
// * real SMGetRelX(integer playerId), SMGetRelY(integer playerId)
// - Position of the mouse relative to the center of the screen
// - Set with buttonTriggers
//
// * real SMGetDifXs(integer playerId), SMGetDifYs(integer playerId)
// - Difference with previous mouse position on map, compensated for Target Distance and Field of View
// - Set with moveTriggers
//
// * real SMGetX(integer playerId), SMGetY(integer playerId)
// - Difference with previous mouse position on screen
// - Set with moveTriggers
//
// * real SM_minX, SM_maxX, SM_minY, SM_maxY
// - Mouse position bounds
// - Default: Camera Bounds
//
// * real SM_distMpl
// - Multiplier for Target Distance compensation
// - Only applied if larger than current Target Distance
// - Difference/Distance*SM_distMpl
// - Default: 1650
//
// * real SM_fovMpl
// - Multiplier for Field of View compensation (in Radians!)
// - Only applied if larger than current Field of View
// - Difference/FoV*SM_fovMpl
// - Default: Deg2Rad(70)
//
//===========================================================================
library ScreenMouse initializer InitScreenMouse
globals
private constant real R90 = Deg2Rad(90)
private gamecache gcSM = InitGameCache("ScreenMouse.w3v")
private constant string DIFX = "difx"
private constant string DIFY = "dify"
private constant string DIFX_S = "difxs"
private constant string DIFY_S = "difys"
private constant string RELX = "relx"
private constant string RELY = "rely"
private hashtable htbSM = InitHashtable()
private constant key X
private constant key Y
private constant key LEFT_DOWN
private constant key RIGHT_DOWN
private constant key DO_LEFT
private constant key DO_RIGHT
private constant key DO_BOTH
private constant key TRG_MOVE
real SM_minX // GetCameraBound cannot be called at init
real SM_maxX
real SM_minY
real SM_maxY
real SM_distMpl = 1650
real SM_fovMpl = Deg2Rad(70)
endglobals
//===============================================================================
//===============================================================================
//===============================================================================
//==== MOUSE FUNCS ==============================================================
//===============================================================================
//==== Compensate angles and save ====
//==== ! This function should only be called locally ! ====
private function SaveScreenDif takes real difX, real difY, string keyP, string keyX, string keyY returns nothing
local real field
local real tmpX
// Compensate Rotation
set field = GetCameraField(CAMERA_FIELD_ROTATION)
set tmpX = difX // Save original newX for newY calculation
set difX = Cos(field-R90)*(difX) + Sin(field-R90)*(difY)
set difY = Cos(field+R90)*(-difY) - Sin(field+R90)*(-tmpX)
// Compensate Roll
set field = GetCameraField(CAMERA_FIELD_ROLL)
set tmpX = difX // Save original newX for newY calculation
set difX = Sin(field-R90)*(-difX) + Cos(field-R90)*(-difY)
set difY = Sin(field+R90)*(difY) - Cos(field+R90)*(tmpX)
// Compensate AoA
set difY = Sin(-GetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK))*difY
call StoreReal(gcSM, keyP, keyX, difX)
call StoreReal(gcSM, keyP, keyY, difY)
call SyncStoredReal(gcSM, keyP, keyX)
call SyncStoredReal(gcSM, keyP, keyY)
endfunction
//========
//==== Check for valid mouse position ====
private function IsValidPosition takes real x, real y returns boolean
return (x != 0 or y != 0) and x >= SM_minX and x <= SM_maxX and y >= SM_minY and y <= SM_maxY // Mouse on UI gives (0, 0)
endfunction
//========
//==== Mouse Move ====
private function MouseMoveCndAcn takes nothing returns boolean
local real newX
local real newY
local real realTmp
local real realTmp2
local player plr = GetTriggerPlayer()
local integer pId = GetPlayerId(plr)
local trigger trg = GetTriggeringTrigger()
local integer hIdMove = GetHandleId(trg)
local boolean success = false
local string keyP
if HaveSavedBoolean(htbSM, pId, hIdMove) and LoadBoolean(htbSM, pId, hIdMove) then
call DisableTrigger(trg)
set newX = BlzGetTriggerPlayerMouseX()
set newY = BlzGetTriggerPlayerMouseY()
if IsValidPosition(newX, newY) then
if not HaveSavedReal(htbSM, pId, X) or not HaveSavedReal(htbSM, pId, Y) then
call SaveReal(htbSM, pId, X, newX)
call SaveReal(htbSM, pId, Y, newY)
else
set realTmp = LoadReal(htbSM, pId, X)
set realTmp2 = LoadReal(htbSM, pId, Y)
call SaveReal(htbSM, pId, X, newX)
call SaveReal(htbSM, pId, Y, newY)
if IsValidPosition(realTmp, realTmp2) and plr == GetLocalPlayer() then
set newX = realTmp-newX
set newY = realTmp2-newY
// Compensate Distance
set realTmp = GetCameraField(CAMERA_FIELD_TARGET_DISTANCE)
if realTmp > SM_distMpl then
set newX = newX/realTmp*SM_distMpl
set newY = newY/realTmp*SM_distMpl
endif
// Compensate FoV
set realTmp = GetCameraField(CAMERA_FIELD_FIELD_OF_VIEW)
if realTmp > SM_fovMpl then
set newX = newX/realTmp*SM_fovMpl
set newY = newY/realTmp*SM_fovMpl
endif
set keyP = I2S(pId)
call StoreReal(gcSM, keyP, DIFX_S, newX)
call StoreReal(gcSM, keyP, DIFY_S, newY)
call SyncStoredReal(gcSM, keyP, DIFX_S)
call SyncStoredReal(gcSM, keyP, DIFY_S)
call SaveScreenDif(newX, newY, keyP, DIFX, DIFY)
set success = true
endif // saved valid & local player
endif // have saved
endif // new valid
call EnableTrigger(trg)
endif // move enabled for player
if not success then
set keyP = I2S(pId)
call StoreReal(gcSM, keyP, DIFX, 0)
call StoreReal(gcSM, keyP, DIFY, 0)
call StoreReal(gcSM, keyP, DIFX_S, 0)
call StoreReal(gcSM, keyP, DIFY_S, 0)
endif
set plr = null
set trg = null
return success // trigger/player combo is enabled and local player?
endfunction
//========
//==== Mouse Button ====
private function MouseBtnCndAcn takes nothing returns boolean
local player plr = GetTriggerPlayer()
local integer pId = GetPlayerId(plr)
local integer hIdBtn = GetHandleId(GetTriggeringTrigger())
local mousebuttontype mouseBtn
local real mouseX
local real mouseY
local integer p_hBtnId
local trigger moveTrg = null
local integer hIdMove
local boolean enable
if HaveSavedBoolean(htbSM, pId, hIdBtn) and LoadBoolean(htbSM, pId, hIdBtn) then
set mouseBtn = BlzGetTriggerPlayerMouseButton()
set mouseX = BlzGetTriggerPlayerMouseX()
set mouseY = BlzGetTriggerPlayerMouseY()
// Mouse Down
if GetTriggerEventId() == EVENT_PLAYER_MOUSE_DOWN then
// MOUSE_BUTTON_TYPE_MIDDLE does not fire this event as of 1.30.4
if mouseBtn == MOUSE_BUTTON_TYPE_LEFT then
call SaveBoolean(htbSM, pId, LEFT_DOWN, true)
elseif mouseBtn == MOUSE_BUTTON_TYPE_RIGHT then
call SaveBoolean(htbSM, pId, RIGHT_DOWN, true)
endif
// Set relative position
if IsValidPosition(mouseX, mouseY) and plr == GetLocalPlayer() then
call SaveScreenDif(GetCameraTargetPositionX()-mouseX, GetCameraTargetPositionY()-mouseY, I2S(pId), RELX, RELY)
endif
// Mouse Up
elseif mouseBtn == MOUSE_BUTTON_TYPE_LEFT then
call SaveBoolean(htbSM, pId, LEFT_DOWN, false)
elseif mouseBtn == MOUSE_BUTTON_TYPE_RIGHT then
call SaveBoolean(htbSM, pId, RIGHT_DOWN, false)
endif
// Enable/Disable Drag
set p_hBtnId = pId+hIdBtn*100
if HaveSavedHandle(htbSM, p_hBtnId, TRG_MOVE) then
set moveTrg = LoadTriggerHandle(htbSM, p_hBtnId, TRG_MOVE)
set hIdMove = GetHandleId(moveTrg)
if HaveSavedBoolean(htbSM, pId, hIdMove) and LoadBoolean(htbSM, pId, hIdMove) then
set enable = LoadBoolean(htbSM, pId, RIGHT_DOWN)
if LoadBoolean(htbSM, pId, LEFT_DOWN) then
set enable = (enable and LoadBoolean(htbSM, p_hBtnId, DO_BOTH)) or (not enable and LoadBoolean(htbSM, p_hBtnId, DO_LEFT))
else
set enable = enable and LoadBoolean(htbSM, p_hBtnId, DO_RIGHT)
endif
if enable then
// Enable Move trigger
if not IsTriggerEnabled(moveTrg) then
call SaveReal(htbSM, pId, X, mouseX)
call SaveReal(htbSM, pId, Y, mouseY)
call EnableTrigger(moveTrg)
endif
else
call DisableTrigger(moveTrg)
endif
endif
set moveTrg = null
endif
set plr = null
return true
endif
set plr = null
return false // trigger/player combo is disabled
endfunction
//===========================================================================
//===========================================================================
//===============================================================================
//===============================================================================
//===============================================================================
//==== API FUNCS ================================================================
//===============================================================================
//==== Register MOVE to trigger/player ====
function SMRegisterPlayerMove takes trigger moveTrg, player plr returns boolean
local integer hIdMove = GetHandleId(moveTrg)
local integer pId = GetPlayerId(plr)
if not HaveSavedBoolean(htbSM, pId, hIdMove) then
call SaveBoolean(htbSM, pId, hIdMove, true)
call DisableTrigger(moveTrg)
call TriggerRegisterPlayerEvent(moveTrg, plr, EVENT_PLAYER_MOUSE_MOVE)
call TriggerAddCondition(moveTrg, function MouseMoveCndAcn)
return true
endif
return false // trigger/player combo already registered
endfunction
//========
//==== Enable/Disable MOVE for trigger/player ====
function SMEnablePlayerMove takes boolean enable, trigger moveTrg, integer pId returns boolean
local integer hIdMove = GetHandleId(moveTrg)
if HaveSavedBoolean(htbSM, pId, hIdMove) then
call SaveBoolean(htbSM, pId, hIdMove, enable)
if not enable then
call DisableTrigger(moveTrg)
endif
return true
endif
return false // not found
endfunction
//========
//==== Register BUTTON to trigger/player ====
function SMRegisterPlayerButton takes trigger btnTrg, player plr returns boolean
local integer hIdBtn = GetHandleId(btnTrg)
local integer pId = GetPlayerId(plr)
if not HaveSavedBoolean(htbSM, pId, hIdBtn) then
call SaveBoolean(htbSM, pId, hIdBtn, true)
if not HaveSavedBoolean(htbSM, pId, LEFT_DOWN) then
call SaveBoolean(htbSM, pId, LEFT_DOWN, false)
call SaveBoolean(htbSM, pId, RIGHT_DOWN, false)
endif
call TriggerRegisterPlayerEvent(btnTrg, plr, EVENT_PLAYER_MOUSE_DOWN)
call TriggerRegisterPlayerEvent(btnTrg, plr, EVENT_PLAYER_MOUSE_UP)
call TriggerAddCondition(btnTrg, function MouseBtnCndAcn)
return true
endif
return false // trigger/player combo already registered
endfunction
//========
//==== Enable/Disable MOVE for trigger/player ====
function SMEnablePlayerButton takes boolean enable, trigger btnTrg, integer pId returns boolean
local integer hIdBtn = GetHandleId(btnTrg)
if HaveSavedBoolean(htbSM, pId, hIdBtn) then
call SaveBoolean(htbSM, pId, hIdBtn, enable)
if enable then
call EnableTrigger(btnTrg)
else
call DisableTrigger(btnTrg)
endif
return true
endif
return false // not found
endfunction
//========
//==== Register DRAG to triggers/player ====
function SMRegisterPlayerDrag takes trigger btnTrg, trigger moveTrg, player plr, boolean left, boolean right, boolean both returns boolean
local integer hIdBtn = GetHandleId(btnTrg)
local integer pId = GetPlayerId(plr)
local integer p_hBtnId = pId+hIdBtn*100
if not HaveSavedHandle(htbSM, p_hBtnId, TRG_MOVE) then
call SaveTriggerHandle(htbSM, p_hBtnId, TRG_MOVE, moveTrg)
call SaveBoolean(htbSM, p_hBtnId, DO_LEFT, left)
call SaveBoolean(htbSM, p_hBtnId, DO_RIGHT, right)
call SaveBoolean(htbSM, p_hBtnId, DO_BOTH, both)
call SMRegisterPlayerButton(btnTrg, plr)
call SMRegisterPlayerMove(moveTrg, plr)
return true
endif
return false // player/btn trg combo already registered
endfunction
//========
//==== Enable/Disable DRAG for trigger/player ====
function SMEnablePlayerDrag takes boolean left, boolean right, boolean both, trigger btnTrg, integer pId returns boolean
local integer id = pId+GetHandleId(btnTrg)*100
if HaveSavedHandle(htbSM, id, TRG_MOVE) then
call SaveBoolean(htbSM, id, DO_LEFT, left)
call SaveBoolean(htbSM, id, DO_RIGHT, right)
call SaveBoolean(htbSM, id, DO_BOTH, both)
if left or right or both then
call EnableTrigger(btnTrg)
else
call DisableTrigger(btnTrg)
call DisableTrigger(LoadTriggerHandle(htbSM, id, TRG_MOVE))
endif
return true
endif
return false // not found
endfunction
//========
//==== Get Left Down ====
function SMIsLeftDown takes integer playerId returns boolean
return HaveSavedBoolean(htbSM, playerId, LEFT_DOWN) and LoadBoolean(htbSM, playerId, LEFT_DOWN)
endfunction
//========
//==== Get Right Down ====
function SMIsRightDown takes integer playerId returns boolean
return HaveSavedBoolean(htbSM, playerId, RIGHT_DOWN) and LoadBoolean(htbSM, playerId, RIGHT_DOWN)
endfunction
//========
// ==== Get difX ====
function SMGetDifX takes integer playerId returns real
local string keyP = I2S(playerId)
if HaveStoredReal(gcSM, keyP, DIFX) then
return GetStoredReal(gcSM, keyP, DIFX)
endif
return 0.0
endfunction
//========
// ==== Get difY ====
function SMGetDifY takes integer playerId returns real
local string keyP = I2S(playerId)
if HaveStoredReal(gcSM, keyP, DIFY) then
return GetStoredReal(gcSM, keyP, DIFY)
endif
return 0.0
endfunction
//========
// ==== Get difXs ====
function SMGetDifXs takes integer playerId returns real
local string keyP = I2S(playerId)
if HaveStoredReal(gcSM, keyP, DIFX_S) then
return GetStoredReal(gcSM, keyP, DIFX_S)
endif
return 0.0
endfunction
//========
// ==== Get difYs ====
function SMGetDifYs takes integer playerId returns real
local string keyP = I2S(playerId)
if HaveStoredReal(gcSM, keyP, DIFY_S) then
return GetStoredReal(gcSM, keyP, DIFY_S)
endif
return 0.0
endfunction
//========
// ==== Get X ====
function SMGetX takes integer playerId returns real
if HaveSavedReal(htbSM, playerId, X) then
return LoadReal(htbSM, playerId, X)
endif
return 0.0
endfunction
//========
// ==== Get Y ====
function SMGetY takes integer playerId returns real
if HaveSavedReal(htbSM, playerId, Y) then
return LoadReal(htbSM, playerId, Y)
endif
return 0.0
endfunction
//========
// ==== Get Relative X ====
function SMGetRelX takes integer playerId returns real
local string keyP = I2S(playerId)
if HaveStoredReal(gcSM, keyP, RELX) then
return GetStoredReal(gcSM, keyP, RELX)
endif
return 0.0
endfunction
//========
// ==== Get Relative Y ====
function SMGetRelY takes integer playerId returns real
local string keyP = I2S(playerId)
if HaveStoredReal(gcSM, keyP, RELY) then
return GetStoredReal(gcSM, keyP, RELY)
endif
return 0.0
endfunction
//===========================================================================
//===========================================================================
//===============================================================================
//===============================================================================
//===============================================================================
//==== INITIALIZER ==============================================================
//===============================================================================
private function InitScreenMouse takes nothing returns nothing
call TriggerSleepAction(0) // For GetCameraBound
// Get map bounds
set SM_minX = GetCameraBoundMinX()
set SM_maxX = GetCameraBoundMaxX()
set SM_minY = GetCameraBoundMinY()
set SM_maxY = GetCameraBoundMaxY()
endfunction
//===============================================================================
//===============================================================================
endlibrary
//===========================================================================
//
// Dialog Pages System v1.0.2a
// by loktar
// -------------------------------------------------------------------------
// * Create a dialog with automatic pages
// * Optionally show an index page
// * Automatic Next/Previous/Back/Cancel buttons
// -------------------------------------------------------------------------
//
// -------
// * API *
// -------
// * NOTES:
// - dialogId refers to handle id
// - buttonId and pageId refer to zero-indexed id
//
// * boolean DialogPDisplay(player plr, integer dialogId, boolean display)
// - Display/Hide dialog
// - If displayed when dialog is already displayed, it will be updated
// - Returns false if the dialog wasn't found
//
// * integer DialogPCreate(string message, boolean showIndex)
// - Create a new dialog
// - Returns dialog handle id (dialogId)
//
// * boolean DialogPDestroy(integer dialogId)
// - Destroy dialog
// - Returns false if the dialog wasn't found
//
// * boolean DialogPSetPage(integer dialogId, integer pageId)
// - Set dialog page
// - Set to 0 if pageId < 0 or to maximum pageId if pageId > maximum pageId
// - Returns false if the dialog wasn't found
//
// * boolean DialogPSetMessage (integer dialogId, string message)
// boolean DialogPSetButtonsPP(integer dialogId, integer buttonsPP)
// - Set dialog message/buttons per page
// - Returns false if the dialog wasn't found
//
// * boolean DialogPSetButtonsText (integer dialogId, string next, string previous, string back, string cancel)
// * boolean DialogPSetButtonsHotkey(integer dialogId, integer next, integer previous, integer back, integer cancel)
// boolean DialogPDisplayButtons (integer dialogId, boolean next, boolean previous, boolean back, boolean cancel)
// - Set browse buttons text/hotkey/visibility
// - Returns false if the dialog wasn't found
//
// * dialog DialogPGetHandle(integer dialogId)
// - Get dialog handle
// - Returns null if the dialog wasn't found
//
// * trigger DialogPGetTrigger(integer dialogId)
// - Get dialog trigger
// - Executed/Evaluated when the dialog is clicked
// - Execution of actions prevented when Next, Previous, Back, Cancel and index page buttons are clicked
// - Returns null if the dialog wasn't found
//
// * integer DialogPGetClickedId(integer dialogId)
// - Get dialog last clicked buttonId
// - Returns DP_BROWSED for Next, Previous, Back and index page buttons
// - Returns DP_CANCELED for Cancel button
// - Returns DP_NONE if no button has been clicked yet
// - Returns DP_NOT_FOUND if the dialog wasn't found
//
// * BUTTONS *
// -----------
// * integer DialogPAddButton (integer dialogId, string text, integer hotkey)
// integer DialogPAddQuitButton(integer dialogId, boolean doScoreScreen, string text, integer hotkey)
// - Add (quit) button to dialog
// - Returns buttonId (not a handle id)
// - Returns DP_NOT_FOUND if the dialog wasn't found
//
// * boolean DialogPSetButton (integer dialogId, integer buttonId, string text, integer hotkey)
// boolean DialogPSetQuitButton(integer dialogId, integer buttonId, boolean doScoreScreen, string text, integer hotkey)
// - Set (quit) button (doScoreScreen), text and hotkey
// - Can both be used on regular and quit buttons
// -- Using SetQuitButton on a regular button will turn it into a quit button
// - Returns false if the dialog or button wasn't found
//
// * string DialogPGetButtonText(integer dialogId, integer buttonId)
// - Get button text
// - Returns null if the dialog or button wasn't found
//
// * INDEX *
// ---------
// * boolean DialogPEnableIndex(integer diagId, boolean enable)
// - Enable/Disable index and set page to 0
// - If enabled, also opens index
// - Index is only shown when number of buttons > buttons per page
// - Returns false if the dialog wasn't found
//
// * boolean DialogPSetIndexPage(integer dialogId, integer pageId)
// - Set dialog index page
// - Set to 0 if pageId < 0 or to maximum pageId if pageId > maximum pageId
// - Returns false if the dialog wasn't found
//
// * INDEX BUTTONS *
// -----------------
// * boolean DialogPSetIndexButton(integer dialogId, integer pageId, string text, integer hotkey)
// - Set index button text and hotkey
// - Text and hotkey will be saved even if page doesn't (yet) exist
// - Returns false if the dialog wasn't found
//
// * CONFIG VARIABLES *
// --------------------
// * integer DP_btnsPP
// - Default number of buttons to show per page
// - Does not include Next, Previous, Back or Cancel buttons
// - Default: 5
//
// * string DP_strNext, DP_strPrev, DP_strBack, DP_strCancel
// integer DP_hkNext, DP_hkPrev, DP_hkBack, DP_hkCancel
// boolean DP_showNext, DP_showPrev, DP_showBack, DP_showCancel
// - Default settings for Next, Previous, Back and Cancel buttons
// - Text: "Next >", "< Previous", "< Back", "Cancel"
// - Hotkeys: 0 (all)
// - Visibility: true (all)
// -- When index is enabled, Next and Previous buttons are on index pages, Back button is on normal pages
// -- When there are 2 pages, Previous button on first page and Next button on second page are always hidden
// -- When there are less than 2 pages, Next and Previous buttons are always hidden
//
//===========================================================================
library DialogPages
globals
// Dialogs Hashtable
private hashtable htbDialogs = InitHashtable()
// handles
private constant key DIAG
private constant key BTN_HTB
private constant key TRG
// config
private constant key MSG
private constant key BTNS_PP
private constant key INDEX_ENABLE
// state
private constant key BTN_CNT
private constant key PAGE_ID
private constant key CLICKED_ID
private constant key INDEX_OPEN
private constant key INDEX_PAGE_ID
// Buttons Hashtables
private constant key CURR_BTNS
private constant key BTN_STR
private constant key BTN_HK
private constant key BTN_QUIT
private constant key INDEX_BTN_STR
private constant key INDEX_BTN_HK
private constant integer BTN_NEXT = -1 // make sure it doesn't collide with buttonIds
private constant integer BTN_PREV = -2
private constant integer BTN_BACK = -3
private constant integer BTN_CANCEL = -4
private constant key BTN_SHOW
// Clicked Ids
constant integer DP_NONE = -1 // make sure it doesn't collide with buttonIds
constant integer DP_BROWSED = -2
constant integer DP_CANCELED = -3
constant integer DP_NOT_FOUND = -4
// Settings
integer DP_btnsPP = 5
boolean DP_showNext = true
boolean DP_showPrev = true
boolean DP_showBack = true
boolean DP_showCancel = true
string DP_strNext = "Next >"
string DP_strPrev = "< Previous"
string DP_strBack = "< Back"
string DP_strCancel = "Cancel"
integer DP_hkNext = 0
integer DP_hkPrev = 0
integer DP_hkBack = 0
integer DP_hkCancel = 0
endglobals
//===============================================================================
//===============================================================================
//===============================================================================
//==== DIALOGS ==================================================================
//===============================================================================
//==== Display Current Page ====
function DialogPDisplay takes player plr, integer diagId, boolean display returns boolean
local dialog diag = null
local hashtable htbBtns = null
local integer btnCnt
local integer btnsPP
local integer pageId
local integer pageIdMax
local integer btnId
local integer btnIdMax
local integer keyStr
local integer keyHk
local integer btnHk
local string btnStr
local string msg
local boolean indexEnable
local boolean indexOpen
if HaveSavedHandle(htbDialogs, diagId, DIAG) then
set diag = LoadDialogHandle(htbDialogs, diagId, DIAG)
set htbBtns = LoadHashtableHandle(htbDialogs, diagId, BTN_HTB)
// Clear current dialog page
call FlushChildHashtable(htbBtns, CURR_BTNS)
call DialogClear(diag)
// Prepare the new dialog page
if display then
set btnCnt = LoadInteger(htbDialogs, diagId, BTN_CNT)
set btnsPP = LoadInteger(htbDialogs, diagId, BTNS_PP)
if btnCnt > 0 and btnsPP > 0 then
set pageIdMax = (btnCnt-1)/btnsPP
set indexEnable = btnCnt > btnsPP and LoadBoolean(htbDialogs, diagId, INDEX_ENABLE)
set indexOpen = indexEnable and LoadBoolean(htbDialogs, diagId, INDEX_OPEN)
// Get page data
if indexOpen then
set btnCnt = pageIdMax+1
set pageIdMax = (btnCnt-1)/btnsPP
set pageId = LoadInteger(htbDialogs, diagId, INDEX_PAGE_ID)
set keyStr = INDEX_BTN_STR
set keyHk = INDEX_BTN_HK
else
set pageId = LoadInteger(htbDialogs, diagId, PAGE_ID)
set keyStr = BTN_STR
set keyHk = BTN_HK
endif
if pageId > pageIdMax then
set pageId = pageIdMax
endif
// Get btn data
set btnId = pageId*btnsPP
set btnIdMax = btnId+btnsPP-1
if btnIdMax >= btnCnt then
if btnId >= btnCnt then
set btnId = btnCnt-1
endif
set btnIdMax = btnCnt-1
endif
// Add buttons
loop
exitwhen btnId > btnIdMax
// Get button text & hotkey
if HaveSavedString(htbBtns, keyStr, btnId) then
set btnStr = LoadStr(htbBtns, keyStr, btnId)
else
set btnStr = "Page "+I2S(btnId+1) // Added Button always has saved string
endif
if HaveSavedInteger(htbBtns, keyHk, btnId) then
set btnHk = LoadInteger(htbBtns, keyHk, btnId)
else
set btnHk = 0
endif
if HaveSavedBoolean(htbBtns, BTN_QUIT, btnId) then
call SaveInteger(htbBtns, CURR_BTNS, GetHandleId(DialogAddQuitButton(diag, LoadBoolean(htbBtns, BTN_QUIT, btnId), btnStr, btnHk)), btnId)
else
call SaveInteger(htbBtns, CURR_BTNS, GetHandleId(DialogAddButton(diag, btnStr, btnHk)), btnId)
endif
set btnId = btnId+1
endloop
// Add next/previous buttons
if btnCnt > btnsPP and (not indexEnable or indexOpen) then
if LoadBoolean(htbBtns, BTN_SHOW, BTN_NEXT) and (pageId == 0 or pageIdMax > 1) then
set btnId = GetHandleId(DialogAddButton(diag, LoadStr(htbBtns, BTN_STR, BTN_NEXT), LoadInteger(htbBtns, BTN_HK, BTN_NEXT)))
call SaveBoolean(htbBtns, CURR_BTNS, btnId, true)
endif
if LoadBoolean(htbBtns, BTN_SHOW, BTN_PREV) and (pageId == 1 or pageIdMax > 1) then
set btnId = GetHandleId(DialogAddButton(diag, LoadStr(htbBtns, BTN_STR, BTN_PREV), LoadInteger(htbBtns, BTN_HK, BTN_PREV)))
call SaveBoolean(htbBtns, CURR_BTNS, btnId, false)
endif
endif
else
set indexEnable = false
set indexOpen = false
endif
// Add Back/cancel buttons
if indexEnable and not indexOpen and LoadBoolean(htbBtns, BTN_SHOW, BTN_BACK) then
set btnId = GetHandleId(DialogAddButton(diag, LoadStr(htbBtns, BTN_STR, BTN_BACK), LoadInteger(htbBtns, BTN_HK, BTN_BACK)))
call SaveBoolean(htbBtns, CURR_BTNS, btnId, true)
endif
if LoadBoolean(htbBtns, BTN_SHOW, BTN_CANCEL) then
call DialogAddButton(diag, LoadStr(htbBtns, BTN_STR, BTN_CANCEL), LoadInteger(htbBtns, BTN_HK, BTN_CANCEL))
endif
// Set message
set msg = LoadStr(htbDialogs, diagId, MSG)
if msg != "" and msg != null then
call DialogSetMessage(diag, msg)
endif
endif
call DialogDisplay(plr, diag, display)
set diag = null
set htbBtns = null
return true
endif
return false // dialog not found
endfunction
//========
//==== Dialog Clicked ====
private function DialogClickedCndAcn takes nothing returns boolean
local integer diagId = GetHandleId(GetClickedDialog())
local integer btnId = GetHandleId(GetClickedButton())
local hashtable htbBtns = LoadHashtableHandle(htbDialogs, diagId, BTN_HTB)
local integer pageId
local integer btnCnt = LoadInteger(htbDialogs, diagId, BTN_CNT)
local integer btnsPP = LoadInteger(htbDialogs, diagId, BTNS_PP)
local integer keyPageId
local boolean indexEnable = btnCnt > btnsPP and LoadBoolean(htbDialogs, diagId, INDEX_ENABLE)
local boolean indexOpen = indexEnable and LoadBoolean(htbDialogs, diagId, INDEX_OPEN)
if HaveSavedInteger(htbBtns, CURR_BTNS, btnId) then
// INDEX BTN
if indexOpen then
// Save pageId & ID, hide index, and show dialog
call SaveInteger(htbDialogs, diagId, PAGE_ID, LoadInteger(htbBtns, CURR_BTNS, btnId))
call SaveInteger(htbDialogs, diagId, CLICKED_ID, DP_BROWSED)
call SaveBoolean(htbDialogs, diagId, INDEX_OPEN, false)
call DialogPDisplay(GetTriggerPlayer(), diagId, true)
// REGULAR BTN
else
// Save clicked ID and hide/clear dialog
call SaveInteger(htbDialogs, diagId, CLICKED_ID, LoadInteger(htbBtns, CURR_BTNS, btnId))
call DialogPDisplay(GetTriggerPlayer(), diagId, false)
set htbBtns = null
return true
endif
// Back, Next or Previous Pushed
elseif HaveSavedBoolean(htbBtns, CURR_BTNS, btnId) then
if indexEnable then
// INDEX NEXT/PREVIOUS BTN
if indexOpen then
// Set new Page data
set keyPageId = INDEX_PAGE_ID
set btnCnt = (LoadInteger(htbDialogs, diagId, BTN_CNT)-1)/btnsPP+1
// BACK BTN
else // open index
call SaveBoolean(htbDialogs, diagId, INDEX_OPEN, true)
endif
// REGULAR NEXT/PREVIOUS BTN
else
// Set new Page data
set keyPageId = PAGE_ID
set btnCnt = LoadInteger(htbDialogs, diagId, BTN_CNT)
endif
if not indexEnable or indexOpen then
set pageId = LoadInteger(htbDialogs, diagId, keyPageId)
// NEXT
if LoadBoolean(htbBtns, CURR_BTNS, btnId) then
if pageId >= (btnCnt-1)/btnsPP then
set pageId = 0
else
set pageId = pageId+1
endif
// PREVIOUS
elseif pageId == 0 then
set pageId = (btnCnt-1)/btnsPP
else
set pageId = pageId-1
endif
// Save pageId and ID (-1)
call SaveInteger(htbDialogs, diagId, keyPageId, pageId)
call SaveInteger(htbDialogs, diagId, CLICKED_ID, DP_BROWSED)
endif
// Show new dialog
call DialogPDisplay(GetTriggerPlayer(), diagId, true)
// CANCEL
else
// Save ID (-2) and hide/clear dialog
call SaveInteger(htbDialogs, diagId, CLICKED_ID, DP_CANCELED)
call DialogPDisplay(GetTriggerPlayer(), diagId, false)
endif
set htbBtns = null
return false
endfunction
//========
//==== Create Dialog ====
function DialogPCreate takes string msg, boolean showIndex returns integer
local dialog diag = DialogCreate()
local trigger trg = CreateTrigger()
local hashtable htbBtns = InitHashtable()
local integer diagId = GetHandleId(diag)
// Handles
call SaveDialogHandle(htbDialogs, diagId, DIAG, diag)
call SaveHashtableHandle(htbDialogs, diagId, BTN_HTB, htbBtns)
call SaveTriggerHandle(htbDialogs, diagId, TRG, trg)
// Config
call SaveStr(htbDialogs, diagId, MSG, msg)
call SaveInteger(htbDialogs, diagId, BTNS_PP, DP_btnsPP)
call SaveBoolean(htbDialogs, diagId, INDEX_ENABLE, showIndex)
call SaveBoolean(htbBtns, BTN_SHOW, BTN_NEXT, DP_showNext)
call SaveBoolean(htbBtns, BTN_SHOW, BTN_PREV, DP_showPrev)
call SaveBoolean(htbBtns, BTN_SHOW, BTN_BACK, DP_showBack)
call SaveBoolean(htbBtns, BTN_SHOW, BTN_CANCEL, DP_showCancel)
call SaveStr(htbBtns, BTN_STR, BTN_NEXT, DP_strNext)
call SaveStr(htbBtns, BTN_STR, BTN_PREV, DP_strPrev)
call SaveStr(htbBtns, BTN_STR, BTN_BACK, DP_strBack)
call SaveStr(htbBtns, BTN_STR, BTN_CANCEL, DP_strCancel)
call SaveInteger(htbBtns, BTN_HK, BTN_NEXT, DP_hkNext)
call SaveInteger(htbBtns, BTN_HK, BTN_PREV, DP_hkPrev)
call SaveInteger(htbBtns, BTN_HK, BTN_BACK, DP_hkBack)
call SaveInteger(htbBtns, BTN_HK, BTN_CANCEL, DP_hkCancel)
// State
call SaveInteger(htbDialogs, diagId, BTN_CNT, 0)
call SaveInteger(htbDialogs, diagId, PAGE_ID, 0)
call SaveInteger(htbDialogs, diagId, CLICKED_ID, DP_NONE)
call SaveBoolean(htbDialogs, diagId, INDEX_OPEN, showIndex)
call SaveInteger(htbDialogs, diagId, INDEX_PAGE_ID, 0)
// Register dialog event
call TriggerRegisterDialogEvent(trg, diag)
call TriggerAddCondition(trg, function DialogClickedCndAcn)
set diag = null
set trg = null
set htbBtns = null
return diagId
endfunction
//========
//==== Destroy Dialog ====
function DialogPDestroy takes integer diagId returns boolean
local dialog diag = null
if HaveSavedHandle(htbDialogs, diagId, DIAG) then
set diag = LoadDialogHandle(htbDialogs, diagId, DIAG)
// Destroy trigger & dialog
if HaveSavedHandle(htbDialogs, diagId, TRG) then
call DestroyTrigger(LoadTriggerHandle(htbDialogs, diagId, TRG))
endif
call DialogClear(diag)
call DialogDestroy(diag)
// Flush hashtables
call FlushParentHashtable(LoadHashtableHandle(htbDialogs, diagId, BTN_HTB))
call FlushChildHashtable(htbDialogs, diagId)
set diag = null
return true
endif
return false // Dialog not found
endfunction
//========
//==== Set Page ====
function DialogPSetPage takes integer diagId, integer pageId returns boolean
local integer pageIdMax
if HaveSavedInteger(htbDialogs, diagId, PAGE_ID) then
if pageId < 0 then
set pageId = 0
elseif pageId > 0 then
set pageIdMax = (LoadInteger(htbDialogs, diagId, BTN_CNT)-1)/LoadInteger(htbDialogs, diagId, BTNS_PP)
if pageId > pageIdMax then
set pageId = pageIdMax
endif
endif
call SaveInteger(htbDialogs, diagId, PAGE_ID, pageId)
return true
endif
return false // dialog not found
endfunction
//========
//==== Set Message ====
function DialogPSetMessage takes integer diagId, string msg returns boolean
if HaveSavedString(htbDialogs, diagId, MSG) then
call SaveStr(htbDialogs, diagId, MSG, msg)
return true
endif
return false // dialog not found
endfunction
//========
//==== Set Buttons Per Page ====
function DialogPSetButtonsPP takes integer diagId, integer btnsPP returns boolean
if HaveSavedInteger(htbDialogs, diagId, BTNS_PP) then
call SaveInteger(htbDialogs, diagId, BTNS_PP, btnsPP)
return true
endif
return false // dialog not found
endfunction
//========
//==== Set Browse Buttons Text ====
function DialogPSetButtonsText takes integer diagId, string next, string prev, string back, string cancel returns boolean
local hashtable htbBtns = null
if HaveSavedHandle(htbDialogs, diagId, BTN_HTB) then
set htbBtns = LoadHashtableHandle(htbDialogs, diagId, BTN_HTB)
call SaveStr(htbBtns, BTN_STR, BTN_NEXT, next)
call SaveStr(htbBtns, BTN_STR, BTN_PREV, prev)
call SaveStr(htbBtns, BTN_STR, BTN_BACK, back)
call SaveStr(htbBtns, BTN_STR, BTN_CANCEL, cancel)
set htbBtns = null
return true
endif
return false // dialog not found
endfunction
//========
//==== Set Browse Buttons Hotkey ====
function DialogPSetButtonsHotkey takes integer diagId, integer next, integer prev, integer back, integer cancel returns boolean
local hashtable htbBtns = null
if HaveSavedHandle(htbDialogs, diagId, BTN_HTB) then
set htbBtns = LoadHashtableHandle(htbDialogs, diagId, BTN_HTB)
call SaveInteger(htbBtns, BTN_HK, BTN_NEXT, next)
call SaveInteger(htbBtns, BTN_HK, BTN_PREV, prev)
call SaveInteger(htbBtns, BTN_HK, BTN_BACK, back)
call SaveInteger(htbBtns, BTN_HK, BTN_CANCEL, cancel)
set htbBtns = null
return true
endif
return false // dialog not found
endfunction
//========
//==== Display Browse Buttons ====
function DialogPDisplayButtons takes integer diagId, boolean next, boolean prev, boolean back, boolean cancel returns boolean
local hashtable htbBtns = null
if HaveSavedHandle(htbDialogs, diagId, BTN_HTB) then
set htbBtns = LoadHashtableHandle(htbDialogs, diagId, BTN_HTB)
call SaveBoolean(htbBtns, BTN_SHOW, BTN_NEXT, next)
call SaveBoolean(htbBtns, BTN_SHOW, BTN_PREV, prev)
call SaveBoolean(htbBtns, BTN_SHOW, BTN_BACK, back)
call SaveBoolean(htbBtns, BTN_SHOW, BTN_CANCEL, cancel)
set htbBtns = null
return true
endif
return false // dialog not found
endfunction
//========
//==== Get Dialog Handle ====
function DialogPGetHandle takes integer diagId returns dialog
if HaveSavedHandle(htbDialogs, diagId, DIAG) then
return LoadDialogHandle(htbDialogs, diagId, DIAG)
endif
return null // dialog not found
endfunction
//========
//==== Get Dialog Trigger ====
function DialogPGetTrigger takes integer diagId returns trigger
if HaveSavedHandle(htbDialogs, diagId, TRG) then
return LoadTriggerHandle(htbDialogs, diagId, TRG)
endif
return null // dialog not found
endfunction
//========
//==== Get Clicked Button Id ====
function DialogPGetClickedId takes integer diagId returns integer
if HaveSavedInteger(htbDialogs, diagId, CLICKED_ID) then
return LoadInteger(htbDialogs, diagId, CLICKED_ID)
endif
return DP_NOT_FOUND // Dialog not found
endfunction
//===========================================================================
//===========================================================================
//===============================================================================
//===============================================================================
//===============================================================================
//==== BUTTONS ==================================================================
//===============================================================================
//==== Add Button ====
function DialogPAddButton takes integer diagId, string text, integer hotkey returns integer
local integer btnCnt
local hashtable htbBtns = null
if HaveSavedHandle(htbDialogs, diagId, BTN_HTB) then
set btnCnt = LoadInteger(htbDialogs, diagId, BTN_CNT)
set htbBtns = LoadHashtableHandle(htbDialogs, diagId, BTN_HTB)
call SaveStr(htbBtns, BTN_STR, btnCnt, text)
call SaveInteger(htbBtns, BTN_HK, btnCnt, hotkey)
call SaveInteger(htbDialogs, diagId, BTN_CNT, btnCnt+1)
set htbBtns = null
return btnCnt
endif
return DP_NOT_FOUND // dialog not found
endfunction
//========
//==== Add Quit Button ====
function DialogPAddQuitButton takes integer diagId, boolean doSS, string text, integer hotkey returns integer
local integer id = DialogPAddButton(diagId, text, hotkey)
if id != DP_NOT_FOUND then
call SaveBoolean(LoadHashtableHandle(htbDialogs, diagId, BTN_HTB), BTN_QUIT, id, doSS)
endif
return id
endfunction
//========
//==== Set Button Text/Hotkey ====
function DialogPSetButton takes integer diagId, integer btnId, string text, integer hotkey returns boolean
local hashtable htbBtns = null
if HaveSavedHandle(htbDialogs, diagId, BTN_HTB) then
set htbBtns = LoadHashtableHandle(htbDialogs, diagId, BTN_HTB)
if HaveSavedString(htbBtns, BTN_STR, btnId) then
call SaveStr(htbBtns, BTN_STR, btnId, text)
call SaveInteger(htbBtns, BTN_HK, btnId, hotkey)
set htbBtns = null
return true
endif
set htbBtns = null
endif
return false // dialog or button not found
endfunction
//========
//==== Set Quit Button doSS/Text/Hotkey ====
function DialogPSetQuitButton takes integer diagId, integer btnId, boolean doSS, string text, integer hotkey returns boolean
if DialogPSetButton(diagId, btnId, text, hotkey) then
call SaveBoolean(LoadHashtableHandle(htbDialogs, diagId, BTN_HTB), BTN_QUIT, btnId, doSS)
return true
endif
return false
endfunction
//========
//==== Get Button Text ====
function DialogPGetButtonText takes integer diagId, integer btnId returns string
local hashtable htbBtns = null
local string txt
if HaveSavedHandle(htbDialogs, diagId, BTN_HTB) then
set htbBtns = LoadHashtableHandle(htbDialogs, diagId, BTN_HTB)
if HaveSavedString(htbBtns, BTN_STR, btnId) then
set txt = LoadStr(htbBtns, BTN_STR, btnId)
set htbBtns = null
return txt
endif
set htbBtns = null
endif
return null // dialog or btn not found
endfunction
//===========================================================================
//===========================================================================
//===============================================================================
//===============================================================================
//===============================================================================
//==== INDEX ====================================================================
//===============================================================================
//==== Enable/Disable Index Page ====
function DialogPEnableIndex takes integer diagId, boolean enable returns boolean
if HaveSavedBoolean(htbDialogs, diagId, INDEX_ENABLE) then
call SaveBoolean(htbDialogs, diagId, INDEX_ENABLE, enable)
call SaveBoolean(htbDialogs, diagId, INDEX_OPEN, enable)
call SaveInteger(htbDialogs, diagId, INDEX_PAGE_ID, 0)
return true
endif
return false // dialog not found
endfunction
//========
//==== Set Index Page ====
function DialogPSetIndexPage takes integer diagId, integer pageId returns boolean
local integer pageIdMax
local integer btnsPP
if HaveSavedInteger(htbDialogs, diagId, INDEX_PAGE_ID) then
if pageId < 0 then
set pageId = 0
elseif pageId > 0 then
set btnsPP = LoadInteger(htbDialogs, diagId, BTNS_PP)
set pageIdMax = ((LoadInteger(htbDialogs, diagId, BTN_CNT)-1)/btnsPP)/btnsPP
if pageId > pageIdMax then
set pageId = pageIdMax
endif
endif
call SaveInteger(htbDialogs, diagId, INDEX_PAGE_ID, pageId)
return true
endif
return false // dialog not found
endfunction
//===========================================================================
//===========================================================================
//===============================================================================
//===============================================================================
//===============================================================================
//==== INDEX BUTTONS ============================================================
//===============================================================================
//==== Set Index Button Text/Hotkey ====
function DialogPSetIndexButton takes integer diagId, integer btnId, string text, integer hotkey returns boolean
local hashtable htbBtns = null
if HaveSavedHandle(htbDialogs, diagId, BTN_HTB) then
set htbBtns = LoadHashtableHandle(htbDialogs, diagId, BTN_HTB)
call SaveStr(htbBtns, INDEX_BTN_STR, btnId, text)
call SaveInteger(htbBtns, INDEX_BTN_HK, btnId, hotkey)
set htbBtns = null
return true
endif
return false // dialog not found
endfunction
//===============================================================================
//===============================================================================
endlibrary
//===========================================================================
//
// IMV Common v.1.0.0
// by loktar
// -------------------------------------------------------------------------
// * Functionality common to Importless Model Viewer and its libraries
// -------------------------------------------------------------------------
//
// -------
// * API *
// -------
// * -
//
//===========================================================================
library IMVCommon initializer InitIMVCommon
globals
// Misc
integer vId
player plrViewer
// Range Formats
constant key F_NONE
constant key F_DEG // Degrees
constant key F_PCT // Percent
constant key F_INT // Integer stored as Real -> R2I (but I2R not needed when passing to func or comparing)
// Errors
private constant sound SND_ERR = CreateSound("Sound\\Interface\\Error.wav", false, false, false, 10, 10, "DefaultEAX")
constant key ADJ // Adjust
constant key NO_ADJ // Don't Adjust
constant key SLNT_ADJ // Silent Adjust
endglobals
//===============================================================================
//===============================================================================
//===============================================================================
//==== UTILITY FUNCTIONS ========================================================
//===============================================================================
//==== Display msg ====
function DisplayMsg takes string msg, boolean error returns nothing
local string color
if error then
set color = "ffff0000"
if not GetSoundIsPlaying(SND_ERR) then
call StartSound(SND_ERR)
endif
else
set color = "ffffff00"
endif
call DisplayTimedTextToPlayer(plrViewer, 0.5, 0, 5, "|c"+color+msg+"|r")
endfunction
//========
//==== Real to String Precision 0 (no decimal) ====
function R2S0 takes real value returns string
local string str = R2SW(value, 0, 0)
return SubString(str, 0, StringLength(str)-2) // Remove decimal
endfunction
//========
//==== Clamp degrees between 0-360 ====
function ClampDeg takes real value, boolean to360 returns real
local real mod = 360
if value > 360 or (not to360 and value == 360) then
set mod = -360
endif
loop
exitwhen (value > 0 and value < 360) or (not to360 and value == 0) or (to360 and value == 360)
set value = value+mod
endloop
return value
endfunction
//===========================================================================
//===========================================================================
//===============================================================================
//===============================================================================
//===============================================================================
//==== RANGE STRUCT =============================================================
//===============================================================================
struct range
private real min
private real max
real incr
integer format
private string errMsg
static method create takes real min, real max, real incr, integer format, string errMsg returns range
local range r = range.allocate()
set r.min = min
set r.max = max
set r.incr = incr
set r.format = format
set r.errMsg = errMsg
return r
endmethod
method Validate takes real value, integer adjust returns boolean
if this.format == F_DEG then
set value = ClampDeg(value, true)
endif
// VALID
if value >= this.min and value <= this.max then
return true
// INVALID
elseif adjust == NO_ADJ then
call DisplayMsg(this.errMsg, true)
elseif adjust != SLNT_ADJ and not GetSoundIsPlaying(SND_ERR) then
call StartSound(SND_ERR)
endif
return false
endmethod
method Adjust takes real value returns real
if this.format == F_DEG then
set value = ClampDeg(value, true)
endif
if value < this.min then
if this.format == F_DEG and this.min-value > value-this.max+360 then // Get the value that is closest (min if equal diff)
set value = this.max
else
set value = this.min
endif
elseif value > this.max then
if this.format != F_DEG or this.min-value+360 >= value-this.max then // Get the value that is closest (max if equal diff)
set value = this.max
else
set value = this.min
endif
endif
if this.format == F_DEG then
set value = ClampDeg(value, false) // Set to 0 if 360
endif
return value
endmethod
endstruct
//===============================================================================
//===============================================================================
//===============================================================================
//==== INITIALIZER ==============================================================
//===============================================================================
private function InitIMVCommon takes nothing returns nothing
set plrViewer = GetLocalPlayer()
set vId = GetPlayerId(plrViewer)
endfunction
//===============================================================================
//===============================================================================
endlibrary
//===========================================================================
//
// Special Effect Library v1.0.2
// by loktar
// -------------------------------------------------------------------------
// *
// -------------------------------------------------------------------------
//
// -------
// * API *
// -------
// * -
//
//===========================================================================
library SfxLib initializer InitSfxLib requires ScreenMouse, IMVCommon
globals
// Misc
constant integer PID_MAX = bj_MAX_PLAYERS+3
// Fields
constant integer SFX_POSX = 0
constant integer SFX_POSY = 1
constant integer SFX_POSZ = 2
constant integer SFX_HEIGHT = 3
constant integer SFX_SCALE = 4
constant integer SFX_ROLL = 5
constant integer SFX_PITCH = 6
constant integer SFX_YAW = 7
constant integer SFX_ALPHA = 8
constant integer SFX_COLOR = 9
constant integer SFX_SPEED = 10
constant integer SFX_CNT = 11
range array rngSfxFields[SFX_CNT]
// Effect
private boolean animPaused = false
private real array valSfx[SFX_CNT]
private string pathSfx = ""
private effect hndlSfx = null
// Animation
private integer cntSubanims = 0
private string strSfxAnim = "Stand"
private string array strSubanims
private animtype animType = ANIM_TYPE_STAND
private subanimtype array subanimTypes
// Animation Types Hashtable
private constant key ANIM_TYPES
private constant key SUBANIM_TYPES
private hashtable htbAnimTypes = InitHashtable()
// Mouse Control
trigger trgSfxMouseBtn = CreateTrigger()
private trigger trgMouseMove = CreateTrigger()
endglobals
//===============================================================================
//===============================================================================
//===============================================================================
//==== UTILITY FUNCTIONS ========================================================
//===============================================================================
//==== Split string by divider ====
private function SplitStr takes string str, string divider returns string
local integer strLen = StringLength(str)
local integer i = 0
loop
exitwhen i >= strLen or SubString(str, i, i+1) == divider
set i = i+1
endloop
return SubString(str, 0, i)
endfunction
//===============================================================================
//===============================================================================
//===============================================================================
//==== FIELDS ===================================================================
//===============================================================================
//==== Get effect field ====
function GetSfxField takes integer id returns real
if id >= 0 and id < SFX_CNT then
return valSfx[id]
endif
return 0.0
endfunction
//========
//==== Set effect position ====
function SetSfxPos takes real x, real y, real z, integer adjust returns boolean
local boolean valid = rngSfxFields[SFX_POSX].Validate(x, adjust)
if not valid and adjust != NO_ADJ then
set x = rngSfxFields[SFX_POSX].Adjust(x)
set valid = true
endif
if valid then
set valid = rngSfxFields[SFX_POSY].Validate(y, adjust)
if not valid and adjust != NO_ADJ then
set y = rngSfxFields[SFX_POSY].Adjust(y)
set valid = true
endif
if valid then
set valid = rngSfxFields[SFX_POSZ].Validate(z, adjust)
if not valid and adjust != NO_ADJ then
set z = rngSfxFields[SFX_POSZ].Adjust(z)
set valid = true
endif
if valid and (x != valSfx[SFX_POSX] or y != valSfx[SFX_POSY] or z != valSfx[SFX_POSZ]) then
set valSfx[SFX_POSX] = x
set valSfx[SFX_POSY] = y
set valSfx[SFX_POSZ] = z
if hndlSfx != null then
call BlzSetSpecialEffectPosition(hndlSfx, x, y, z)
endif
return true
endif
endif
endif
return false
endfunction
//========
//==== Set effect field ====
function SetSfxField takes integer id, real value, integer adjust returns boolean
local boolean valid
if id >= 0 and id < SFX_CNT then
if rngSfxFields[id].format == F_DEG then
set value = ClampDeg(value, false)
endif
set valid = rngSfxFields[id].Validate(value, adjust)
if not valid and adjust != NO_ADJ then
set value = rngSfxFields[id].Adjust(value)
set valid = true
endif
if valid and value != valSfx[id] then
set valSfx[id] = value
if hndlSfx != null then
if id == SFX_POSX then
call BlzSetSpecialEffectX(hndlSfx, value)
elseif id == SFX_POSY then
call BlzSetSpecialEffectY(hndlSfx, value)
elseif id == SFX_POSZ then
call BlzSetSpecialEffectZ(hndlSfx, value)
elseif id == SFX_HEIGHT then
call BlzSetSpecialEffectHeight(hndlSfx, value)
elseif id == SFX_SCALE then
call BlzSetSpecialEffectScale(hndlSfx, value*0.01)
elseif id == SFX_ROLL then
call BlzSetSpecialEffectRoll(hndlSfx, Deg2Rad(value))
elseif id == SFX_PITCH then
call BlzSetSpecialEffectPitch(hndlSfx, Deg2Rad(value))
elseif id == SFX_YAW then
call BlzSetSpecialEffectYaw(hndlSfx, Deg2Rad(value))
elseif id == SFX_ALPHA then
call BlzSetSpecialEffectAlpha(hndlSfx, R2I(value*2.55))
elseif id == SFX_COLOR then
call BlzSetSpecialEffectColorByPlayer(hndlSfx, Player(R2I(value)))
elseif id == SFX_SPEED and not animPaused then
call BlzSetSpecialEffectTimeScale(hndlSfx, value*0.01)
endif
endif
return true
endif
endif
return false
endfunction
//===========================================================================
//===========================================================================
//===============================================================================
//===============================================================================
//===============================================================================
//==== SFX & ANIMATION ==========================================================
//===============================================================================
//==== Play currently set Animation ====
function PlaySfxAnim takes boolean reset returns nothing
local integer i
if hndlSfx != null then
if reset then
call BlzSpecialEffectClearSubAnimations(hndlSfx)
set i = 0
loop
exitwhen i >= cntSubanims
call BlzSpecialEffectAddSubAnimation(hndlSfx, subanimTypes[i])
set i = i+1
endloop
endif
call BlzPlaySpecialEffect(hndlSfx, animType)
if animPaused then
call BlzSetSpecialEffectTimeScale(hndlSfx, 0)
else
call BlzSetSpecialEffectTimeScale(hndlSfx, valSfx[SFX_SPEED]*0.01)
endif
endif
endfunction
//========
//==== Load Effect ====
function LoadSfx takes string path returns string
local integer strLen
local string name = ""
if path != pathSfx then
if hndlSfx != null then
// Hide and destroy current SFX
call BlzSetSpecialEffectPosition(hndlSfx, SM_minX, SM_minY, -50)
call DestroyEffect(hndlSfx)
endif
// Create new SFX
set pathSfx = path
set hndlSfx = AddSpecialEffect(pathSfx, valSfx[SFX_POSX], valSfx[SFX_POSY])
// Apply properties
call BlzSetSpecialEffectZ(hndlSfx, valSfx[SFX_POSZ])
call BlzSetSpecialEffectHeight(hndlSfx, valSfx[SFX_HEIGHT])
call BlzSetSpecialEffectScale(hndlSfx, valSfx[SFX_SCALE]*0.01)
call BlzSetSpecialEffectRoll(hndlSfx, Deg2Rad(valSfx[SFX_ROLL]))
call BlzSetSpecialEffectPitch(hndlSfx, Deg2Rad(valSfx[SFX_PITCH]))
call BlzSetSpecialEffectYaw(hndlSfx, Deg2Rad(valSfx[SFX_YAW]))
call BlzSetSpecialEffectAlpha(hndlSfx, R2I(valSfx[SFX_ALPHA]*2.55))
call BlzSetSpecialEffectColorByPlayer(hndlSfx, Player(R2I(valSfx[SFX_COLOR])))
// Play Anim
call PlaySfxAnim(true)
loop // Get Model Name
set strLen = StringLength(path)
exitwhen strLen <= 0
set name = SplitStr(path, "\\")
set path = SubString(path, StringLength(name)+1, strLen)
endloop
set name = SubString(name, 0, StringLength(name)-4) // remove extension
endif
return name
endfunction
//========
//==== Add subanimation ====
function ToggleSfxSubanim takes string str, boolean remove, boolean play returns boolean
local integer strLen
local integer strHash
local integer iSub
local string substr
local boolean changed = false
local boolean found
local subanimtype subanim
loop
// Exit when string is empty
set strLen = StringLength(str)
exitwhen strLen <= 0
set substr = SplitStr(str, " ")
set str = SubString(str, StringLength(substr)+1, strLen)
set strHash = StringHash(StringCase(substr, false))
if HaveSavedInteger(htbAnimTypes, SUBANIM_TYPES, strHash) then
// REMOVE
if remove then
set subanim = ConvertSubAnimType(LoadInteger(htbAnimTypes, SUBANIM_TYPES, strHash))
set iSub = 0
set found = false
loop
exitwhen iSub >= cntSubanims
if not found and subanimTypes[iSub] == subanim then // Subanim found
set found = true
set changed = true
endif
if found then // Subanim has been removed
if iSub == cntSubanims-1 then // Last in array -> set to null and set count
set subanimTypes[iSub] = null
set strSubanims[iSub] = null
set cntSubanims = cntSubanims-1
else // Shift subsequent subanims
set subanimTypes[iSub] = subanimTypes[iSub+1]
set strSubanims[iSub] = strSubanims[iSub+1]
endif
endif
set iSub = iSub+1
endloop
// ADD
else
set subanimTypes[cntSubanims] = ConvertSubAnimType(LoadInteger(htbAnimTypes, SUBANIM_TYPES, strHash))
set strSubanims[cntSubanims] = substr
if hndlSfx != null then
call BlzSpecialEffectAddSubAnimation(hndlSfx, subanimTypes[cntSubanims])
endif
set cntSubanims = cntSubanims+1
set changed = true
endif
else
call DisplayMsg("Invalid subanimation type: \""+substr+"\".", true)
endif
endloop
if play then
call PlaySfxAnim(remove) // reset if subanim removed
endif
return changed
endfunction
//========
//==== Play effect animation ====
function SetSfxAnim takes string str returns boolean
local integer strHash
local string substr
set substr = SplitStr(str, " ")
set str = SubString(str, StringLength(substr)+1, StringLength(str))
set strHash = StringHash(StringCase(substr, false))
if HaveSavedInteger(htbAnimTypes, ANIM_TYPES, strHash) then
set animType = ConvertAnimType(LoadInteger(htbAnimTypes, ANIM_TYPES, strHash))
set strSfxAnim = substr
set cntSubanims = 0
if hndlSfx != null then // Clear subanimations
call BlzSpecialEffectClearSubAnimations(hndlSfx)
endif
call ToggleSfxSubanim(str, false, false)
else
call DisplayMsg("Invalid animation type: \""+substr+"\".", true)
return false // Main animation invalid -> abort
endif
call PlaySfxAnim(false)
return true
endfunction
//========
//==== Pause/resume animation ====
function PauseSfxAnim takes boolean pause returns nothing
set animPaused = pause
if pause then
call BlzSetSpecialEffectTimeScale(hndlSfx, 0)
elseif valSfx[SFX_SPEED] <= 0 then
call SetSfxField(SFX_SPEED, 100, SLNT_ADJ)
else
call BlzSetSpecialEffectTimeScale(hndlSfx, valSfx[SFX_SPEED]*0.01)
endif
endfunction
//========
//==== Get animation paused state ====
function IsSfxAnimPaused takes nothing returns boolean
return animPaused
endfunction
//========
//==== Get animation string ====
function GetSfxAnimStr takes integer index returns string
local string str
if index > 0 then
if index <= cntSubanims then
return strSubanims[index-1]
endif
return null
else
set str = strSfxAnim
if index < 0 then
set index = 0
loop
exitwhen index >= cntSubanims
set str = str+" "+strSubanims[index]
set index = index+1
endloop
endif
return str
endif
endfunction
//===========================================================================
//===========================================================================
//===============================================================================
//===============================================================================
//===============================================================================
//==== MOUSE CONTROLS ===========================================================
//===============================================================================
private function MouseMoveCndAcn takes nothing returns boolean
local real x
local real y
if SMIsRightDown(vId) then
// MOVE
if not SMIsLeftDown(vId) then
set x = SMGetDifXs(vId)
set y = SMGetDifYs(vId)
if x != 0 or y != 0 then
call SetSfxPos(valSfx[SFX_POSX] - x, valSfx[SFX_POSY] - y, valSfx[SFX_POSZ], SLNT_ADJ)
endif
// ZOOM
else
set y = SMGetDifY(vId)
if y != 0 then
call SetSfxField(SFX_SCALE, valSfx[SFX_SCALE] - y*(rngSfxFields[SFX_SCALE].incr/4), SLNT_ADJ)
endif
endif
// ROTATE
elseif SMIsLeftDown(vId) then
set x = SMGetDifX(vId)
if x != 0 then
call SetSfxField(SFX_YAW, valSfx[SFX_YAW] - x*(rngSfxFields[SFX_YAW].incr/4), SLNT_ADJ)
endif
endif
return false
endfunction
//===============================================================================
//===============================================================================
//===============================================================================
//==== INITIALIZER ==============================================================
//===============================================================================
private function InitSfxLib takes nothing returns nothing
call TriggerSleepAction(0) // For struct create
// Field ranges min max incr format errMsg
set rngSfxFields[SFX_POSX] = range.create(SM_minX, SM_maxX, 10, F_NONE, "Invalid position X ("+R2S0(SM_minX)+" - "+R2S0(SM_maxX)+").")
set rngSfxFields[SFX_POSY] = range.create(SM_minY, SM_maxY, 10, F_NONE, "Invalid position Y ("+R2S0(SM_minY)+" - "+R2S0(SM_maxY)+").")
set rngSfxFields[SFX_POSY] = range.create(-1000, 1000, 10, F_NONE, "Invalid position Z (-1000 - 1000).")
set rngSfxFields[SFX_HEIGHT] = range.create(-1000, 1000, 20, F_NONE, "Invalid height (-1000 - 1000).")
set rngSfxFields[SFX_SCALE] = range.create(0, 1000, 10, F_PCT, "Invalid scale (0% - 1000%).")
set rngSfxFields[SFX_ROLL] = range.create(0, 360, 7.5, F_DEG, "")
set rngSfxFields[SFX_PITCH] = range.create(0, 360, 7.5, F_DEG, "")
set rngSfxFields[SFX_YAW] = range.create(0, 360, 7.5, F_DEG, "")
set rngSfxFields[SFX_ALPHA] = range.create(0, 100, 5, F_PCT, "Invalid alpha (0% - 100%).")
set rngSfxFields[SFX_COLOR] = range.create(0, PID_MAX, 1, F_INT, "Invalid player number (1 - "+I2S(PID_MAX+1)+").")
set rngSfxFields[SFX_SPEED] = range.create(0, 1000, 10, F_PCT, "Invalid animation speed (0% - 1000%).")
// Default values
set valSfx[SFX_POSX] = 0
set valSfx[SFX_POSY] = 0
set valSfx[SFX_POSZ] = 0
set valSfx[SFX_HEIGHT] = 0
set valSfx[SFX_SCALE] = 100
set valSfx[SFX_ROLL] = 0
set valSfx[SFX_PITCH] = 0
set valSfx[SFX_YAW] = 0
set valSfx[SFX_ALPHA] = 100
set valSfx[SFX_COLOR] = 0
set valSfx[SFX_SPEED] = 100
// ANIMATION HASHTABLE
call SaveInteger(htbAnimTypes, ANIM_TYPES, StringHash("birth"), 0)
call SaveInteger(htbAnimTypes, ANIM_TYPES, StringHash("death"), 1)
call SaveInteger(htbAnimTypes, ANIM_TYPES, StringHash("decay"), 2)
call SaveInteger(htbAnimTypes, ANIM_TYPES, StringHash("dissipate"), 3)
call SaveInteger(htbAnimTypes, ANIM_TYPES, StringHash("stand"), 4)
call SaveInteger(htbAnimTypes, ANIM_TYPES, StringHash("walk"), 5)
call SaveInteger(htbAnimTypes, ANIM_TYPES, StringHash("attack"), 6)
call SaveInteger(htbAnimTypes, ANIM_TYPES, StringHash("morph"), 7)
call SaveInteger(htbAnimTypes, ANIM_TYPES, StringHash("sleep"), 8)
call SaveInteger(htbAnimTypes, ANIM_TYPES, StringHash("spell"), 9)
call SaveInteger(htbAnimTypes, ANIM_TYPES, StringHash("portrait"), 10)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("rooted"), 11)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("alternateex"), 12)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("looping"), 13)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("slam"), 14)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("throw"), 15)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("spiked"), 16)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("fast"), 17)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("spin"), 18)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("ready"), 19)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("channel"), 20)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("defend"), 21)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("victory"), 22)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("turn"), 23)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("left"), 24)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("right"), 25)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("fire"), 26)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("flesh"), 27)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("hit"), 28)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("wounded"), 29)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("light"), 30)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("moderate"), 31)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("severe"), 32)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("critical"), 33)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("complete"), 34)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("gold"), 35)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("lumber"), 36)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("work"), 37)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("talk"), 38)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("first"), 39)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("second"), 40)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("third"), 41)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("fourth"), 42)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("fifth"), 43)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("one"), 44)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("two"), 45)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("three"), 46)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("four"), 47)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("five"), 48)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("small"), 49)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("medium"), 50)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("large"), 51)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("upgrade"), 52)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("drain"), 53)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("fill"), 54)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("chainlightning"), 55)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("eattrea"), 56)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("puke"), 57)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("flail"), 58)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("off"), 59)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("swim"), 60)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("entangle"), 61)
call SaveInteger(htbAnimTypes, SUBANIM_TYPES, StringHash("berserk"), 62)
// Mouse Control
call DisableTrigger(trgSfxMouseBtn)
call SMRegisterPlayerDrag(trgSfxMouseBtn, trgMouseMove, plrViewer, true, true, true)
call TriggerAddCondition(trgMouseMove, function MouseMoveCndAcn)
endfunction
//===============================================================================
//===============================================================================
endlibrary
//===========================================================================
//
// Camera Library v1.0.2
// by loktar
// -------------------------------------------------------------------------
// *
// -------------------------------------------------------------------------
//
// -------
// * API *
// -------
// * -
//
//===========================================================================
library CameraLib initializer InitCameraLib requires ScreenMouse, DialogPages, IMVCommon
globals
// Fields
constant integer CAM_POSX = 7 // PosX and PosY have no camerafield
constant integer CAM_POSY = 8
constant integer CAM_ZOFF = 6 // the rest are camerafield handle ids (0-6)
constant integer CAM_ROT = 5
constant integer CAM_AOA = 2
constant integer CAM_ROLL = 4
constant integer CAM_DIST = 0
constant integer CAM_FOV = 3
constant integer CAM_FARZ = 1
constant integer CAM_CNT = 9
range array rngCamFields[CAM_CNT]
// Current Camera
private camerasetup currentCam = CreateCameraSetup()
trigger trgCamLock = CreateTrigger()
// Setups
private integer cntCams = 0
private integer iAppliedCam = -1
private camerasetup array cams
private hashtable htbCamDiag = null
private gamecache gcaCams = InitGameCache("CameraLib.w3v")
trigger trgCamSaved = null // User trigger
trigger trgCamApplied = null // User trigger
trigger trgCamDeleted = null // User trigger
// Mouse Control
trigger trgCamMouseBtn = CreateTrigger()
private trigger trgMouseMove = CreateTrigger()
endglobals
//===============================================================================
//===============================================================================
//===============================================================================
//==== UTILITY FUNCTIONS ========================================================
//===============================================================================
//==== Display invalid cam msg ====
private function DisplayCamError takes nothing returns nothing
local string str = ""
if cntCams <= 0 then
set str = "none available"
else
set str = "cam 1"
if cntCams > 1 then
set str = str+" - cam "+I2S(cntCams)
endif
endif
call DisplayMsg("Invalid camera index ("+str+").", true)
endfunction
//===============================================================================
//===============================================================================
//===============================================================================
//==== FIELDS ===================================================================
//===============================================================================
//==== Get Camera Field ====
private function GetCamField takes camerasetup camera, integer id returns real
if id >= 0 and id < CAM_CNT then
if id == CAM_POSX then
return CameraSetupGetDestPositionX(camera)
elseif id == CAM_POSY then
return CameraSetupGetDestPositionY(camera)
else
return CameraSetupGetField(camera, ConvertCameraField(id))
endif
endif
return 0.0
endfunction
//========
//==== Set Camera Field ====
private function SetCamField takes camerasetup camera, integer id, real value returns nothing
if id >= 0 and id < CAM_CNT then
if id == CAM_POSX then
call CameraSetupSetDestPosition(camera, value, GetCamField(camera, CAM_POSY), 0)
elseif id == CAM_POSY then
call CameraSetupSetDestPosition(camera, GetCamField(camera, CAM_POSX), value, 0)
else
call CameraSetupSetField(camera, ConvertCameraField(id), value, 0)
endif
endif
endfunction
//===========================================================================
//===========================================================================
//==== Get Current Camera Field ====
function GetCurrentCamField takes integer id returns real
return GetCamField(currentCam, id)
endfunction
//========
//==== Get Applied Camera Field ====
function GetAppliedCamField takes integer id returns real
if iAppliedCam >= 0 and iAppliedCam < cntCams then
return GetCamField(cams[iAppliedCam], id)
endif
return 0.0
endfunction
//========
//==== Set Current Camera Position ====
function SetCurrentCamPos takes real x, real y, integer adjust returns boolean
local boolean valid = rngCamFields[CAM_POSX].Validate(x, adjust)
if not valid and adjust != NO_ADJ then
set x = rngCamFields[CAM_POSX].Adjust(x)
set valid = true
endif
if valid then
set valid = rngCamFields[CAM_POSY].Validate(y, adjust)
if not valid and adjust != NO_ADJ then
set y = rngCamFields[CAM_POSY].Adjust(y)
set valid = true
endif
// Update value if it has actually changed
if valid and (x != GetCamField(currentCam, CAM_POSX) or y != GetCamField(currentCam, CAM_POSY)) then
call CameraSetupSetDestPosition(currentCam, x, y, 0)
return true
endif
endif
return false
endfunction
//========
//==== Set Current Camera Field ====
function SetCurrentCamField takes integer id, real value, integer adjust returns boolean
local boolean valid
if id >= 0 and id < CAM_CNT then
if rngCamFields[id].format == F_DEG then
set value = ClampDeg(value, false)
endif
set valid = rngCamFields[id].Validate(value, adjust)
if not valid and adjust != NO_ADJ then
set value = rngCamFields[id].Adjust(value)
set valid = true
endif
// Update value if it has actually changed
if valid and value != GetCamField(currentCam, id) then
call SetCamField(currentCam, id, value)
return true
endif
endif
return false
endfunction
//===========================================================================
//===========================================================================
//===============================================================================
//===============================================================================
//===============================================================================
//==== SETUPS ===================================================================
//===============================================================================
//==== Compare cams ====
private function CompareCams takes camerasetup cam1, camerasetup cam2 returns boolean
local integer id = 0
loop
exitwhen id >= CAM_CNT
if GetCamField(cam1, id) != GetCamField(cam2, id) then
return false
endif
set id = id+1
endloop
return true
endfunction
//========
//==== Check if cam exists and return id ====
private function GetCamId takes camerasetup cam returns integer
local integer id = 0
loop
exitwhen id >= cntCams
if CompareCams(cam, cams[id]) then
return id
endif
set id = id+1
endloop
return -1
endfunction
//========
//==== Compare cam to current cam ====
private function IsCurrentCam takes integer iCam returns boolean
local integer id = 0
if iCam >= 0 and iCam < cntCams then
return CompareCams(currentCam, cams[iCam])
endif
return false
endfunction
//========
//==== Save Camera ====
private function SaveCam takes camerasetup camsetup, integer iCam returns nothing
local string sCam
local integer id
if iCam >= 0 and iCam <= cntCams then
// Save cam
set cams[iCam] = camsetup
// Update count
if iCam == cntCams then
set cntCams = cntCams+1
call StoreInteger(gcaCams, "data", "cntCams", cntCams)
// Eval/Execute user trigger
if trgCamSaved != null and TriggerEvaluate(trgCamSaved) then
call TriggerExecute(trgCamSaved)
endif
endif
// Store data
set sCam = I2S(iCam)
set id = 0
loop
exitwhen id >= CAM_CNT
call StoreReal(gcaCams, sCam, I2S(id), GetCamField(camsetup, id))
set id = id+1
endloop
call SaveGameCache(gcaCams)
endif
endfunction
//========
//==== Save Default Cameras ====
private function SaveDefaultCams takes nothing returns nothing
local integer cntSaved = 0
local string msg
if GetCamId(gg_cam_Cam0) == -1 then
call SaveCam(gg_cam_Cam0, cntCams)
set cntSaved = cntSaved+1
endif
if GetCamId(gg_cam_Cam1) == -1 then
call SaveCam(gg_cam_Cam1, cntCams)
set cntSaved = cntSaved+1
endif
if GetCamId(gg_cam_Cam2) == -1 then
call SaveCam(gg_cam_Cam2, cntCams)
set cntSaved = cntSaved+1
endif
set msg = I2S(cntSaved)+" default camera setup"
if cntSaved != 1 then
set msg = msg+"s"
endif
set msg = msg+" added"
if cntSaved > 0 then
set msg = msg+" (cam "+I2S(cntCams-cntSaved+1)
if cntSaved > 1 then
set msg = msg+" - cam "+I2S(cntCams)
endif
set msg = msg+")"
endif
set msg = msg+"."
call DisplayMsg(msg, false)
endfunction
//===========================================================================
//===========================================================================
//==== Check if a cam setup is applied ====
function IsCamApplied takes nothing returns boolean
return iAppliedCam >= 0 and iAppliedCam < cntCams
endfunction
//========
//==== Get applied cam index ====
function GetAppliedCamIndex takes nothing returns integer
if iAppliedCam >= 0 and iAppliedCam < cntCams then
return iAppliedCam
endif
return -1
endfunction
//========
//==== Get max cam index ====
function GetCamCount takes nothing returns integer
return cntCams
endfunction
//========
//==== Apply Camera ====
function ApplyCam takes integer iCam returns nothing
local integer id
if iCam >= 0 and iCam < cntCams and (iCam != iAppliedCam or not IsCurrentCam(iAppliedCam)) then
// Update index
if iCam != iAppliedCam then
set iAppliedCam = iCam
call StoreInteger(gcaCams, "data", "iAppliedCam", iAppliedCam)
call SaveGameCache(gcaCams)
endif
// Apply
set id = 0
loop
exitwhen id >= CAM_CNT
call SetCurrentCamField(id, GetCamField(cams[iAppliedCam], id), SLNT_ADJ)
set id = id+1
endloop
call DisplayMsg("Applied cam "+I2S(iAppliedCam+1)+".", false)
// Eval/Execute user trigger
if trgCamApplied != null and TriggerEvaluate(trgCamApplied) then
call TriggerExecute(trgCamApplied)
endif
elseif iCam >= 0 and iCam < cntCams then
call DisplayMsg("Cam "+I2S(iCam+1)+" already applied.", false)
else
call DisplayCamError()
endif
endfunction
//========
//==== Save Current Camera ====
function SaveCurrentCam takes nothing returns nothing
local integer id = GetCamId(currentCam)
local camerasetup newCam
if id == -1 then // Current cam doesn't exist yet
// Copy current cam
set newCam = CreateCameraSetup()
set id = 0
loop
exitwhen id >= CAM_CNT
call SetCamField(newCam, id, GetCamField(currentCam, id))
set id = id+1
endloop
// Save the copy
set iAppliedCam = cntCams
call StoreInteger(gcaCams, "data", "iAppliedCam", iAppliedCam)
call SaveCam(newCam, cntCams) // increments cntCams and saves gamecache
call DisplayMsg("Current camera saved as cam "+I2S(iAppliedCam+1)+".", false)
else
call DisplayMsg("Current camera already saved as cam "+I2S(id+1)+".", true)
endif
endfunction
//========
//==== Delete Camera ====
function DeleteCam takes integer iCam returns nothing
local integer i
local string sCam
local string sShift
if iCam >= 0 and iCam < cntCams then
set sShift = ""
// Flush, and shift subsequent cams
call FlushStoredMission(gcaCams, I2S(iCam))
if iCam < cntCams-1 then // Deleted cam is not last in array
set i = iCam+1
loop
exitwhen i >= cntCams
call SaveCam(cams[i], i-1)
set i = i+1
endloop
call FlushStoredMission(gcaCams, I2S(cntCams-1))
if iCam < cntCams-2 then // Deleted cam is not second last in array
set sShift = "cams "+I2S(iCam+2)+" - "+I2S(cntCams)+" to "+I2S(iCam+1)+" - "+I2S(cntCams-1)
else // Deleted cam is second last in array
set sShift = "cam "+I2S(iCam+2)+" to "+I2S(iCam+1)
endif
set sShift = " (renumbered "+sShift+")"
endif
// Update cam count and null last in array
set cntCams = cntCams-1
call StoreInteger(gcaCams, "data", "cntCams", cntCams)
set cams[cntCams] = null
// Update current cam index
if iCam <= iAppliedCam then
if iCam == iAppliedCam then // Applied cam was deleted
set iAppliedCam = -1
else // Applied cam was shifted
set iAppliedCam = iAppliedCam-1
endif
call StoreInteger(gcaCams, "data", "iAppliedCam", iAppliedCam)
endif
// Save cache
call SaveGameCache(gcaCams)
call DisplayMsg("Deleted cam "+I2S(iCam+1)+sShift+".", false)
// Eval/Execute user trigger
if trgCamDeleted != null and TriggerEvaluate(trgCamDeleted) then
call TriggerExecute(trgCamDeleted)
endif
else
call DisplayCamError()
endif
endfunction
//========
//==== Get Stored Cameras ====
function GetStoredCams takes nothing returns nothing
local integer cntStoredCams = 0
local integer cntCamsBefore
local integer id
local integer iCam
local string sCam
if HaveStoredInteger(gcaCams, "data", "cntCams") then
set cntStoredCams = GetStoredInteger(gcaCams, "data", "cntCams")
if cntStoredCams > 0 then
set iCam = cntCams
set cntCamsBefore = cntCams
set cntCams = cntCams+cntStoredCams
loop
exitwhen iCam >= cntCams
// Copy data
set cams[iCam] = CreateCameraSetup()
set sCam = I2S(iCam)
set id = 0
loop
exitwhen id >= CAM_CNT
call SetCamField(cams[iCam], id, GetStoredReal(gcaCams, sCam, I2S(id)))
set id = id+1
endloop
set iCam = iCam+1
endloop
call DisplayMsg(I2S(cntStoredCams)+" camera setups loaded (cam "+I2S(cntCamsBefore+1)+" - "+I2S(cntCams)+").", false)
// Cameras loaded - get stored iAppliedCam and apply
set iCam = GetStoredInteger(gcaCams, "data", "iAppliedCam")+cntCamsBefore // adjust for former cntCams
if (iCam < cntCamsBefore or iCam >= cntCams) and (iAppliedCam < 0 or iAppliedCam >= cntCamsBefore) then
set iCam = cntCamsBefore
endif
if iCam >= cntCamsBefore and iCam < cntCams then
call ApplyCam(iCam)
endif
endif
endif
if cntStoredCams <= 0 then
call DisplayMsg("No stored camera setups found.", false)
endif
// No cameras - get defaults
if cntCams <= 0 then
call SaveDefaultCams()
if cntCams > 0 then // check if any defaults were saved
call ApplyCam(0)
endif
endif
endfunction
//===========================================================================
//===========================================================================
//===============================================================================
//===============================================================================
//===============================================================================
//==== TRIGGERS =================================================================
//===============================================================================
//==== Cam Lock ====
private function CamLockCndAcn takes nothing returns boolean
call CameraSetupApplyForceDuration(currentCam, true, 0)
return false
endfunction
//========
//==== Cam Dialog Clicked ====
private function CamDiagCndAcn takes nothing returns boolean
local integer diagId = GetHandleId(GetClickedDialog())
local integer iBtn = DialogPGetClickedId(diagId)
local integer iCam
if iBtn != DP_BROWSED and iBtn != DP_NOT_FOUND then
if iBtn != DP_CANCELED then
set iCam = LoadInteger(htbCamDiag, 0, iBtn)
if iCam >= 0 and iCam < cntCams then
if LoadBoolean(htbCamDiag, 1, 0) then
call DeleteCam(iCam)
else
call ApplyCam(iCam)
endif
elseif iCam == cntCams then
call SaveDefaultCams()
endif
endif
call FlushParentHashtable(htbCamDiag)
set htbCamDiag = null
call DialogPDestroy(diagId)
endif
return false
endfunction
//========
//==== Cam Dialog ====
function ShowCamDiag takes boolean delete returns nothing
local integer diagId
local integer iCam
set htbCamDiag = InitHashtable()
if cntCams <= 0 then
set diagId = DialogPCreate("No camera setups available.", false)
else
if not delete then
if cntCams == 1 and IsCurrentCam(0) then
set diagId = DialogPCreate("Cam 1 already applied.", false)
else
set diagId = DialogPCreate("Apply camera setup:", false)
endif
else
set diagId = DialogPCreate("Delete camera setup:", false)
endif
call SaveBoolean(htbCamDiag, 1, 0, delete)
set iCam = 0
loop
exitwhen iCam >= cntCams
if delete or iCam != iAppliedCam or not IsCurrentCam(iCam) then
call SaveInteger(htbCamDiag, 0, DialogPAddButton(diagId, "Cam "+I2S(iCam+1), 0), iCam)
endif
set iCam = iCam+1
endloop
endif
if not delete and (GetCamId(gg_cam_Cam0) == -1 or GetCamId(gg_cam_Cam1) == -1 or GetCamId(gg_cam_Cam2) == -1) then
call SaveInteger(htbCamDiag, 0, DialogPAddButton(diagId, "Add Defaults", 0), cntCams)
endif
call TriggerAddCondition(DialogPGetTrigger(diagId), function CamDiagCndAcn)
call DialogPDisplay(plrViewer, diagId, true)
endfunction
//===========================================================================
//===========================================================================
//===============================================================================
//===============================================================================
//===============================================================================
//==== MOUSE CONTROLS ===========================================================
//===============================================================================
private function MouseMoveCndAcn takes nothing returns boolean
local real x
local real y
if SMIsRightDown(vId) then
// MOVE
if not SMIsLeftDown(vId) then
set x = SMGetDifXs(vId)
set y = SMGetDifYs(vId)
if x != 0 or y != 0 then
set x = GetCameraTargetPositionX() + x*rngCamFields[CAM_POSX].incr
set y = GetCameraTargetPositionY() + y*rngCamFields[CAM_POSY].incr
call SetCurrentCamPos(x, y, SLNT_ADJ)
endif
// ZOOM
else
set y = SMGetDifY(vId)
if y != 0 then
call SetCurrentCamField(CAM_DIST, GetCameraField(CAMERA_FIELD_TARGET_DISTANCE) + SMGetDifY(vId)*rngCamFields[CAM_DIST].incr, SLNT_ADJ)
endif
endif
elseif SMIsLeftDown(vId) then
// ROTATE
set x = SMGetDifX(vId)
set y = SMGetDifY(vId)
if x != 0 or y != 0 then
call SetCurrentCamField(CAM_ROT, Rad2Deg(GetCameraField(CAMERA_FIELD_ROTATION)) + x*rngCamFields[CAM_ROT].incr, SLNT_ADJ)
call SetCurrentCamField(CAM_AOA, Rad2Deg(GetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK)) - y*rngCamFields[CAM_AOA].incr, SLNT_ADJ)
endif
endif
return false
endfunction
//===============================================================================
//===============================================================================
//===============================================================================
//==== INITIALIZER ==============================================================
//===============================================================================
private function InitCameraLib takes nothing returns nothing
call TriggerSleepAction(0) // For struct create
// Field ranges min max incr format errMsg
set rngCamFields[CAM_POSX] = range.create(SM_minX, SM_maxX, 10, F_NONE, "Invalid position X ("+R2S0(SM_minX)+" - "+R2S0(SM_maxX)+").")
set rngCamFields[CAM_POSY] = range.create(SM_minY, SM_maxY, 10, F_NONE, "Invalid position Y ("+R2S0(SM_minY)+" - "+R2S0(SM_maxY)+").")
set rngCamFields[CAM_ZOFF] = range.create(0, 4096, 20, F_NONE, "Invalid height offset (0 - 4096).")
set rngCamFields[CAM_ROT] = range.create(0, 360, 10, F_DEG, "")
set rngCamFields[CAM_AOA] = range.create(205, 335, 10, F_DEG, "Invalid angle of attack (205° - 335°).")
set rngCamFields[CAM_ROLL] = range.create(0, 360, 10, F_DEG, "")
set rngCamFields[CAM_DIST] = range.create(100, 100000, 50, F_NONE, "Invalid target distance (100 - 100000).")
set rngCamFields[CAM_FOV] = range.create(20, 120, 10, F_DEG, "Invalid field of view (20° - 120°).")
set rngCamFields[CAM_FARZ] = range.create(101, 10000, 100, F_NONE, "Invalid far clipping (101 - 10000).")
// Camera lock
call DisableTrigger(trgCamLock)
call TriggerRegisterTimerEvent(trgCamLock, 0.01, true)
call TriggerAddCondition(trgCamLock, function CamLockCndAcn)
// Mouse Control
call DisableTrigger(trgCamMouseBtn)
call SMRegisterPlayerDrag(trgCamMouseBtn, trgMouseMove, plrViewer, true, true, true)
call TriggerAddCondition(trgMouseMove, function MouseMoveCndAcn)
endfunction
//===============================================================================
//===============================================================================
endlibrary
//===========================================================================
//
// Importless Model Viewer v1.2.2
// by loktar
// -------------------------------------------------------------------------
// * View models without editing the map
// * * Load from war3mod.mpq (folder), Local Files, and WC3 data
// * * Can be added while the map is loaded
// * Mouse controls
// * Model, animation and camera interface (and chat commands)
// * Camera setup management
// -------------------------------------------------------------------------
//
// -------
// * Mouse Controls *
// -------
// * - Switch between Camera and Model
// * - Hold Left: Rotate
// * - Hold Right: Move
// * - Hold Left+Right: Zoom/Scale
//
// -------
// * Model Commands *
// -------
// * -load [model path, no extension]
// * -modelx [CamBoundMinX - CamBoundMaxX] (position x)
// * -modely [CamBoundMinY - CamBoundMaxY] (position y)
// * -modelz [-1000 - 1000] (position z)
// * -scale [0% - 1000%]
// * -yaw [x°] (xy rotation)
// * -pitch [x°] (xz rotation)
// * -roll [x°] (yz rotation)
// * -alpha [0% - 100%]
// * -color [1 - 25] (player number)
//
// -------
// * Animation Commands *
// -------
// * -anim [name] [subanim 1] [subanim 2] [...]
// * -anim add [subanim 1] [subanim 2] [...]
// * -anim remove [subanim 1] [subanim 2] [...]
// * -pause (pause/resume)
// * -speed [0% - 1000%]
// * -forceloop (toggle force loop)
// * -forceloop [0.1s+] (force loop duration)
//
// -------
// * Camera Commands *
// -------
// * -cam [number] (apply camera setup)
// * -cam save (save current camera)
// * -cam delete [number] (delete camera setup)
// * -camx [CamBoundMinX - CamBoundMaxX] (position x)
// * -camy [CamBoundMinY - CamBoundMaxY] (position y)
// * -camz [0 - 4096] (position z/target height)
// * -distance [100 - 100000] (target distance)
// * -rotation [x°] (xy rotation)
// * -aoa [205° - 335°] (xz rotation/angle of attack)
// * -camroll [x°] (yz rotation)
// * -fov [20° - 120°] (field of view)
// * -farz [101 - 10000] (far clipping)
//
// -------
// * Environment Commands *
// -------
// * -tod [hh:mm] (time of day)
// * -tods [0%+] (time of day speed)
//
// -------
// * Animation Names *
// -------
// * stand | birth | death | decay | dissipate | walk | attack | morph | sleep | spell | portrait
//
// -------
// * Subanimation Names *
// -------
// * first | second | third | fourth | fifth | defend | channel | slam | victory | throw | spin |
// * ready | upgrade | lumber | gold | work | talk | swim | flesh | entangle | chainlightning | rooted |
// * eattree | berserk | spiked | light | moderate | severe | critical | small | medium | large | alternateex |
// * looping | wounded | fast | turn | left | right | fire | one | two | three | four | five | fill |
// * puke | drain | flail | hit | off | complete
//
//===========================================================================
library ModelViewer initializer InitModelViewer requires CameraLib, SfxLib
globals
// Multiboard items
private constant key MBI_CAM
private constant key MBI_SFX
private constant key MBI_ANIM
private hashtable htbMBIHandles = InitHashtable()
// Button Control
private constant integer CTRL_SFX = 'A004'
private constant integer CTRL_ANIM = 'A00F'
private constant integer CTRL_CAM = 'A00Z'
private constant key CTRL_OPEN
private constant key CTRL_OFF
private constant sound SND_CLICK = CreateSound("Sound\\Interface\\MouseClick1.wav", false, false, false, 10, 10, "DefaultEAX")
private hashtable htbBtnCtrls = InitHashtable() // Toggle ability ids
private unit MVUnit
// Dialog Strings
private string array strColors[25]
private string array strAnims[11]
private string array strSubanims[52]
// Force Loop
private constant key DRN_FRCLP
private string tltAutoloop1 = "Repeats the animation every "
private string tltAutoloop2 = " seconds.\nChat command: -forceloop\n\n|cffc3dbffClick to enable forceloop.|r"
private real tmoForceLoop = 2
private timer tmrForceLoop = CreateTimer()
private trigger trgForceLoop = CreateTrigger()
endglobals
//===============================================================================
//===============================================================================
//===============================================================================
//==== UTILITY FUNCTIONS ========================================================
//===============================================================================
//==== Real to String Precision 1 ====
private function R2S1 takes real value returns string
return R2SW(value, 0, 1)
endfunction
//===============================================================================
//===============================================================================
//===============================================================================
//==== MULTIBOARD ===============================================================
//===============================================================================
private function UpdateMB takes integer setId, integer fieldId returns nothing
local string value = ""
local integer format = F_NONE
// MODEL
if setId == MBI_SFX then
// Animation string
if fieldId == MBI_ANIM then
set value = GetSfxAnimStr(-1)
elseif fieldId >= 0 and fieldId < SFX_CNT and fieldId != SFX_COLOR then
// Model Position XYZ
if fieldId == SFX_POSX or fieldId == SFX_POSY or fieldId == SFX_POSZ then
set fieldId = SFX_POSX
set value = R2S1(GetSfxField(SFX_POSX))+", "+R2S1(GetSfxField(SFX_POSY))+", "+R2S1(GetSfxField(SFX_POSZ))
// Model Orientation Yaw, Pitch, Roll
elseif fieldId == SFX_ROLL or fieldId == SFX_PITCH or fieldId == SFX_YAW then
set fieldId = SFX_ROLL
set value = R2S1(GetSfxField(SFX_YAW))+"°, "+R2S1(GetSfxField(SFX_PITCH))+"°, "+R2S1(GetSfxField(SFX_ROLL))+"°"
// Other SFX Fields
else
set value = R2S1(GetSfxField(fieldId))
set format = rngSfxFields[fieldId].format
endif
endif
// CAMERA
elseif setId == MBI_CAM then
if fieldId >= 0 and fieldId < CAM_CNT then
// Cam Position XYZ
if fieldId == CAM_POSX or fieldId == CAM_POSY or fieldId == CAM_ZOFF then
set fieldId = CAM_POSX
set value = R2S1(GetCurrentCamField(CAM_POSX))+", "+R2S1(GetCurrentCamField(CAM_POSY))+", "+R2S1(GetCurrentCamField(CAM_ZOFF))
// Cam Orientation Rot, AoA, Roll
elseif fieldId == CAM_ROT or fieldId == CAM_AOA or fieldId == CAM_ROLL then
set fieldId = CAM_ROT
set value = R2S1(GetCurrentCamField(CAM_ROT))+"°, "+R2S1(GetCurrentCamField(CAM_AOA))+"°, "+R2S1(GetCurrentCamField(CAM_ROLL))+"°"
// Other cam fields
else
set value = R2S1(GetCurrentCamField(fieldId))
set format = rngCamFields[fieldId].format
endif
endif
endif
if value != "" then
if format == F_DEG then // Degrees - Add °
set value = value+"°"
elseif format == F_PCT then // Percent - Add %
set value = value+"%"
endif
if fieldId == SFX_SPEED and IsSfxAnimPaused() then
set value = value+" (Paused)"
endif
call MultiboardSetItemValue(LoadMultiboardItemHandle(htbMBIHandles, setId, fieldId), value)
endif
endfunction
//===============================================================================
//===============================================================================
//===============================================================================
//==== MODEL & ANIMATION ========================================================
//===============================================================================
private function SfxCmdCndAcn takes nothing returns boolean
local string strOrig = GetEventPlayerChatString() // Preserve case for display
local string str = StringCase(strOrig, false)
local integer strLen = StringLength(str)
local integer id = -1
local real value
local boolean wasDisbld
local boolean disable
// LOAD MODEL
if strLen >= 7 and SubString(str, 0, 6) == "-load " then
set str = LoadSfx(SubString(strOrig, 6, strLen)+".mdl")
if str != "" then
call BlzSetUnitName(MVUnit, str)
endif
// ADD SUBANIMATION
elseif strLen >= 11 and SubString(str, 0, 10) == "-anim add " then
if ToggleSfxSubanim(SubString(strOrig, 10, strLen), false, true) then
call UpdateMB(MBI_SFX, MBI_ANIM)
if GetSfxAnimStr(2) == null then // Added subanim is only one
call BlzUnitDisableAbility(MVUnit, 'A013', false, false)
endif
endif
// REMOVE SUBANIMATION
elseif strLen >= 14 and SubString(str, 0, 13) == "-anim remove " then
if ToggleSfxSubanim(SubString(strOrig, 13, strLen), true, true) then
call UpdateMB(MBI_SFX, MBI_ANIM)
if GetSfxAnimStr(1) == null then // No subanim left
call BlzUnitDisableAbility(MVUnit, 'A013', true, false)
endif
endif
// SET ANIMATION
elseif strLen >= 7 and SubString(str, 0, 6) == "-anim " then
set wasDisbld = GetSfxAnimStr(1) == null
if SetSfxAnim(SubString(strOrig, 6, strLen)) then
call UpdateMB(MBI_SFX, MBI_ANIM)
set disable = GetSfxAnimStr(1) == null
if wasDisbld != disable then
call BlzUnitDisableAbility(MVUnit, 'A013', disable, false)
endif
endif
// PAUSE/RESUME ANIMATION
elseif str == "-pause" then
call BlzUnitHideAbility(MVUnit, 'A011', false) // doesn't work if hidden
if IsSfxAnimPaused() then
call IssueImmediateOrder(MVUnit, "magicundefense")
else
call IssueImmediateOrder(MVUnit, "magicdefense")
endif
call BlzUnitHideAbility(MVUnit, 'A011', true)
// TOGGLE FORCE LOOP
elseif str == "-forceloop" then
call BlzUnitHideAbility(MVUnit, 'A00J', false) // doesn't work if hidden
if IsTriggerEnabled(trgForceLoop) then
call IssueImmediateOrder(MVUnit, "unimmolation")
else
call IssueImmediateOrder(MVUnit, "immolation")
endif
call BlzUnitHideAbility(MVUnit, 'A00J', true)
// SET FORCE LOOP DURATION
elseif strLen >= 12 and SubString(str, 0, 11) == "-forceloop " then
set value = S2R(SubString(str, 11, strLen))
if value < 0.1 then
call DisplayMsg("Invalid force loop duration (0.1s or more).", true)
else
set tmoForceLoop = value
call BlzSetAbilityTooltip('A016', "Force Loop Duration: "+R2S1(tmoForceLoop)+"s", 0)
/*call BlzUnitHideAbility(MVUnit, 'A016', true) // force update
call BlzUnitHideAbility(MVUnit, 'A016', false)*/
endif
else
set id = -1
// POS X
if strLen >= 9 and SubString(str, 0, 8) == "-modelx " then
set id = SFX_POSX
set value = S2R(SubString(str, 8, strLen))
// POS Y
elseif strLen >= 9 and SubString(str, 0, 8) == "-modely " then
set id = SFX_POSY
set value = S2R(SubString(str, 8, strLen))
// POS Z
elseif strLen >= 9 and SubString(str, 0, 8) == "-modelz " then
set id = SFX_POSZ
set value = S2R(SubString(str, 8, strLen))
// SCALE
elseif strLen >= 8 and SubString(str, 0, 7) == "-scale " then
set id = SFX_SCALE
set value = S2R(SubString(str, 7, strLen))
// ROLL
elseif strLen >= 7 and SubString(str, 0, 6) == "-roll " then
set id = SFX_ROLL
set value = S2R(SubString(str, 6, strLen))
// PITCH
elseif strLen >= 8 and SubString(str, 0, 7) == "-pitch " then
set id = SFX_PITCH
set value = S2R(SubString(str, 7, strLen))
// YAW
elseif strLen >= 6 and SubString(str, 0, 5) == "-yaw " then
set id = SFX_YAW
set value = S2R(SubString(str, 5, strLen))
// ALPHA
elseif strLen >= 8 and SubString(str, 0, 7) == "-alpha " then
set id = SFX_ALPHA
set value = S2R(SubString(str, 7, strLen))
// COLOR
elseif strLen >= 8 and SubString(str, 0, 7) == "-color " then
set id = SFX_COLOR
set value = S2I(SubString(str, 7, strLen))-1
// ANIMATION SPEED
elseif strLen >= 8 and SubString(str, 0, 7) == "-speed " then
set id = SFX_SPEED
set value = S2R(SubString(str, 7, strLen))
endif
if id != -1 and SetSfxField(id, value, NO_ADJ) then
if id == SFX_COLOR then
call SetUnitColor(MVUnit, ConvertPlayerColor(R2I(value)))
call SetUnitState(MVUnit, UNIT_STATE_LIFE, value+1)
else
call UpdateMB(MBI_SFX, id)
endif
endif
endif
return false
endfunction
//========
//==== Force Loop ====
private function AutoloopCndAcn takes nothing returns boolean
call PlaySfxAnim(false)
call TimerStart(tmrForceLoop, tmoForceLoop, false, null)
return false
endfunction
//===============================================================================
//===============================================================================
//===============================================================================
//==== CAMERA ===================================================================
//===============================================================================
private function CamCmdCndAcn takes nothing returns boolean
local string str = StringCase(GetEventPlayerChatString(), false)
local integer strLen = StringLength(str)
local integer id
local real value
// Save Camera
if str == "-cam save" then
call SaveCurrentCam()
// Delete Camera
elseif strLen >= 13 and SubString(str, 0, 12) == "-cam delete " then
call DeleteCam(S2I(SubString(str, 12, strLen))-1)
// Apply Camera
elseif strLen >= 6 and SubString(str, 0, 5) == "-cam " then
call ApplyCam(S2I(SubString(str, 5, strLen))-1)
else
set id = -1
// POS X
if strLen >= 7 and SubString(str, 0, 6) == "-camx " then
set id = CAM_POSX
set value = S2R(SubString(str, 6, strLen))
// POS Y
elseif strLen >= 7 and SubString(str, 0, 6) == "-camy " then
set id = CAM_POSY
set value = S2R(SubString(str, 6, strLen))
// HEIGHT OFFSET
elseif strLen >= 7 and SubString(str, 0, 6) == "-camz " then
set id = CAM_ZOFF
set value = S2R(SubString(str, 6, strLen))
// Distance
elseif strLen >= 11 and SubString(str, 0, 10) == "-distance " then
set id = CAM_DIST
set value = S2R(SubString(str, 10, strLen))
// Rotation
elseif strLen >= 11 and SubString(str, 0, 10) == "-rotation " then
set id = CAM_ROT
set value = S2R(SubString(str, 10, strLen))
// Angle of Attack
elseif strLen >= 6 and SubString(str, 0, 5) == "-aoa " then
set id = CAM_AOA
set value = S2R(SubString(str, 5, strLen))
// Roll
elseif strLen >= 10 and SubString(str, 0, 9) == "-camroll " then
set id = CAM_ROLL
set value = S2R(SubString(str, 9, strLen))
// Field of View
elseif strLen >= 6 and SubString(str, 0, 5) == "-fov " then
set id = CAM_FOV
set value = S2R(SubString(str, 5, strLen))
// Far Z
elseif strLen >= 7 and SubString(str, 0, 6) == "-farz " then
set id = CAM_FARZ
set value = S2R(SubString(str, 6, strLen))
endif
if id != -1 and SetCurrentCamField(id, value, NO_ADJ) then
call UpdateMB(MBI_CAM, id)
endif
endif
return false
endfunction
//========
//==== Camera Applied -> Update MB & "Mana" ====
private function CamAppliedCndAcn takes nothing returns boolean
call UpdateMB(MBI_CAM, CAM_POSX) // Also updates POSY and ZOFF
call UpdateMB(MBI_CAM, CAM_DIST)
call UpdateMB(MBI_CAM, CAM_ROT) // Also updates AOA and ROLL
call UpdateMB(MBI_CAM, CAM_FOV)
call UpdateMB(MBI_CAM, CAM_FARZ)
call SetUnitState(MVUnit, UNIT_STATE_MANA, GetAppliedCamIndex()+1)
return false
endfunction
//========
//==== Camera Saved or Deleted -> Update "Mana" ====
private function CamSaveDeleteCndAcn takes nothing returns boolean
call BlzSetUnitMaxMana(MVUnit, GetCamCount())
call SetUnitState(MVUnit, UNIT_STATE_MANA, GetAppliedCamIndex()+1)
return false
endfunction
//===========================================================================
//===========================================================================
//===============================================================================
//===============================================================================
//===============================================================================
//==== ENVIRONMENT ==============================================================
//===============================================================================
private function EnvironmentCmdCndAcn takes nothing returns boolean
local string str = StringCase(GetEventPlayerChatString(), false)
local integer strLen = StringLength(str)
local real realTmp
if strLen >= 7 and SubString(str, 0, 4) == "-tod" then
// TIME OF DAY SPEED
if SubString(str, 0, 6) == "-tods " then
set realTmp = S2R(SubString(str, 6, strLen))
if realTmp >= 0 then
call SetTimeOfDayScale(realTmp*0.01)
else
call DisplayMsg("Invalid time of day speed (0% or more).", true)
endif
// TIME OF DAY
elseif strLen >= 9 and SubString(str, 0, 5) == "-tod " then
set str = SubString(str, 5, strLen)
set strLen = StringLength(str)
if strLen == 4 then
set strLen = 0
elseif strLen == 5 then
set strLen = 1
else
set realTmp = -1
endif
if realTmp != -1 and SubString(str, 1+strLen, 2+strLen) == ":" then // h:mm
set realTmp = S2R(SubString(str, 0, 1+strLen)) + S2R(SubString(str, 2+strLen, 4+strLen))/59*0.99
endif
if realTmp >= 0 and realTmp <= 23.99 then
call SetFloatGameState(GAME_STATE_TIME_OF_DAY, realTmp)
else
call DisplayMsg("Invalid time of day (0:00 - 23:59).", true)
endif
endif
endif
return false
endfunction
//===============================================================================
//===============================================================================
//===============================================================================
//==== BUTTON CONTROLS ==========================================================
//===============================================================================
//==== Team Color Dialog ====
private function ColorDiagCndAcn takes nothing returns boolean
local integer diagId = GetHandleId(GetClickedDialog())
local integer iBtn
local integer iPlr
local string strBtn
// Create dialog
if diagId == 0 then
set diagId = DialogPCreate("Set team color:", true)
call DialogPAddButton(diagId, "|c"+strColors[0]+"Red|r (1)", 0)
call DialogPAddButton(diagId, "|c"+strColors[1]+"Blue|r (2)", 0)
call DialogPAddButton(diagId, "|c"+strColors[2]+"Teal|r (3)", 0)
call DialogPAddButton(diagId, "|c"+strColors[3]+"Purple|r (4)", 0)
call DialogPAddButton(diagId, "|c"+strColors[4]+"Yellow|r (5)", 0)
call DialogPAddButton(diagId, "|c"+strColors[5]+"Orange|r (6)", 0)
call DialogPAddButton(diagId, "|c"+strColors[6]+"Green|r (7)", 0)
call DialogPAddButton(diagId, "|c"+strColors[7]+"Pink|r (8)", 0)
call DialogPAddButton(diagId, "|c"+strColors[8]+"Gray|r (9)", 0)
call DialogPAddButton(diagId, "|c"+strColors[9]+"Light Blue|r (10)", 0)
call DialogPAddButton(diagId, "|c"+strColors[10]+"Dark Green|r (11)", 0)
call DialogPAddButton(diagId, "|c"+strColors[11]+"Brown|r (12)", 0)
call DialogPAddButton(diagId, "|c"+strColors[12]+"Maroon|r (13)", 0)
call DialogPAddButton(diagId, "|c"+strColors[13]+"Navy|r (14)", 0)
call DialogPAddButton(diagId, "|c"+strColors[14]+"Turquoise|r (15)", 0)
call DialogPAddButton(diagId, "|c"+strColors[15]+"Violet|r (16)", 0)
call DialogPAddButton(diagId, "|c"+strColors[16]+"Wheat|r (17)", 0)
call DialogPAddButton(diagId, "|c"+strColors[17]+"Peach|r (18)", 0)
call DialogPAddButton(diagId, "|c"+strColors[18]+"Mint|r (19)", 0)
call DialogPAddButton(diagId, "|c"+strColors[19]+"Lavender|r (20)", 0)
call DialogPAddButton(diagId, "|c"+strColors[20]+"Coal|r (21)", 0)
call DialogPAddButton(diagId, "|c"+strColors[21]+"Snow|r (22)", 0)
call DialogPAddButton(diagId, "|c"+strColors[22]+"Emerald|r (23)", 0)
call DialogPAddButton(diagId, "|c"+strColors[23]+"Peanut|r (24)", 0)
call DialogPAddButton(diagId, "|c"+strColors[24]+"Black|r (Neutral)", 0)
// Setup index page
set iBtn = 0
loop
exitwhen iBtn > 4
set strBtn = "Player "
set iPlr = 0
loop
exitwhen iPlr > 4
set strBtn = strBtn+"|c"+strColors[iBtn*5+iPlr]+I2S(iBtn*5+iPlr+1)+"|r"
if iPlr < 4 then
set strBtn = strBtn+" - "
endif
set iPlr = iPlr+1
endloop
call DialogPSetIndexButton(diagId, iBtn, strBtn, 0)
set iBtn = iBtn+1
endloop
// Add condition and display
call TriggerAddCondition(DialogPGetTrigger(diagId), function ColorDiagCndAcn)
call DialogPDisplay(plrViewer, diagId, true)
// Dialog clicked
else
set iBtn = DialogPGetClickedId(diagId)
if iBtn != DP_BROWSED and iBtn != DP_NOT_FOUND then
if iBtn >= 0 and iBtn <= 24 and SetSfxField(SFX_COLOR, iBtn, NO_ADJ) then
call SetUnitColor(MVUnit, ConvertPlayerColor(iBtn))
call SetUnitState(MVUnit, UNIT_STATE_LIFE, iBtn+1)
endif
call DialogPDestroy(diagId)
endif
endif
return false
endfunction
//========
//==== Animation Dialog ====
private function AnimDiagCndAcn takes nothing returns boolean
local integer diagId = GetHandleId(GetClickedDialog())
local integer i
local boolean hadSubanims
// Create dialog
if diagId == 0 then
set diagId = DialogPCreate("Set animation:", false)
call DialogPSetButtonsPP(diagId, 6)
set i = 0
loop
exitwhen i > 10
call DialogPAddButton(diagId, strAnims[i], 0)
set i = i+1
endloop
call TriggerAddCondition(DialogPGetTrigger(diagId), function AnimDiagCndAcn)
call DialogPDisplay(plrViewer, diagId, true)
// Dialog clicked
else
set i = DialogPGetClickedId(diagId)
if i != DP_BROWSED and i != DP_NOT_FOUND then
if i != DP_CANCELED then
set hadSubanims = GetSfxAnimStr(1) != null
if SetSfxAnim(DialogPGetButtonText(diagId, i)) then
call UpdateMB(MBI_SFX, MBI_ANIM)
if hadSubanims then
call BlzUnitDisableAbility(MVUnit, 'A013', true, false)
endif
endif
call DialogPDestroy(diagId)
set DP_btnsPP = 5
endif
endif
endif
return false
endfunction
//========
//==== Add subanimation Dialog ====
private function AddSubanimDiagCndAcn takes nothing returns boolean
local integer diagId = GetHandleId(GetClickedDialog())
local integer i
local integer iAnim
local string anim
local boolean used
// Create dialog
if diagId == 0 then
set diagId = DialogPCreate("Add a subanimation:", false)
set i = 0
loop
exitwhen i > 51
set used = false
set iAnim = 1
loop
set anim = GetSfxAnimStr(iAnim)
exitwhen used or anim == null
set used = StringCase(strSubanims[i], false) == StringCase(anim, false)
set iAnim = iAnim+1
endloop
if not used then
call DialogPAddButton(diagId, strSubanims[i], 0)
endif
set i = i+1
endloop
call TriggerAddCondition(DialogPGetTrigger(diagId), function AddSubanimDiagCndAcn)
call DialogPDisplay(plrViewer, diagId, true)
// Dialog clicked
else
set i = DialogPGetClickedId(diagId)
if i != DP_BROWSED and i != DP_NOT_FOUND then
if i != DP_CANCELED and ToggleSfxSubanim(DialogPGetButtonText(diagId, i), false, true) then
call UpdateMB(MBI_SFX, MBI_ANIM)
if GetSfxAnimStr(2) == null then // Added subanim is the only one
call BlzUnitDisableAbility(MVUnit, 'A013', false, false)
call BlzUnitHideAbility(MVUnit, 'A013', true) // otherwise it is shown "twice"
endif
endif
call DialogPDestroy(diagId)
endif
endif
return false
endfunction
//========
//==== Remove subanimation Dialog ====
private function RemSubanimDiagCndAcn takes nothing returns boolean
local integer diagId = GetHandleId(GetClickedDialog())
local integer i
local string anim
// Create dialog
if diagId == 0 then
set diagId = DialogPCreate("Remove a subanimation:", false)
set i = 1
loop
set anim = GetSfxAnimStr(i)
exitwhen anim == null
call DialogPAddButton(diagId, anim, 0)
set i = i+1
endloop
call TriggerAddCondition(DialogPGetTrigger(diagId), function RemSubanimDiagCndAcn)
call DialogPDisplay(plrViewer, diagId, true)
// Dialog clicked
else
set i = DialogPGetClickedId(diagId)
if i != DP_BROWSED and i != DP_NOT_FOUND then
if i != DP_CANCELED and ToggleSfxSubanim(DialogPGetButtonText(diagId, i), true, true) then
call UpdateMB(MBI_SFX, MBI_ANIM)
if GetSfxAnimStr(1) == null then // No subanims left
call BlzUnitDisableAbility(MVUnit, 'A013', true, false)
endif
endif
call DialogPDestroy(diagId)
endif
endif
return false
endfunction
//========
//==== Set Model Controls ====
private function SetupCtrls takes integer id, boolean close, boolean init returns nothing
local integer page = GetUnitAbilityLevel(MVUnit, id)
local boolean switch = not close and LoadInteger(htbBtnCtrls, CTRL_OPEN, 0) != CTRL_OFF
if switch then
if page == 1 then
set page = 2
else
set page = 1
endif
call SetUnitAbilityLevel(MVUnit, id, page)
call BlzSetUnitArmor(MVUnit, page)
else
if not init then
call BlzUnitHideAbility(MVUnit, CTRL_SFX, not close)
call BlzUnitHideAbility(MVUnit, CTRL_ANIM, not close)
call BlzUnitHideAbility(MVUnit, CTRL_CAM, not close)
call BlzUnitHideAbility(MVUnit, 'A00H', not close) // Apply Cam
call BlzUnitHideAbility(MVUnit, 'A00A', not close) // Save Cam
call BlzUnitHideAbility(MVUnit, 'A00G', not close) // Delete Cam
call BlzUnitHideAbility(MVUnit, 'A008', not close) // Mouse Controls
if close then
call SaveInteger(htbBtnCtrls, CTRL_OPEN, 0, CTRL_OFF)
call BlzSetUnitArmor(MVUnit, 0)
else
call SaveInteger(htbBtnCtrls, CTRL_OPEN, 0, id)
call BlzSetUnitArmor(MVUnit, page)
endif
endif
if not init or id == CTRL_ANIM then // Make sure this is only done once at init
call BlzUnitHideAbility(MVUnit, 'A009', close) // Increase
call BlzUnitHideAbility(MVUnit, 'A00M', close) // Decrease
call BlzUnitHideAbility(MVUnit, 'A00L', close) // Reset
call BlzUnitHideAbility(MVUnit, 'A00I', close) // Close
if init or id != CTRL_ANIM then
call BlzUnitHideAbility(MVUnit, 'A00P', close) // Page
endif
if id == CTRL_ANIM then
call BlzUnitHideAbility(MVUnit, 'A011', close) // Play/Pause
endif
if init then
call BlzUnitDisableAbility(MVUnit, 'A013', GetSfxAnimStr(1) == null, false) // Remove Subanim
endif
endif
endif
// MODEL CONTROLS
if id == CTRL_SFX then
if switch or page == 1 or init then
call BlzUnitHideAbility(MVUnit, 'A00N', close or page == 2) // PosX
call BlzUnitHideAbility(MVUnit, 'A00O', close or page == 2) // PosY
call BlzUnitHideAbility(MVUnit, 'A00Q', close or page == 2) // PosZ
call BlzUnitHideAbility(MVUnit, 'A00R', close or page == 2) // Scale
call BlzUnitHideAbility(MVUnit, 'A00S', close or page == 2) // Roll
call BlzUnitHideAbility(MVUnit, 'A00T', close or page == 2) // Pitch
call BlzUnitHideAbility(MVUnit, 'A00U', close or page == 2) // Yaw
endif
if switch or page == 2 or init then
call BlzUnitHideAbility(MVUnit, 'A00V', close or page == 1) // Alpha
call BlzUnitHideAbility(MVUnit, 'A010', close or page == 1) // Color
endif
if close then
call SetPlayerTechResearched(plrViewer, 'R001', 0)
elseif not switch then
call SetPlayerTechResearched(plrViewer, 'R001', 1)
endif
// ANIMATION CONTROLS
elseif id == CTRL_ANIM then
call BlzUnitHideAbility(MVUnit, 'A00Y', close) // Set Anim
call BlzUnitHideAbility(MVUnit, 'A012', close) // Add Subanim
call BlzUnitHideAbility(MVUnit, 'A013', close) // Remove Subanim
call BlzUnitHideAbility(MVUnit, 'A00J', close) // Force Loop
call BlzUnitHideAbility(MVUnit, 'A014', close) // Speed
call BlzUnitHideAbility(MVUnit, 'A016', close) // Force Loop duration
if close then
call SetPlayerTechResearched(plrViewer, 'R002', 0)
elseif not switch then
call SetPlayerTechResearched(plrViewer, 'R002', 1)
endif
// CAMERA CONTROLS
elseif id == CTRL_CAM then
if switch or page == 1 or init then
call BlzUnitHideAbility(MVUnit, 'A007', close or page == 2) // PosX
call BlzUnitHideAbility(MVUnit, 'A003', close or page == 2) // PosY
call BlzUnitHideAbility(MVUnit, 'A00E', close or page == 2) // PosZ
call BlzUnitHideAbility(MVUnit, 'A00D', close or page == 2) // Distance
call BlzUnitHideAbility(MVUnit, 'A00C', close or page == 2) // Rotation
call BlzUnitHideAbility(MVUnit, 'A000', close or page == 2) // AoA
call BlzUnitHideAbility(MVUnit, 'A00B', close or page == 2) // Roll
endif
if switch or page == 2 or init then
call BlzUnitHideAbility(MVUnit, 'A006', close or page == 1) // FoV
call BlzUnitHideAbility(MVUnit, 'A005', close or page == 1) // FarZ
endif
if close then
call SetPlayerTechResearched(plrViewer, 'R000', 0)
elseif not switch then
call SetPlayerTechResearched(plrViewer, 'R000', 1)
endif
endif
// Activate field
if not close then
set id = LoadInteger(htbBtnCtrls, id, page)
if id != CTRL_OFF then
call IssueImmediateOrder(MVUnit, OrderId2String(id))
endif
endif
endfunction
//=========
//==== Button Control ====
private function ButtonControlCndAcn takes nothing returns boolean
local integer spellId = GetSpellAbilityId()
local integer openId = LoadInteger(htbBtnCtrls, CTRL_OPEN, 0)
local integer id
local real value
// APPLY OR DELETE CAMERA
if (spellId == 'A00H' or spellId == 'A00G') and openId == CTRL_OFF then // Apply Cam == Remove Subanim
call ShowCamDiag(spellId == 'A00G') // A00G -> delete
// SAVE CAMERA
elseif spellId == 'A00A' then
call SaveCurrentCam()
// MODEL COLOR DIALOG
elseif spellId == 'A010' and openId == CTRL_SFX then // == Add Subanim
call ColorDiagCndAcn()
// ANIMATION DIALOG
elseif spellId == 'A00Y' then
call AnimDiagCndAcn()
// ADD SUBANIMATION DIALOG
elseif spellId == 'A012' and openId == CTRL_ANIM then // == Model Color
call AddSubanimDiagCndAcn()
// REMOVE SUBANIMATION DIALOG
elseif spellId == 'A013' and openId == CTRL_ANIM then // == Apply Cam
call RemSubanimDiagCndAcn()
// OPEN CONTROLS
elseif spellId == CTRL_SFX or spellId == CTRL_ANIM or spellId == CTRL_CAM then
call SetupCtrls(spellId, false, false)
// CLOSE CONTROLS
elseif spellId == 'A00I' then
call SetupCtrls(openId, true, false)
// NEXT PAGE
elseif spellId == 'A00P' then
call SetupCtrls(openId, false, false)
// MODEL & CAM CONTROLS
elseif (spellId == 'A009' or spellId == 'A00M' or spellId == 'A00L')/* and openId != CTRL_ANIM */then // == Anim Ctrls
set id = LoadInteger(htbBtnCtrls, openId, GetUnitAbilityLevel(MVUnit, openId))
if id != CTRL_OFF and HaveSavedInteger(htbBtnCtrls, openId, id) then
set id = LoadInteger(htbBtnCtrls, openId, id)
// MODEL CONTROLS
if openId == CTRL_SFX then
// INCREASE
if spellId == 'A009' then
set value = GetSfxField(id) + rngSfxFields[id].incr
// DECREASE
elseif spellId == 'A00M' then
set value = GetSfxField(id) - rngSfxFields[id].incr
// RESET
elseif id == SFX_POSX then
set value = GetCurrentCamField(CAM_POSX)
elseif id == SFX_POSY then
set value = GetCurrentCamField(CAM_POSY)
elseif id == SFX_SCALE or id == SFX_ALPHA then
set value = 100
elseif id == SFX_ROLL then
set value = 160
else
set value = 0
endif
if SetSfxField(id, value, ADJ) then
call UpdateMB(MBI_SFX, id)
endif
// ANIM CONTROLS
elseif openId == CTRL_ANIM then
// SPEED
if id == SFX_SPEED then
// INCREASE
if spellId == 'A009' then
set value = GetSfxField(SFX_SPEED) + rngSfxFields[SFX_SPEED].incr
// DECREASE
elseif spellId == 'A00M' then
set value = GetSfxField(SFX_SPEED) - rngSfxFields[SFX_SPEED].incr
// RESET
else
set value = 100
endif
if SetSfxField(SFX_SPEED, value, ADJ) then
call UpdateMB(MBI_SFX, SFX_SPEED)
endif
// FORCE LOOP
elseif id == DRN_FRCLP then
// INCREASE
if spellId == 'A009' then
set tmoForceLoop = tmoForceLoop + 0.1
// DECREASE
elseif spellId == 'A00M' then
set value = tmoForceLoop - 0.1
if value < 0.1 then
set tmoForceLoop = 0.1
else
set tmoForceLoop = value
endif
// RESET
else
set tmoForceLoop = 2
endif
call BlzSetAbilityTooltip('A016', "Force Loop Duration: "+R2S1(tmoForceLoop)+"s", 0)
endif
// CAM CONTROLS
elseif openId == CTRL_CAM then
// INCREASE
if spellId == 'A009' then
set value = GetCurrentCamField(id) + rngCamFields[id].incr
// DECREASE
elseif spellId == 'A00M' then
set value = GetCurrentCamField(id) - rngCamFields[id].incr
// RESET
elseif IsCamApplied() then
set value = GetAppliedCamField(id)
else
set id = -1
call DisplayMsg("No camera setup applied.", true)
endif
if id != -1 and SetCurrentCamField(id, value, ADJ) then
call UpdateMB(MBI_CAM, id)
endif
endif
else
call DisplayMsg("Nothing selected.", true)
endif
endif
return false
endfunction
//========
//==== Escape pushed - close controls ====
private function EscCtrlsCndAcn takes nothing returns boolean
if LoadInteger(htbBtnCtrls, CTRL_OPEN, 0) != CTRL_OFF then
if not GetSoundIsPlaying(SND_CLICK) then
call StartSound(SND_CLICK)
endif
call IssueImmediateOrder(MVUnit, "taunt") // Back button
endif
return false
endfunction
//========
//==== Button Toggle ====
private function ButtonTogglesCndAcn takes nothing returns boolean
local integer orderId = GetIssuedOrderId()
local integer openId
// Switch Mouse Controls - Camera/Model
if orderId == OrderId("defend") then
call DisableTrigger(trgCamMouseBtn)
call EnableTrigger(trgSfxMouseBtn)
elseif orderId == OrderId("undefend") then
call DisableTrigger(trgSfxMouseBtn)
call EnableTrigger(trgCamMouseBtn)
// Play/Pause Animation
elseif orderId == OrderId("magicdefense") then
call PauseSfxAnim(true)
call UpdateMB(MBI_SFX, SFX_SPEED)
if IsTriggerEnabled(trgForceLoop) then
call PauseTimer(tmrForceLoop)
endif
elseif orderId == OrderId("magicundefense") then
call PauseSfxAnim(false)
call UpdateMB(MBI_SFX, SFX_SPEED)
if IsTriggerEnabled(trgForceLoop) then
call ResumeTimer(tmrForceLoop)
endif
// Force Loop
elseif orderId == OrderId("immolation") then
call EnableTrigger(trgForceLoop)
call TimerStart(tmrForceLoop, tmoForceLoop, false, null)
if IsSfxAnimPaused() then
call PauseTimer(tmrForceLoop)
endif
elseif orderId == OrderId("unimmolation") then
call DisableTrigger(trgForceLoop)
call PauseTimer(tmrForceLoop)
// TOGGLES
else
set openId = LoadInteger(htbBtnCtrls, CTRL_OPEN, 0)
if openId != CTRL_OFF then
if HaveSavedBoolean(htbBtnCtrls, CTRL_OFF, orderId) then
set orderId = CTRL_OFF // TOGGLE OFF
endif
if orderId == CTRL_OFF or HaveSavedInteger(htbBtnCtrls, openId, orderId) then
call SaveInteger(htbBtnCtrls, openId, GetUnitAbilityLevel(MVUnit, openId), orderId)
endif
endif
endif
return false
endfunction
//===========================================================================
//===========================================================================
//===============================================================================
//===============================================================================
//===============================================================================
//==== MOUSE CONTROLS ===========================================================
//===============================================================================
//==== Cam Control ====
private function CamMouseBtnCndAcn takes nothing returns boolean
if not SMIsLeftDown(vId) and not SMIsRightDown(vId) then
call UpdateMB(MBI_CAM, CAM_POSX) // Also updates POSY
call UpdateMB(MBI_CAM, CAM_DIST)
call UpdateMB(MBI_CAM, CAM_ROT) // Also updates AoA and Roll
endif
return false
endfunction
//========
//==== Model Control ====
private function SfxMouseBtnCndAcn takes nothing returns boolean
if not SMIsLeftDown(vId) and not SMIsRightDown(vId) then
call UpdateMB(MBI_SFX, SFX_POSX) // Also updates POSY
call UpdateMB(MBI_SFX, SFX_SCALE)
call UpdateMB(MBI_SFX, SFX_ROLL) // Also updates Pitch and Yaw
endif
return false
endfunction
//===========================================================================
//===========================================================================
//===============================================================================
//===============================================================================
//===============================================================================
//==== INITIALIZER ==============================================================
//===============================================================================
private function InitModelViewer takes nothing returns nothing
local quest infoQuests
local multiboard mtb
local multiboarditem mbi
local trigger trg
local real titleW
local integer startLoc
call TriggerSleepAction(0) // For StopMusic & Multiboards
// MAP SETUP
call FogEnable(false)
call FogMaskEnable(false)
call EnableWorldFogBoundary(false)
call StopMusic(false)
call EnableDragSelect(false, false)
// CONTROL PANEL
set MVUnit = gg_unit_hhou_0002
call SelectUnit(MVUnit, true)
call SaveInteger(htbBtnCtrls, CTRL_OPEN, 0, CTRL_OFF)
call SaveInteger(htbBtnCtrls, CTRL_SFX, 1, CTRL_OFF) // Page 1
call SaveInteger(htbBtnCtrls, CTRL_SFX, 2, CTRL_OFF) // Page 2
call SaveInteger(htbBtnCtrls, CTRL_CAM, 1, CTRL_OFF) // Page 1
call SaveInteger(htbBtnCtrls, CTRL_CAM, 2, CTRL_OFF) // Page 2
call SetupCtrls(CTRL_SFX, true, true)
call SetupCtrls(CTRL_ANIM, true, true)
call SetupCtrls(CTRL_CAM, true, true)
call SaveInteger(htbBtnCtrls, CTRL_CAM, OrderId("innerfireon"), CAM_POSX)
call SaveInteger(htbBtnCtrls, CTRL_SFX, OrderId("innerfireon"), SFX_POSX)
call SaveInteger(htbBtnCtrls, CTRL_ANIM, OrderId("innerfireon"), SFX_SPEED)
call SaveBoolean(htbBtnCtrls, CTRL_OFF, OrderId("innerfireoff"), false)
call SaveInteger(htbBtnCtrls, CTRL_CAM, OrderId("repairon"), CAM_POSY)
call SaveInteger(htbBtnCtrls, CTRL_SFX, OrderId("repairon"), SFX_POSY)
call SaveInteger(htbBtnCtrls, CTRL_ANIM, OrderId("repairon"), DRN_FRCLP)
call SaveBoolean(htbBtnCtrls, CTRL_OFF, OrderId("repairoff"), false)
call SaveInteger(htbBtnCtrls, CTRL_CAM, OrderId("replenishlifeon"), CAM_ZOFF)
call SaveInteger(htbBtnCtrls, CTRL_SFX, OrderId("replenishlifeon"), SFX_POSZ)
call SaveBoolean(htbBtnCtrls, CTRL_OFF, OrderId("replenishlifeoff"), false)
call SaveInteger(htbBtnCtrls, CTRL_CAM, OrderId("curseon"), CAM_DIST)
call SaveInteger(htbBtnCtrls, CTRL_SFX, OrderId("curseon"), SFX_SCALE)
call SaveBoolean(htbBtnCtrls, CTRL_OFF, OrderId("curseoff"), false)
call SaveInteger(htbBtnCtrls, CTRL_CAM, OrderId("bloodluston"), CAM_ROT)
call SaveInteger(htbBtnCtrls, CTRL_SFX, OrderId("bloodluston"), SFX_ROLL)
call SaveBoolean(htbBtnCtrls, CTRL_OFF, OrderId("bloodlustoff"), false)
call SaveInteger(htbBtnCtrls, CTRL_CAM, OrderId("healon"), CAM_AOA)
call SaveInteger(htbBtnCtrls, CTRL_SFX, OrderId("healon"), SFX_PITCH)
call SaveBoolean(htbBtnCtrls, CTRL_OFF, OrderId("healoff"), false)
call SaveInteger(htbBtnCtrls, CTRL_CAM, OrderId("spellstealon"), CAM_ROLL)
call SaveInteger(htbBtnCtrls, CTRL_SFX, OrderId("spellstealon"), SFX_YAW)
call SaveBoolean(htbBtnCtrls, CTRL_OFF, OrderId("spellstealoff"), false)
call SaveInteger(htbBtnCtrls, CTRL_CAM, OrderId("slowon"), CAM_FOV)
call SaveInteger(htbBtnCtrls, CTRL_SFX, OrderId("slowon"), SFX_ALPHA)
call SaveBoolean(htbBtnCtrls, CTRL_OFF, OrderId("slowoff"), false)
call SaveInteger(htbBtnCtrls, CTRL_CAM, OrderId("raisedeadon"), CAM_FARZ)
call SaveBoolean(htbBtnCtrls, CTRL_OFF, OrderId("raisedeadoff"), false)
// Team Color Codes
set strColors[0] = "ffff0303"
set strColors[1] = "ff0042ff"
set strColors[2] = "ff1ce6b9"
set strColors[3] = "ff540081"
set strColors[4] = "fffffc00"
set strColors[5] = "fffe8a0e"
set strColors[6] = "ff20c000"
set strColors[7] = "ffe55bb0"
set strColors[8] = "ff959697"
set strColors[9] = "ff7ebff1"
set strColors[10] = "ff106246"
set strColors[11] = "ff4e2a04"
set strColors[12] = "ff9b0000"
set strColors[13] = "ff0000c3"
set strColors[14] = "ff00eaff"
set strColors[15] = "ffbe00fe"
set strColors[16] = "ffebcd87"
set strColors[17] = "fff8a48b"
set strColors[18] = "ffbfff80"
set strColors[19] = "ffdcb9eb"
set strColors[20] = "ff282828"
set strColors[21] = "ffebf0ff"
set strColors[22] = "ff00781e"
set strColors[23] = "ffa46f33"
set strColors[24] = "ff000000"
// Animation names
set strAnims[0] = "Birth"
set strAnims[1] = "Death"
set strAnims[2] = "Decay"
set strAnims[3] = "Dissipate"
set strAnims[4] = "Stand"
set strAnims[5] = "Walk"
set strAnims[6] = "Attack"
set strAnims[7] = "Morph"
set strAnims[8] = "Sleep"
set strAnims[9] = "Spell"
set strAnims[10] = "Portrait"
// Subanim names
set strSubanims[0] = "First"
set strSubanims[1] = "Second"
set strSubanims[2] = "Third"
set strSubanims[3] = "Fourth"
set strSubanims[4] = "Fifth"
set strSubanims[5] = "Defend"
set strSubanims[6] = "Channel"
set strSubanims[7] = "Slam"
set strSubanims[8] = "Victory"
set strSubanims[9] = "Throw"
set strSubanims[10] = "Spin"
set strSubanims[11] = "Ready"
set strSubanims[12] = "Upgrade"
set strSubanims[13] = "Lumber"
set strSubanims[14] = "Gold"
set strSubanims[15] = "Work"
set strSubanims[16] = "Talk"
set strSubanims[17] = "Swim"
set strSubanims[18] = "Flesh"
set strSubanims[19] = "Entangle"
set strSubanims[20] = "ChainLightning"
set strSubanims[21] = "Rooted"
set strSubanims[22] = "EatTrea"
set strSubanims[23] = "Berserk"
set strSubanims[24] = "Spiked"
set strSubanims[25] = "Light"
set strSubanims[26] = "Moderate"
set strSubanims[27] = "Severe"
set strSubanims[28] = "Critical"
set strSubanims[29] = "Small"
set strSubanims[30] = "Medium"
set strSubanims[31] = "Large"
set strSubanims[32] = "AlternateEx"
set strSubanims[33] = "Looping"
set strSubanims[34] = "Wounded"
set strSubanims[35] = "Fast"
set strSubanims[36] = "Turn"
set strSubanims[37] = "Left"
set strSubanims[38] = "Right"
set strSubanims[39] = "Fire"
set strSubanims[40] = "One"
set strSubanims[41] = "Two"
set strSubanims[42] = "Three"
set strSubanims[43] = "Four"
set strSubanims[44] = "Five"
set strSubanims[45] = "Fill"
set strSubanims[46] = "Puke"
set strSubanims[47] = "Drain"
set strSubanims[48] = "Flail"
set strSubanims[49] = "Hit"
set strSubanims[50] = "Off"
set strSubanims[51] = "Complete"
// MULTIBOARD
set titleW = 0.09
set mtb = CreateMultiboard()
call MultiboardSetTitleText(mtb, "Properties")
call MultiboardSetRowCount(mtb, 11)
call MultiboardSetColumnCount(mtb, 2)
call MultiboardSetItemsStyle(mtb, true, false)
call MultiboardSetItemsWidth(mtb, 0.11)
// MDL Position XYZ
set mbi = MultiboardGetItem(mtb, 0, 0)
call MultiboardSetItemWidth(mbi, titleW)
call MultiboardSetItemValue(mbi, "Position:")
call MultiboardSetItemIcon(mbi, "ReplaceableTextures\\CommandButtons\\BTNForestTrollTrapper.blp")
call MultiboardSetItemStyle(mbi, true, true)
set mbi = MultiboardGetItem(mtb, 0, 1) // Value set in setup below
call SaveMultiboardItemHandle(htbMBIHandles, MBI_SFX, SFX_POSX, mbi)
// MDL Scale
set mbi = MultiboardGetItem(mtb, 1, 0)
call MultiboardSetItemWidth(mbi, titleW)
call MultiboardSetItemValue(mbi, "Scale:")
call MultiboardSetItemIcon(mbi, "ReplaceableTextures\\CommandButtons\\BTNForestTrollTrapper.blp")
call MultiboardSetItemStyle(mbi, true, true)
set mbi = MultiboardGetItem(mtb, 1, 1)
call MultiboardSetItemValue(mbi, "100.0%") // Default
call SaveMultiboardItemHandle(htbMBIHandles, MBI_SFX, SFX_SCALE, mbi)
// MDL Orientation Roll, Pitch, Yaw
set mbi = MultiboardGetItem(mtb, 2, 0)
call MultiboardSetItemWidth(mbi, titleW)
call MultiboardSetItemValue(mbi, "Orientation:")
call MultiboardSetItemIcon(mbi, "ReplaceableTextures\\CommandButtons\\BTNForestTrollTrapper.blp")
call MultiboardSetItemStyle(mbi, true, true)
set mbi = MultiboardGetItem(mtb, 2, 1)
call MultiboardSetItemValue(mbi, "160.0°, 0.0°, 0.0°") // Setup below
call SaveMultiboardItemHandle(htbMBIHandles, MBI_SFX, SFX_ROLL, mbi)
// MDL Alpha
set mbi = MultiboardGetItem(mtb, 3, 0)
call MultiboardSetItemWidth(mbi, titleW)
call MultiboardSetItemValue(mbi, "Alpha:")
call MultiboardSetItemIcon(mbi, "ReplaceableTextures\\CommandButtons\\BTNForestTrollTrapper.blp")
call MultiboardSetItemStyle(mbi, true, true)
set mbi = MultiboardGetItem(mtb, 3, 1)
call MultiboardSetItemValue(mbi, "100.0%") // Default
call SaveMultiboardItemHandle(htbMBIHandles, MBI_SFX, SFX_ALPHA, mbi)
// Animation
set mbi = MultiboardGetItem(mtb, 4, 0)
call MultiboardSetItemWidth(mbi, titleW+0.11)
call MultiboardSetItemValue(mbi, "Stand") // Default
call MultiboardSetItemIcon(mbi, "ReplaceableTextures\\CommandButtons\\BTNInvisibility.blp")
call MultiboardSetItemStyle(mbi, true, true)
call SaveMultiboardItemHandle(htbMBIHandles, MBI_SFX, MBI_ANIM, mbi)
set mbi = MultiboardGetItem(mtb, 4, 1)
call MultiboardSetItemWidth(mbi, 0)
// Anim Speed
set mbi = MultiboardGetItem(mtb, 5, 0)
call MultiboardSetItemWidth(mbi, titleW)
call MultiboardSetItemValue(mbi, "Speed:")
call MultiboardSetItemIcon(mbi, "ReplaceableTextures\\CommandButtons\\BTNInvisibility.blp")
call MultiboardSetItemStyle(mbi, true, true)
set mbi = MultiboardGetItem(mtb, 5, 1)
call MultiboardSetItemValue(mbi, "100%") // Default
call SaveMultiboardItemHandle(htbMBIHandles, MBI_SFX, SFX_SPEED, mbi)
set startLoc = GetPlayerStartLocation(plrViewer)
// Cam Position X, Y, Z
set mbi = MultiboardGetItem(mtb, 6, 0)
call MultiboardSetItemWidth(mbi, titleW)
call MultiboardSetItemValue(mbi, "Position:")
call MultiboardSetItemIcon(mbi, "ReplaceableTextures\\CommandButtons\\BTNCamera.blp")
call MultiboardSetItemStyle(mbi, true, true)
set mbi = MultiboardGetItem(mtb, 6, 1)
call MultiboardSetItemValue(mbi, R2S1(GetStartLocationX(startLoc))+", "+R2S1(GetStartLocationY(startLoc))+", 0.0") // Default game camera
call SaveMultiboardItemHandle(htbMBIHandles, MBI_CAM, CAM_POSX, mbi)
// Cam Target Distance
set mbi = MultiboardGetItem(mtb, 7, 0)
call MultiboardSetItemWidth(mbi, titleW)
call MultiboardSetItemValue(mbi, "Distance:")
call MultiboardSetItemIcon(mbi, "ReplaceableTextures\\CommandButtons\\BTNCamera.blp")
call MultiboardSetItemStyle(mbi, true, true)
set mbi = MultiboardGetItem(mtb, 7, 1)
call MultiboardSetItemValue(mbi, "1650.0") // Default game camera
call SaveMultiboardItemHandle(htbMBIHandles, MBI_CAM, CAM_DIST, mbi)
// Cam Orientation Rot, AoA, Roll
set mbi = MultiboardGetItem(mtb, 8, 0)
call MultiboardSetItemWidth(mbi, titleW)
call MultiboardSetItemValue(mbi, "Orientation:")
call MultiboardSetItemIcon(mbi, "ReplaceableTextures\\CommandButtons\\BTNCamera.blp")
call MultiboardSetItemStyle(mbi, true, true)
set mbi = MultiboardGetItem(mtb, 8, 1)
call MultiboardSetItemValue(mbi, "90.0°, 304.0°, 0.0°") // Default game camera
call SaveMultiboardItemHandle(htbMBIHandles, MBI_CAM, CAM_ROT, mbi)
// Cam Field of View
set mbi = MultiboardGetItem(mtb, 9, 0)
call MultiboardSetItemWidth(mbi, titleW)
call MultiboardSetItemValue(mbi, "Field of View:")
call MultiboardSetItemIcon(mbi, "ReplaceableTextures\\CommandButtons\\BTNCamera.blp")
call MultiboardSetItemStyle(mbi, true, true)
set mbi = MultiboardGetItem(mtb, 9, 1)
call MultiboardSetItemValue(mbi, "70.0°") // Default game camera
call SaveMultiboardItemHandle(htbMBIHandles, MBI_CAM, CAM_FOV, mbi)
// Cam Far Z
set mbi = MultiboardGetItem(mtb, 10, 0)
call MultiboardSetItemWidth(mbi, titleW)
call MultiboardSetItemValue(mbi, "Far Clipping:")
call MultiboardSetItemIcon(mbi, "ReplaceableTextures\\CommandButtons\\BTNCamera.blp")
call MultiboardSetItemStyle(mbi, true, true)
set mbi = MultiboardGetItem(mtb, 10, 1)
call MultiboardSetItemValue(mbi, "5000.0") // Default game camera
call SaveMultiboardItemHandle(htbMBIHandles, MBI_CAM, CAM_FARZ, mbi)
call MultiboardDisplay(mtb, true)
set mtb = null
set mbi = null
// CAM SETUP
call GetStoredCams()
call BlzSetUnitMaxMana(MVUnit, GetCamCount())
call CamAppliedCndAcn() // update MB and current cam (Mana)
// MODEL SETUP
call SetSfxField(SFX_POSX, GetCurrentCamField(CAM_POSX), SLNT_ADJ) // Start at cam target
call SetSfxField(SFX_POSY, GetCurrentCamField(CAM_POSY), SLNT_ADJ)
call UpdateMB(MBI_SFX, SFX_POSX) // Also updates POSY and HEIGHT
call SetSfxField(SFX_YAW, 160, SLNT_ADJ) // Already set in MB setup
call BlzSetUnitName(MVUnit, LoadSfx("units\\creeps\\ForestTrollTrapper\\ForestTrollTrapper.mdx"))
// ENVIRONMENT SETUP
call SetTimeOfDayScale(0)
call SetFloatGameState(GAME_STATE_TIME_OF_DAY, 12)
// TRIGGERS
// Model & Animation Commands
set trg = CreateTrigger()
call TriggerRegisterPlayerChatEvent(trg, plrViewer, "-load ", false)
call TriggerRegisterPlayerChatEvent(trg, plrViewer, "-anim ", false)
call TriggerRegisterPlayerChatEvent(trg, plrViewer, "-modelx ", false)
call TriggerRegisterPlayerChatEvent(trg, plrViewer, "-modely ", false)
call TriggerRegisterPlayerChatEvent(trg, plrViewer, "-modelz ", false)
call TriggerRegisterPlayerChatEvent(trg, plrViewer, "-scale ", false)
call TriggerRegisterPlayerChatEvent(trg, plrViewer, "-roll ", false)
call TriggerRegisterPlayerChatEvent(trg, plrViewer, "-pitch ", false)
call TriggerRegisterPlayerChatEvent(trg, plrViewer, "-yaw ", false)
call TriggerRegisterPlayerChatEvent(trg, plrViewer, "-alpha ", false)
call TriggerRegisterPlayerChatEvent(trg, plrViewer, "-color ", false)
call TriggerRegisterPlayerChatEvent(trg, plrViewer, "-pause", false)
call TriggerRegisterPlayerChatEvent(trg, plrViewer, "-speed ", false)
call TriggerRegisterPlayerChatEvent(trg, plrViewer, "-forceloop", false)
call TriggerAddCondition(trg, function SfxCmdCndAcn)
// Camera Commands
set trg = CreateTrigger()
call TriggerRegisterPlayerChatEvent(trg, plrViewer, "-cam ", false)
call TriggerRegisterPlayerChatEvent(trg, plrViewer, "-camx ", false)
call TriggerRegisterPlayerChatEvent(trg, plrViewer, "-camy ", false)
call TriggerRegisterPlayerChatEvent(trg, plrViewer, "-camz ", false)
call TriggerRegisterPlayerChatEvent(trg, plrViewer, "-distance ", false)
call TriggerRegisterPlayerChatEvent(trg, plrViewer, "-rotation ", false)
call TriggerRegisterPlayerChatEvent(trg, plrViewer, "-aoa ", false)
call TriggerRegisterPlayerChatEvent(trg, plrViewer, "-camroll ", false)
call TriggerRegisterPlayerChatEvent(trg, plrViewer, "-fov ", false)
call TriggerRegisterPlayerChatEvent(trg, plrViewer, "-farz ", false)
call TriggerAddCondition(trg, function CamCmdCndAcn)
// Environment Commands
set trg = CreateTrigger()
call TriggerRegisterPlayerChatEvent(trg, plrViewer, "-tod ", false)
call TriggerRegisterPlayerChatEvent(trg, plrViewer, "-tods ", false)
call TriggerAddCondition(trg, function EnvironmentCmdCndAcn)
// Force Loop
call DisableTrigger(trgForceLoop)
call TriggerRegisterTimerExpireEvent(trgForceLoop, tmrForceLoop)
call TriggerAddCondition(trgForceLoop, function AutoloopCndAcn)
// CameraLib triggers
call EnableTrigger(trgCamLock) // Enable camera lock
set trgCamApplied = CreateTrigger() // Camera Applied
call TriggerAddCondition(trgCamApplied, function CamAppliedCndAcn)
set trgCamSaved = CreateTrigger() // Camera Saved
call TriggerAddCondition(trgCamSaved, function CamSaveDeleteCndAcn)
set trgCamDeleted = CreateTrigger() // Camera Deleted
call TriggerAddCondition(trgCamDeleted, function CamSaveDeleteCndAcn)
// Button Control
set trg = CreateTrigger() // Buttons
call TriggerRegisterUnitEvent(trg, MVUnit, EVENT_UNIT_SPELL_CAST)
call TriggerAddCondition(trg, function ButtonControlCndAcn)
set trg = CreateTrigger() // Close menu
call TriggerRegisterPlayerEvent(trg, plrViewer, EVENT_PLAYER_END_CINEMATIC)
call TriggerAddCondition(trg, function EscCtrlsCndAcn)
set trg = CreateTrigger() // Toggles & Mouse mode switch
call TriggerRegisterUnitEvent(trg, MVUnit, EVENT_UNIT_ISSUED_ORDER)
call TriggerAddCondition(trg, function ButtonTogglesCndAcn)
set trg = null
// Mouse Control
call EnableTrigger(trgCamMouseBtn) // Enable camera control
call TriggerAddCondition(trgCamMouseBtn, function CamMouseBtnCndAcn)
call TriggerAddCondition(trgSfxMouseBtn, function SfxMouseBtnCndAcn)
// QUESTS
set infoQuests = CreateQuest()
call QuestSetTitle(infoQuests, "Model")
call QuestSetIconPath(infoQuests, "ReplaceableTextures\\CommandButtons\\BTNForestTrollTrapper.blp")
call QuestSetRequired(infoQuests, true)
call QuestSetDiscovered(infoQuests, true)
call QuestSetDescription(infoQuests, "-load [model path, no extension]
-modelx ["+R2S0(SM_minX)+" - "+R2S0(SM_maxX)+"] (position x)
-modely ["+R2S0(SM_minY)+" - "+R2S0(SM_maxY)+"] (position y)
-modelz [-1000 - 1000] (position z)
-scale [0% - 1000%]
-yaw [x°] (xy rotation)
-pitch [x°] (xz rotation)
-roll [x°] (yz rotation)
-alpha [0% - 100%]
-color [1 - 25] (player number)")
set infoQuests = CreateQuest()
call QuestSetTitle(infoQuests, "Animation")
call QuestSetIconPath(infoQuests, "ReplaceableTextures\\CommandButtons\\BTNInvisibility.blp")
call QuestSetRequired(infoQuests, false)
call QuestSetDiscovered(infoQuests, true)
call QuestSetDescription(infoQuests, "-anim [name] [subanim name 1] [subanim name 2] [...]
-anim add [subanim 1] [subanim 2] [...]
-anim remove [subanim 1] [subanim 2] [...]
-pause (pause/resume)
-speed [0% - 1000%]
-forceloop (toggle force loop)
-forceloop [0.1s+] (set force loop duration)")
set infoQuests = CreateQuest()
call QuestSetTitle(infoQuests, "Animation Names")
call QuestSetIconPath(infoQuests, "ReplaceableTextures\\CommandButtons\\BTNInvisibility.blp")
call QuestSetRequired(infoQuests, false)
call QuestSetDiscovered(infoQuests, true)
call QuestSetDescription(infoQuests, "stand | birth | death | decay | dissipate | walk | attack | morph | sleep | spell | portrait")
set infoQuests = CreateQuest()
call QuestSetTitle(infoQuests, "Subanimation Names")
call QuestSetIconPath(infoQuests, "ReplaceableTextures\\CommandButtons\\BTNInvisibility.blp")
call QuestSetRequired(infoQuests, false)
call QuestSetDiscovered(infoQuests, true)
call QuestSetDescription(infoQuests, "first | second | third | fourth | fifth | defend | channel | slam | victory | throw | spin | ready | upgrade | lumber | gold | work | talk | swim | flesh | entangle | chainlightning | rooted | eattree | berserk | spiked | light | moderate | severe | critical | small | medium | large | alternateex | looping | wounded | fast | turn | left | right | fire | one | two | three | four | five | fill | puke | drain | flail | hit | off | complete")
set infoQuests = CreateQuest()
call QuestSetTitle(infoQuests, "Camera")
call QuestSetIconPath(infoQuests, "ReplaceableTextures\\CommandButtons\\BTNCamera.blp")
call QuestSetRequired(infoQuests, true)
call QuestSetDiscovered(infoQuests, true)
call QuestSetDescription(infoQuests, "-cam [cam number] (apply camera setup)
-cam save (save current camera)
-cam delete [cam number] (delete camera setup)
-camx ["+R2S0(SM_minX)+" - "+R2S0(SM_maxX)+"] (position x)
-camy ["+R2S0(SM_minY)+" - "+R2S0(SM_maxY)+"] (position y)
-camz [0 - 4096] (position z/height offset)
-distance [100 - 100000] (target distance)
-rotation [x°] (xy rotation)
-aoa [205° - 335°] (xz rotation/angle of attack)
-camroll [x°] (yz rotation)
-fov [20° - 120°] (field of view)
-farz [101 - 10000] (far clipping)")
set infoQuests = CreateQuest()
call QuestSetTitle(infoQuests, "Environment")
call QuestSetIconPath(infoQuests, "ReplaceableTextures\\CommandButtons\\BTNNightElfBuild.blp")
call QuestSetRequired(infoQuests, true)
call QuestSetDiscovered(infoQuests, true)
call QuestSetDescription(infoQuests, "-tod [hh:mm] (time of day)
-tods [0%+] (time of day speed)")
set infoQuests = null
call TriggerSleepAction(0.75)
call FlashQuestDialogButton()
endfunction
//===============================================================================
//===============================================================================
endlibrary
/*
v1.2.2b
- Minimum force loop duration now also enforced with button controls (lacks error sound for now)
v1.2.2a (fix)
- Fixed Delete Subanimation appearing in main menu after adding a subanimation
- Fixed Force Loop duration tooltip update
- Increased minimum force loop duration to 0.1s
- Fixed model Position Z tooltip (Height -> Position Z)
v1.2.2
- Switched model yaw/roll following recent patch
- Current animation is now included in animation selection dialog
- Somewhat improved mouse controls (?)
- DialogPages updated to v1.0.2a
- ScreenMouse updated to 1.1.2
- Misc
- Camera Library v1.0.2:
-- Adding default cams now only adds those that don't already exist
-- Removed "Add defaults" from Delete cam dialog
-- Removed "Add defaults" from Apply dialog if all defaults already exist
- SFX Library v1.0.2:
-- Added field: Position Z (now used instead of Height in SetSfxPos)
-- Mouse controls now sets Yaw instead of Roll following recent patch
v1.2.1
- Added Animation Controls interface
- Added chat commands: "-anim add", "-anim remove", "-pause", "-forceloop"
- Team color dialog text is now colored
- Armor card now displays open button menu
- Customized some interface text (e.g. Quests -> Commands)
- Implemented ESC hotkey for Back button as was already shown in tooltip
- Removed autocast hotkeys because they're useless here
- Now creating dialogs with DialogPages system
- Updated ScreenMouse to v1.1.1
- Misc
- Camera Library v1.0.1:
-- Now creating dialogs with DialogPages system
-- Misc
- SFX Library v1.0.1:
-- Added ToggleSfxSubanim(), PauseSfxAnim(), IsSfxAnimPaused() and GetSfxAnimStr()
-- Misc
v1.2.0
- General:
-- System split up into several libraries (ScreenMouse, IMVCommon, Camera Library, Special Effect Library)
--- Future updates will add support for multiple players/effects and add configuration and documentation
-- Multiboard reorganised and model properties added
-- Replaced R2SP with R2S0 (IMVCommon) and R2S1 (ModelViewer), which make use of native R2SW
-- Replaced Farm ("Model Viewer" unit) with camera prop, which has model's color
-- Misc
- Model:
-- Added model alpha
-- Added full model controls (chat commands & interface)
-- Color numbers changed to 1-25 from 0-28
-- Showing color player id as HP
-- Showing model name as selected unit's name
-- Fixed a few bugs with model mouse control
- Camera:
-- Now comparing to all camera setups before saving current
-- Applied cam hidden from Apply Cam dialog if not changed
-- Showing cam number and amount as mana
-- Added second page to controls with FoV (moved) and FarZ (added)
-- Numbering now starts at 1
v1.1.3
- Improved Mouse controls
- Reduced range of Angle of Attack
- Several icons replaced with stock icons to reduce filesize
- Farm is now under terrain
- Misc
v1.1.2
- Added camera setup management (apply/save/delete - gamecache)
- Moved model and cam presets to center of map
- Saved 60kb+ by compressing icons ^_^
- Fixed a bug where 0°/360° was regarded as an error for a max of 360° (AoA)
v1.1.1
- Added full camera controls (buttons and chat commands)
- Added multiboard with camera properties
- Disabled boundary tinting and music
- Fixed duplicate "-roll" command
- Misc improvements
v1.1.0
- Added basic mouse controls (+ passive ability with instructions)
- "-timescale" command changed to "-speed"
- Yaw, pitch, roll now in degrees
- Time of day now in hh:mm (24h) format
- New camera presets (cam 0 is the same)
- Removed cam lock/unlock
- Fixed not being able to set model roll
- Replaced long AnimType and SubAnimType getter functions with a hashtable
- Misc improvements/tweaks/optimizations
*/