ff_u_itm_appear
Universal dye.
On login, gives the universal dye (ff_u_itm_appear) to a player character
that never received it. A persistent variable on the character remembers the
gift, so a dye that was sold, dropped or destroyed is not given again.
The gift is delayed so that it happens after other scripts that replace the inventory of new characters.
Activating the dye opens the appearance editor where the player character stands, with the helmet (colors only) and armor sections. No area is created, no copy is spawned and the player character does not move: it is paralyzed in place and its own equipped items are edited. Cancelling, switching section or closing the editor restores the items not confirmed. The dye only works in an area where resting is allowed.
While the editor is open, a persistent variable is set on the character. If the player logs out with the editor open, the character is freed from the paralysis on the next login.
Variables
ENABLE__FF_U_ITM_APPEARANCE: (string) (opt-out) Set to "N" on module
to disable the unit.
Source code
// @code
#include "ff_i_core"
#include "x3_inc_string"
const string ENABLE__FF_U_ITM_APPEARANCE = "ENABLE__FF_U_ITM_APPEARANCE";
const string FF_U_ITM_APPEARANCE = "FF_U_ITM_APPEARANCE";
const string FF_U_ITM_APPEARANCE_EDITOR = "FF_U_ITM_APPEARANCE_EDITOR";
const string DYE_TAG = "ff_u_itm_appear";
const string DYE_RESREF = "ff_u_itm_appear";
// Set on the PC while the editor is open.
const string APP_EDITOR_OPEN = "APP_EDITOR_OPEN";
// Prefix of the PC locals holding, per inventory slot, the item as it was
// before the editor changed it.
const string APP_BACKUP = "APP_BACKUP_";
// NUI event types
const string APP_EVENT_CLICK = "click";
const string APP_EVENT_WATCH = "watch";
// Window binds
const string APP_BIND_GEOMETRY = "geometry";
const string APP_BIND_RESIZABLE = "resizable";
const string APP_BIND_CLOSABLE = "closable";
const string APP_BIND_TRANSPARENT = "transparent";
const string APP_BIND_BORDER = "border";
// Window bind holding the ID of the encouraged color button.
const string APP_BIND_ENCOURAGED = "NUI_DATA_ENCOURAGED";
// -----------------------------------------------------------------------------
// Utilities
// -----------------------------------------------------------------------------
//! @brief Scale fVal down with the GUI scale of oPC, capped at 150%.
float AppScale(object oPC, float fVal)
{
float fScale = GetPlayerDeviceProperty(oPC, PLAYER_DEVICE_PROPERTY_GUI_SCALE) / 100.0;
if (fScale > 1.5)
fScale = 1.5;
return fVal / fScale;
}
//! @brief Paralyze oPC while the editor is open.
void AppParalyze(object oPC)
{
ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectCutsceneParalyze(), oPC);
}
//! @brief Remove every cutscene paralysis effect from oPC.
void AppUnparalyze(object oPC)
{
effect eLoop = GetFirstEffect(oPC);
while (GetIsEffectValid(eLoop))
{
if (GetEffectType(eLoop) == EFFECT_TYPE_CUTSCENE_PARALYZE)
RemoveEffect(oPC, eLoop);
eLoop = GetNextEffect(oPC);
}
}
//! @brief Return the label of entry nIdx of the combo entries bound to sBind.
string AppGetComboLabel(object oPC, int nToken, string sBind, int nIdx)
{
json jEntry = JsonArrayGet(NuiGetBind(oPC, nToken, sBind), nIdx);
return JsonGetString(JsonArrayGet(jEntry, 0));
}
// -----------------------------------------------------------------------------
// Editor mode
// -----------------------------------------------------------------------------
//! @brief Equip oItem in nSlot of oPC. The PC is paralyzed, so the equip
//! bypasses the action queue.
void AppEquip(object oPC, object oItem, int nSlot)
{
NWNX_Creature_RunEquip(oPC, oItem, nSlot);
}
//! @brief Return the camera direction that faces oPC.
float AppGetCameraDirection(object oPC)
{
float fDirection = GetFacing(oPC) + 180.0;
if (fDirection >= 360.0)
fDirection -= 360.0;
return fDirection;
}
//! @brief Disable or enable the GUI panels the player must not use while editing.
void AppDisableGuiPanels(object oPC, int bDisable)
{
SetGuiPanelDisabled(oPC, GUI_PANEL_MINIMAP, bDisable);
SetGuiPanelDisabled(oPC, GUI_PANEL_COMPASS, bDisable);
SetGuiPanelDisabled(oPC, GUI_PANEL_INVENTORY, bDisable);
SetGuiPanelDisabled(oPC, GUI_PANEL_PLAYERLIST, bDisable);
SetGuiPanelDisabled(oPC, GUI_PANEL_JOURNAL, bDisable);
SetGuiPanelDisabled(oPC, GUI_PANEL_SPELLBOOK, bDisable);
SetGuiPanelDisabled(oPC, GUI_PANEL_CHARACTERSHEET, bDisable);
SetGuiPanelDisabled(oPC, GUI_PANEL_GOLD_INVENTORY, bDisable);
SetGuiPanelDisabled(oPC, GUI_PANEL_GOLD_BARTER, bDisable);
SetGuiPanelDisabled(oPC, GUI_PANEL_RADIAL_TRIGGER, bDisable);
SetGuiPanelDisabled(oPC, GUI_PANEL_RADIAL_CREATURE, bDisable);
SetGuiPanelDisabled(oPC, GUI_PANEL_RADIAL_ITEM, bDisable);
SetGuiPanelDisabled(oPC, GUI_PANEL_RADIAL_PLACEABLE, bDisable);
SetGuiPanelDisabled(oPC, GUI_PANEL_RADIAL_DOOR, bDisable);
SetGuiPanelDisabled(oPC, GUI_PANEL_RADIAL_QUICKBAR, bDisable);
}
//! @brief Enter editor mode: oPC is paralyzed where it stands and its camera is saved.
void AppEnterEditor(object oPC)
{
SetLocalInt(oPC, APP_EDITOR_OPEN, TRUE);
NWNX_Object_SetInt(oPC, FF_U_ITM_APPEARANCE_EDITOR, 1, TRUE);
AppDisableGuiPanels(oPC, TRUE);
AssignCommand(oPC, StoreCameraFacing());
AppParalyze(oPC);
}
//! @brief Leave editor mode: revert unconfirmed changes, free oPC and restore its camera.
void AppLeaveEditor(object oPC);
// -----------------------------------------------------------------------------
// Constants
const string APP_ACTIVE_WINDOW = "APP_ACTIVE_WINDOW";
const string APP_GEOMETRY_WINDOW = "APP_GEOMETRY_WINDOW";
const string APP_PREV_COLOR_BTN = "APP_PREV_COLOR_BTN";
const string APP_COLOR_TE = "APP_COLOR_TE";
const string APP_NEXT_COLOR_BTN = "APP_NEXT_COLOR_BTN";
const string APP_ARROW_PREV_BTN = "cc_arrow_l_btn";
const string APP_ARROW_NEXT_BTN = "cc_arrow_r_btn";
const string APP_RANDOMIZE_BTN = "APP_RANDOMIZE_BTN";
const string APP_CONFIRM_BTN = "APP_CONFIRM_BTN";
const string APP_CANCEL_BTN = "APP_CANCEL_BTN";
const string APP_BTN = "APP_BTN_";
const string APP_COLOR_BTN = "APP_COLOR_BTN_";
const string APP_COLOR_BTN_ENCOURAGED = "_ENCOURAGED";
const string APP_COLOR_BTN_ACTIVE = "APP_COLOR_BTN_ACTIVE";
const float APP_BACKGROUND_IMAGE_WIDTH = 542.0;
const float APP_UPPER_SPACER_HEIGHT = 50.0;
const float APP_LEFT_SPACER_WIDTH = 33.0;
const float APP_COLOR_BTN_WIDTH = 25.0;
const float APP_COLOR_BTN_HEIGHT = 25.0;
const float APP_BTN_WIDTH = 40.0;
const float APP_BTN_HEIGHT = 40.0;
const float APP_BOTTOM_BTN_WIDTH = 50.0;
const float APP_BOTTOM_BTN_HEIGHT = 50.0;
const float APP_OFFSET = 10.0;
const string APP_COLOR_BTN_PREFIX = "APP_COLOR_BTN_PREFIX_";
const int APP_MAX_COLUMNS = 11;
const int APP_MAX_ROWS = 16;
const string APP_RIGHT_PANEL_WINDOW = "APP_RIGHT_PANEL_WINDOW";
const string APP_HELMET_WINDOW = "APP_HELMET_WINDOW";
const string APP_ARMOR_WINDOW = "APP_ARMOR_WINDOW";
const float APP_IMAGE_WIDTH = 85.0;
const float APP_IMAGE_HEIGHT = 85.0;
const float APP_RIGHT_PANEL_IMAGE_WIDTH = 180.0;
const string APP_RIGHT_CLOSE_BTN = "APP_RIGHT_CLOSE_BTN";
const string ARMOR_PART = "ARMOR_PART_";
const string ARMOR_PART_ENCOURAGED = "ARMOR_PART_ENCOURAGED_";
const string ARMOR_PART_ENCOURAGED_CURRENT = "ARMOR_PART_ENCOURAGED_CURRENT";
const string ARMOR_ENTRIES = "ARMOR_ENTRIES";
const string ARMOR_ID = "ARMOR_ID";
const string ARMOR_ELEMENTS_ID = "ARMOR_ELEMENTS_ID";
const string ARMOR_ELEMENTS_ENTRIES = "ARMOR_ELEMENTS_ENTRIES";
const string APP_PREV_ARMOR_PART = "APP_PREV_ARMOR_PART";
const string APP_NEXT_ARMOR_PART = "APP_NEXT_ARMOR_PART";
const string APP_PREV_ELEMENT = "APP_PREV_ELEMENT";
const string APP_NEXT_ELEMENT = "APP_NEXT_ELEMENT";
const string APP_ARMOR_PART_IMAGE = "APP_ARMOR_PART_IMAGE";
const string APP_ARMOR_PART_IMAGE_2 = "APP_ARMOR_PART_IMAGE_2";
const string APP_ARMOR_SPECIFIC_COLOR = "APP_ARMOR_SPECIFIC_COLOR";
const string APP_ARMOR_CLEAR_BTN = "APP_ARMOR_CLEAR_BTN";
float APP_ARMOR_BUTTON_WIDTH = 20.0;
float APP_ARMOR_BUTTON_HEIGHT = 25.0;
float APP_ARMOR_IMAGE_WIDTH = 175.0;
float APP_ARMOR_IMAGE_HEIGHT = 245.0;
float APP_ARMOR_COMBO_WIDTH = 150.0;
// -----------------------------------------------------------------------------
// Equipment
int HasEquipedArmor(object oPC)
{
object oItem = GetItemInSlot(INVENTORY_SLOT_CHEST, oPC);
return GetIsObjectValid(oItem);
}
int HasEquipedHelmet(object oPC)
{
object oItem = GetItemInSlot(INVENTORY_SLOT_HEAD, oPC);
return GetIsObjectValid(oItem);
}
// -----------------------------------------------------------------------------
// Camera
float GetCameraHeightForBody(object oPC)
{
int nRace = GetRacialType(oPC);
float fHeight;
switch(nRace)
{
case RACIAL_TYPE_DWARF:
fHeight = 0.8;
break;
case RACIAL_TYPE_ELF:
fHeight = 0.8;
break;
case RACIAL_TYPE_GNOME:
fHeight = 0.8;
break;
case RACIAL_TYPE_HALFLING:
fHeight = 0.8;
break;
case RACIAL_TYPE_HALFELF:
case RACIAL_TYPE_HUMAN:
fHeight = 0.8;
break;
case RACIAL_TYPE_HALFORC:
fHeight = 0.8;
break;
}
return fHeight;
}
float GetCameraDistanceForBody(object oPC)
{
int nRace = GetRacialType(oPC);
float fDistance;
switch(nRace)
{
case RACIAL_TYPE_DWARF:
fDistance = 3.0;
break;
case RACIAL_TYPE_ELF:
fDistance = 3.0;
break;
case RACIAL_TYPE_GNOME:
fDistance = 3.0;
break;
case RACIAL_TYPE_HALFLING:
fDistance = 3.0;
break;
case RACIAL_TYPE_HALFELF:
case RACIAL_TYPE_HUMAN:
fDistance = 3.0;
break;
case RACIAL_TYPE_HALFORC:
fDistance = 3.0;
break;
}
return fDistance;
}
float GetCameraHeightForFace(object oPC)
{
int nRace = GetRacialType(oPC);
float fHeight;
switch(nRace)
{
case RACIAL_TYPE_DWARF:
fHeight = 1.35;
break;
case RACIAL_TYPE_ELF:
fHeight = 1.6;
break;
case RACIAL_TYPE_GNOME:
fHeight = 1.25;
break;
case RACIAL_TYPE_HALFLING:
fHeight = 1.2;
break;
case RACIAL_TYPE_HALFELF:
case RACIAL_TYPE_HUMAN:
fHeight = 1.8;
break;
case RACIAL_TYPE_HALFORC:
fHeight = 2.0;
break;
}
return fHeight;
}
float GetCameraDistanceForFace(object oPC)
{
int nRace = GetRacialType(oPC);
float fDistance;
switch(nRace)
{
case RACIAL_TYPE_DWARF:
fDistance = 1.0;
break;
case RACIAL_TYPE_ELF:
fDistance = 1.0;
break;
case RACIAL_TYPE_GNOME:
fDistance = 1.0;
break;
case RACIAL_TYPE_HALFLING:
fDistance = 1.0;
break;
case RACIAL_TYPE_HALFELF:
case RACIAL_TYPE_HUMAN:
fDistance = 1.0;
break;
case RACIAL_TYPE_HALFORC:
fDistance = 1.0;
break;
}
return fDistance;
}
void SetCameraBody(object oPC)
{
float fScale = GetLocalFloat(oPC, "SCALE");
fScale = fScale == 0.0 ? 1.0 : fScale;
float fDistance = GetCameraDistanceForBody(oPC) * fScale;
float fHeight = GetCameraHeightForBody(oPC) * fScale;
AssignCommand(oPC,
SetCameraFacing(
AppGetCameraDirection(oPC),
fDistance,
90.0,
CAMERA_TRANSITION_TYPE_SNAP));
SetCameraHeight(oPC, fHeight);
//DelayCommand(1.0, LockCamera(oPC));
}
void SetCameraFace(object oPC)
{
float fScale = GetLocalFloat(oPC, "SCALE");
fScale = fScale == 0.0 ? 1.0 : fScale;
float fDistance = GetCameraDistanceForFace(oPC) * fScale;
float fHeight = GetCameraHeightForFace(oPC) * fScale;
AssignCommand(oPC,
SetCameraFacing(
AppGetCameraDirection(oPC),
fDistance,
90.0,
CAMERA_TRANSITION_TYPE_SNAP));
SetCameraHeight(oPC, fHeight);
}
// -----------------------------------------------------------------------------
// NUI
void AppDestroyActiveWindow(object oPC)
{
int nToken = GetLocalInt(oPC, APP_ACTIVE_WINDOW);
if(nToken > 0)
{
NuiDestroy(oPC, nToken);
SetLocalInt(oPC, APP_ACTIVE_WINDOW, 0);
}
}
void AppSetActiveWindow(object oPC, int nToken)
{
SetLocalInt(oPC, APP_ACTIVE_WINDOW, nToken);
}
void AppSetGeometryWindow(object oPC, json jGeometry)
{
SetLocalJson(oPC, APP_GEOMETRY_WINDOW, jGeometry);
}
void AppCreateGeometryWindow(object oPC, float fRightPanelX)
{
int nDeviceHeigt = GetPlayerDeviceProperty(oPC, PLAYER_DEVICE_PROPERTY_GUI_HEIGHT);
float fWindowWidth = APP_BACKGROUND_IMAGE_WIDTH + APP_OFFSET;
float fWindowHeight = nDeviceHeigt + APP_OFFSET;
json jGeometry = NuiRect(
fRightPanelX - APP_BACKGROUND_IMAGE_WIDTH + 3.0,
0.0,
AppScale(oPC, fWindowWidth),
AppScale(oPC, fWindowHeight));
AppSetGeometryWindow(oPC, jGeometry);
}
json AppGetGeometryWindow(object oPC)
{
return GetLocalJson(oPC, APP_GEOMETRY_WINDOW);
}
void AppOffColorEncouraged(object oPC, int nToken)
{
string sBtnId = JsonGetString(NuiGetBind(oPC, nToken, APP_BIND_ENCOURAGED));
if(sBtnId != "")
{
NuiSetBind(oPC, nToken, sBtnId, JsonBool(FALSE));
NuiSetBind(oPC, nToken, APP_BIND_ENCOURAGED, JsonString(""));
}
}
void AppOnColorEncouraged(
object oPC,
int nToken,
string sBtnId)
{
NuiSetBind(oPC, nToken, sBtnId, JsonBool(TRUE));
NuiSetBind(oPC, nToken, APP_BIND_ENCOURAGED, JsonString(sBtnId));
}
int AppValidateColor(int nColor)
{
if(nColor == 255)
{
return nColor;
}
if(nColor < 0)
{
nColor = 175;
}
else if(nColor > 175)
{
nColor = 0;
}
return nColor;
}
//! @brief Set the foreground color of the current NUI builder node.
void AppSetForegroundColor()
{
// NUI_SetForegroundColor(NuiColor(168, 127, 0));
NUI_SetForegroundColor(NuiColor(255, 255, 255));
}
//! @brief Add a spacer of fixed width.
void AppAddSpacerWidth(float fWidth)
{
NUI_StartElement(NuiSpacer());
NUI_SetWidth(fWidth);
NUI_End();
}
//! @brief Add a spacer of fixed height.
void AppAddSpacerHeight(float fHeight)
{
NUI_StartElement(NuiSpacer());
NUI_SetHeight(fHeight);
NUI_End();
}
void AppSetColorNui(
object oPC,
int nToken,
int nColor,
int nColorChannel)
{
NuiSetBindWatch(oPC, nToken, APP_COLOR_TE, FALSE);
NuiSetBind(oPC, nToken, APP_COLOR_TE, JsonString(IntToString(nColor)));
NuiSetBindWatch(oPC, nToken, APP_COLOR_TE, TRUE);
AppOffColorEncouraged(oPC, nToken);
AppOnColorEncouraged(oPC, nToken, APP_BTN + IntToString(nColor));
}
string AppGetColorPickerButtonBind(int nId)
{
return APP_COLOR_BTN + IntToString(nId);
}
string AppGetColorPickerButtonEncouragedBind(int nId)
{
return AppGetColorPickerButtonBind(nId) + APP_COLOR_BTN_ENCOURAGED;
}
void AppAddColorPickerButton(
object oPC,
int nId,
string sTooltip)
{
string sBind = AppGetColorPickerButtonBind(nId);
NUI_StartElement(NuiButtonImage(NuiBind(sBind)));
NUI_SetId(sBind);
NUI_SetTooltip(JsonString(sTooltip));
NUI_SetWidth(AppScale(oPC, 40.0));
NUI_SetHeight(AppScale(oPC, 40.0));
NUI_SetEncouraged(NuiBind(AppGetColorPickerButtonEncouragedBind(nId)));
AppSetForegroundColor();
NUI_End();
}
void AppSetColorPickerButtonEncouraged(
object oPC,
int nToken,
int nButtonCount,
string sBindActive,
int nStartId = 0)
{
int nEndId = nStartId + nButtonCount;
int i;
for(i = nStartId; i < nEndId; i++)
{
string sBind = AppGetColorPickerButtonBind(i);
if(sBind == sBindActive)
{
NuiSetBind(oPC, nToken,
AppGetColorPickerButtonEncouragedBind(i), JsonBool(TRUE));
NuiSetBind(oPC, nToken, APP_COLOR_BTN_ACTIVE, JsonInt(i));
}
else
{
NuiSetBind(oPC, nToken,
AppGetColorPickerButtonEncouragedBind(i), JsonBool(FALSE));
}
}
}
void FeedAppColorTemplate(
object oPC,
int nToken,
string sInitColorBtnPrefix)
{
int nMax = APP_MAX_COLUMNS * APP_MAX_ROWS;
int i;
for(i = 0; i < nMax; i++)
{
string sId = IntToString(i);
string sBind = APP_COLOR_BTN_PREFIX + sId;
NuiSetBind(oPC, nToken, sBind, JsonString(sInitColorBtnPrefix + sId));
}
}
void AddAppColorTemplateTopSpacer(float fHeight)
{
NUI_StartRow();
AppAddSpacerHeight(fHeight);
NUI_End();
}
void AddAppColorTemplateLabelName(object oPC, string sWindowNameLabel)
{
NUI_StartRow();
NUI_StartElement(NuiLabel(
JsonString(sWindowNameLabel),
JsonInt(NUI_HALIGN_CENTER),
JsonInt(NUI_VALIGN_MIDDLE)));
NUI_SetHeight(AppScale(oPC, 30.0));
AppSetForegroundColor();
NUI_End();
NUI_End();
}
void AddAppColorTemplateColorPicker(object oPC)
{
int i,j;
float fScaleGui = GetPlayerDeviceProperty(oPC, PLAYER_DEVICE_PROPERTY_GUI_SCALE) / 100.0;
float fButtonSpace = 11 * fScaleGui;
float fButtonWidthScaled = AppScale(oPC, APP_COLOR_BTN_WIDTH);
float fButtonHeightScaled = AppScale(oPC, APP_COLOR_BTN_HEIGHT);
float fHeight = APP_MAX_COLUMNS * (fButtonHeightScaled + fButtonSpace);
NUI_StartGroup(FALSE, NUI_SCROLLBARS_NONE);
NUI_SetHeight(AppScale(oPC, fHeight));
NUI_StartRow();
AppAddSpacerWidth(AppScale(oPC, APP_LEFT_SPACER_WIDTH));
NUI_StartColumn();
for(i = 0; i < APP_MAX_COLUMNS; i++)
{
NUI_StartRow();
for(j = 0; j < APP_MAX_ROWS; j++)
{
string sId = IntToString(j + i * 16);
string sBtnId = APP_BTN + sId;
NUI_StartElement(NuiButtonImage(NuiBind(APP_COLOR_BTN_PREFIX + sId)));
NUI_SetId(sBtnId);
NUI_SetTooltip(JsonString(sId));
NUI_SetEncouraged(NuiBind(sBtnId));
NUI_SetWidth(fButtonWidthScaled);
NUI_SetHeight(fButtonHeightScaled);
AppSetForegroundColor();
NUI_End();
}
NUI_End();
}
NUI_End();
NUI_AddSpacer();
NUI_End();
NUI_End();
}
void AddAppColorTemplateColorChooser(object oPC)
{
float fButtonWidthScaled = AppScale(oPC, APP_BTN_WIDTH);
float fButtonHeightScaled = AppScale(oPC, APP_BTN_HEIGHT);
NUI_StartRow();
NUI_AddSpacer();
NUI_StartElement(NuiButtonImage(JsonString(APP_ARROW_PREV_BTN)));
NUI_SetId(APP_PREV_COLOR_BTN);
NUI_SetTooltip(JsonString("Previous color"));
NUI_SetDimensions(fButtonWidthScaled, fButtonHeightScaled);
NUI_End();
NUI_StartElement(NuiTextEdit(
JsonString(""),
NuiBind(APP_COLOR_TE),
3,
FALSE));
NUI_SetTooltip(JsonString("Color"));
AppSetForegroundColor();
NUI_SetDimensions(fButtonWidthScaled, fButtonHeightScaled);
NUI_End();
NUI_StartElement(NuiButtonImage(JsonString(APP_ARROW_NEXT_BTN)));
NUI_SetId(APP_NEXT_COLOR_BTN);
NUI_SetTooltip(JsonString("Next color"));
NUI_SetDimensions(fButtonWidthScaled, fButtonHeightScaled);
NUI_End();
NUI_AddSpacer();
NUI_End();
}
void AddAppColorTemplateButtonPanel(object oPC)
{
float fButtonWidthScaled = AppScale(oPC, APP_BOTTOM_BTN_WIDTH);
float fButtonHeightScaled = AppScale(oPC, APP_BOTTOM_BTN_HEIGHT);
NUI_StartRow();
NUI_AddSpacer();
NUI_StartElement(NuiButtonImage(JsonString("app_confirm")));
NUI_SetTooltip(JsonString("Confirm"));
NUI_SetId(APP_CONFIRM_BTN);
NUI_SetDimensions(fButtonWidthScaled, fButtonHeightScaled);
NUI_End();
NUI_AddSpacer();
NUI_StartElement(NuiButtonImage(JsonString("custom_close_nui")));
NUI_SetTooltip(JsonString("Cancel"));
NUI_SetId(APP_CANCEL_BTN);
NUI_SetDimensions(fButtonWidthScaled, fButtonHeightScaled);
NUI_End();
NUI_AddSpacer();
NUI_End();
}
//! @brief Start a window whose geometry, resizable, closable, transparent and
//! border flags are binds, set after NuiCreate().
void AppInitializeWindow()
{
NUI_InitializeWindow(NuiBind(APP_BIND_GEOMETRY));
NUI_SetWindowTitle(JsonNull());
NUI_SetWindowResizable(NuiBind(APP_BIND_RESIZABLE));
NUI_SetWindowCollapsed(JsonBool(FALSE));
NUI_SetWindowClosable(NuiBind(APP_BIND_CLOSABLE));
NUI_SetWindowTransparent(NuiBind(APP_BIND_TRANSPARENT));
NUI_SetWindowBorder(NuiBind(APP_BIND_BORDER));
}
//! @brief Start a color template window: background image, top spacer and label.
//! The root column is left open: add the section elements and the color
//! picker, then call AppFinishColorTemplateWindow().
void AppStartColorTemplateWindow(
object oPC,
string sWindowNameLabel,
float fWindowHeight,
float fTopSpacerHeight = APP_UPPER_SPACER_HEIGHT)
{
AppInitializeWindow();
NUI_StartColumn();
NUI_StartDrawList(JsonBool(FALSE));
NUI_AddDrawListItem(NuiDrawListImage(
JsonBool(TRUE),
JsonString("cc"),
NuiRect(
0.0,
15.0,
AppScale(oPC, APP_BACKGROUND_IMAGE_WIDTH),
AppScale(oPC, fWindowHeight)),
JsonInt(NUI_ASPECT_STRETCH),
JsonInt(NUI_HALIGN_LEFT),
JsonInt(NUI_VALIGN_TOP),
NUI_DRAW_LIST_ITEM_ORDER_BEFORE,
NUI_DRAW_LIST_ITEM_RENDER_ALWAYS));
NUI_End();
AddAppColorTemplateTopSpacer(AppScale(oPC, fTopSpacerHeight));
AddAppColorTemplateLabelName(oPC, sWindowNameLabel);
}
//! @brief Add the button panel, close the root column and open the window.
//! @return The window token.
int AppFinishColorTemplateWindow(
object oPC,
string sWindowName,
string sInitColorBtnPrefix)
{
AddAppColorTemplateButtonPanel(oPC);
NUI_StartRow();
NUI_AddSpacer();
NUI_End();
NUI_End();
int nToken = NuiCreate(oPC, NUI_FinalizeWindow(), sWindowName);
NuiSetBind(oPC, nToken, APP_BIND_GEOMETRY, AppGetGeometryWindow(oPC));
NuiSetBind(oPC, nToken, APP_BIND_RESIZABLE, JsonBool(FALSE));
NuiSetBind(oPC, nToken, APP_BIND_CLOSABLE, JsonBool(FALSE));
NuiSetBind(oPC, nToken, APP_BIND_TRANSPARENT, JsonBool(TRUE));
NuiSetBind(oPC, nToken, APP_BIND_BORDER, JsonBool(FALSE));
AppSetActiveWindow(oPC, nToken);
FeedAppColorTemplate(oPC, nToken, sInitColorBtnPrefix);
return nToken;
}
string AppGetItemColor(int nColorChannel)
{
string sValue;
switch(nColorChannel)
{
case ITEM_APPR_ARMOR_COLOR_LEATHER1:
case ITEM_APPR_ARMOR_COLOR_LEATHER2:
case ITEM_APPR_ARMOR_COLOR_CLOTH1:
case ITEM_APPR_ARMOR_COLOR_CLOTH2:
sValue = "cc_color_";
break;
case ITEM_APPR_ARMOR_COLOR_METAL1:
case ITEM_APPR_ARMOR_COLOR_METAL2:
sValue = "cc_color_m_";
break;
}
return sValue;
}
void AppSetItemColor(
object oPC,
int nToken,
int nColor,
int nColorChannel)
{
nColor = AppValidateColor(nColor);
string sId = IntToString(nColor);
string sBind = AppGetColorPickerButtonBind(nColorChannel);
string sValue = AppGetItemColor(nColorChannel) + sId;
NuiSetBind(oPC, nToken, sBind, JsonString(sValue));
AppSetColorNui(oPC, nToken, nColor, nColorChannel);
}
void CreateNewItem(
object oPC,
object oItem,
int nSlot,
int nType,
int nIndex,
int nNewValue)
{
object oItem = GetItemInSlot(nSlot, oPC);
object oNewItem = CopyItemAndModify(oItem, nType, nIndex, nNewValue);
if(GetIsObjectValid(oNewItem))
{
AppEquip(oPC, oNewItem, nSlot);
DestroyObject(oItem);
}
else
{
SendMessageToPC(oPC, "You can't select this model.");
oNewItem = oItem;
}
}
void AddAppColorPicker(object oPC)
{
NUI_StartRow();
NUI_AddSpacer();
AppAddColorPickerButton(oPC, ITEM_APPR_ARMOR_COLOR_LEATHER1, "Leather color 1");
AppAddColorPickerButton(oPC, ITEM_APPR_ARMOR_COLOR_LEATHER2, "Leather color 2");
AppAddColorPickerButton(oPC, ITEM_APPR_ARMOR_COLOR_CLOTH1, "Cloth color 1");
AppAddColorPickerButton(oPC, ITEM_APPR_ARMOR_COLOR_CLOTH2, "Cloth color 2");
AppAddColorPickerButton(oPC, ITEM_APPR_ARMOR_COLOR_METAL1, "Metal color 1");
AppAddColorPickerButton(oPC, ITEM_APPR_ARMOR_COLOR_METAL2, "Metal color 2");
NUI_AddSpacer();
NUI_End();
}
void FeedBasicColorPickerButtons(
object oPC,
object oItem,
int nToken)
{
int nFirstLeather = GetItemAppearance(oItem,
ITEM_APPR_TYPE_ARMOR_COLOR, ITEM_APPR_ARMOR_COLOR_LEATHER1);
int nSecondLeather = GetItemAppearance(oItem,
ITEM_APPR_TYPE_ARMOR_COLOR, ITEM_APPR_ARMOR_COLOR_LEATHER2);
int nFirstCloth = GetItemAppearance(oItem,
ITEM_APPR_TYPE_ARMOR_COLOR, ITEM_APPR_ARMOR_COLOR_CLOTH1);
int nSecondCloth = GetItemAppearance(oItem,
ITEM_APPR_TYPE_ARMOR_COLOR, ITEM_APPR_ARMOR_COLOR_CLOTH2);
int nFirstMetal = GetItemAppearance(oItem,
ITEM_APPR_TYPE_ARMOR_COLOR, ITEM_APPR_ARMOR_COLOR_METAL1);
int nSecondMetal = GetItemAppearance(oItem,
ITEM_APPR_TYPE_ARMOR_COLOR, ITEM_APPR_ARMOR_COLOR_METAL2);
NuiSetBind(oPC, nToken,
AppGetColorPickerButtonBind(ITEM_APPR_ARMOR_COLOR_LEATHER1),
JsonString("cc_color_" + IntToString(nFirstLeather)));
NuiSetBind(oPC, nToken,
AppGetColorPickerButtonBind(ITEM_APPR_ARMOR_COLOR_LEATHER2),
JsonString("cc_color_" + IntToString(nSecondLeather)));
NuiSetBind(oPC, nToken,
AppGetColorPickerButtonBind(ITEM_APPR_ARMOR_COLOR_CLOTH1),
JsonString("cc_color_" + IntToString(nFirstCloth)));
NuiSetBind(oPC, nToken,
AppGetColorPickerButtonBind(ITEM_APPR_ARMOR_COLOR_CLOTH2),
JsonString("cc_color_" + IntToString(nSecondCloth)));
NuiSetBind(oPC, nToken,
AppGetColorPickerButtonBind(ITEM_APPR_ARMOR_COLOR_METAL1),
JsonString("cc_color_m_" + IntToString(nFirstMetal)));
NuiSetBind(oPC, nToken,
AppGetColorPickerButtonBind(ITEM_APPR_ARMOR_COLOR_METAL2),
JsonString("cc_color_m_" + IntToString(nSecondMetal)));
int nActive = JsonGetInt(NuiGetBind(oPC, nToken, APP_COLOR_BTN_ACTIVE));
switch(nActive)
{
case ITEM_APPR_ARMOR_COLOR_LEATHER1:
AppSetItemColor(oPC, nToken, nFirstLeather, nActive);
break;
case ITEM_APPR_ARMOR_COLOR_LEATHER2:
AppSetItemColor(oPC, nToken, nSecondLeather, nActive);
break;
case ITEM_APPR_ARMOR_COLOR_CLOTH1:
AppSetItemColor(oPC, nToken, nFirstCloth, nActive);
break;
case ITEM_APPR_ARMOR_COLOR_CLOTH2:
AppSetItemColor(oPC, nToken, nSecondCloth, nActive);
break;
case ITEM_APPR_ARMOR_COLOR_METAL1:
AppSetItemColor(oPC, nToken, nFirstMetal, nActive);
break;
case ITEM_APPR_ARMOR_COLOR_METAL2:
AppSetItemColor(oPC, nToken, nSecondMetal, nActive);
break;
}
}
int AppComboValidate(
object oPC,
int nToken,
string sEntriesBind,
string sIdBind,
int nAction)
{
int nActive = JsonGetInt(NuiGetBind(oPC, nToken, sIdBind));
json jEntries = NuiGetBind(oPC, nToken, sEntriesBind);
int nLength = JsonGetLength(jEntries);
int i;
for(i = 0; i < nLength; i++)
{
json jEntry = JsonArrayGet(jEntries, i);
int nEntryId = JsonGetInt(JsonArrayGet(jEntry, 1));
if(nEntryId == nActive)
{
break;
}
}
int nId;
i += nAction;
if(i >= nLength)
{
return JsonGetInt(JsonArrayGet(JsonArrayGet(jEntries, 0), 1));
}
if(i < 0)
{
return JsonGetInt(JsonArrayGet(JsonArrayGet(jEntries, nLength - 1), 1));
}
return JsonGetInt(JsonArrayGet(JsonArrayGet(jEntries, i), 1));
}
void AppRightPanelOffEncouraged(object oPC, int nToken)
{
NuiSetBind(oPC, nToken, APP_HELMET_WINDOW, JsonBool(FALSE));
NuiSetBind(oPC, nToken, APP_ARMOR_WINDOW, JsonBool(FALSE));
}
// -----------------------------------------------------------------------------
// Backup
//! @brief Save the item in nSlot of oPC before it is edited. An existing backup is kept.
void AppBackupSlot(object oPC, int nSlot)
{
string sKey = APP_BACKUP + IntToString(nSlot);
if (JsonGetType(GetLocalJson(oPC, sKey)) != JSON_TYPE_NULL)
return;
object oItem = GetItemInSlot(nSlot, oPC);
if (GetIsObjectValid(oItem))
SetLocalJson(oPC, sKey, ObjectToJson(oItem, TRUE));
}
//! @brief Put back the item saved by AppBackupSlot, if any.
void AppRestoreSlot(object oPC, int nSlot)
{
string sKey = APP_BACKUP + IntToString(nSlot);
json jItem = GetLocalJson(oPC, sKey);
if (JsonGetType(jItem) == JSON_TYPE_NULL)
return;
DeleteLocalJson(oPC, sKey);
object oCurrent = GetItemInSlot(nSlot, oPC);
object oItem = JsonToObject(jItem, GetLocation(oPC), oPC, TRUE);
AppEquip(oPC, oItem, nSlot);
DestroyObject(oCurrent);
}
//! @brief Put back every item edited but not confirmed.
void AppRestorePending(object oPC)
{
AppRestoreSlot(oPC, INVENTORY_SLOT_HEAD);
AppRestoreSlot(oPC, INVENTORY_SLOT_CHEST);
}
//! @brief Confirm button: keep the edited item in nSlot.
void AppCommitSlot(object oPC, int nSlot)
{
DeleteLocalJson(oPC, APP_BACKUP + IntToString(nSlot));
}
//! @brief Cancel button: drop the changes to the item in nSlot.
void AppRevertSlot(object oPC, int nSlot)
{
AppRestoreSlot(oPC, nSlot);
}
// -----------------------------------------------------------------------------
// Helmet
void FeedHelmetColor(
object oPC,
int nToken,
int nChannel)
{
object oHelmet = GetItemInSlot(INVENTORY_SLOT_HEAD, oPC);
string sBind = AppGetColorPickerButtonBind(nChannel);
int nColor = GetItemAppearance(oHelmet, ITEM_APPR_TYPE_ARMOR_COLOR, nChannel);
string sId = IntToString(nColor);
AppOffColorEncouraged(oPC, nToken);
AppOnColorEncouraged(oPC, nToken, APP_BTN + sId);
NuiSetBind(oPC, nToken, APP_COLOR_TE, JsonString(sId));
string sValue = AppGetItemColor(nChannel);
NuiSetBind(oPC, nToken, sBind, JsonString(sValue + sId));
AppSetColorPickerButtonEncouraged(oPC, nToken, 6, sBind, 0);
FeedAppColorTemplate(oPC, nToken, sValue);
}
void FeedAppHelmetWindow(
object oPC,
int nToken)
{
object oHelmet = GetItemInSlot(INVENTORY_SLOT_HEAD, oPC);
NuiSetBind(oPC, nToken, APP_COLOR_BTN_ACTIVE, JsonInt(0));
NuiSetBind(oPC, nToken,
AppGetColorPickerButtonEncouragedBind(ITEM_APPR_ARMOR_COLOR_LEATHER1), JsonBool(TRUE));
FeedBasicColorPickerButtons(oPC, oHelmet, nToken);
}
void CreateAppHelmetWindow(object oPC)
{
AppStartColorTemplateWindow(oPC, "Helmet", 1015.0, 85.0);
AddAppColorPicker(oPC);
AddAppColorTemplateColorPicker(oPC);
AddAppColorTemplateColorChooser(oPC);
AppAddSpacerHeight(AppScale(oPC, 10.0));
int nToken = AppFinishColorTemplateWindow(oPC, APP_HELMET_WINDOW, "cc_color_");
FeedAppHelmetWindow(oPC, nToken);
NuiSetBindWatch(oPC, nToken, APP_COLOR_TE, TRUE);
}
void AppHelmetColorEvents(
object oPC,
int nToken,
int nColor)
{
int nChannel = JsonGetInt(NuiGetBind(oPC, nToken, APP_COLOR_BTN_ACTIVE));
object oHelmet = GetItemInSlot(INVENTORY_SLOT_HEAD, oPC);
CreateNewItem(oPC, oHelmet, INVENTORY_SLOT_HEAD, ITEM_APPR_TYPE_ARMOR_COLOR, nChannel, nColor);
AppSetItemColor(oPC, nToken, nColor, nChannel);
}
void AppHelmetEvents(
string sEventType,
string sEventElem,
object oPC,
int nToken)
{
if(sEventType == APP_EVENT_CLICK)
{
if(FindSubString(sEventElem, APP_COLOR_BTN) >= 0)
{
int nChannel = StringToInt(StringReplace(sEventElem, APP_COLOR_BTN, ""));
NuiSetBindWatch(oPC, nToken, APP_COLOR_TE, FALSE);
FeedHelmetColor(oPC, nToken, nChannel);
NuiSetBindWatch(oPC, nToken, APP_COLOR_TE, TRUE);
}
else if(FindSubString(sEventElem, APP_BTN) >= 0)
{
int nColor = StringToInt(StringReplace(sEventElem, APP_BTN, ""));
AppHelmetColorEvents(oPC, nToken, nColor);
}
else if(sEventElem == APP_PREV_COLOR_BTN)
{
string sBtnId = JsonGetString(NuiGetBind(oPC, nToken, APP_BIND_ENCOURAGED));
int nColor = StringToInt(StringReplace(sBtnId, APP_BTN, ""));
nColor--;
AppHelmetColorEvents(oPC, nToken, nColor);
}
else if(sEventElem == APP_NEXT_COLOR_BTN)
{
string sBtnId = JsonGetString(NuiGetBind(oPC, nToken, APP_BIND_ENCOURAGED));
int nColor = StringToInt(StringReplace(sBtnId, APP_BTN, ""));
nColor++;
AppHelmetColorEvents(oPC, nToken, nColor);
}
else if(sEventElem == APP_CONFIRM_BTN)
{
AppCommitSlot(oPC, INVENTORY_SLOT_HEAD);
AppDestroyActiveWindow(oPC);
int nTokenPanel = NuiFindWindow(oPC, APP_RIGHT_PANEL_WINDOW);
AppRightPanelOffEncouraged(oPC, nTokenPanel);
}
else if(sEventElem == APP_CANCEL_BTN)
{
AppRevertSlot(oPC, INVENTORY_SLOT_HEAD);
AppDestroyActiveWindow(oPC);
int nTokenPanel = NuiFindWindow(oPC, APP_RIGHT_PANEL_WINDOW);
AppRightPanelOffEncouraged(oPC, nTokenPanel);
}
}
else if(sEventType == APP_EVENT_WATCH)
{
if(sEventElem == APP_COLOR_TE)
{
int nColor = StringToInt(JsonGetString(NuiGetBind(oPC, nToken, APP_COLOR_TE)));
AppHelmetColorEvents(oPC, nToken, nColor);
}
}
}
// -----------------------------------------------------------------------------
// Armor
string Get2daPart(int nModel)
{
string s2daParts;
switch(nModel)
{
case ITEM_APPR_ARMOR_MODEL_RFOOT:
case ITEM_APPR_ARMOR_MODEL_LFOOT:
s2daParts = "parts_foot";
break;
case ITEM_APPR_ARMOR_MODEL_RSHIN:
case ITEM_APPR_ARMOR_MODEL_LSHIN:
s2daParts = "parts_shin";
break;
case ITEM_APPR_ARMOR_MODEL_RTHIGH:
case ITEM_APPR_ARMOR_MODEL_LTHIGH:
s2daParts = "parts_legs";
break;
case ITEM_APPR_ARMOR_MODEL_PELVIS:
s2daParts = "parts_pelvis";
break;
case ITEM_APPR_ARMOR_MODEL_TORSO:
s2daParts = "parts_chest";
break;
case ITEM_APPR_ARMOR_MODEL_BELT:
s2daParts = "parts_belt";
break;
case ITEM_APPR_ARMOR_MODEL_NECK:
s2daParts = "parts_neck";
break;
case ITEM_APPR_ARMOR_MODEL_RFOREARM:
case ITEM_APPR_ARMOR_MODEL_LFOREARM:
s2daParts = "parts_forearm";
break;
case ITEM_APPR_ARMOR_MODEL_RBICEP:
case ITEM_APPR_ARMOR_MODEL_LBICEP:
s2daParts = "parts_bicep";
break;
case ITEM_APPR_ARMOR_MODEL_RSHOULDER:
case ITEM_APPR_ARMOR_MODEL_LSHOULDER:
s2daParts = "parts_shoulder";
break;
case ITEM_APPR_ARMOR_MODEL_RHAND:
case ITEM_APPR_ARMOR_MODEL_LHAND:
s2daParts = "parts_hand";
break;
case ITEM_APPR_ARMOR_MODEL_ROBE:
s2daParts = "parts_robe";
break;
}
return s2daParts;
}
void AddModelArmorNui(
object oPC,
int nPart,
string sTooltip)
{
string sPart = IntToString(nPart);
NUI_StartElement(NuiButton(JsonString("")));
NUI_SetId(ARMOR_PART + sPart);
NUI_SetEncouraged(NuiBind(ARMOR_PART_ENCOURAGED + sPart));
NUI_SetTooltip(JsonString(sTooltip));
NUI_SetWidth(AppScale(oPC, APP_ARMOR_BUTTON_WIDTH));
AppSetForegroundColor();
NUI_End();
}
void AddAppArmorSpecificColorPicker(object oPC)
{
NUI_StartRow();
NUI_AddSpacer();
NUI_StartElement(NuiCheck(JsonString("Color only the selected part"), NuiBind(APP_ARMOR_SPECIFIC_COLOR)));
NUI_SetWidth(AppScale(oPC, 220.0));
NUI_SetHeight(AppScale(oPC, 40.0));
AppSetForegroundColor();
NUI_End();
NUI_StartElement(NuiButton(JsonString("Clrear")));
NUI_SetId(APP_ARMOR_CLEAR_BTN);
NUI_SetTooltip(JsonString("Clear selected color"));
NUI_SetVisible(NuiBind(APP_ARMOR_SPECIFIC_COLOR));
NUI_SetWidth(AppScale(oPC, 100.0));
NUI_SetHeight(AppScale(oPC, 40.0));
AppSetForegroundColor();
NUI_End();
NUI_AddSpacer();
NUI_End();
}
void AddAppArmorPartsUpperSpacer()
{
NUI_StartRow();
AppAddSpacerHeight(20.0);
NUI_End();
}
//! @brief Open a row of armor part buttons. Close with NUI_End().
void AppStartArmorPartsRow(object oPC)
{
NUI_StartRow();
NUI_SetHeight(AppScale(oPC, APP_ARMOR_BUTTON_HEIGHT));
}
void AddAppArmorParts(object oPC)
{
AddAppArmorPartsUpperSpacer();
AppStartArmorPartsRow(oPC);
AppAddSpacerWidth(AppScale(oPC, 40.0));
AddModelArmorNui(oPC, 0, "Right shoulder");
AppAddSpacerWidth(AppScale(oPC, 9.0));
AddModelArmorNui(oPC, 1, "Neck");
AppAddSpacerWidth(AppScale(oPC, 10.0));
AddModelArmorNui(oPC, 2, "Left shoulder");
NUI_AddSpacer();
NUI_End();
AppStartArmorPartsRow(oPC);
AppAddSpacerWidth(AppScale(oPC, 30.0));
AddModelArmorNui(oPC, 3, "Right biceps");
AppAddSpacerWidth(AppScale(oPC, 19.0));
AddModelArmorNui(oPC, 4, "Torso");
AppAddSpacerWidth(AppScale(oPC, 20.0));
AddModelArmorNui(oPC, 5, "Left biceps");
NUI_AddSpacer();
NUI_End();
AppStartArmorPartsRow(oPC);
AppAddSpacerWidth(AppScale(oPC, 25.0));
AddModelArmorNui(oPC, 6, "Right forearm");
AddModelArmorNui(oPC, 10, "Pelvis");
AddModelArmorNui(oPC, 7, "Belt");
AddModelArmorNui(oPC, 10, "Pelvis");
AddModelArmorNui(oPC, 8, "Left forearm");
NUI_AddSpacer();
NUI_End();
AppStartArmorPartsRow(oPC);
AppAddSpacerWidth(AppScale(oPC, 25.0));
AddModelArmorNui(oPC, 9, "Right hand");
AddModelArmorNui(oPC, 10, "Pelvis");
AddModelArmorNui(oPC, 7, "Belt");
AddModelArmorNui(oPC, 10, "Pelvis");
AddModelArmorNui(oPC, 11, "Left hand");
NUI_AddSpacer();
NUI_End();
AppStartArmorPartsRow(oPC);
AppAddSpacerWidth(AppScale(oPC, 48.0));
AddModelArmorNui(oPC, 12, "Right thigh");
AppAddSpacerWidth(AppScale(oPC, 20.0));
AddModelArmorNui(oPC, 13, "Left thigh");
NUI_AddSpacer();
NUI_End();
AppStartArmorPartsRow(oPC);
AppAddSpacerWidth(AppScale(oPC, 48.0));
AddModelArmorNui(oPC, 14, "Right shin");
AppAddSpacerWidth(AppScale(oPC, 20.0));
AddModelArmorNui(oPC, 15, "Left shin");
NUI_AddSpacer();
NUI_End();
AppStartArmorPartsRow(oPC);
AppAddSpacerWidth(AppScale(oPC, 47.0));
AddModelArmorNui(oPC, 16, "Right foot");
AppAddSpacerWidth(AppScale(oPC, 24.0));
AddModelArmorNui(oPC, 17, "Left foot");
NUI_AddSpacer();
NUI_End();
}
void AddAppArmorRobe(object oPC)
{
string sPart = "18";
NUI_StartRow();
AppAddSpacerWidth(AppScale(oPC, 20.0));
NUI_StartElement(NuiButton(JsonString("")));
NUI_SetId(ARMOR_PART + sPart);
NUI_SetEncouraged(NuiBind(ARMOR_PART_ENCOURAGED + sPart));
NUI_SetTooltip(JsonString("Robe"));
NUI_SetWidth(AppScale(oPC, APP_ARMOR_IMAGE_WIDTH - 50.0));
NUI_SetHeight(AppScale(oPC, APP_ARMOR_IMAGE_HEIGHT - 25.0));
AppSetForegroundColor();
NUI_End();
NUI_End();
}
//! @brief Open a column drawn over by sImageStatic and the image bound to
//! sImageBind. Close with NUI_End().
void AppStartArmorPartsImage(
string sImageStatic,
string sImageBind,
float fWidth,
float fHeight)
{
NUI_StartColumn();
NUI_SetWidth(fWidth);
NUI_SetHeight(fHeight);
NUI_StartDrawList(JsonBool(FALSE));
NUI_AddDrawListItem(NuiDrawListImage(
JsonBool(TRUE),
JsonString(sImageStatic),
NuiRect(
0.0,
0.0,
fWidth,
fHeight),
JsonInt(NUI_ASPECT_FIT),
JsonInt(NUI_HALIGN_CENTER),
JsonInt(NUI_VALIGN_MIDDLE),
NUI_DRAW_LIST_ITEM_ORDER_AFTER,
NUI_DRAW_LIST_ITEM_RENDER_ALWAYS));
NUI_AddDrawListItem(NuiDrawListImage(
JsonBool(TRUE),
NuiBind(sImageBind),
NuiRect(
0.0,
0.0,
fWidth,
fHeight),
JsonInt(NUI_ASPECT_FIT),
JsonInt(NUI_HALIGN_CENTER),
JsonInt(NUI_VALIGN_MIDDLE),
NUI_DRAW_LIST_ITEM_ORDER_AFTER,
NUI_DRAW_LIST_ITEM_RENDER_ALWAYS));
NUI_End();
}
void AddAppArmorNextElements(object oPC)
{
float fWidth = AppScale(oPC, APP_ARMOR_IMAGE_WIDTH);
float fHeight = AppScale(oPC, APP_ARMOR_IMAGE_HEIGHT);
NUI_StartRow();
NUI_AddSpacer();
AppStartArmorPartsImage("app_armor_body", APP_ARMOR_PART_IMAGE, fWidth, fHeight);
AddAppArmorParts(oPC);
NUI_End();
AppStartArmorPartsImage("app_cloth_body", APP_ARMOR_PART_IMAGE_2, fWidth, fHeight);
AddAppArmorRobe(oPC);
NUI_End();
NUI_AddSpacer();
NUI_End();
}
void AddAppArmorPartPicker(object oPC)
{
float fButtonWidthScaled = AppScale(oPC, APP_BTN_WIDTH);
float fButtonHeightScaled = AppScale(oPC, APP_BTN_HEIGHT);
NUI_StartRow();
NUI_StartElement(NuiButtonImage(JsonString(APP_ARROW_PREV_BTN)));
NUI_SetId(APP_PREV_ARMOR_PART);
NUI_SetDimensions(fButtonWidthScaled, fButtonHeightScaled);
NUI_SetTooltip(JsonString("Previous armor part"));
AppSetForegroundColor();
NUI_End();
NUI_StartElement(NuiCombo(NuiBind(ARMOR_ENTRIES), NuiBind(ARMOR_ID)));
NUI_SetHeight(fButtonHeightScaled);
NUI_SetWidth(AppScale(oPC, APP_ARMOR_COMBO_WIDTH));
NUI_End();
NUI_StartElement(NuiButtonImage(JsonString(APP_ARROW_NEXT_BTN)));
NUI_SetId(APP_NEXT_ARMOR_PART);
NUI_SetDimensions(fButtonWidthScaled, fButtonHeightScaled);
NUI_SetTooltip(JsonString("Next armor part"));
AppSetForegroundColor();
NUI_End();
NUI_End();
}
void AddAppArmorPickerElements(object oPC)
{
float fButtonWidthScaled = AppScale(oPC, APP_BTN_WIDTH);
float fButtonHeightScaled = AppScale(oPC, APP_BTN_HEIGHT);
NUI_StartRow();
NUI_StartElement(NuiButtonImage(JsonString(APP_ARROW_PREV_BTN)));
NUI_SetId(APP_PREV_ELEMENT);
NUI_SetDimensions(fButtonWidthScaled, fButtonHeightScaled);
NUI_SetTooltip(JsonString("Previous element"));
AppSetForegroundColor();
NUI_End();
NUI_StartElement(NuiCombo(NuiBind(ARMOR_ELEMENTS_ENTRIES), NuiBind(ARMOR_ELEMENTS_ID)));
NUI_SetHeight(fButtonHeightScaled);
NUI_SetWidth(AppScale(oPC, APP_ARMOR_COMBO_WIDTH));
NUI_End();
NUI_StartElement(NuiButtonImage(JsonString(APP_ARROW_NEXT_BTN)));
NUI_SetId(APP_NEXT_ELEMENT);
NUI_SetDimensions(fButtonWidthScaled, fButtonHeightScaled);
NUI_SetTooltip(JsonString("Next element"));
AppSetForegroundColor();
NUI_End();
NUI_End();
}
void AddAppArmorPartPickerMerge(object oPC)
{
NUI_StartRow();
AppAddSpacerWidth(AppScale(oPC, 27.0));
AddAppArmorPartPicker(oPC);
AddAppArmorPickerElements(oPC);
NUI_AddSpacer();
NUI_End();
}
int GetAppArmorModelFromComboId(int nId)
{
switch(nId)
{
case 0:
return ITEM_APPR_ARMOR_MODEL_RSHOULDER;
case 1:
return ITEM_APPR_ARMOR_MODEL_NECK;
case 2:
return ITEM_APPR_ARMOR_MODEL_LSHOULDER;
case 3:
return ITEM_APPR_ARMOR_MODEL_RBICEP;
case 4:
return ITEM_APPR_ARMOR_MODEL_TORSO;
case 5:
return ITEM_APPR_ARMOR_MODEL_LBICEP;
case 6:
return ITEM_APPR_ARMOR_MODEL_RFOREARM;
case 7:
return ITEM_APPR_ARMOR_MODEL_BELT;
case 8:
return ITEM_APPR_ARMOR_MODEL_LFOREARM;
case 9:
return ITEM_APPR_ARMOR_MODEL_RHAND;
case 10:
return ITEM_APPR_ARMOR_MODEL_PELVIS;
case 11:
return ITEM_APPR_ARMOR_MODEL_LHAND;
case 12:
return ITEM_APPR_ARMOR_MODEL_RTHIGH;
case 13:
return ITEM_APPR_ARMOR_MODEL_LTHIGH;
case 14:
return ITEM_APPR_ARMOR_MODEL_RSHIN;
case 15:
return ITEM_APPR_ARMOR_MODEL_LSHIN;
case 16:
return ITEM_APPR_ARMOR_MODEL_RFOOT;
case 17:
return ITEM_APPR_ARMOR_MODEL_LFOOT;
case 18:
return ITEM_APPR_ARMOR_MODEL_ROBE;
}
return 0;
}
void FeedArmorColor(
object oPC,
object oItem,
int nToken,
int nType,
int nColorChannelId,
int nChannel)
{
string sBind = AppGetColorPickerButtonBind(nColorChannelId);
int nColor = GetItemAppearance(oItem, nType, nChannel);
string sId = IntToString(nColor);
AppOffColorEncouraged(oPC, nToken);
AppOnColorEncouraged(oPC, nToken, APP_BTN + sId);
NuiSetBind(oPC, nToken, APP_COLOR_TE, JsonString(sId));
string sValue = AppGetItemColor(nColorChannelId);
NuiSetBind(oPC, nToken, sBind, JsonString(sValue + sId));
AppSetColorPickerButtonEncouraged(oPC, nToken, 6, sBind, 0);
FeedAppColorTemplate(oPC, nToken, sValue);
}
void FeedArmorPartModels(
object oPC,
int nToken,
int nModel)
{
string s2daParts = Get2daPart(nModel);
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oPC);
int nArmorAc = 0;
if(nModel == ITEM_APPR_ARMOR_MODEL_TORSO)
{
int nChestId = GetItemAppearance(oArmor, ITEM_APPR_TYPE_ARMOR_MODEL, ITEM_APPR_ARMOR_MODEL_TORSO);
nArmorAc = StringToInt(Get2DAString("parts_chest", "ACBONUS", nChestId));
}
json jModels = JsonArray();
int nLength = Get2DARowCount(s2daParts);
int nAppearance = GetItemAppearance(oArmor, ITEM_APPR_TYPE_ARMOR_MODEL, nModel);
int nId, nAppearanceId = 0;
int i;
for(i=0; i<=nLength; i++)
{
if(nAppearance == i)
{
nAppearanceId = nId;
}
string sAcBonus = Get2DAString(s2daParts, "ACBONUS", i);
if(sAcBonus != "")
{
if(nModel == ITEM_APPR_ARMOR_MODEL_TORSO && nArmorAc != StringToInt(sAcBonus))
{
continue;
}
jModels = JsonArrayInsert(jModels, NuiComboEntry(IntToString(i), nId++));
}
}
NuiSetBind(oPC, nToken, ARMOR_ELEMENTS_ENTRIES, jModels);
NuiSetBind(oPC, nToken, ARMOR_ELEMENTS_ID, JsonInt(nAppearanceId));
}
void FeedAppArmorSpecificColor(
object oPC,
object oArmor,
int nModel,
int nToken)
{
int nChannel = ITEM_APPR_ARMOR_NUM_COLORS + (nModel * ITEM_APPR_ARMOR_NUM_COLORS);
int nFirstLeather = GetItemAppearance(oArmor,
ITEM_APPR_TYPE_ARMOR_COLOR, nChannel + ITEM_APPR_ARMOR_COLOR_LEATHER1);
int nSecondLeather = GetItemAppearance(oArmor,
ITEM_APPR_TYPE_ARMOR_COLOR, nChannel + ITEM_APPR_ARMOR_COLOR_LEATHER2);
int nFirstCloth = GetItemAppearance(oArmor,
ITEM_APPR_TYPE_ARMOR_COLOR, nChannel + ITEM_APPR_ARMOR_COLOR_CLOTH1);
int nSecondCloth = GetItemAppearance(oArmor,
ITEM_APPR_TYPE_ARMOR_COLOR, nChannel + ITEM_APPR_ARMOR_COLOR_CLOTH2);
int nFirstMetal = GetItemAppearance(oArmor,
ITEM_APPR_TYPE_ARMOR_COLOR, nChannel + ITEM_APPR_ARMOR_COLOR_METAL1);
int nSecondMetal = GetItemAppearance(oArmor,
ITEM_APPR_TYPE_ARMOR_COLOR, nChannel + ITEM_APPR_ARMOR_COLOR_METAL2);
NuiSetBind(oPC, nToken,
AppGetColorPickerButtonBind(ITEM_APPR_ARMOR_COLOR_LEATHER1),
JsonString("cc_color_" + IntToString(nFirstLeather)));
NuiSetBind(oPC, nToken,
AppGetColorPickerButtonBind(ITEM_APPR_ARMOR_COLOR_LEATHER2),
JsonString("cc_color_" + IntToString(nSecondLeather)));
NuiSetBind(oPC, nToken,
AppGetColorPickerButtonBind(ITEM_APPR_ARMOR_COLOR_CLOTH1),
JsonString("cc_color_" + IntToString(nFirstCloth)));
NuiSetBind(oPC, nToken,
AppGetColorPickerButtonBind(ITEM_APPR_ARMOR_COLOR_CLOTH2),
JsonString("cc_color_" + IntToString(nSecondCloth)));
NuiSetBind(oPC, nToken,
AppGetColorPickerButtonBind(ITEM_APPR_ARMOR_COLOR_METAL1),
JsonString("cc_color_m_" + IntToString(nFirstMetal)));
NuiSetBind(oPC, nToken,
AppGetColorPickerButtonBind(ITEM_APPR_ARMOR_COLOR_METAL2),
JsonString("cc_color_m_" + IntToString(nSecondMetal)));
int nActive = JsonGetInt(NuiGetBind(oPC, nToken, APP_COLOR_BTN_ACTIVE));
switch(nActive)
{
case ITEM_APPR_ARMOR_COLOR_LEATHER1:
AppSetItemColor(oPC, nToken, nFirstLeather, nChannel);
break;
case ITEM_APPR_ARMOR_COLOR_LEATHER2:
AppSetItemColor(oPC, nToken, nSecondLeather, nChannel);
break;
case ITEM_APPR_ARMOR_COLOR_CLOTH1:
AppSetItemColor(oPC, nToken, nFirstCloth, nChannel);
break;
case ITEM_APPR_ARMOR_COLOR_CLOTH2:
AppSetItemColor(oPC, nToken, nSecondCloth, nChannel);
break;
case ITEM_APPR_ARMOR_COLOR_METAL1:
AppSetItemColor(oPC, nToken, nFirstMetal, nChannel);
break;
case ITEM_APPR_ARMOR_COLOR_METAL2:
AppSetItemColor(oPC, nToken, nSecondMetal, nChannel);
break;
}
}
void FeedAppArmorPart(
object oPC,
int nToken,
int nId)
{
string sId = IntToString(nId);
string sEncouragedPart = ARMOR_PART_ENCOURAGED + sId;
NuiSetBindWatch(oPC, nToken, ARMOR_ID, FALSE);
NuiSetBindWatch(oPC, nToken, ARMOR_ELEMENTS_ID, FALSE);
string sCurrentPart = JsonGetString(NuiGetBind(oPC, nToken, ARMOR_PART_ENCOURAGED_CURRENT));
if(sCurrentPart != "")
{
NuiSetBind(oPC, nToken, sCurrentPart, JsonBool(FALSE));
}
NuiSetBind(oPC, nToken, ARMOR_PART_ENCOURAGED_CURRENT, JsonString(sEncouragedPart));
NuiSetBind(oPC, nToken, sEncouragedPart, JsonBool(TRUE));
NuiSetBind(oPC, nToken, ARMOR_ID, JsonInt(nId));
if(nId < 18)
{
NuiSetBind(oPC, nToken, APP_ARMOR_PART_IMAGE, JsonString(ARMOR_PART + IntToString(nId)));
NuiSetBind(oPC, nToken, APP_ARMOR_PART_IMAGE_2, JsonString("app_cloth_body"));
}
else
{
NuiSetBind(oPC, nToken, APP_ARMOR_PART_IMAGE, JsonString("app_armor_body"));
NuiSetBind(oPC, nToken, APP_ARMOR_PART_IMAGE_2, JsonString(ARMOR_PART + IntToString(nId)));
}
FeedArmorPartModels(oPC, nToken, GetAppArmorModelFromComboId(nId));
NuiSetBindWatch(oPC, nToken, ARMOR_ID, TRUE);
NuiSetBindWatch(oPC, nToken, ARMOR_ELEMENTS_ID, TRUE);
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oPC);
if(JsonGetInt(NuiGetBind(oPC, nToken, APP_ARMOR_SPECIFIC_COLOR)))
{
int nModelPart = GetAppArmorModelFromComboId(nId);
FeedAppArmorSpecificColor(oPC, oArmor, nModelPart, nToken);
}
else
{
FeedBasicColorPickerButtons(oPC, oArmor, nToken);
}
}
void FeedAppArmorWindow(object oPC, int nToken)
{
json jEntries = JsonArray();
jEntries = JsonArrayInsert(jEntries, NuiComboEntry("Right shoulder", 0));
jEntries = JsonArrayInsert(jEntries, NuiComboEntry("Neck", 1));
jEntries = JsonArrayInsert(jEntries, NuiComboEntry("Left shoulder", 2));
jEntries = JsonArrayInsert(jEntries, NuiComboEntry("Right biceps", 3));
jEntries = JsonArrayInsert(jEntries, NuiComboEntry("Torso", 4));
jEntries = JsonArrayInsert(jEntries, NuiComboEntry("Left biceps", 5));
jEntries = JsonArrayInsert(jEntries, NuiComboEntry("Right forearm", 6));
jEntries = JsonArrayInsert(jEntries, NuiComboEntry("Belt", 7));
jEntries = JsonArrayInsert(jEntries, NuiComboEntry("Left forearm", 8));
jEntries = JsonArrayInsert(jEntries, NuiComboEntry("Right hand", 9));
jEntries = JsonArrayInsert(jEntries, NuiComboEntry("Pelvis", 10));
jEntries = JsonArrayInsert(jEntries, NuiComboEntry("Left hand", 11));
jEntries = JsonArrayInsert(jEntries, NuiComboEntry("Right thigh", 12));
jEntries = JsonArrayInsert(jEntries, NuiComboEntry("Left thigh", 13));
jEntries = JsonArrayInsert(jEntries, NuiComboEntry("Right shin", 14));
jEntries = JsonArrayInsert(jEntries, NuiComboEntry("Left shin", 15));
jEntries = JsonArrayInsert(jEntries, NuiComboEntry("Right foot", 16));
jEntries = JsonArrayInsert(jEntries, NuiComboEntry("Left foot", 17));
jEntries = JsonArrayInsert(jEntries, NuiComboEntry("Robe", 18));
NuiSetBind(oPC, nToken, ARMOR_ENTRIES, jEntries);
NuiSetBind(oPC, nToken, ARMOR_ID, JsonInt(0));
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oPC);
NuiSetBind(oPC, nToken, APP_COLOR_BTN_ACTIVE, JsonInt(0));
NuiSetBind(oPC, nToken,
AppGetColorPickerButtonEncouragedBind(ITEM_APPR_ARMOR_COLOR_LEATHER1), JsonBool(TRUE));
FeedBasicColorPickerButtons(oPC, oArmor, nToken);
NuiSetBind(oPC, nToken, APP_ARMOR_PART_IMAGE, JsonString("ARMOR_PART_0"));
}
void FeedAppArmorElement(
object oPC,
int nToken,
int nId)
{
NuiSetBindWatch(oPC, nToken, ARMOR_ELEMENTS_ID, FALSE);
NuiSetBind(oPC, nToken, ARMOR_ELEMENTS_ID, JsonInt(nId));
int nModelId = JsonGetInt(NuiGetBind(oPC, nToken, ARMOR_ID));
int nModelPart = GetAppArmorModelFromComboId(nModelId);
int nNewValue = StringToInt(
AppGetComboLabel(oPC, nToken, ARMOR_ELEMENTS_ENTRIES, nId));
CreateNewItem(
oPC,
GetItemInSlot(INVENTORY_SLOT_CHEST, oPC),
INVENTORY_SLOT_CHEST,
ITEM_APPR_TYPE_ARMOR_MODEL,
nModelPart,
nNewValue);
NuiSetBindWatch(oPC, nToken, ARMOR_ELEMENTS_ID, TRUE);
}
void CreateAppArmorWindow(object oPC)
{
AppStartColorTemplateWindow(oPC, "Armor", 1030.0, 80.0);
AddAppColorPicker(oPC);
AddAppArmorSpecificColorPicker(oPC);
AddAppColorTemplateColorPicker(oPC);
AddAppColorTemplateColorChooser(oPC);
AddAppArmorPartPickerMerge(oPC);
AddAppArmorNextElements(oPC);
int nToken = AppFinishColorTemplateWindow(oPC, APP_ARMOR_WINDOW, "cc_color_");
NuiSetBindWatch(oPC, nToken, ARMOR_ID, TRUE);
FeedAppArmorWindow(oPC, nToken);
NuiSetBindWatch(oPC, nToken, APP_COLOR_TE, TRUE);
NuiSetBindWatch(oPC, nToken, ARMOR_ELEMENTS_ID, TRUE);
NuiSetBindWatch(oPC, nToken, APP_ARMOR_SPECIFIC_COLOR, TRUE);
}
void AppArmorColorEvents(
object oPC,
int nToken,
int nColor)
{
int nChannel = JsonGetInt(NuiGetBind(oPC, nToken, APP_COLOR_BTN_ACTIVE));
int nChannelId = nChannel;
if(JsonGetInt(NuiGetBind(oPC, nToken, APP_ARMOR_SPECIFIC_COLOR)))
{
int nModelId = JsonGetInt(NuiGetBind(oPC, nToken, ARMOR_ID));
int nModelPart = GetAppArmorModelFromComboId(nModelId);
nChannel = ITEM_APPR_ARMOR_NUM_COLORS +
(nModelPart * ITEM_APPR_ARMOR_NUM_COLORS) + nChannel;
}
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oPC);
CreateNewItem(oPC, oArmor, INVENTORY_SLOT_CHEST, ITEM_APPR_TYPE_ARMOR_COLOR, nChannel, nColor);
AppSetItemColor(oPC, nToken, nColor, nChannelId);
}
void AppArmorEvents(
string sEventType,
string sEventElem,
object oPC,
int nToken)
{
if(sEventType == APP_EVENT_CLICK)
{
if(FindSubString(sEventElem, APP_COLOR_BTN) >= 0)
{
int nChannel = StringToInt(StringReplace(sEventElem, APP_COLOR_BTN, ""));
int nChannelColor = nChannel;
if(JsonGetInt(NuiGetBind(oPC, nToken, APP_ARMOR_SPECIFIC_COLOR)))
{
int nModelId = JsonGetInt(NuiGetBind(oPC, nToken, ARMOR_ID));
int nModelPart = GetAppArmorModelFromComboId(nModelId);
nChannel = ITEM_APPR_ARMOR_NUM_COLORS +
(nModelPart * ITEM_APPR_ARMOR_NUM_COLORS) + nChannel;
}
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oPC);
NuiSetBindWatch(oPC, nToken, APP_COLOR_TE, FALSE);
FeedArmorColor(oPC, oArmor, nToken, ITEM_APPR_TYPE_ARMOR_COLOR, nChannelColor, nChannel);
NuiSetBindWatch(oPC, nToken, APP_COLOR_TE, TRUE);
}
else if(sEventElem == APP_PREV_ARMOR_PART)
{
int nId = AppComboValidate(oPC, nToken, ARMOR_ENTRIES, ARMOR_ID, -1);
FeedAppArmorPart(oPC, nToken, nId);
}
else if(sEventElem == APP_NEXT_ARMOR_PART)
{
int nId = AppComboValidate(oPC, nToken, ARMOR_ENTRIES, ARMOR_ID, 1);
FeedAppArmorPart(oPC, nToken, nId);
}
else if(sEventElem == APP_PREV_ELEMENT)
{
int nId = AppComboValidate(oPC, nToken, ARMOR_ELEMENTS_ENTRIES, ARMOR_ELEMENTS_ID, -1);
FeedAppArmorElement(oPC, nToken, nId);
}
else if(sEventElem == APP_NEXT_ELEMENT)
{
int nId = AppComboValidate(oPC, nToken, ARMOR_ELEMENTS_ENTRIES, ARMOR_ELEMENTS_ID, 1);
FeedAppArmorElement(oPC, nToken, nId);
}
else if(sEventElem == APP_PREV_COLOR_BTN)
{
string sBtnId = JsonGetString(NuiGetBind(oPC, nToken, APP_BIND_ENCOURAGED));
int nColor = StringToInt(StringReplace(sBtnId, APP_BTN, ""));
nColor += -1;
AppArmorColorEvents(oPC, nToken, nColor);
}
else if(sEventElem == APP_NEXT_COLOR_BTN)
{
string sBtnId = JsonGetString(NuiGetBind(oPC, nToken, APP_BIND_ENCOURAGED));
int nColor = StringToInt(StringReplace(sBtnId, APP_BTN, ""));
nColor += 1;
AppArmorColorEvents(oPC, nToken, nColor);
}
else if(sEventElem == APP_ARMOR_CLEAR_BTN)
{
AppArmorColorEvents(oPC, nToken, 255);
}
else if(FindSubString(sEventElem, APP_BTN) >= 0)
{
int nColor = StringToInt(StringReplace(sEventElem, APP_BTN, ""));
AppArmorColorEvents(oPC, nToken, nColor);
}
else if(FindSubString(sEventElem, ARMOR_PART) >= 0)
{
int nId = StringToInt(StringReplace(sEventElem, ARMOR_PART, ""));
FeedAppArmorPart(oPC, nToken, nId);
}
else if(sEventElem == APP_CONFIRM_BTN)
{
AppCommitSlot(oPC, INVENTORY_SLOT_CHEST);
AppDestroyActiveWindow(oPC);
int nTokenPanel = NuiFindWindow(oPC, APP_RIGHT_PANEL_WINDOW);
AppRightPanelOffEncouraged(oPC, nTokenPanel);
}
else if(sEventElem == APP_CANCEL_BTN)
{
AppRevertSlot(oPC, INVENTORY_SLOT_CHEST);
AppDestroyActiveWindow(oPC);
int nTokenPanel = NuiFindWindow(oPC, APP_RIGHT_PANEL_WINDOW);
AppRightPanelOffEncouraged(oPC, nTokenPanel);
}
}
else if(sEventType == APP_EVENT_WATCH)
{
if(sEventElem == ARMOR_ID)
{
int nId = JsonGetInt(NuiGetBind(oPC, nToken, sEventElem));
FeedAppArmorPart(oPC, nToken, nId);
}
else if(sEventElem == ARMOR_ELEMENTS_ID)
{
int nId = JsonGetInt(NuiGetBind(oPC, nToken, sEventElem));
FeedAppArmorElement(oPC, nToken, nId);
}
else if(sEventElem == APP_ARMOR_SPECIFIC_COLOR)
{
int nChannel = JsonGetInt(NuiGetBind(oPC, nToken, APP_COLOR_BTN_ACTIVE));
int nChannelColor = nChannel;
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oPC);
if(JsonGetInt(NuiGetBind(oPC, nToken, APP_ARMOR_SPECIFIC_COLOR)))
{
int nModelId = JsonGetInt(NuiGetBind(oPC, nToken, ARMOR_ID));
int nModelPart = GetAppArmorModelFromComboId(nModelId);
nChannel = ITEM_APPR_ARMOR_NUM_COLORS +
(nModelPart * ITEM_APPR_ARMOR_NUM_COLORS) + nChannel;
FeedAppArmorSpecificColor(oPC, oArmor, nModelPart, nToken);
}
else
{
FeedBasicColorPickerButtons(oPC, oArmor, nToken);
}
NuiSetBindWatch(oPC, nToken, APP_COLOR_TE, FALSE);
FeedArmorColor(oPC, oArmor, nToken, ITEM_APPR_TYPE_ARMOR_COLOR, nChannelColor, nChannel);
NuiSetBindWatch(oPC, nToken, APP_COLOR_TE, TRUE);
}
else if(sEventElem == APP_COLOR_TE)
{
int nColor = StringToInt(JsonGetString(NuiGetBind(oPC, nToken, APP_COLOR_TE)));
AppArmorColorEvents(oPC, nToken, nColor);
}
}
}
// -----------------------------------------------------------------------------
// Right panel
void AppRightPanelButton(
string sWindow,
string sImage,
int bEnabled,
string sTooltip,
float fWidth,
float fHeight)
{
NUI_StartRow();
NUI_AddSpacer();
NUI_StartElement(NuiButtonImage(JsonString(sImage)));
NUI_SetId(sWindow);
NUI_SetTooltip(JsonString(sTooltip));
NUI_SetEncouraged(NuiBind(sWindow));
NUI_SetEnabled(JsonBool(bEnabled));
NUI_SetWidth(fWidth);
NUI_SetHeight(fHeight);
AppSetForegroundColor();
NUI_End();
NUI_AddSpacer();
NUI_End();
}
void AppRightPanelCloseButton(
float fWidth,
float fHeight)
{
NUI_StartRow();
NUI_AddSpacer();
NUI_StartElement(NuiButtonImage(JsonString("custom_close_nui")));
NUI_SetId(APP_RIGHT_CLOSE_BTN);
NUI_SetTooltip(JsonString("Close"));
NUI_SetWidth(fWidth);
NUI_SetHeight(fHeight);
AppSetForegroundColor();
NUI_End();
NUI_AddSpacer();
NUI_End();
}
void CreateAppRightPanelWindow(object oPC)
{
int nDeviceWidth = GetPlayerDeviceProperty(oPC, PLAYER_DEVICE_PROPERTY_GUI_WIDTH);
int nDeviceHeigt = GetPlayerDeviceProperty(oPC, PLAYER_DEVICE_PROPERTY_GUI_HEIGHT);
float fHeight = AppScale(oPC, APP_IMAGE_HEIGHT);
float fWidth = AppScale(oPC, APP_IMAGE_WIDTH);
float fOffset = AppScale(oPC, 10.0);
float fImageWidth = AppScale(oPC, APP_RIGHT_PANEL_IMAGE_WIDTH) - fOffset;
float fWindowWidth = fImageWidth + fOffset;
float fWindowHeight = AppScale(oPC, IntToFloat(nDeviceHeigt));
AppInitializeWindow();
NUI_StartColumn();
NUI_StartDrawList(JsonBool(FALSE));
NUI_AddDrawListItem(NuiDrawListImage(
JsonBool(TRUE),
JsonString("cc_right_panel"),
NuiRect(
0.0,
0.0,
fImageWidth,
fWindowHeight),
JsonInt(NUI_ASPECT_STRETCH),
JsonInt(NUI_HALIGN_LEFT),
JsonInt(NUI_VALIGN_TOP),
NUI_DRAW_LIST_ITEM_ORDER_BEFORE,
NUI_DRAW_LIST_ITEM_RENDER_ALWAYS));
NUI_End();
NUI_StartRow();
NUI_SetHeight(AppScale(oPC, 30.0));
NUI_AddSpacer();
NUI_End();
AppRightPanelButton(
APP_HELMET_WINDOW,
"app_helmet",
HasEquipedHelmet(oPC),
"Helmet",
fWidth,
fHeight);
AppRightPanelButton(
APP_ARMOR_WINDOW,
"app_armor",
HasEquipedArmor(oPC),
"Armor",
fWidth,
fHeight);
AppRightPanelCloseButton(fWidth, fHeight);
NUI_StartRow();
NUI_AddSpacer();
NUI_End();
NUI_End();
int nToken = NuiCreate(oPC, NUI_FinalizeWindow(), APP_RIGHT_PANEL_WINDOW);
NuiSetBind(oPC, nToken, APP_BIND_GEOMETRY, NuiRect(
IntToFloat(nDeviceWidth),
0.0,
fWindowWidth,
fWindowHeight));
NuiSetBind(oPC, nToken, APP_BIND_RESIZABLE, JsonBool(FALSE));
NuiSetBind(oPC, nToken, APP_BIND_CLOSABLE, JsonBool(FALSE));
NuiSetBind(oPC, nToken, APP_BIND_TRANSPARENT, JsonBool(TRUE));
NuiSetBind(oPC, nToken, APP_BIND_BORDER, JsonBool(FALSE));
AppCreateGeometryWindow(oPC, nDeviceWidth - APP_RIGHT_PANEL_IMAGE_WIDTH);
}
void AppRightPanelEvents(
string sEventType,
string sEventElem,
object oPC,
int nToken)
{
if(sEventType == APP_EVENT_CLICK)
{
if(NuiFindWindow(oPC, sEventElem) > 0)
{
return;
}
// Changes not confirmed in the previous section are dropped.
AppRestorePending(oPC);
AppDestroyActiveWindow(oPC);
AppRightPanelOffEncouraged(oPC, nToken);
NuiSetBind(oPC, nToken, sEventElem, JsonBool(TRUE));
if(sEventElem == APP_HELMET_WINDOW)
{
AppBackupSlot(oPC, INVENTORY_SLOT_HEAD);
DelayCommand(0.1, CreateAppHelmetWindow(oPC));
SetCameraFace(oPC);
}
else if(sEventElem == APP_ARMOR_WINDOW)
{
AppBackupSlot(oPC, INVENTORY_SLOT_CHEST);
DelayCommand(0.1, CreateAppArmorWindow(oPC));
SetCameraBody(oPC);
}
else if(sEventElem == APP_RIGHT_CLOSE_BTN)
{
NuiDestroy(oPC, nToken);
AppLeaveEditor(oPC);
}
}
}
// -----------------------------------------------------------------------------
// Unit
// -----------------------------------------------------------------------------
void AppLeaveEditor(object oPC)
{
AppRestorePending(oPC);
DeleteLocalInt(oPC, APP_EDITOR_OPEN);
NWNX_Object_DeleteInt(oPC, FF_U_ITM_APPEARANCE_EDITOR);
AppUnparalyze(oPC);
AppDisableGuiPanels(oPC, FALSE);
SetCameraHeight(oPC, 0.0);
AssignCommand(oPC, RestoreCameraFacing());
}
// -----------------------------------------------------------------------------
//! @brief Open the editor on oPC where it stands.
//! @param oPC A player character.
void AppOpenEditor(object oPC);
void AppOpenEditor(object oPC)
{
ClearAllActions(TRUE, oPC);
AppEnterEditor(oPC);
CreateAppRightPanelWindow(oPC);
}
// -----------------------------------------------------------------------------
//! @brief Return TRUE if oCreature has a cutscene paralysis effect.
//! @param oCreature A creature.
int GetIsCutsceneParalyzed(object oCreature);
int GetIsCutsceneParalyzed(object oCreature)
{
effect eLoop = GetFirstEffect(oCreature);
while (GetIsEffectValid(eLoop))
{
if (GetEffectType(eLoop) == EFFECT_TYPE_CUTSCENE_PARALYZE)
return TRUE;
eLoop = GetNextEffect(oCreature);
}
return FALSE;
}
// -----------------------------------------------------------------------------
//! @brief Free oPC if it logged out while the editor was open.
//! Local variables on a PC are kept across a relog until the server restarts,
//! and the editor flag is a persistent NWNX variable saved with the character.
//! The editor state is always cleared: items changed but not confirmed are put
//! back while their backups still exist, a PC still paralyzed by the editor is
//! freed, and the editor can be opened again.
//! @param oPC A player character.
void ResetEditorOnLogin(object oPC);
void ResetEditorOnLogin(object oPC)
{
if (!GetIsObjectValid(oPC))
return;
AppRestorePending(oPC);
DeleteLocalInt(oPC, APP_EDITOR_OPEN);
DeleteLocalInt(oPC, APP_ACTIVE_WINDOW);
if (!NWNX_Object_GetInt(oPC, FF_U_ITM_APPEARANCE_EDITOR))
return;
if (!GetIsCutsceneParalyzed(oPC))
{
LogNotice(__FILE__ + ": " + GetPCInfo(oPC) + " left the appearance editor but is not paralyzed");
return;
}
AppUnparalyze(oPC);
AppDisableGuiPanels(oPC, FALSE);
NWNX_Object_DeleteInt(oPC, FF_U_ITM_APPEARANCE_EDITOR);
LogNotice(__FILE__ + ": " + GetPCInfo(oPC) + " freed from the appearance editor");
}
// -----------------------------------------------------------------------------
//! @brief Give the universal dye to oPC, unless already given.
//! @param oPC A player character.
void GiveDyeOnce(object oPC);
void GiveDyeOnce(object oPC)
{
if (!GetIsObjectValid(oPC))
return;
if (NWNX_Object_GetInt(oPC, FF_U_ITM_APPEARANCE))
return;
object oDye = CreateItemOnObject(DYE_RESREF, oPC);
if (!GetIsObjectValid(oDye))
{
LogError(__FILE__ + ": could not create " + DYE_RESREF + " on " + GetPCInfo(oPC));
return;
}
SetIdentified(oDye, TRUE);
NWNX_Object_SetInt(oPC, FF_U_ITM_APPEARANCE, 1, TRUE);
}
// -----------------------------------------------------------------------------
//! @brief Return TRUE if oPC stands in an area where resting is allowed.
//! @param oPC A player character.
int GetIsSafeArea(object oPC);
int GetIsSafeArea(object oPC)
{
if (NWNX_Area_GetNoRestingAllowed(GetArea(oPC)))
return FALSE;
return TRUE;
}
// -----------------------------------------------------------------------------
//! @brief Open the appearance editor on oPC, if allowed here.
//! @param oPC The dye's activator.
void OnDyeActivate(object oPC);
void OnDyeActivate(object oPC)
{
if (GetLocalInt(oPC, APP_EDITOR_OPEN))
return;
if (!GetIsSafeArea(oPC))
{
FloatingTextStringOnCreature("The dye can only be used in a safe place.", oPC, FALSE);
return;
}
AppOpenEditor(oPC);
}
// -----------------------------------------------------------------------------
//! @brief Dispatch a NUI event to the editor window it belongs to.
void OnNuiEvent();
void OnNuiEvent()
{
object oPC = NuiGetEventPlayer();
int nToken = NuiGetEventWindow();
string sWindow = NuiGetWindowId(oPC, nToken);
string sEventType = NuiGetEventType();
string sEventElem = NuiGetEventElement();
if (FALSE) {}
else if (sWindow == APP_RIGHT_PANEL_WINDOW)
AppRightPanelEvents(sEventType, sEventElem, oPC, nToken);
else if (sWindow == APP_HELMET_WINDOW)
AppHelmetEvents(sEventType, sEventElem, oPC, nToken);
else if (sWindow == APP_ARMOR_WINDOW)
AppArmorEvents(sEventType, sEventElem, oPC, nToken);
}
// =============================================================================
void main()
{
string sEvent = NWNX_Events_GetCurrentEvent();
if (sEvent == ON_REGISTER)
{
if (!GetModuleFlag(ENABLE__FF_U_ITM_APPEARANCE, TRUE))
return;
SubscribeToEvent(ON_DEFAULT_CLIENT_ENTER, __FILE__);
SubscribeToEvent(ON_NUI_EVENT, __FILE__);
}
else if (sEvent == ON_DEFAULT_CLIENT_ENTER)
{
object oPC = GetEnteringObject();
if (GetIsPC(oPC) && !GetIsDM(oPC))
{
// Effects of a loading character may not be applied yet; wait a little.
DelayCommand(1.0f, ResetEditorOnLogin(oPC));
DelayCommand(3.0f, GiveDyeOnce(oPC));
}
}
else if (sEvent == NWNX_ON_RUN_EVENT_SCRIPT_BEFORE)
{
if (GetCurrentlyRunningEvent() == EVENT_SCRIPT_MODULE_ON_ACTIVATE_ITEM)
OnDyeActivate(GetItemActivator());
}
else if (sEvent == ON_NUI_EVENT)
OnNuiEvent();
}