Increased HP of Practice Dummy

Increased HP of Practice Dummy.  Added instanced player room with persistent storage in Inn.  Full compile.  Updated release archive.
This commit is contained in:
Jaysyn904 2024-09-21 14:31:54 -04:00
parent d481e97d69
commit 8c530509fe
73 changed files with 17784 additions and 252 deletions

@ -124,7 +124,7 @@
},
"SkyBox": {
"type": "byte",
"value": 0
"value": 48
},
"SunAmbientColor": {
"type": "dword",
@ -11173,7 +11173,7 @@
},
"Version": {
"type": "dword",
"value": 6
"value": 7
},
"Width": {
"type": "int",

@ -54,7 +54,7 @@
},
"LoadScreenID": {
"type": "word",
"value": 154
"value": 155
},
"ModListenCheck": {
"type": "int",
@ -124,7 +124,7 @@
},
"SkyBox": {
"type": "byte",
"value": 0
"value": 4
},
"SunAmbientColor": {
"type": "dword",
@ -11173,7 +11173,7 @@
},
"Version": {
"type": "dword",
"value": 7
"value": 8
},
"Width": {
"type": "int",

@ -11173,7 +11173,7 @@
},
"Version": {
"type": "dword",
"value": 78
"value": 80
},
"Width": {
"type": "int",

@ -1187,13 +1187,17 @@
}
]
},
"TileBrdrDisabled": {
"type": "byte",
"value": 0
},
"Tileset": {
"type": "resref",
"value": "tin01"
},
"Version": {
"type": "dword",
"value": 5
"value": 6
},
"Width": {
"type": "int",

@ -0,0 +1,350 @@
{
"__data_type": "ARE ",
"ChanceLightning": {
"type": "int",
"value": 0
},
"ChanceRain": {
"type": "int",
"value": 0
},
"ChanceSnow": {
"type": "int",
"value": 0
},
"Comments": {
"type": "cexostring",
"value": "Valeford Tavern and Inn, Your Room"
},
"Creator_ID": {
"type": "int",
"value": -1
},
"DayNightCycle": {
"type": "byte",
"value": 0
},
"Expansion_List": {
"type": "list",
"value": []
},
"Flags": {
"type": "dword",
"value": 1
},
"FogClipDist": {
"type": "float",
"value": 45.0
},
"Height": {
"type": "int",
"value": 2
},
"ID": {
"type": "int",
"value": -1
},
"IsNight": {
"type": "byte",
"value": 1
},
"LightingScheme": {
"type": "byte",
"value": 13
},
"LoadScreenID": {
"type": "word",
"value": 47
},
"ModListenCheck": {
"type": "int",
"value": 0
},
"ModSpotCheck": {
"type": "int",
"value": 0
},
"MoonAmbientColor": {
"type": "dword",
"value": 2960685
},
"MoonDiffuseColor": {
"type": "dword",
"value": 6457991
},
"MoonFogAmount": {
"type": "byte",
"value": 5
},
"MoonFogColor": {
"type": "dword",
"value": 0
},
"MoonShadows": {
"type": "byte",
"value": 0
},
"Name": {
"type": "cexolocstring",
"value": {
"0": "Valeford Tavern and Inn, Your Room"
}
},
"NoRest": {
"type": "byte",
"value": 0
},
"OnEnter": {
"type": "resref",
"value": ""
},
"OnExit": {
"type": "resref",
"value": "pc_room_onexit"
},
"OnHeartbeat": {
"type": "resref",
"value": ""
},
"OnUserDefined": {
"type": "resref",
"value": ""
},
"PlayerVsPlayer": {
"type": "byte",
"value": 0
},
"ResRef": {
"type": "resref",
"value": "vit_pc_rooms"
},
"ShadowOpacity": {
"type": "byte",
"value": 60
},
"SkyBox": {
"type": "byte",
"value": 6
},
"SunAmbientColor": {
"type": "dword",
"value": 0
},
"SunDiffuseColor": {
"type": "dword",
"value": 0
},
"SunFogAmount": {
"type": "byte",
"value": 0
},
"SunFogColor": {
"type": "dword",
"value": 0
},
"SunShadows": {
"type": "byte",
"value": 0
},
"Tag": {
"type": "cexostring",
"value": "VIT_PC_ROOMS"
},
"Tile_List": {
"type": "list",
"value": [
{
"__struct_id": 1,
"Tile_AnimLoop1": {
"type": "byte",
"value": 1
},
"Tile_AnimLoop2": {
"type": "byte",
"value": 1
},
"Tile_AnimLoop3": {
"type": "byte",
"value": 1
},
"Tile_Height": {
"type": "int",
"value": 0
},
"Tile_ID": {
"type": "int",
"value": 94
},
"Tile_MainLight1": {
"type": "byte",
"value": 4
},
"Tile_MainLight2": {
"type": "byte",
"value": 13
},
"Tile_Orientation": {
"type": "int",
"value": 0
},
"Tile_SrcLight1": {
"type": "byte",
"value": 3
},
"Tile_SrcLight2": {
"type": "byte",
"value": 3
}
},
{
"__struct_id": 1,
"Tile_AnimLoop1": {
"type": "byte",
"value": 1
},
"Tile_AnimLoop2": {
"type": "byte",
"value": 1
},
"Tile_AnimLoop3": {
"type": "byte",
"value": 1
},
"Tile_Height": {
"type": "int",
"value": 0
},
"Tile_ID": {
"type": "int",
"value": 94
},
"Tile_MainLight1": {
"type": "byte",
"value": 30
},
"Tile_MainLight2": {
"type": "byte",
"value": 13
},
"Tile_Orientation": {
"type": "int",
"value": 0
},
"Tile_SrcLight1": {
"type": "byte",
"value": 2
},
"Tile_SrcLight2": {
"type": "byte",
"value": 2
}
},
{
"__struct_id": 1,
"Tile_AnimLoop1": {
"type": "byte",
"value": 1
},
"Tile_AnimLoop2": {
"type": "byte",
"value": 1
},
"Tile_AnimLoop3": {
"type": "byte",
"value": 1
},
"Tile_Height": {
"type": "int",
"value": 0
},
"Tile_ID": {
"type": "int",
"value": 94
},
"Tile_MainLight1": {
"type": "byte",
"value": 4
},
"Tile_MainLight2": {
"type": "byte",
"value": 13
},
"Tile_Orientation": {
"type": "int",
"value": 3
},
"Tile_SrcLight1": {
"type": "byte",
"value": 2
},
"Tile_SrcLight2": {
"type": "byte",
"value": 2
}
},
{
"__struct_id": 1,
"Tile_AnimLoop1": {
"type": "byte",
"value": 1
},
"Tile_AnimLoop2": {
"type": "byte",
"value": 1
},
"Tile_AnimLoop3": {
"type": "byte",
"value": 1
},
"Tile_Height": {
"type": "int",
"value": 0
},
"Tile_ID": {
"type": "int",
"value": 191
},
"Tile_MainLight1": {
"type": "byte",
"value": 30
},
"Tile_MainLight2": {
"type": "byte",
"value": 14
},
"Tile_Orientation": {
"type": "int",
"value": 0
},
"Tile_SrcLight1": {
"type": "byte",
"value": 3
},
"Tile_SrcLight2": {
"type": "byte",
"value": 3
}
}
]
},
"TileBrdrDisabled": {
"type": "byte",
"value": 0
},
"Tileset": {
"type": "resref",
"value": "tin01"
},
"Version": {
"type": "dword",
"value": 16
},
"Width": {
"type": "int",
"value": 2
},
"WindPower": {
"type": "int",
"value": 0
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,235 @@
{
"__data_type": "DLG ",
"DelayEntry": {
"type": "dword",
"value": 0
},
"DelayReply": {
"type": "dword",
"value": 0
},
"EndConverAbort": {
"type": "resref",
"value": "nw_walk_wp"
},
"EndConversation": {
"type": "resref",
"value": "nw_walk_wp"
},
"EntryList": {
"type": "list",
"value": [
{
"__struct_id": 0,
"ActionParams": {
"type": "list",
"value": []
},
"Animation": {
"type": "dword",
"value": 0
},
"AnimLoop": {
"type": "byte",
"value": 1
},
"Comment": {
"type": "cexostring",
"value": ""
},
"Delay": {
"type": "dword",
"value": 4294967295
},
"Quest": {
"type": "cexostring",
"value": ""
},
"RepliesList": {
"type": "list",
"value": [
{
"__struct_id": 0,
"Active": {
"type": "resref",
"value": ""
},
"ConditionParams": {
"type": "list",
"value": []
},
"Index": {
"type": "dword",
"value": 1
},
"IsChild": {
"type": "byte",
"value": 0
}
},
{
"__struct_id": 1,
"Active": {
"type": "resref",
"value": ""
},
"ConditionParams": {
"type": "list",
"value": []
},
"Index": {
"type": "dword",
"value": 0
},
"IsChild": {
"type": "byte",
"value": 0
}
}
]
},
"Script": {
"type": "resref",
"value": ""
},
"Sound": {
"type": "resref",
"value": ""
},
"Speaker": {
"type": "cexostring",
"value": ""
},
"Text": {
"type": "cexolocstring",
"value": {
"0": "This door leads up to your room, would you like to go there now?"
}
}
}
]
},
"NumWords": {
"type": "dword",
"value": 26
},
"PreventZoomIn": {
"type": "byte",
"value": 0
},
"ReplyList": {
"type": "list",
"value": [
{
"__struct_id": 0,
"ActionParams": {
"type": "list",
"value": []
},
"Animation": {
"type": "dword",
"value": 0
},
"AnimLoop": {
"type": "byte",
"value": 1
},
"Comment": {
"type": "cexostring",
"value": ""
},
"Delay": {
"type": "dword",
"value": 4294967295
},
"EntriesList": {
"type": "list",
"value": []
},
"Quest": {
"type": "cexostring",
"value": ""
},
"Script": {
"type": "resref",
"value": ""
},
"Sound": {
"type": "resref",
"value": ""
},
"Text": {
"type": "cexolocstring",
"value": {
"0": "No, not just yet."
}
}
},
{
"__struct_id": 1,
"ActionParams": {
"type": "list",
"value": []
},
"Animation": {
"type": "dword",
"value": 0
},
"AnimLoop": {
"type": "byte",
"value": 1
},
"Comment": {
"type": "cexostring",
"value": ""
},
"Delay": {
"type": "dword",
"value": 4294967295
},
"EntriesList": {
"type": "list",
"value": []
},
"Quest": {
"type": "cexostring",
"value": ""
},
"Script": {
"type": "resref",
"value": "at_enter_pc_room"
},
"Sound": {
"type": "resref",
"value": ""
},
"Text": {
"type": "cexolocstring",
"value": {
"0": "Yes, I think it's time for some rest."
}
}
}
]
},
"StartingList": {
"type": "list",
"value": [
{
"__struct_id": 0,
"Active": {
"type": "resref",
"value": ""
},
"ConditionParams": {
"type": "list",
"value": []
},
"Index": {
"type": "dword",
"value": 0
}
}
]
}
}

@ -749,6 +749,20 @@
"value": "Combat Dummy"
}
},
{
"__struct_id": 9,
"Comment": {
"type": "cexostring",
"value": "Combat Dummy"
}
},
{
"__struct_id": 9,
"Comment": {
"type": "cexostring",
"value": "Combat Dummy"
}
},
{
"__struct_id": 9,
"Comment": {

@ -40,14 +40,14 @@
"__struct_id": 8,
"Comment": {
"type": "cexostring",
"value": "Fancy Door"
"value": "Strong Door"
}
},
{
"__struct_id": 8,
"Comment": {
"type": "cexostring",
"value": "Strong Door"
"value": "Door to Inn Rooms"
}
}
]

@ -0,0 +1,118 @@
{
"__data_type": "GIC ",
"Creature List": {
"type": "list",
"value": []
},
"Door List": {
"type": "list",
"value": [
{
"__struct_id": 8,
"Comment": {
"type": "cexostring",
"value": "Strong Door"
}
}
]
},
"Encounter List": {
"type": "list",
"value": []
},
"List": {
"type": "list",
"value": []
},
"Placeable List": {
"type": "list",
"value": [
{
"__struct_id": 9,
"Comment": {
"type": "cexostring",
"value": "volition's Bio Placeables by volition\r\n"
}
},
{
"__struct_id": 9,
"Comment": {
"type": "cexostring",
"value": ""
}
},
{
"__struct_id": 9,
"Comment": {
"type": "cexostring",
"value": ""
}
},
{
"__struct_id": 9,
"Comment": {
"type": "cexostring",
"value": "Low treasure script."
}
},
{
"__struct_id": 9,
"Comment": {
"type": "cexostring",
"value": "Chair that one can sit on.\r\n\r\nCreated by Shir'le E. Illios\r\nshirle@drowwanderer.com\r\nhttp://chosen.drowwanderer.com\r\n"
}
},
{
"__struct_id": 9,
"Comment": {
"type": "cexostring",
"value": "TCC - Interiors\r\nby The_NWNCCC"
}
},
{
"__struct_id": 9,
"Comment": {
"type": "cexostring",
"value": "Source: Bathroom Fixtures by Lisa"
}
},
{
"__struct_id": 9,
"Comment": {
"type": "cexostring",
"value": "Charlie's Oriental Placables v1.0 by Charlie\r\n"
}
},
{
"__struct_id": 9,
"Comment": {
"type": "cexostring",
"value": ""
}
},
{
"__struct_id": 9,
"Comment": {
"type": "cexostring",
"value": ""
}
}
]
},
"SoundList": {
"type": "list",
"value": []
},
"StoreList": {
"type": "list",
"value": []
},
"TriggerList": {
"type": "list",
"value": []
},
"WaypointList": {
"type": "list",
"value": []
}
}

@ -8345,7 +8345,7 @@
},
"XPosition": {
"type": "float",
"value": 7.472731113433838
"value": 7.515176296234131
},
"YOrientation": {
"type": "float",
@ -8353,7 +8353,7 @@
},
"YPosition": {
"type": "float",
"value": 55.04598999023438
"value": 55.32783126831055
},
"ZPosition": {
"type": "float",

@ -81642,7 +81642,7 @@
},
"Bearing": {
"type": "float",
"value": 1.570794224739075
"value": 0.9326602220535278
},
"BodyBag": {
"type": "byte",
@ -81658,7 +81658,7 @@
},
"CurrentHP": {
"type": "short",
"value": 100
"value": 6000
},
"Description": {
"type": "cexolocstring",
@ -81689,7 +81689,7 @@
},
"HP": {
"type": "short",
"value": 100
"value": 6000
},
"Interruptable": {
"type": "byte",
@ -81732,7 +81732,7 @@
},
"OnDeath": {
"type": "resref",
"value": ""
"value": "death_dummy"
},
"OnDisarm": {
"type": "resref",
@ -81844,15 +81844,15 @@
},
"X": {
"type": "float",
"value": 106.1102294921875
"value": 105.3882293701172
},
"Y": {
"type": "float",
"value": 33.10503768920898
"value": 33.36203384399414
},
"Z": {
"type": "float",
"value": 0.01000607013702393
"value": -5.7220458984375e-006
}
},
{
@ -81871,7 +81871,7 @@
},
"Bearing": {
"type": "float",
"value": 1.570794224739075
"value": 2.331650495529175
},
"BodyBag": {
"type": "byte",
@ -81887,7 +81887,7 @@
},
"CurrentHP": {
"type": "short",
"value": 100
"value": 3000
},
"Description": {
"type": "cexolocstring",
@ -81918,7 +81918,7 @@
},
"HP": {
"type": "short",
"value": 100
"value": 3000
},
"Interruptable": {
"type": "byte",
@ -81961,7 +81961,7 @@
},
"OnDeath": {
"type": "resref",
"value": ""
"value": "death_dummy"
},
"OnDisarm": {
"type": "resref",
@ -82073,11 +82073,469 @@
},
"X": {
"type": "float",
"value": 105.9644927978516
"value": 105.5486373901367
},
"Y": {
"type": "float",
"value": 44.63613891601563
"value": 44.69867706298828
},
"Z": {
"type": "float",
"value": 0.009992370381951332
}
},
{
"__struct_id": 9,
"AnimationState": {
"type": "byte",
"value": 0
},
"Appearance": {
"type": "dword",
"value": 39
},
"AutoRemoveKey": {
"type": "byte",
"value": 0
},
"Bearing": {
"type": "float",
"value": -1.570796251296997
},
"BodyBag": {
"type": "byte",
"value": 0
},
"CloseLockDC": {
"type": "byte",
"value": 0
},
"Conversation": {
"type": "resref",
"value": ""
},
"CurrentHP": {
"type": "short",
"value": 6000
},
"Description": {
"type": "cexolocstring",
"value": {
"0": "With its bucket head and straw-filled chest, the combat dummy seems far from threatening.",
"id": 14599
}
},
"DisarmDC": {
"type": "byte",
"value": 15
},
"Faction": {
"type": "dword",
"value": 1
},
"Fort": {
"type": "byte",
"value": 16
},
"Hardness": {
"type": "byte",
"value": 0
},
"HasInventory": {
"type": "byte",
"value": 0
},
"HP": {
"type": "short",
"value": 6000
},
"Interruptable": {
"type": "byte",
"value": 1
},
"KeyName": {
"type": "cexostring",
"value": ""
},
"KeyRequired": {
"type": "byte",
"value": 0
},
"Lockable": {
"type": "byte",
"value": 0
},
"Locked": {
"type": "byte",
"value": 0
},
"LocName": {
"type": "cexolocstring",
"value": {
"0": "Practice Dummy",
"id": 5681
}
},
"OnClick": {
"type": "resref",
"value": ""
},
"OnClosed": {
"type": "resref",
"value": ""
},
"OnDamaged": {
"type": "resref",
"value": "use_dummy"
},
"OnDeath": {
"type": "resref",
"value": "death_dummy"
},
"OnDisarm": {
"type": "resref",
"value": ""
},
"OnHeartbeat": {
"type": "resref",
"value": ""
},
"OnInvDisturbed": {
"type": "resref",
"value": ""
},
"OnLock": {
"type": "resref",
"value": ""
},
"OnMeleeAttacked": {
"type": "resref",
"value": ""
},
"OnOpen": {
"type": "resref",
"value": ""
},
"OnSpellCastAt": {
"type": "resref",
"value": ""
},
"OnTrapTriggered": {
"type": "resref",
"value": ""
},
"OnUnlock": {
"type": "resref",
"value": ""
},
"OnUsed": {
"type": "resref",
"value": ""
},
"OnUserDefined": {
"type": "resref",
"value": ""
},
"OpenLockDC": {
"type": "byte",
"value": 18
},
"Plot": {
"type": "byte",
"value": 0
},
"PortraitId": {
"type": "word",
"value": 397
},
"Ref": {
"type": "byte",
"value": 0
},
"Static": {
"type": "byte",
"value": 0
},
"Tag": {
"type": "cexostring",
"value": "CombatDummy"
},
"TemplateResRef": {
"type": "resref",
"value": "2_28"
},
"TrapDetectable": {
"type": "byte",
"value": 1
},
"TrapDetectDC": {
"type": "byte",
"value": 0
},
"TrapDisarmable": {
"type": "byte",
"value": 1
},
"TrapFlag": {
"type": "byte",
"value": 0
},
"TrapOneShot": {
"type": "byte",
"value": 1
},
"TrapType": {
"type": "byte",
"value": 0
},
"Type": {
"type": "byte",
"value": 0
},
"Useable": {
"type": "byte",
"value": 1
},
"Will": {
"type": "byte",
"value": 0
},
"X": {
"type": "float",
"value": 92.04000091552734
},
"Y": {
"type": "float",
"value": 36.38000106811523
},
"Z": {
"type": "float",
"value": 0.0
}
},
{
"__struct_id": 9,
"AnimationState": {
"type": "byte",
"value": 0
},
"Appearance": {
"type": "dword",
"value": 39
},
"AutoRemoveKey": {
"type": "byte",
"value": 0
},
"Bearing": {
"type": "float",
"value": -1.570796251296997
},
"BodyBag": {
"type": "byte",
"value": 0
},
"CloseLockDC": {
"type": "byte",
"value": 0
},
"Conversation": {
"type": "resref",
"value": ""
},
"CurrentHP": {
"type": "short",
"value": 6000
},
"Description": {
"type": "cexolocstring",
"value": {
"0": "With its bucket head and straw-filled chest, the combat dummy seems far from threatening.",
"id": 14599
}
},
"DisarmDC": {
"type": "byte",
"value": 15
},
"Faction": {
"type": "dword",
"value": 1
},
"Fort": {
"type": "byte",
"value": 16
},
"Hardness": {
"type": "byte",
"value": 0
},
"HasInventory": {
"type": "byte",
"value": 0
},
"HP": {
"type": "short",
"value": 6000
},
"Interruptable": {
"type": "byte",
"value": 1
},
"KeyName": {
"type": "cexostring",
"value": ""
},
"KeyRequired": {
"type": "byte",
"value": 0
},
"Lockable": {
"type": "byte",
"value": 0
},
"Locked": {
"type": "byte",
"value": 0
},
"LocName": {
"type": "cexolocstring",
"value": {
"0": "Practice Dummy",
"id": 5681
}
},
"OnClick": {
"type": "resref",
"value": ""
},
"OnClosed": {
"type": "resref",
"value": ""
},
"OnDamaged": {
"type": "resref",
"value": "use_dummy"
},
"OnDeath": {
"type": "resref",
"value": "death_dummy"
},
"OnDisarm": {
"type": "resref",
"value": ""
},
"OnHeartbeat": {
"type": "resref",
"value": ""
},
"OnInvDisturbed": {
"type": "resref",
"value": ""
},
"OnLock": {
"type": "resref",
"value": ""
},
"OnMeleeAttacked": {
"type": "resref",
"value": ""
},
"OnOpen": {
"type": "resref",
"value": ""
},
"OnSpellCastAt": {
"type": "resref",
"value": ""
},
"OnTrapTriggered": {
"type": "resref",
"value": ""
},
"OnUnlock": {
"type": "resref",
"value": ""
},
"OnUsed": {
"type": "resref",
"value": ""
},
"OnUserDefined": {
"type": "resref",
"value": ""
},
"OpenLockDC": {
"type": "byte",
"value": 18
},
"Plot": {
"type": "byte",
"value": 0
},
"PortraitId": {
"type": "word",
"value": 397
},
"Ref": {
"type": "byte",
"value": 0
},
"Static": {
"type": "byte",
"value": 0
},
"Tag": {
"type": "cexostring",
"value": "CombatDummy"
},
"TemplateResRef": {
"type": "resref",
"value": "2_28"
},
"TrapDetectable": {
"type": "byte",
"value": 1
},
"TrapDetectDC": {
"type": "byte",
"value": 0
},
"TrapDisarmable": {
"type": "byte",
"value": 1
},
"TrapFlag": {
"type": "byte",
"value": 0
},
"TrapOneShot": {
"type": "byte",
"value": 1
},
"TrapType": {
"type": "byte",
"value": 0
},
"Type": {
"type": "byte",
"value": 0
},
"Useable": {
"type": "byte",
"value": 1
},
"Will": {
"type": "byte",
"value": 0
},
"X": {
"type": "float",
"value": 92.0537109375
},
"Y": {
"type": "float",
"value": 41.48401260375977
},
"Z": {
"type": "float",

@ -2732,226 +2732,6 @@
"Door List": {
"type": "list",
"value": [
{
"__struct_id": 8,
"AnimationState": {
"type": "byte",
"value": 0
},
"Appearance": {
"type": "dword",
"value": 0
},
"AutoRemoveKey": {
"type": "byte",
"value": 0
},
"Bearing": {
"type": "float",
"value": -0.0
},
"CloseLockDC": {
"type": "byte",
"value": 0
},
"Conversation": {
"type": "resref",
"value": ""
},
"CurrentHP": {
"type": "short",
"value": 15
},
"Description": {
"type": "cexolocstring",
"value": {
"id": 9077
}
},
"DisarmDC": {
"type": "byte",
"value": 15
},
"Faction": {
"type": "dword",
"value": 1
},
"Fort": {
"type": "byte",
"value": 16
},
"GenericType_New": {
"type": "dword",
"value": 1
},
"Hardness": {
"type": "byte",
"value": 5
},
"HP": {
"type": "short",
"value": 15
},
"Interruptable": {
"type": "byte",
"value": 1
},
"KeyName": {
"type": "cexostring",
"value": ""
},
"KeyRequired": {
"type": "byte",
"value": 0
},
"LinkedTo": {
"type": "cexostring",
"value": ""
},
"LinkedToFlags": {
"type": "byte",
"value": 0
},
"LoadScreenID": {
"type": "word",
"value": 0
},
"Lockable": {
"type": "byte",
"value": 0
},
"Locked": {
"type": "byte",
"value": 1
},
"LocName": {
"type": "cexolocstring",
"value": {
"0": "Plot Door",
"id": 5349
}
},
"OnClick": {
"type": "resref",
"value": ""
},
"OnClosed": {
"type": "resref",
"value": ""
},
"OnDamaged": {
"type": "resref",
"value": ""
},
"OnDeath": {
"type": "resref",
"value": ""
},
"OnDisarm": {
"type": "resref",
"value": ""
},
"OnFailToOpen": {
"type": "resref",
"value": ""
},
"OnHeartbeat": {
"type": "resref",
"value": ""
},
"OnLock": {
"type": "resref",
"value": ""
},
"OnMeleeAttacked": {
"type": "resref",
"value": ""
},
"OnOpen": {
"type": "resref",
"value": ""
},
"OnSpellCastAt": {
"type": "resref",
"value": ""
},
"OnTrapTriggered": {
"type": "resref",
"value": ""
},
"OnUnlock": {
"type": "resref",
"value": ""
},
"OnUserDefined": {
"type": "resref",
"value": ""
},
"OpenLockDC": {
"type": "byte",
"value": 99
},
"Plot": {
"type": "byte",
"value": 1
},
"PortraitId": {
"type": "word",
"value": 0
},
"Ref": {
"type": "byte",
"value": 0
},
"Tag": {
"type": "cexostring",
"value": "plotdoor"
},
"TemplateResRef": {
"type": "resref",
"value": "door_fancy001"
},
"TrapDetectable": {
"type": "byte",
"value": 1
},
"TrapDetectDC": {
"type": "byte",
"value": 0
},
"TrapDisarmable": {
"type": "byte",
"value": 1
},
"TrapFlag": {
"type": "byte",
"value": 0
},
"TrapOneShot": {
"type": "byte",
"value": 1
},
"TrapType": {
"type": "byte",
"value": 0
},
"Will": {
"type": "byte",
"value": 0
},
"X": {
"type": "float",
"value": 5.0
},
"Y": {
"type": "float",
"value": 34.9900016784668
},
"Z": {
"type": "float",
"value": 1.399999976158142
}
},
{
"__struct_id": 8,
"AnimationState": {
@ -3389,6 +3169,227 @@
"type": "float",
"value": 0.0
}
},
{
"__struct_id": 8,
"AnimationState": {
"type": "byte",
"value": 0
},
"Appearance": {
"type": "dword",
"value": 0
},
"AutoRemoveKey": {
"type": "byte",
"value": 0
},
"Bearing": {
"type": "float",
"value": -3.46451997756958e-007
},
"CloseLockDC": {
"type": "byte",
"value": 0
},
"Conversation": {
"type": "resref",
"value": "doorcv_inn_room"
},
"CurrentHP": {
"type": "short",
"value": 15
},
"Description": {
"type": "cexolocstring",
"value": {
"0": "This door leads to the inn rooms above.",
"id": 9078
}
},
"DisarmDC": {
"type": "byte",
"value": 15
},
"Faction": {
"type": "dword",
"value": 1
},
"Fort": {
"type": "byte",
"value": 16
},
"GenericType_New": {
"type": "dword",
"value": 1
},
"Hardness": {
"type": "byte",
"value": 5
},
"HP": {
"type": "short",
"value": 15
},
"Interruptable": {
"type": "byte",
"value": 1
},
"KeyName": {
"type": "cexostring",
"value": ""
},
"KeyRequired": {
"type": "byte",
"value": 1
},
"LinkedTo": {
"type": "cexostring",
"value": ""
},
"LinkedToFlags": {
"type": "byte",
"value": 0
},
"LoadScreenID": {
"type": "word",
"value": 0
},
"Lockable": {
"type": "byte",
"value": 0
},
"Locked": {
"type": "byte",
"value": 1
},
"LocName": {
"type": "cexolocstring",
"value": {
"0": "Door to Inn Rooms",
"id": 5349
}
},
"OnClick": {
"type": "resref",
"value": ""
},
"OnClosed": {
"type": "resref",
"value": ""
},
"OnDamaged": {
"type": "resref",
"value": ""
},
"OnDeath": {
"type": "resref",
"value": "x2_door_death"
},
"OnDisarm": {
"type": "resref",
"value": ""
},
"OnFailToOpen": {
"type": "resref",
"value": "cv_inn_door"
},
"OnHeartbeat": {
"type": "resref",
"value": ""
},
"OnLock": {
"type": "resref",
"value": ""
},
"OnMeleeAttacked": {
"type": "resref",
"value": ""
},
"OnOpen": {
"type": "resref",
"value": ""
},
"OnSpellCastAt": {
"type": "resref",
"value": ""
},
"OnTrapTriggered": {
"type": "resref",
"value": ""
},
"OnUnlock": {
"type": "resref",
"value": ""
},
"OnUserDefined": {
"type": "resref",
"value": ""
},
"OpenLockDC": {
"type": "byte",
"value": 18
},
"Plot": {
"type": "byte",
"value": 1
},
"PortraitId": {
"type": "word",
"value": 2624
},
"Ref": {
"type": "byte",
"value": 0
},
"Tag": {
"type": "cexostring",
"value": "inn2pcrooms"
},
"TemplateResRef": {
"type": "resref",
"value": "inn2pcrooms"
},
"TrapDetectable": {
"type": "byte",
"value": 1
},
"TrapDetectDC": {
"type": "byte",
"value": 0
},
"TrapDisarmable": {
"type": "byte",
"value": 1
},
"TrapFlag": {
"type": "byte",
"value": 0
},
"TrapOneShot": {
"type": "byte",
"value": 1
},
"TrapType": {
"type": "byte",
"value": 0
},
"Will": {
"type": "byte",
"value": 0
},
"X": {
"type": "float",
"value": 5.0
},
"Y": {
"type": "float",
"value": 34.9900016784668
},
"Z": {
"type": "float",
"value": 1.399999976158142
}
}
]
},

File diff suppressed because it is too large Load Diff

@ -510,6 +510,13 @@
"type": "resref",
"value": "wol_a_dymond"
}
},
{
"__struct_id": 6,
"Area_Name": {
"type": "resref",
"value": "vit_pc_rooms"
}
}
]
},
@ -832,7 +839,7 @@
},
"Mod_OnNuiEvent": {
"type": "resref",
"value": ""
"value": "mmd_onnui"
},
"Mod_OnPlrChat": {
"type": "resref",
@ -864,7 +871,7 @@
},
"Mod_OnPlrTarget": {
"type": "resref",
"value": "prc_onplaytarget"
"value": "mmd_onplaytarget"
},
"Mod_OnPlrTileAct": {
"type": "resref",
@ -1213,6 +1220,21 @@
"type": "int",
"value": 1
}
},
{
"__struct_id": 0,
"Name": {
"type": "cexostring",
"value": "PW_MODE"
},
"Type": {
"type": "dword",
"value": 1
},
"Value": {
"type": "int",
"value": 1
}
}
]
}

@ -26593,6 +26593,25 @@
"value": "prc_pm_mage2"
}
},
{
"__struct_id": 0,
"CR": {
"type": "float",
"value": 3.0
},
"FACTION": {
"type": "cexostring",
"value": "Defender"
},
"NAME": {
"type": "cexostring",
"value": "Spiritual Weapon"
},
"RESREF": {
"type": "resref",
"value": "prc_spirit_weapn"
}
},
{
"__struct_id": 0,
"CR": {

@ -14,6 +14,22 @@
"type": "byte",
"value": 0
},
"LIST": {
"type": "list",
"value": [
{
"__struct_id": 0,
"NAME": {
"type": "cexostring",
"value": "\"Create Area\" Door"
},
"RESREF": {
"type": "resref",
"value": "inn2pcrooms"
}
}
]
},
"STRREF": {
"type": "dword",
"value": 6688

@ -1153,6 +1153,17 @@
"value": "4mi_15_6"
}
},
{
"__struct_id": 0,
"NAME": {
"type": "cexostring",
"value": "Unarmed Spiritual Weapon \"Fists\""
},
"RESREF": {
"type": "resref",
"value": "prc_sprtwp_armor"
}
},
{
"__struct_id": 0,
"NAME": {
@ -7333,6 +7344,17 @@
"value": "servantprops4"
}
},
{
"__struct_id": 0,
"NAME": {
"type": "cexostring",
"value": "Spiritual Weapon Properties"
},
"RESREF": {
"type": "resref",
"value": "prc_sprtwpn_hide"
}
},
{
"__struct_id": 0,
"RESREF": {
@ -8977,6 +8999,17 @@
"value": 16807690
}
},
{
"__struct_id": 0,
"NAME": {
"type": "cexostring",
"value": "Spirtual Weapon Slam"
},
"RESREF": {
"type": "resref",
"value": "prc_sprtwpn_slam"
}
},
{
"__struct_id": 0,
"RESREF": {
@ -14000,6 +14033,17 @@
"value": 767
}
},
{
"__struct_id": 0,
"RESREF": {
"type": "resref",
"value": "prc_scr_997"
},
"STRREF": {
"type": "dword",
"value": 16790493
}
},
{
"__struct_id": 0,
"RESREF": {
@ -21029,6 +21073,50 @@
"value": 6340
}
},
{
"__struct_id": 0,
"RESREF": {
"type": "resref",
"value": "prc_scr_874"
},
"STRREF": {
"type": "dword",
"value": 16790512
}
},
{
"__struct_id": 0,
"RESREF": {
"type": "resref",
"value": "prc_scr_865"
},
"STRREF": {
"type": "dword",
"value": 16790497
}
},
{
"__struct_id": 0,
"RESREF": {
"type": "resref",
"value": "prc_scr_868"
},
"STRREF": {
"type": "dword",
"value": 16790502
}
},
{
"__struct_id": 0,
"RESREF": {
"type": "resref",
"value": "prc_scr_871"
},
"STRREF": {
"type": "dword",
"value": 16790507
}
},
{
"__struct_id": 0,
"NAME": {
@ -22107,6 +22195,17 @@
"value": 917
}
},
{
"__struct_id": 0,
"RESREF": {
"type": "resref",
"value": "prc_scr_877"
},
"STRREF": {
"type": "dword",
"value": 16790517
}
},
{
"__struct_id": 0,
"RESREF": {
@ -22206,6 +22305,28 @@
"value": 2671
}
},
{
"__struct_id": 0,
"RESREF": {
"type": "resref",
"value": "prc_scr_880"
},
"STRREF": {
"type": "dword",
"value": 16790522
}
},
{
"__struct_id": 0,
"RESREF": {
"type": "resref",
"value": "prc_scr_881"
},
"STRREF": {
"type": "dword",
"value": 16790525
}
},
{
"__struct_id": 0,
"NAME": {
@ -22899,6 +23020,17 @@
"value": 16829598
}
},
{
"__struct_id": 0,
"RESREF": {
"type": "resref",
"value": "prc_scr_884"
},
"STRREF": {
"type": "dword",
"value": 16790530
}
},
{
"__struct_id": 0,
"NAME": {
@ -24579,7 +24711,7 @@
},
"RESREF": {
"type": "resref",
"value": "mc_blckstickbloo"
"value": "mc_blckstickbld"
}
},
{
@ -24755,7 +24887,7 @@
},
"RESREF": {
"type": "resref",
"value": "mc_pieceofleathe"
"value": "mc_pieceofleathr"
}
},
{
@ -25668,7 +25800,7 @@
},
"RESREF": {
"type": "resref",
"value": "mc_grasshopperhl"
"value": "mc_grasshopprhlg"
}
},
{

Binary file not shown.

BIN
_module/ncs/cv_inn_door.ncs Normal file

Binary file not shown.

BIN
_module/ncs/death_dummy.ncs Normal file

Binary file not shown.

BIN
_module/ncs/mmd_onnui.ncs Normal file

Binary file not shown.

Binary file not shown.

BIN
_module/ncs/mod_nui.ncs Normal file

Binary file not shown.

BIN
_module/ncs/mod_target.ncs Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
_module/ncs/sei_sit.ncs Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -0,0 +1,44 @@
void main()
{
//:: Declare major variables
object oPC = GetPCSpeaker();
object oBaseArea = GetObjectByTag("VIT_PC_ROOMS");
string sPCName = GetName(oPC);
string sBaseResRef = GetResRef(oBaseArea);
string sBaseName = GetName(oBaseArea);
string sNewTag = sPCName+sBaseResRef;
string sNewName = sPCName+"'s Room at the Valeford Tavern & Inn";
//:: Create instanced area from player's information
CreateArea(sBaseResRef, sNewTag, sNewName);
//:: Get information about new area instance
object oNewRoom = GetObjectByTag(sNewTag);
string sNewResRef = GetResRef(oNewRoom);
location lEntry = GetLocation(GetObjectByTag("PC_ROOM_MAT"));
//:: Create entry waypoint in new area instance
CreateObject(OBJECT_TYPE_WAYPOINT, "nw_waypoint001", lEntry, FALSE, "WP_"+sNewTag);
//:: Make sure the area is valid
object oTarget;
location lTarget;
oTarget = GetWaypointByTag("WP_"+sNewTag);
lTarget = GetLocation(oTarget);
if (GetAreaFromLocation(lTarget)==OBJECT_INVALID)
{
SendMessageToPC(oPC, "Warning: Area does not exist!");
return;
}
//:: Move PC to instanced area.
AssignCommand(oPC, ClearAllActions());
AssignCommand(oPC, ActionJumpToLocation(lTarget));
}

@ -0,0 +1,10 @@
void main()
{
object oPC = GetClickingObject();
if (!GetIsPC(oPC)) return;
ActionStartConversation(oPC, "");
}

@ -0,0 +1,22 @@
void RespawnPlaceable(string sPlaceableTag, location lLocation)
{
// Destroy any existing placeable with the same tag to avoid duplication
object oPlaceable = GetObjectByTag(sPlaceableTag);
if (oPlaceable != OBJECT_INVALID)
{
DestroyObject(oPlaceable);
}
// Create the placeable at the same location
CreateObject(OBJECT_TYPE_PLACEABLE, sPlaceableTag, lLocation);
}
void main()
{
// Get the placeable's tag and location before it is destroyed
string sPlaceableTag = GetTag(OBJECT_SELF);
location lLocation = GetLocation(OBJECT_SELF);
// Delay the respawn for 5 minutes (300 seconds)
DelayCommand(300.0, RespawnPlaceable(sPlaceableTag, lLocation));
}

File diff suppressed because it is too large Load Diff

494
_module/nss/inc_examine.nss Normal file

@ -0,0 +1,494 @@
/*
Examine NUI Windows
Created By: Daz
*/
#include "inc_nui"
#include "inc_util"
const string EXAMINE_NUI_WINDOW_ID = "EXAMINEWINDOW";
const string EXAMINE_WINDOW_GEOMETRY_JSON = "EXAMINE_WINDOW_GEOMETRY_JSON";
const string EXAMINE_GENERIC_WINDOW_JSON = "EXAMINE_GENERIC_WINDOW_JSON";
const string EXAMINE_ITEM_WINDOW_JSON = "EXAMINE_ITEM_WINDOW_JSON";
const string EXAMINE_CURRENT_WINDOW_TYPE = "EXAMINE_CURRENT_WINDOW_TYPE";
const string EXAMINE_CURRENT_OBJECT = "EXAMINE_CURRENT_OBJECT";
const float EXAMINE_GENERIC_WINDOW_WIDTH = 500.0f;
const float EXAMINE_GENERIC_WINDOW_HEIGHT = 255.0f;
const float EXAMINE_ITEM_WINDOW_WIDTH = 500.0f;
const float EXAMINE_ITEM_WINDOW_HEIGHT = 400.0f;
void Examine_DisablePanels(object oPlayer);
json Examine_GetWindowJson(int nPanel);
json Examine_GetGenericWindowJson();
json Examine_GetItemWindowJson();
float Examine_GetWindowWidth(int nPanel);
float Examine_GetWindowHeight(int nPanel);
void Examine_HandleGUIEvents(object oPlayer, object oTarget, int nPanel);
void Examine_HandleNUIEvents(object oPlayer, int nToken, string sType, string sElement, int nArrayIndex);
void Examine_SetData(object oPlayer, int nToken, object oTarget, int nPanel);
void Examine_SetGenericData(object oPlayer, int nToken, object oTarget, int nPanel);
string Examine_GetItemPropertyString(itemproperty ip);
void Examine_SetItemData(object oPlayer, int nToken, object oItem);
void Examine_DisablePanels(object oPlayer)
{
SetGuiPanelDisabled(oPlayer, GUI_PANEL_EXAMINE_CREATURE, TRUE);
SetGuiPanelDisabled(oPlayer, GUI_PANEL_EXAMINE_ITEM, TRUE);
SetGuiPanelDisabled(oPlayer, GUI_PANEL_EXAMINE_PLACEABLE, TRUE);
SetGuiPanelDisabled(oPlayer, GUI_PANEL_EXAMINE_DOOR, TRUE);
}
json Examine_GetWindowJson(int nPanel)
{
json jWindow;
switch (nPanel)
{
case GUI_PANEL_EXAMINE_CREATURE:
case GUI_PANEL_EXAMINE_PLACEABLE:
case GUI_PANEL_EXAMINE_DOOR:
jWindow = Examine_GetGenericWindowJson();
break;
case GUI_PANEL_EXAMINE_ITEM:
jWindow = Examine_GetItemWindowJson();
break;
}
return jWindow;
}
json Examine_GetGenericWindowJson()
{
json jRoot = GetLocalJson(GetModule(), EXAMINE_GENERIC_WINDOW_JSON);
if (jRoot == JsonNull())
{
json jCol = JsonArray(), jRow;
jRow = JsonArray();
{
json jSubCol, jSubRow;
jSubCol = JsonArray();
// Image
jSubRow = JsonArray();
{
json jImage = NuiImage(NuiBind("image_1"), JsonInt(NUI_ASPECT_EXACTSCALED), JsonInt(NUI_HALIGN_CENTER), JsonInt(NUI_VALIGN_TOP));
jImage = NuiWidth(jImage, 64.0f);
jImage = NuiHeight(jImage, 100.0f);
jSubRow = JsonArrayInsert(jSubRow, jImage);
}
jSubCol = NuiInsertRow(jSubCol, jSubRow);
// Spacer
jSubRow = JsonArray();
{
jSubRow = JsonArrayInsert(jSubRow, NuiSpacer());
}
jSubCol = NuiInsertRow(jSubCol, jSubRow);
jRow = JsonArrayInsert(jRow, NuiCol(jSubCol));
jSubCol = JsonArray();
// Description Label
jSubRow = JsonArray();
{
json jHeader = NuiHeader(JsonString("Description"));
jSubRow = JsonArrayInsert(jSubRow, jHeader);
}
jSubCol = NuiInsertRow(jSubCol, jSubRow);
// Description Text
jSubRow = JsonArray();
{
json jDescription = NuiText(NuiBind("description"));
jDescription = NuiHeight(jDescription, 160.0f);
jSubRow = JsonArrayInsert(jSubRow, jDescription);
}
jSubCol = NuiInsertRow(jSubCol, jSubRow);
// Spacer
jSubRow = JsonArray();
{
jSubRow = JsonArrayInsert(jSubRow, NuiSpacer());
}
jSubCol = NuiInsertRow(jSubCol, jSubRow);
jRow = JsonArrayInsert(jRow, NuiCol(jSubCol));
}
jCol = NuiInsertRow(jCol, jRow);
jRoot = NuiCol(jCol);
SetLocalJson(GetModule(), EXAMINE_GENERIC_WINDOW_JSON, jRoot);
}
return jRoot;
}
json Examine_GetItemWindowJson()
{
json jRoot = GetLocalJson(GetModule(), EXAMINE_ITEM_WINDOW_JSON);
if (jRoot == JsonNull())
{
json jCol = JsonArray(), jRow;
jRow = JsonArray();
{
json jSubCol, jSubRow;
jSubCol = JsonArray();
// Image
jSubRow = JsonArray();
{
json jImage = NuiImage(NuiBind("image_1"), JsonInt(NUI_ASPECT_EXACTSCALED), JsonInt(NUI_HALIGN_CENTER), JsonInt(NUI_VALIGN_TOP));
json jRect = NuiRect(0.0f, 0.0f, 64.0f, 192.0f);
json jDrawList = JsonArray();
jDrawList = JsonArrayInsert(jDrawList, NuiDrawListImage(NuiBind("complex_item"), NuiBind("image_2"), jRect, JsonInt(NUI_ASPECT_EXACTSCALED), JsonInt(NUI_HALIGN_CENTER), JsonInt(NUI_VALIGN_TOP)));
jDrawList = JsonArrayInsert(jDrawList, NuiDrawListImage(NuiBind("complex_item"), NuiBind("image_3"), jRect, JsonInt(NUI_ASPECT_EXACTSCALED), JsonInt(NUI_HALIGN_CENTER), JsonInt(NUI_VALIGN_TOP)));
jImage = NuiDrawList(jImage, JsonBool(TRUE), jDrawList);
jImage = NuiWidth(jImage, 64.0f);
jImage = NuiHeight(jImage, 192.0f);
jSubRow = JsonArrayInsert(jSubRow, jImage);
}
jSubCol = NuiInsertRow(jSubCol, jSubRow);
// Button?
jSubRow = JsonArray();
{
json jButton = NuiButton(JsonString("Button?"));
jButton = NuiId(jButton, "btn_button");
jButton = NuiWidth(jButton, 64.0f);
jButton = NuiHeight(jButton, 35.0f);
jSubRow = JsonArrayInsert(jSubRow, jButton);
}
//jSubCol = NuiInsertRow(jSubCol, jSubRow);
// Spacer
jSubRow = JsonArray();
{
jSubRow = JsonArrayInsert(jSubRow, NuiSpacer());
}
jSubCol = NuiInsertRow(jSubCol, jSubRow);
jRow = JsonArrayInsert(jRow, NuiCol(jSubCol));
jSubCol = JsonArray();
// Description Label
jSubRow = JsonArray();
{
json jHeader = NuiHeader(JsonString("Description"));
jSubRow = JsonArrayInsert(jSubRow, jHeader);
}
jSubCol = NuiInsertRow(jSubCol, jSubRow);
// Description Text
jSubRow = JsonArray();
{
json jDescription = NuiText(NuiBind("description"));
jDescription = NuiHeight(jDescription, 160.0f);
jSubRow = JsonArrayInsert(jSubRow, jDescription);
}
jSubCol = NuiInsertRow(jSubCol, jSubRow);
// Item Properties Label
jSubRow = JsonArray();
{
json jHeader = NuiHeader(JsonString("Item Properties"));
jSubRow = JsonArrayInsert(jSubRow, jHeader);
}
jSubCol = NuiInsertRow(jSubCol, jSubRow);
// Item Properties List
jSubRow = JsonArray();
{
json jListTemplate = JsonArray();
{
json jLabel = NuiLabel(NuiBind("property"), JsonInt(NUI_HALIGN_LEFT), JsonInt(NUI_VALIGN_MIDDLE));
jLabel = NuiStyleForegroundColor(jLabel, NuiBind("color"));
jListTemplate = JsonArrayInsert(jListTemplate, NuiListTemplateCell(jLabel, 0.0f, TRUE));
}
json jList = NuiList(jListTemplate, NuiBind("property"), 16.0f);
jList = NuiHeight(jList, 105.0f);
jSubRow = JsonArrayInsert(jSubRow, jList);
}
jSubCol = NuiInsertRow(jSubCol, jSubRow);
// Spacer
jSubRow = JsonArray();
{
jSubRow = JsonArrayInsert(jSubRow, NuiSpacer());
}
jSubCol = NuiInsertRow(jSubCol, jSubRow);
jRow = JsonArrayInsert(jRow, NuiCol(jSubCol));
}
jCol = NuiInsertRow(jCol, jRow);
jRoot = NuiCol(jCol);
SetLocalJson(GetModule(), EXAMINE_ITEM_WINDOW_JSON, jRoot);
}
return jRoot;
}
float Examine_GetWindowWidth(int nPanel)
{
float fWidth;
switch (nPanel)
{
case GUI_PANEL_EXAMINE_CREATURE:
case GUI_PANEL_EXAMINE_PLACEABLE:
case GUI_PANEL_EXAMINE_DOOR:
fWidth = EXAMINE_GENERIC_WINDOW_WIDTH;
break;
case GUI_PANEL_EXAMINE_ITEM:
fWidth = EXAMINE_ITEM_WINDOW_WIDTH;
break;
}
return fWidth;
}
float Examine_GetWindowHeight(int nPanel)
{
float fHeight;
switch (nPanel)
{
case GUI_PANEL_EXAMINE_CREATURE:
case GUI_PANEL_EXAMINE_PLACEABLE:
case GUI_PANEL_EXAMINE_DOOR:
fHeight = EXAMINE_GENERIC_WINDOW_HEIGHT;
break;
case GUI_PANEL_EXAMINE_ITEM:
fHeight = EXAMINE_ITEM_WINDOW_HEIGHT;
break;
}
return fHeight;
}
void Examine_HandleGUIEvents(object oPlayer, object oTarget, int nPanel)
{
json jGeometry = GetLocalJson(oPlayer, EXAMINE_WINDOW_GEOMETRY_JSON);
int nToken = NuiFindWindow(oPlayer, EXAMINE_NUI_WINDOW_ID);
if (nToken)
{
if (GetLocalObject(oPlayer, EXAMINE_CURRENT_OBJECT) == oTarget)
return;
int bIsItemExamine = nPanel == GUI_PANEL_EXAMINE_ITEM;
int nCurrentWindowType = GetLocalInt(oPlayer, EXAMINE_CURRENT_WINDOW_TYPE);
if (bIsItemExamine && nCurrentWindowType != GUI_PANEL_EXAMINE_ITEM)
{
NuiSetGroupLayout(oPlayer, nToken, NUI_WINDOW_ROOT_GROUP, Examine_GetWindowJson(nPanel));
NuiSetBind(oPlayer, nToken, NUI_WINDOW_GEOMETRY_BIND, NuiSetRectHeight(jGeometry, Examine_GetWindowHeight(nPanel)));
}
else if (!bIsItemExamine && nCurrentWindowType == GUI_PANEL_EXAMINE_ITEM)
{
NuiSetGroupLayout(oPlayer, nToken, NUI_WINDOW_ROOT_GROUP, Examine_GetWindowJson(nPanel));
NuiSetBind(oPlayer, nToken, NUI_WINDOW_GEOMETRY_BIND, NuiSetRectHeight(jGeometry, Examine_GetWindowHeight(nPanel)));
}
Examine_SetData(oPlayer, nToken, oTarget, nPanel);
SetLocalInt(oPlayer, EXAMINE_CURRENT_WINDOW_TYPE, nPanel);
SetLocalObject(oPlayer, EXAMINE_CURRENT_OBJECT, oTarget);
return;
}
json jRoot = Examine_GetWindowJson(nPanel);
json jWindow = NuiWindow(jRoot, NuiBind(NUI_WINDOW_TITLE_BIND), NuiBind(NUI_WINDOW_GEOMETRY_BIND), JsonBool(FALSE), JsonNull(), JsonBool(TRUE), JsonBool(FALSE), JsonBool(TRUE));
float fWidth = Examine_GetWindowWidth(nPanel);
float fHeight = Examine_GetWindowHeight(nPanel);
if (jGeometry == JsonNull())
jGeometry = NuiGetCenteredGeometryRect(oPlayer, fWidth, fHeight);
else
{
jGeometry = NuiSetRectWidth(jGeometry, fWidth);
jGeometry = NuiSetRectHeight(jGeometry, fHeight);
}
nToken = NuiCreate(oPlayer, jWindow, EXAMINE_NUI_WINDOW_ID);
NuiSetBindWatch(oPlayer, nToken, NUI_WINDOW_GEOMETRY_BIND, TRUE);
NuiSetBind(oPlayer, nToken, NUI_WINDOW_GEOMETRY_BIND, jGeometry);
Examine_SetData(oPlayer, nToken, oTarget, nPanel);
SetLocalInt(oPlayer, EXAMINE_CURRENT_WINDOW_TYPE, nPanel);
SetLocalObject(oPlayer, EXAMINE_CURRENT_OBJECT, oTarget);
}
void Examine_HandleNUIEvents(object oPlayer, int nToken, string sType, string sElement, int nArrayIndex)
{
if (sType == NUI_EVENT_CLOSE)
{
DeleteLocalInt(oPlayer, EXAMINE_CURRENT_WINDOW_TYPE);
DeleteLocalObject(oPlayer, EXAMINE_CURRENT_OBJECT);
}
else if (sType == NUI_EVENT_WATCH)
{
if (sElement == NUI_WINDOW_GEOMETRY_BIND)
{
SetLocalJson(oPlayer, EXAMINE_WINDOW_GEOMETRY_JSON, NuiGetBind(oPlayer, nToken, NUI_WINDOW_GEOMETRY_BIND));
}
}
}
int Examine_HandleIdentifyItem(object oPlayer, object oItem)
{
int bIdentified = GetIdentified(oItem);
if (!bIdentified)
{
int nIdentifySkillRank = GetSkillRank(SKILL_LORE, oPlayer);
if (nIdentifySkillRank < 0)
return FALSE;
if (nIdentifySkillRank > 55)
{
SetIdentified(oItem, TRUE);
return TRUE;
}
int nMaxItemGPValue = StringToInt(Get2DAString("skillvsitemcost", "DeviceCostMax", nIdentifySkillRank));
SetIdentified(oItem, TRUE);
bIdentified = GetGoldPieceValue(oItem) <= nMaxItemGPValue;
SetIdentified(oItem, bIdentified);
}
return bIdentified;
}
void Examine_SetData(object oPlayer, int nToken, object oTarget, int nPanel)
{
Examine_SetGenericData(oPlayer, nToken, oTarget, nPanel);
if (nPanel == GUI_PANEL_EXAMINE_ITEM)
Examine_SetItemData(oPlayer, nToken, oTarget);
}
void Examine_SetGenericData(object oPlayer, int nToken, object oTarget, int nPanel)
{
string sTitle, sDescription;
json jImage1, jImage2, jImage3;
int bComplexItem = FALSE;
switch (nPanel)
{
case GUI_PANEL_EXAMINE_CREATURE:
case GUI_PANEL_EXAMINE_PLACEABLE:
case GUI_PANEL_EXAMINE_DOOR:
{
sTitle = GetName(oTarget);
jImage1 = JsonString(GetPortraitResRef(oTarget) + "m");
sDescription = GetDescription(oTarget);
break;
}
case GUI_PANEL_EXAMINE_ITEM:
{
int bIdentified = Examine_HandleIdentifyItem(oPlayer, oTarget);
int nBaseItemType = GetBaseItemType(oTarget);
sTitle = Util_GetItemName(oTarget, bIdentified);
json jItem = ObjectToJson(oTarget);
json jComplexIconData = Util_GetComplexIconData(jItem, nBaseItemType);
if (JsonGetType(jComplexIconData))
{
jImage1 = JsonObjectGet(jComplexIconData, "bottom");
jImage2 = JsonObjectGet(jComplexIconData, "middle");
jImage3 = JsonObjectGet(jComplexIconData, "top");
bComplexItem = TRUE;
}
else
{
jImage1 = JsonString(Util_GetIconResref(oTarget, jItem, nBaseItemType));
}
sDescription = GetDescription(oTarget, FALSE, bIdentified);
int nStatsStrRef = StringToInt(Get2DAString("baseitems", "BaseItemStatRef", nBaseItemType));
if (nStatsStrRef)
{
sDescription += "\n\n" + GetStringByStrRef(nStatsStrRef);
}
break;
}
}
NuiSetBind(oPlayer, nToken, NUI_WINDOW_TITLE_BIND, JsonString(sTitle));
NuiSetBind(oPlayer, nToken, "image_1", jImage1);
if (bComplexItem)
{
NuiSetBind(oPlayer, nToken, "image_2", jImage2);
NuiSetBind(oPlayer, nToken, "image_3", jImage3);
}
NuiSetBind(oPlayer, nToken, "complex_item", JsonBool(bComplexItem));
NuiSetBind(oPlayer, nToken, "description", JsonString(sDescription));
}
string Examine_GetItemPropertyString(itemproperty ip)
{
int nType = GetItemPropertyType(ip);
string sName = GetStringByStrRef(StringToInt(Get2DAString("itempropdef", "GameStrRef", nType)));
int nSubType = GetItemPropertySubType(ip);
if(nSubType != -1)
{
string sSubTypeResRef = Get2DAString("itempropdef", "SubTypeResRef", nType);
int nStrRef = StringToInt(Get2DAString(sSubTypeResRef, "Name", nSubType));
if(nStrRef)
sName += " " + GetStringByStrRef(nStrRef);
}
int nParam1 = GetItemPropertyParam1(ip);
if(nParam1 != -1)
{
string sParamResRef = Get2DAString("iprp_paramtable", "TableResRef", nParam1);
string sSubTypeResRef = Get2DAString("itempropdef", "SubTypeResRef", nType);
string sTableResRef = Get2DAString(sSubTypeResRef, "TableResRef", nParam1);
int nStrRef = StringToInt(Get2DAString(sParamResRef, "Name", GetItemPropertyParam1Value(ip)));
if(nStrRef)
sName += " " + GetStringByStrRef(nStrRef);
}
int nCostTable = GetItemPropertyCostTable(ip);
if(nCostTable != -1)
{
string sCostTableResRef = Get2DAString("iprp_costtable", "Name", nCostTable);
int nStrRef = StringToInt(Get2DAString(sCostTableResRef, "Name", GetItemPropertyCostTableValue(ip)));
if(nStrRef)
sName += " " + GetStringByStrRef(nStrRef);
}
return sName;
}
void Examine_SetItemData(object oPlayer, int nToken, object oItem)
{
int bIdentified = GetIdentified(oItem);
json jProperties = JsonArray();
json jColors = JsonArray();
if (bIdentified)
{
itemproperty ip = GetFirstItemProperty(oItem);
while (GetIsItemPropertyValid(ip))
{
jProperties = JsonArrayInsert(jProperties, JsonString(Examine_GetItemPropertyString(ip)));
jColors = JsonArrayInsert(jColors, GetItemPropertyDurationType(ip) == DURATION_TYPE_TEMPORARY ? NuiColor(0, 0, 255) : NuiColor(255, 255, 255));
ip = GetNextItemProperty(oItem);
}
}
NuiSetBind(oPlayer, nToken, "property", jProperties);
NuiSetBind(oPlayer, nToken, "color", jColors);
}

300
_module/nss/inc_gennui.nss Normal file

@ -0,0 +1,300 @@
/*
Generic NUI Windows
Created By: Daz
*/
#include "inc_nui"
const string GNW_WINDOW_PREFIX = "GNW";
const string GNW_OK_CANCEL_WINDOW = "OKCANCEL";
const string GNW_OPTIONS_WINDOW = "OPTIONS";
const string GNW_INFO_WINDOW = "INFO";
const string GNW_MENU_WINDOW = "MENU";
// Call this in your EVENT_SCRIPT_MODULE_ON_NUI_EVENT script
void GNW_HandleNUIEvents();
void GNW_ShowOkCancelWindow(object oPlayer, string sText, string sOkAction, string sCancelAction);
json GNW_AddOption(json jOptions, string sLabel, string sVarName, object oTarget);
void GNW_ShowOptionsWindow(object oPlayer, string sTitle, json jOptions);
void GNW_ShowInfoWindow(object oPlayer, string sTitle, string sText);
void GNW_HandleNUIEvents()
{
object oPlayer = NuiGetEventPlayer();
int nToken = NuiGetEventWindow();
string sWindowId = NuiGetWindowId(oPlayer, nToken);
if (GetStringLeft(sWindowId, GetStringLength(GNW_WINDOW_PREFIX)) != GNW_WINDOW_PREFIX)
return;
string sType = NuiGetEventType();
string sElement = NuiGetEventElement();
if (sWindowId == GNW_WINDOW_PREFIX + GNW_OK_CANCEL_WINDOW)
{
if (sType == "click")
{
if (sElement == "btn_ok")
{
ExecuteScriptChunk(GetLocalString(oPlayer, GNW_WINDOW_PREFIX + GNW_OK_CANCEL_WINDOW + "_OKACTION"), oPlayer);
NuiDestroy(oPlayer, nToken);
}
else if (sElement == "btn_cancel")
{
ExecuteScriptChunk(GetLocalString(oPlayer, GNW_WINDOW_PREFIX + GNW_OK_CANCEL_WINDOW + "_CANCELACTION"), oPlayer);
NuiDestroy(oPlayer, nToken);
}
}
else if (sType == "close")
{
ExecuteScriptChunk(GetLocalString(oPlayer, GNW_WINDOW_PREFIX + GNW_OK_CANCEL_WINDOW + "_CANCELACTION"), oPlayer);
}
}
else if (sWindowId == GNW_WINDOW_PREFIX + GNW_OPTIONS_WINDOW)
{
if (sType == "click")
{
if (sElement == "btn_ok")
{
NuiDestroy(oPlayer, nToken);
}
}
else if (sType == "watch")
{
json jOptions = GetLocalJson(oPlayer, GNW_WINDOW_PREFIX + GNW_OPTIONS_WINDOW);
json jChecked = NuiGetBind(oPlayer, nToken, "checked");
int nOption, nNumOptions = JsonGetLength(jOptions);
for (nOption = 0; nOption < nNumOptions; nOption++)
{
json jOption = JsonArrayGet(jOptions, nOption);
string sVarName = JsonGetString(JsonObjectGet(jOption, "varname"));
object oTarget = StringToObject(JsonGetString(JsonObjectGet(jOption, "target")));
int bCurrentValue = GetLocalInt(oTarget, sVarName);
int bNewValue = JsonGetInt(JsonArrayGet(jChecked, nOption));
if (bCurrentValue != bNewValue)
{
SetLocalInt(oTarget, sVarName, bNewValue);
SendMessageToPC(oPlayer, "Setting '" + sVarName + "' on " + GetName(oTarget) + " to " + IntToString(bNewValue));
}
}
}
}
else if (sWindowId == GNW_WINDOW_PREFIX + GNW_INFO_WINDOW)
{
if (sType == "click")
{
if (sElement == "btn_ok")
{
NuiDestroy(oPlayer, nToken);
}
}
}
else if (sWindowId == GNW_WINDOW_PREFIX + GNW_MENU_WINDOW)
{
if (sType == "click")
{
if (sElement == "btn_menu")
{
int bSelected = JsonGetInt(NuiGetBind(oPlayer, nToken, "btn_menu"));
SendMessageToPC(oPlayer, "Menu: " + (bSelected ? "Open" : "Close"));
}
}
}
}
void GNW_ShowOkCancelWindow(object oPlayer, string sText, string sOkAction, string sCancelAction)
{
object oModule = GetModule();
json jWindow = GetLocalJson(oModule, GNW_WINDOW_PREFIX + GNW_OK_CANCEL_WINDOW);
if (jWindow == JsonNull())
{
json jCol;
json jRow;
jCol = JsonArray();
jRow = JsonArray();
{
json jText = NuiText(NuiBind("text"));
jRow = JsonArrayInsert(jRow, jText);
}
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
jRow = JsonArray();
{
json jButtonCancel = NuiButton(JsonString("Cancel"));
jButtonCancel = NuiId(jButtonCancel, "btn_cancel");
jButtonCancel = NuiWidth(jButtonCancel, 100.0f);
jButtonCancel = NuiHeight(jButtonCancel, 35.0f);
jRow = JsonArrayInsert(jRow, jButtonCancel);
jRow = JsonArrayInsert(jRow, NuiSpacer());
json jButtonOK = NuiButton(JsonString("OK"));
jButtonOK = NuiId(jButtonOK, "btn_ok");
jButtonOK = NuiWidth(jButtonOK, 100.0f);
jButtonOK = NuiHeight(jButtonOK, 35.0f);
jRow = JsonArrayInsert(jRow, jButtonOK);
}
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
json jRoot = NuiCol(jCol);
jWindow = NuiWindow(jRoot, JsonBool(FALSE), NuiRect(-1.0f, -1.0f, 400.0f, 200.0f), JsonBool(FALSE), JsonBool(FALSE), JsonBool(FALSE), JsonBool(FALSE), JsonBool(TRUE));
SetLocalJson(oModule, GNW_WINDOW_PREFIX + GNW_OK_CANCEL_WINDOW, jWindow);
}
int nToken = NuiCreate(oPlayer, jWindow, GNW_WINDOW_PREFIX + GNW_OK_CANCEL_WINDOW);
NuiSetBind(oPlayer, nToken, "text", JsonString(sText));
SetLocalString(oPlayer, GNW_WINDOW_PREFIX + GNW_OK_CANCEL_WINDOW + "_OKACTION", sOkAction);
SetLocalString(oPlayer, GNW_WINDOW_PREFIX + GNW_OK_CANCEL_WINDOW + "_CANCELACTION", sCancelAction);
}
json GNW_AddOption(json jOptions, string sLabel, string sVarName, object oTarget)
{
json jOption = JsonObject();
jOption = JsonObjectSet(jOption, "label", JsonString(sLabel));
jOption = JsonObjectSet(jOption, "varname", JsonString(sVarName));
jOption = JsonObjectSet(jOption, "target", JsonString(ObjectToString(oTarget)));
return JsonArrayInsert(jOptions, jOption);
}
void GNW_ShowOptionsWindow(object oPlayer, string sTitle, json jOptions)
{
object oModule = GetModule();
json jWindow = GetLocalJson(oModule, GNW_WINDOW_PREFIX + GNW_OPTIONS_WINDOW);
if (jWindow == JsonNull())
{
json jCol;
json jRow;
jCol = JsonArray();
jRow = JsonArray();
{
json jListTemplate = JsonArray();
{
json jCheck = NuiCheck(NuiBind("labels"), NuiBind("checked"));
jListTemplate = JsonArrayInsert(jListTemplate, NuiListTemplateCell(jCheck, 0.0f, TRUE));
}
jRow = JsonArrayInsert(jRow, NuiList(jListTemplate, NuiBind("checked"), 15.0f));
}
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
jRow = JsonArray();
{
jRow = JsonArrayInsert(jRow, NuiSpacer());
json jButtonOK = NuiButton(JsonString("OK"));
jButtonOK = NuiId(jButtonOK, "btn_ok");
jButtonOK = NuiWidth(jButtonOK, 100.0f);
jButtonOK = NuiHeight(jButtonOK, 35.0f);
jRow = JsonArrayInsert(jRow, jButtonOK);
}
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
json jRoot = NuiCol(jCol);
jWindow = NuiWindow(jRoot, NuiBind("title"), NuiRect(-1.0f, -1.0f, 350.0f, 300.0f), JsonBool(FALSE), JsonNull(), JsonBool(TRUE), JsonBool(FALSE), JsonBool(TRUE));
SetLocalJson(oModule, GNW_WINDOW_PREFIX + GNW_OPTIONS_WINDOW, jWindow);
}
int nToken = NuiCreate(oPlayer, jWindow, GNW_WINDOW_PREFIX + GNW_OPTIONS_WINDOW);
SetLocalJson(oPlayer, GNW_WINDOW_PREFIX + GNW_OPTIONS_WINDOW, jOptions);
NuiSetBind(oPlayer, nToken, "title", JsonString(sTitle));
json jLabels = JsonArray();
json jChecked = JsonArray();
int nOption, nNumOptions = JsonGetLength(jOptions);
for (nOption = 0; nOption < nNumOptions; nOption++)
{
json jOption = JsonArrayGet(jOptions, nOption);
json jLabel = JsonObjectGet(jOption, "label");
string sVarName = JsonGetString(JsonObjectGet(jOption, "varname"));
object oTarget = StringToObject(JsonGetString(JsonObjectGet(jOption, "target")));
jLabels = JsonArrayInsert(jLabels, jLabel);
jChecked = JsonArrayInsert(jChecked, JsonBool(GetLocalInt(oTarget, sVarName)));
}
NuiSetBind(oPlayer, nToken, "labels", jLabels);
NuiSetBind(oPlayer, nToken, "checked", jChecked);
NuiSetBindWatch(oPlayer, nToken, "checked", TRUE);
}
void GNW_ShowInfoWindow(object oPlayer, string sTitle, string sText)
{
object oModule = GetModule();
json jWindow = GetLocalJson(oModule, GNW_WINDOW_PREFIX + GNW_INFO_WINDOW);
if (jWindow == JsonNull())
{
json jCol;
json jRow;
jCol = JsonArray();
jRow = JsonArray();
{
json jText = NuiText(NuiBind("text"));
jRow = JsonArrayInsert(jRow, jText);
}
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
jRow = JsonArray();
{
jRow = JsonArrayInsert(jRow, NuiSpacer());
json jButtonOK = NuiButton(JsonString("OK"));
jButtonOK = NuiId(jButtonOK, "btn_ok");
jButtonOK = NuiWidth(jButtonOK, 100.0f);
jButtonOK = NuiHeight(jButtonOK, 35.0f);
jRow = JsonArrayInsert(jRow, jButtonOK);
jRow = JsonArrayInsert(jRow, NuiSpacer());
}
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
json jRoot = NuiCol(jCol);
jWindow = NuiWindow(jRoot, NuiBind("title"), NuiRect(-1.0f, -1.0f, 400.0f, 200.0f), JsonBool(FALSE), JsonNull(), JsonBool(TRUE), JsonBool(FALSE), JsonBool(TRUE));
SetLocalJson(oModule, GNW_WINDOW_PREFIX + GNW_INFO_WINDOW, jWindow);
}
int nToken = NuiCreate(oPlayer, jWindow, GNW_WINDOW_PREFIX + GNW_INFO_WINDOW);
NuiSetBind(oPlayer, nToken, "title", JsonString(sTitle));
NuiSetBind(oPlayer, nToken, "text", JsonString(sText));
}
void GNW_ShowMenuButton(object oPlayer)
{
object oModule = GetModule();
json jWindow = GetLocalJson(oModule, GNW_WINDOW_PREFIX + GNW_MENU_WINDOW);
if (jWindow == JsonNull())
{
json jButton = NuiButtonSelect(JsonString("Menu"), NuiBind("btn_menu"));
jButton = NuiId(jButton, "btn_menu");
jButton = NuiMargin(jButton, 0.0f);
jButton = NuiWidth(jButton, 72.0f);
jButton = NuiHeight(jButton, 28.0f);
jButton = NuiGroup(jButton, FALSE, NUI_SCROLLBARS_NONE);
jButton = NuiMargin(jButton, 0.0f);
jWindow = NuiWindow(jButton, JsonBool(FALSE), NuiBind(NUI_WINDOW_GEOMETRY_BIND), JsonBool(FALSE), JsonBool(FALSE), JsonBool(FALSE), JsonBool(TRUE), JsonBool(FALSE));
SetLocalJson(oModule, GNW_WINDOW_PREFIX + GNW_INFO_WINDOW, jWindow);
}
int nToken = NuiCreate(oPlayer, jWindow, GNW_WINDOW_PREFIX + GNW_MENU_WINDOW);
float fGuiScale = IntToFloat(GetPlayerDeviceProperty(oPlayer, PLAYER_DEVICE_PROPERTY_GUI_SCALE)) / 100.0f;
float fX = IntToFloat(GetPlayerDeviceProperty(oPlayer, PLAYER_DEVICE_PROPERTY_GUI_WIDTH)) - (80.0f * fGuiScale);
float fY = IntToFloat(GetPlayerDeviceProperty(oPlayer, PLAYER_DEVICE_PROPERTY_GUI_HEIGHT)) - (166.0f * fGuiScale);
NuiSetBind(oPlayer, nToken, NUI_WINDOW_GEOMETRY_BIND, NuiRect(fX, fY, 80.0f, 36.0f));
}

68
_module/nss/inc_nui.nss Normal file

@ -0,0 +1,68 @@
/*
Various NUI Helpers
Created By: Daz
*/
#include "nw_inc_nui"
const string NUI_WINDOW_ROOT_GROUP = "_window_";
const string NUI_WINDOW_TITLE_BIND = "wd_title";
const string NUI_WINDOW_GEOMETRY_BIND = "wd_geometry";
const string NUI_EVENT_OPEN = "open";
const string NUI_EVENT_CLOSE = "close";
const string NUI_EVENT_CLICK = "click";
const string NUI_EVENT_WATCH = "watch";
const string NUI_EVENT_MOUSEDOWN = "mousedown";
const string NUI_EVENT_MOUSEUP = "mouseup";
const string NUI_EVENT_MOUSESCROLL = "mousescroll";
json NuiGetCenteredGeometryRect(object oPlayer, float fWindowWidth, float fWindowHeight);
json NuiSetRectWidth(json jRect, float fWidth);
json NuiSetRectHeight(json jRect, float fHeight);
json NuiInsertRow(json jCol, json jRow);
json NuiHeader(json jHeader, float fHeight = 24.0f, float fWidth = 0.0f);
float NuiGetMouseScrollDelta(json jPayload);
json NuiGetCenteredGeometryRect(object oPlayer, float fWindowWidth, float fWindowHeight)
{
float fGuiScale = IntToFloat(GetPlayerDeviceProperty(oPlayer, PLAYER_DEVICE_PROPERTY_GUI_SCALE)) / 100.0f;
float fX = IntToFloat(GetPlayerDeviceProperty(oPlayer, PLAYER_DEVICE_PROPERTY_GUI_WIDTH) / 2) - ((fWindowWidth * 0.5f) * fGuiScale);
float fY = IntToFloat(GetPlayerDeviceProperty(oPlayer, PLAYER_DEVICE_PROPERTY_GUI_HEIGHT) / 2) - ((fWindowHeight * 0.5f) * fGuiScale);
return NuiRect(fX, fY, fWindowWidth, fWindowHeight);
}
json NuiSetRectWidth(json jRect, float fWidth)
{
return JsonObjectSet(jRect, "w", JsonFloat(fWidth));
}
json NuiSetRectHeight(json jRect, float fHeight)
{
return JsonObjectSet(jRect, "h", JsonFloat(fHeight));
}
json NuiInsertRow(json jCol, json jRow)
{
return JsonArrayInsert(jCol, NuiRow(jRow));
}
json NuiHeader(json jHeader, float fHeight = 24.0f, float fWidth = 0.0f)
{
json jLabel = NuiLabel(jHeader, JsonInt(NUI_HALIGN_CENTER), JsonInt(NUI_VALIGN_MIDDLE));
jLabel = NuiGroup(jLabel, TRUE, NUI_SCROLLBARS_NONE);
jLabel = NuiHeight(jLabel, fHeight);
if (fWidth > 0.0f)
jLabel = NuiWidth(jLabel, fWidth);
return jLabel;
}
float NuiGetMouseScrollDelta(json jPayload)
{
return JsonGetFloat(JsonObjectGet(JsonObjectGet(jPayload, "mouse_scroll"), "y"));
}

@ -0,0 +1,561 @@
/*
NUI Persistent Chest System
Created By: Daz
*/
#include "inc_nui"
#include "inc_util"
//void main (){}
const string PC_NUI_WINDOW_ID = "PCWINDOW";
const string PC_NUI_GOLD_WINDOW_ID = "PCGOLDWINDOW";
const string PC_UUID_ARRAY = "PC_UUID_ARRAY";
const string PC_WINDOW_JSON = "PC_WINDOW_JSON";
const string PC_GOLD_WINDOW_JSON = "PC_GOLD_WINDOW_JSON";
const string PC_TARGETING_MODE = "PC_TARGETING_MODE";
const string PC_GEOMETRY_JSON = "PC_GEOMETRY_JSON";
const string PC_SEARCH_STRING = "PC_SEARCH_STRING";
const int PC_MAX_ITEMS = 500; // The max number of items a player can store in their chest
const int PC_ITEM_WITHDRAW_BATCH = 5; // How many items to deserialize at the same time
const float PC_ITEM_WITHDRAW_DELAY = 0.25f; // The delay between deserialization batches
const int PC_USE_SEARCH_BUTTON = FALSE; // Set to true to use a Search button instead of searching on text change
const int PC_SAVE_ITEM_OBJECT_STATE = TRUE; // Save local variables / temporary itemproperties when serializing items
const int PC_OPEN_INVENTORY_WINDOW = TRUE; // Open the inventory when opening a persistent chest
string PC_GetDatabaseName(object oPlayer);
string PC_GetTableName(object oPlayer);
void PC_InitializeDatabase(object oPlayer);
void PC_CreateNUIWindow(object oPlayer, int bOpenInventory = PC_OPEN_INVENTORY_WINDOW);
void PC_EnterDepositMode(object oPlayer);
void PC_HandleNUIEvents(object oPlayer, string sWindowId, int nToken, string sType, string sElement, int nArrayIndex);
int PC_GetStoredItemAmount(object oPlayer);
void PC_HandleDepositEvent(object oPlayer, object oItem, vector vPosition);
void PC_UpdateItemList(object oPlayer, int nToken);
void PC_WithdrawItems(object oPlayer, int nToken);
int PC_GetStoredGold(object oPlayer);
void PC_SetStoredGold(object oPlayer, int nGold);
void PC_ModifyStoredGold(object oPlayer, int nAmount);
void PC_UpdateGoldData(object oPlayer, int nToken);
void PC_CreateNUIGoldWindow(object oPlayer);
string PC_GetDatabaseName(object oPlayer)
{
return "PC_" + GetObjectUUID(oPlayer) + GetPCPublicCDKey(oPlayer, TRUE);
}
string PC_GetTableName(object oPlayer)
{
return "PC_ITEMS";
}
void PC_InitializeDatabase(object oPlayer)
{// Boring database stuff
string sDatabase = PC_GetDatabaseName(oPlayer);
string sTable = PC_GetTableName(oPlayer);
string sQuery = "SELECT name FROM sqlite_master WHERE type='table' AND name=@table;";
sqlquery sql = SqlPrepareQueryCampaign(sDatabase, sQuery);
SqlBindString(sql, "@table", sTable);
if (!SqlStep(sql))
{
string sQuery = "CREATE TABLE IF NOT EXISTS " + sTable + " (" +
"item_uuid TEXT NOT NULL, " +
"item_name TEXT NOT NULL, " +
"item_baseitem INTEGER NOT NULL, " +
"item_stacksize INTEGER NOT NULL, " +
"item_iconresref TEXT NOT NULL, " +
"item_data TEXT_NOT NULL, " +
"PRIMARY KEY(item_uuid));";
sqlquery sql = SqlPrepareQueryCampaign(sDatabase, sQuery);
SqlStep(sql);
}
}
void PC_CreateNUIWindow(object oPlayer, int bOpenInventory = PC_OPEN_INVENTORY_WINDOW)
{
if (NuiFindWindow(oPlayer, PC_NUI_WINDOW_ID))
return;// Don't re-open the window if it is already open
PC_InitializeDatabase(oPlayer);
json jWindow = GetLocalJson(GetModule(), PC_WINDOW_JSON);
if (jWindow == JsonNull())
{// For efficiency, we only build the window json once and store it in a local json on the module
json jCol;// Our main column to hold all the rows
json jRow;// A reusable row
jCol = JsonArray();// Create an array to hold our rows
jRow = JsonArray();// Create an array to hold our row elements
{// Our first row only has a progress bar to indicate the amount of items stored
json jProgress = NuiProgress(NuiBind("progress"));// The actual progress of the progress bar is bound to 'progress'
jProgress = NuiTooltip(jProgress, NuiBind("progress_tooltip"));// Here we add a tooltip and its bind to update it
jRow = JsonArrayInsert(jRow, jProgress);
json jButtonGold = NuiButtonImage(JsonString("iit_gold_001"));
jButtonGold = NuiTooltip(jButtonGold, NuiBind("gold_tooltip"));
jButtonGold = NuiId(jButtonGold, "btn_gold");
jButtonGold = NuiWidth(jButtonGold, 35.0f);
jButtonGold = NuiHeight(jButtonGold, 35.0f);
//jRow = JsonArrayInsert(jRow, jButtonGold);
}
jCol = JsonArrayInsert(jCol, NuiRow(jRow));// Add the row to the column
jRow = JsonArray();
{// The second row has the search bar, a clear button, and if enabled, a search button
json jSearch = NuiTextEdit(JsonString("Search..."), NuiBind("search"), 64, FALSE);// A simple search bar, we bind whatever the user types to 'search'
jRow = JsonArrayInsert(jRow, jSearch);
json jClearButton = NuiButton(JsonString("X"));
jClearButton = NuiId(jClearButton, "btn_clear");// We give the button an id so we can get its click event
jClearButton = NuiEnabled(jClearButton, NuiBind("btn_clear"));// Here we enable the enabling or disabling of the button.. :D bound to 'btn_clear'
jClearButton = NuiWidth(jClearButton, 35.0f);// Width...
jClearButton = NuiHeight(jClearButton, 35.0f);// Height...
jRow = JsonArrayInsert(jRow, jClearButton);
if (PC_USE_SEARCH_BUTTON)
{
json jSearchButton = NuiButton(JsonString("Search"));
jSearchButton = NuiId(jSearchButton, "btn_search");
jSearchButton = NuiWidth(jSearchButton, 100.0f);
jSearchButton = NuiHeight(jSearchButton, 35.0f);
jRow = JsonArrayInsert(jRow, jSearchButton);
}
}
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
jRow = JsonArray();
{// The third row has the item list, here we also create the template for every list item to use
json jListTemplate = JsonArray();
{
json jImage = NuiImage(NuiBind("icons"), JsonInt(NUI_ASPECT_FIT100), JsonInt(NUI_HALIGN_CENTER), JsonInt(NUI_VALIGN_TOP));
jImage = NuiMargin(jImage, 0.0f);
jImage = NuiTooltip(jImage, NuiBind("tooltips"));
jImage = NuiGroup(jImage, TRUE, NUI_SCROLLBARS_NONE);
jListTemplate = JsonArrayInsert(jListTemplate, NuiListTemplateCell(jImage, 32.0f, FALSE));
json jCheck = NuiCheck(NuiBind("names"), NuiBind("selected"));
jListTemplate = JsonArrayInsert(jListTemplate, NuiListTemplateCell(jCheck, 0.0f, TRUE));
}
json jList = NuiList(jListTemplate, NuiBind("icons"), 32.0f);
jRow = JsonArrayInsert(jRow, jList);
}
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
jRow = JsonArray();
{// The final row has a bunch of buttons, exciting
json jButtonWithdraw = NuiButton(JsonString("Withdraw"));
jButtonWithdraw = NuiId(jButtonWithdraw, "btn_withdraw");
jButtonWithdraw = NuiEnabled(jButtonWithdraw, NuiBind("btn_withdraw"));
jButtonWithdraw = NuiWidth(jButtonWithdraw, 100.0f);
jButtonWithdraw = NuiHeight(jButtonWithdraw, 35.0f);
jRow = JsonArrayInsert(jRow, jButtonWithdraw);
json jButtonDeposit = NuiButton(JsonString("Deposit"));
jButtonDeposit = NuiId(jButtonDeposit, "btn_deposit");
jButtonDeposit = NuiEnabled(jButtonDeposit, NuiBind("btn_deposit"));
jButtonDeposit = NuiWidth(jButtonDeposit, 100.0f);
jButtonDeposit = NuiHeight(jButtonDeposit, 35.0f);
jRow = JsonArrayInsert(jRow, jButtonDeposit);
jRow = JsonArrayInsert(jRow, NuiSpacer());
json jButtonClose = NuiButton(JsonString("Close"));
jButtonClose = NuiId(jButtonClose, "btn_close");
jButtonClose = NuiWidth(jButtonClose, 100.0f);
jButtonClose = NuiHeight(jButtonClose, 35.0f);
jRow = JsonArrayInsert(jRow, jButtonClose);
}
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
json jRoot = NuiCol(jCol);// Turn our column variable into a column
// Bind the window title and geometry, disable resizing and set collapsed to false
jWindow = NuiWindow(jRoot, NuiBind(NUI_WINDOW_TITLE_BIND), NuiBind(NUI_WINDOW_GEOMETRY_BIND), JsonBool(FALSE), JsonNull(), JsonBool(TRUE), JsonBool(FALSE), JsonBool(TRUE));
SetLocalJson(GetModule(), PC_WINDOW_JSON, jWindow);// Store the created window for reuse
}
// We let the user move the window and it'll save the position in a local
// In the case of the local not existing we position the window in its default position
json jGeometry = GetLocalJson(oPlayer, PC_GEOMETRY_JSON);
if (jGeometry == JsonNull())
jGeometry = NuiRect(400.0f, 0.0f, 400.0f, 500.0f);
// Actually create the window for the player!
int nToken = NuiCreate(oPlayer, jWindow, PC_NUI_WINDOW_ID);
// If the search button is not enabled we watch the search bind for changes in the search box
NuiSetBindWatch(oPlayer, nToken, "search", !PC_USE_SEARCH_BUTTON);
// Watch for players moving the window
NuiSetBindWatch(oPlayer, nToken, NUI_WINDOW_GEOMETRY_BIND, TRUE);
// Here we set the initial window position, either to the default position or wherever the player last left it
NuiSetBind(oPlayer, nToken, NUI_WINDOW_GEOMETRY_BIND, jGeometry);
// Setting the window title
NuiSetBind(oPlayer, nToken, NUI_WINDOW_TITLE_BIND, JsonString(GetName(oPlayer) + "'s Persistent Chest"));
// We clear the search bar, this'll invoke the watch event, if enabled, where we do some other stuff
NuiSetBind(oPlayer, nToken, "search", JsonString(""));
// Enable or disable the clear button depending on if we have the search button enabled
// If the search button is disabled we only enable it if the search bar actually has text
NuiSetBind(oPlayer, nToken, "btn_clear", JsonBool(PC_USE_SEARCH_BUTTON));
if (PC_USE_SEARCH_BUTTON)
{
DeleteLocalString(oPlayer, PC_SEARCH_STRING);
PC_UpdateItemList(oPlayer, nToken);
}
PC_UpdateGoldData(oPlayer, nToken);
if (bOpenInventory)
PopUpGUIPanel(oPlayer, GUI_PANEL_INVENTORY);
}
void PC_EnterDepositMode(object oPlayer)
{
SetLocalInt(oPlayer, PC_TARGETING_MODE, TRUE);
EnterTargetingMode(oPlayer, OBJECT_TYPE_ITEM);
}
void PC_HandleNUIEvents(object oPlayer, string sWindowId, int nToken, string sType, string sElement, int nArrayIndex)
{
if (sWindowId == PC_NUI_WINDOW_ID)
{
if (sType == NUI_EVENT_CLICK)
{
if (sElement == "btn_withdraw")
{// The withdraw button is clicked, withdraw some items
PC_WithdrawItems(oPlayer, nToken);
}
else if (sElement == "btn_deposit")
{// The deposit button is clicked, enter deposit mode
PC_EnterDepositMode(oPlayer);
}
else if (sElement == "btn_close")
{// Murder the poor window
NuiDestroy(oPlayer, nToken);
nToken = NuiFindWindow(oPlayer, PC_NUI_GOLD_WINDOW_ID);
if (nToken)
NuiDestroy(oPlayer, nToken);
}
else if (sElement == "btn_search")
{// Handle the search button if enabled
SetLocalString(oPlayer, PC_SEARCH_STRING, JsonGetString(NuiGetBind(oPlayer, nToken, "search")));
PC_UpdateItemList(oPlayer, nToken);
}
else if (sElement == "btn_clear")
{// Handle the clear button
NuiSetBind(oPlayer, nToken, "search", JsonString(""));
if (PC_USE_SEARCH_BUTTON)
{
DeleteLocalString(oPlayer, PC_SEARCH_STRING);
PC_UpdateItemList(oPlayer, nToken);
}
}
else if (sElement == "btn_gold")
{
PC_CreateNUIGoldWindow(oPlayer);
}
}
else if (sType == NUI_EVENT_WATCH)
{
if (sElement == NUI_WINDOW_GEOMETRY_BIND)
{// Whenever the geometry of the window changes this watch event will fire, we just get the bind's value and store it in a local
SetLocalJson(oPlayer, PC_GEOMETRY_JSON, NuiGetBind(oPlayer, nToken, NUI_WINDOW_GEOMETRY_BIND));
}
else if (sElement == "search")
{// Whenever the player types in the search bar this watch event fires, we enable or disable the clear button depending on string length and set the search string in a local
string sSearch = JsonGetString(NuiGetBind(oPlayer, nToken, "search"));
NuiSetBind(oPlayer, nToken, "btn_clear", JsonBool(GetStringLength(sSearch)));
SetLocalString(oPlayer, PC_SEARCH_STRING, sSearch);
PC_UpdateItemList(oPlayer, nToken);
}
}
else if (sType == NUI_EVENT_CLOSE)
{
nToken = NuiFindWindow(oPlayer, PC_NUI_GOLD_WINDOW_ID);
if (nToken)
NuiDestroy(oPlayer, nToken);
}
}
else if (sWindowId == PC_NUI_GOLD_WINDOW_ID)
{
if (sType == NUI_EVENT_CLICK)
{
if (sElement == "btn_deposit")
{
//SendMessageToPC(oPlayer, "Depositing: " + JsonGetString(NuiGetBind(oPlayer, nToken, "amount")) + " gold");
}
else if (sElement == "btn_close")
{
NuiDestroy(oPlayer, nToken);
}
}
}
}
int PC_GetStoredItemAmount(object oPlayer)
{// Wrapper to get the number of stored items
string sQuery = "SELECT COUNT(*) FROM " + PC_GetTableName(oPlayer);
sqlquery sql = SqlPrepareQueryCampaign(PC_GetDatabaseName(oPlayer), sQuery);
return SqlStep(sql) ? SqlGetInt(sql, 0) : 0;
}
void PC_HandleDepositEvent(object oPlayer, object oItem, vector vPosition)
{// This function is fired in the module on player target event
if (!GetLocalInt(oPlayer, PC_TARGETING_MODE))// Make sure it only fires if we're actually depositing an item
return;
DeleteLocalInt(oPlayer, PC_TARGETING_MODE);
if (!GetIsObjectValid(oItem) || GetLocalInt(oItem, "PC_ITEM_DESTROYED") || GetObjectType(oItem) != OBJECT_TYPE_ITEM)
return;// Check the validness of the item
if (GetItemPossessor(oItem) != oPlayer)
{// Check if we actually own the item
SendMessageToPC(oPlayer, "You do not own '" + GetName(oItem) + "'");
return;
}
int nStoredItems = PC_GetStoredItemAmount(oPlayer);
if (nStoredItems >= PC_MAX_ITEMS)
{// Check if we have space...
SendMessageToPC(oPlayer, "Your persistent chest is full, withdraw an item first.");
return;
}
// Here we grab a bunch of data and actually store stuff in the database
// We store the item as json because we need that to get some additional icon data anyway
string sItemUUID = GetObjectUUID(oItem);
int nItemBaseItem = GetBaseItemType(oItem);
string sItemName = Util_GetItemName(oItem, GetIdentified(oItem));
int nItemStackSize = GetItemStackSize(oItem);
json jItemData = ObjectToJson(oItem, PC_SAVE_ITEM_OBJECT_STATE);
string sItemIconResRef = Util_GetIconResref(oItem, jItemData, nItemBaseItem);
string sQuery = "INSERT INTO " + PC_GetTableName(oPlayer) +
"(item_uuid, item_name, item_baseitem, item_stacksize, item_iconresref, item_data) " +
"VALUES(@item_uuid, @item_name, @item_baseitem, @item_stacksize, @item_iconresref, @item_data);";
sqlquery sql = SqlPrepareQueryCampaign(PC_GetDatabaseName(oPlayer), sQuery);
SqlBindString(sql, "@item_uuid", sItemUUID);
SqlBindString(sql, "@item_name", sItemName);
SqlBindInt(sql, "@item_baseitem", nItemBaseItem);
SqlBindInt(sql, "@item_stacksize", nItemStackSize);
SqlBindString(sql, "@item_iconresref", sItemIconResRef);
SqlBindJson(sql, "@item_data", jItemData);
SqlStep(sql);
int nToken = NuiFindWindow(oPlayer, PC_NUI_WINDOW_ID);
if (nToken)
{// Check if the window is still open, if so update the item list and enter targeting mode again if we still have space
PC_UpdateItemList(oPlayer, nToken);
if(++nStoredItems != PC_MAX_ITEMS)
{
PC_EnterDepositMode(oPlayer);
}
}
// Dunno if this is needed but maybe somehow the player clicks on an item before it is destroyed, we'll try to prevent that
SetLocalInt(oItem, "PC_ITEM_DESTROYED", TRUE);
DestroyObject(oItem);
}
void PC_UpdateItemList(object oPlayer, int nToken)
{
json jUUIDArray = JsonArray();// This array is stored on the player so we can map an array index to an items UUID
json jNamesArray = JsonArray();// This array is for the list and stores all the names of the items
json jTooltipArray = JsonArray();// This array is for the list and stores all the baseitem tooltips of the items
json jIconsArray = JsonArray();// This array is for the list and stores all the icons of the items
json jSelectedArray = JsonArray();// This array is for the list and stores wether an item is selected or not
int nNumItems = PC_GetStoredItemAmount(oPlayer);
string sSearch = GetLocalString(oPlayer, PC_SEARCH_STRING);
string sQuery = "SELECT item_uuid, item_name, item_baseitem, item_stacksize, item_iconresref FROM " +
PC_GetTableName(oPlayer) + (sSearch != "" ? " WHERE item_name LIKE @search" : "") +" ORDER BY item_baseitem ASC, item_name ASC;";
sqlquery sql = SqlPrepareQueryCampaign(PC_GetDatabaseName(oPlayer), sQuery);
if (sSearch != "")
SqlBindString(sql, "@search", "%" + sSearch + "%");
while (SqlStep(sql))
{// Loop all items
string sUUID = SqlGetString(sql, 0);
string sName = SqlGetString(sql, 1);
int nBaseItem = SqlGetInt(sql, 2);
int nStackSize = SqlGetInt(sql, 3);
string sIconResRef = SqlGetString(sql, 4);
jUUIDArray = JsonArrayInsert(jUUIDArray, JsonString(sUUID));// Store its UUId
jNamesArray = JsonArrayInsert(jNamesArray, JsonString(sName + (nStackSize > 1 ? " (x" + IntToString(nStackSize) + ")" : "")));// Store its name and stacksize if >1
jTooltipArray = JsonArrayInsert(jTooltipArray, JsonString(GetStringByStrRef(StringToInt(Get2DAString("baseitems", "Name", nBaseItem)))));// Store the tooltip
jIconsArray = JsonArrayInsert(jIconsArray, JsonString(sIconResRef));// Store the icon
jSelectedArray = JsonArrayInsert(jSelectedArray, JsonBool(FALSE));// Set the item as not selected
}
SetLocalJson(oPlayer, PC_UUID_ARRAY, jUUIDArray);// We save this array on the player for later use
// Set the list binds to the new arrays
NuiSetBind(oPlayer, nToken, "icons", jIconsArray);
NuiSetBind(oPlayer, nToken, "names", jNamesArray);
NuiSetBind(oPlayer, nToken, "tooltips", jTooltipArray);
NuiSetBind(oPlayer, nToken, "selected", jSelectedArray);
// Update our progress tracker and its tooltip
NuiSetBind(oPlayer, nToken, "progress", JsonFloat(IntToFloat(nNumItems) / IntToFloat(PC_MAX_ITEMS)));
NuiSetBind(oPlayer, nToken, "progress_tooltip", JsonString(IntToString(nNumItems) + " / " + IntToString(PC_MAX_ITEMS) + " Items Stored"));
// Disable or enable the withdraw and deposit buttons depending on item amounts
NuiSetBind(oPlayer, nToken, "btn_withdraw", JsonBool(nNumItems > 0));
NuiSetBind(oPlayer, nToken, "btn_deposit", JsonBool(nNumItems < PC_MAX_ITEMS));
}
void VoidJsonToObject(json jObject, location locLocation, object oOwner = OBJECT_INVALID, int bLoadObjectState = FALSE)
{
JsonToObject(jObject, locLocation, oOwner, bLoadObjectState);
}
void PC_WithdrawItems(object oPlayer, int nToken)
{
json jSelected = NuiGetBind(oPlayer, nToken, "selected");// This gets the array of selected items
int nNumItems = JsonGetLength(jSelected);
if (!nNumItems)// Why bother doing anything if we have no items stored
return;
string sDatabase = PC_GetDatabaseName(oPlayer);
string sTable = PC_GetTableName(oPlayer);
string sSelectQuery = "SELECT item_data FROM " + sTable + " WHERE item_uuid=@uuid;";
string sDeleteQuery = "DELETE FROM " + sTable + " WHERE item_uuid=@uuid;";
json jUUIDs = GetLocalJson(oPlayer, PC_UUID_ARRAY);// Get our array index <-> uuid map
location locPlayer = GetLocation(oPlayer);
int nItem, nWithdrawnItems = 0;
float fDelay = PC_ITEM_WITHDRAW_DELAY;
sqlquery sql;
for (nItem = 0; nItem < nNumItems; nItem++)
{// Loop all items, this will need improving for big amounts of items
if (JsonGetInt(JsonArrayGet(jSelected, nItem)))
{// Check if the item is selected, if so we withdraw it
string sUUID = JsonGetString(JsonArrayGet(jUUIDs, nItem));// Use the index of the item to get its uuid from the array we stored earlier
sql = SqlPrepareQueryCampaign(sDatabase, sSelectQuery);
SqlBindString(sql, "@uuid", sUUID);
if (SqlStep(sql))
{
json jItem = SqlGetJson(sql, 0);
sql = SqlPrepareQueryCampaign(sDatabase, sDeleteQuery);// Delete the database entry of the item
SqlBindString(sql, "@uuid", sUUID);
SqlStep(sql);
DelayCommand(fDelay, VoidJsonToObject(jItem, locPlayer, oPlayer, PC_SAVE_ITEM_OBJECT_STATE));
nWithdrawnItems++;
}
}
if (nWithdrawnItems == PC_ITEM_WITHDRAW_BATCH)
{// Here we do some stuff to not withdraw all items at once
nWithdrawnItems = 0;
fDelay += PC_ITEM_WITHDRAW_DELAY;
}
}
// Finally update the item list again
PC_UpdateItemList(oPlayer, nToken);
}
int PC_GetStoredGold(object oPlayer)
{
return GetCampaignInt(PC_GetTableName(oPlayer), "PC_GOLD");
}
void PC_SetStoredGold(object oPlayer, int nGold)
{
SetCampaignInt(PC_GetTableName(oPlayer), "PC_GOLD", nGold);
}
void PC_ModifyStoredGold(object oPlayer, int nAmount)
{
PC_SetStoredGold(oPlayer, PC_GetStoredGold(oPlayer) + nAmount);
}
void PC_UpdateGoldData(object oPlayer, int nToken)
{
NuiSetBind(oPlayer, nToken, "gold_tooltip", JsonString("Gold: " + IntToString(PC_GetStoredGold(oPlayer))));
}
void PC_CreateNUIGoldWindow(object oPlayer)
{
if (NuiFindWindow(oPlayer, PC_NUI_GOLD_WINDOW_ID))
return;
json jWindow = GetLocalJson(GetModule(), PC_GOLD_WINDOW_JSON);
if (jWindow == JsonNull())
{
json jCol;
json jRow;
jCol = JsonArray();
jRow = JsonArray();
{
json jTextEdit = NuiTextEdit(JsonString("Amount..."), NuiBind("amount"), 10, FALSE);
jTextEdit = NuiWidth(jTextEdit, 110.0f);
jRow = JsonArrayInsert(jRow, jTextEdit);
jRow = JsonArrayInsert(jRow, NuiSpacer());
json jButtonWithdraw = NuiButton(JsonString("Withdraw"));
jButtonWithdraw = NuiId(jButtonWithdraw, "btn_withdraw");
jButtonWithdraw = NuiEnabled(jButtonWithdraw, NuiBind("btn_withdraw"));
jButtonWithdraw = NuiWidth(jButtonWithdraw, 90.0f);
jButtonWithdraw = NuiHeight(jButtonWithdraw, 35.0f);
jRow = JsonArrayInsert(jRow, jButtonWithdraw);
json jButtonDeposit = NuiButton(JsonString("Deposit"));
jButtonDeposit = NuiId(jButtonDeposit, "btn_deposit");
jButtonDeposit = NuiEnabled(jButtonDeposit, NuiBind("btn_deposit"));
jButtonDeposit = NuiWidth(jButtonDeposit, 90.0f);
jButtonDeposit = NuiHeight(jButtonDeposit, 35.0f);
jRow = JsonArrayInsert(jRow, jButtonDeposit);
}
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
jRow = JsonArray();
{
json jImage = NuiImage(JsonString("iit_gold_001"), JsonInt(NUI_ASPECT_FIT100), JsonInt(NUI_HALIGN_CENTER), JsonInt(NUI_VALIGN_TOP));
jImage = NuiGroup(jImage, FALSE, NUI_SCROLLBARS_NONE);
jImage = NuiWidth(jImage, 35.0f);
jImage = NuiHeight(jImage, 35.0f);
jRow = JsonArrayInsert(jRow, jImage);
json jLabel = NuiLabel(JsonString("Gold: "), JsonInt(NUI_HALIGN_LEFT), JsonInt(NUI_VALIGN_MIDDLE));
jLabel = NuiWidth(jLabel, 40.0f);
jRow = JsonArrayInsert(jRow, jLabel);
json jAmount = NuiLabel(NuiBind("stored_gold"), JsonInt(NUI_HALIGN_LEFT), JsonInt(NUI_VALIGN_MIDDLE));
jAmount = NuiWidth(jAmount, 100.0f);
jRow = JsonArrayInsert(jRow, jAmount);
jRow = JsonArrayInsert(jRow, NuiSpacer());
json jButtonDeposit = NuiButton(JsonString("Close"));
jButtonDeposit = NuiId(jButtonDeposit, "btn_close");
jButtonDeposit = NuiWidth(jButtonDeposit, 90.0f);
jButtonDeposit = NuiHeight(jButtonDeposit, 35.0f);
jRow = JsonArrayInsert(jRow, jButtonDeposit);
}
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
json jRoot = NuiCol(jCol);
jWindow = NuiWindow(jRoot, JsonBool(FALSE), NuiRect(-1.0f, -1.0f, 375.0f, 135.0f), JsonBool(FALSE), JsonBool(FALSE), JsonBool(FALSE), JsonBool(FALSE), JsonBool(TRUE));
SetLocalJson(GetModule(), PC_GOLD_WINDOW_JSON, jWindow);
}
int nToken = NuiCreate(oPlayer, jWindow, PC_NUI_GOLD_WINDOW_ID);
NuiSetBind(oPlayer, nToken, "stored_gold", JsonString("5000000"));
}

@ -0,0 +1,660 @@
/*
Multiplayer TicTacToe NUI Game
Created By: Daz
*/
#include "inc_nui"
#include "inc_util"
const string TTT_WINDOW_ID = "TTT_GAME";
const string TTT_WINDOW_JSON = "TTT_WINDOW_JSON";
const string TTT_WINDOW_GEOMETRY = "TTT_WINDOW_GEOMETRY";
const float TTT_WINDOW_WIDTH = 400.0f;
const float TTT_WINDOW_HEIGHT = 340.0f;
const float TTT_LINE_LENGTH = 50.0f;
const float TTT_LINE_THICKNESS = 10.0f;
const string TTT_GRID_LINE_LEFT = "ttt_ll";
const string TTT_GRID_LINE_RIGHT = "ttt_lr";
const string TTT_GRID_LINE_TOP = "ttt_lt";
const string TTT_GRID_LINE_BOTTOM = "ttt_lb";
const string TTT_GRID_LINE_CENTER = "ttt_lc";
const string TTT_GRID_LINE_VERTICAL = "ttt_lmv";
const string TTT_GRID_LINE_HORIZONTAL = "ttt_lmh";
const string TTT_BIND_HEADER_TEXT = "header_text";
const string TTT_BIND_PORTRAIT_ONE = "po_player1";
const string TTT_BIND_PORTRAIT_TWO = "po_player2";
const string TTT_BIND_INFO_TEXT = "info_text";
const string TTT_BIND_BUTTON_RESTART = "btn_restart";
const string TTT_IMAGE_BLANK = "ttt_blank";
const string TTT_IMAGE_CIRCLE = "ttt_circle";
const string TTT_IMAGE_CROSS = "ttt_cross";
const string TTT_CELL_PREFIX = "ttt_cell_";
const int TTT_NUM_CELLS = 9;
const string TTT_CELL_VALUE_BLANK = "";
const string TTT_CELL_VALUE_CIRCLE = "O";
const string TTT_CELL_VALUE_CROSS = "X";
const string TTT_BOARD = "TTT_BOARD";
const string TTT_PLAYER_ID = "TTT_PLAYER_ID";
const string TTT_PLAYER_ONE = "TTT_PLAYER_ONE";
const string TTT_PLAYER_TWO = "TTT_PLAYER_TWO";
const string TTT_CURRENT_PLAYER = "TTT_CURRENT_PLAYER";
const string TTT_WIN_CONDITIONS = "TTT_WIN_CONDITIONS";
const string TTT_GRID_STATE = "TTT_GRID_STATE";
const string TTT_GAME_STATE = "TTT_GAME_STATE";
const int TTT_GAME_STATE_NONE = 0;
const int TTT_GAME_STATE_WAITING = 1;
const int TTT_GAME_STATE_PLAYING = 2;
const int TTT_GAME_STATE_GAME_OVER = 3;
string TTT_IntToCellString(int nCell);
json TTT_InsertGridLine(json jCol, string sImage, float fWidth, float fHeight);
json TTT_InsertGridCell(json jCol, int nCell);
json TTT_GetTicTacToeGridJson();
json TTT_GetWindowJson();
void TTT_SetRestartButtonEnabled(object oGame, int bEnabled);
int TTT_GetPlayerWindowToken(object oPlayer);
void TTT_SetGame(object oPlayer, object oGame);
object TTT_GetGame(object oPlayer);
void TTT_DeleteGame(object oPlayer);
void TTT_SetPlayerId(object oPlayer, string sPlayerId);
string TTT_GetPlayerId(object oPlayer);
void TTT_DeletePlayerId(object oPlayer);
void TTT_SetPlayer(object oGame, string sPlayerId, object oPlayer);
object TTT_GetPlayer(object oGame, string sPlayerId);
void TTT_DeletePlayer(object oGame, string sPlayerId);
void TTT_SetCurrentPlayer(object oGame, object oPlayer);
object TTT_GetCurrentPlayer(object oGame);
string TTT_GetCurrentPlayerSymbol(object oGame);
object TTT_GetOpponent(object oGame);
object TTT_GetValidatedPlayer(object oGame, string sPlayerId);
int TTT_GetIsPlayerValid(object oGame, string sPlayerId);
int TTT_GetNumPlayers(object oGame);
string TTT_GetFreePlayerId(object oGame);
object TTT_GetSinglePlayer(object oGame);
void TTT_UpdateBind(object oPlayer, string sBindName, json jValue);
void TTT_UpdateBindsForPlayers(object oGame, string sBindName, json jValue);
int TTT_CreateGameWindow(object oPlayer);
void TTT_UpdateStaticBinds(object oGame);
void TTT_UpdateGridCellBind(object oGame, int nCell, json jImage);
string TTT_GetImageFromSymbol(string sSymbol);
void TTT_UpdateGridBinds(object oGame);
void TTT_UpdateInfoTextBind(object oGame, string sText);
void TTT_AddPlayerToGame(object oPlayer, object oGame = OBJECT_SELF);
void TTT_HandleNUIEvents(object oPlayer, int nToken, string sType, string sElement, int nArrayIndex, json jPayload);
json TTT_InsertWinCondition(json jWinConditions, int nValueA, int nValueB, int nValueC);
json TTT_GetWinConditions();
json TTT_GetGridState(object oGame);
void TTT_SetGridState(object oGame, json jGridState);
void TTT_ClearGridState(object oGame);
string TTT_GetGridStateCell(object oGame, int nCell);
void TTT_SetGridStateCell(object oGame, int nCell, string sValue);
int TTT_GetGameState(object oGame);
void TTT_SetGameState(object oGame, int nGameState, string sInfoText);
void TTT_UpdateGameState(object oGame);
int TTT_GetIsDraw(object oGame);
int TTT_GetIsWin(object oGame);
void TTT_RestartGame(object oGame);
void TTT_RemovePlayerFromGame(object oGame, object oPlayer);
void TTT_HandlePlayerExit(object oPlayer);
string TTT_IntToCellString(int nCell)
{
return TTT_CELL_PREFIX + IntToString(nCell);
}
json TTT_InsertGridLine(json jCol, string sImage, float fWidth, float fHeight)
{
json jImage = NuiImage(JsonString(sImage), JsonInt(NUI_ASPECT_EXACT), JsonInt(NUI_HALIGN_CENTER), JsonInt(NUI_VALIGN_MIDDLE));
jImage = NuiMargin(jImage, 0.0f);
jImage = NuiWidth(jImage, fWidth);
jImage = NuiHeight(jImage, fHeight);
return JsonArrayInsert(jCol, NuiMargin(NuiRow(JsonArrayInsert(JsonArray(), jImage)), 0.0f));
}
json TTT_InsertGridCell(json jCol, int nCell)
{
string sCell = TTT_IntToCellString(nCell);
json jImage = NuiImage(NuiBind(sCell), JsonInt(NUI_ASPECT_EXACT), JsonInt(NUI_HALIGN_CENTER), JsonInt(NUI_VALIGN_MIDDLE));
jImage = NuiId(jImage, sCell);
jImage = NuiMargin(jImage, 0.0f);
jImage = NuiWidth(jImage, TTT_LINE_LENGTH);
jImage = NuiHeight(jImage, TTT_LINE_LENGTH);
return JsonArrayInsert(jCol, NuiMargin(NuiRow(JsonArrayInsert(JsonArray(), jImage)), 0.0f));
}
json TTT_GetTicTacToeGridJson()
{
json jCol = JsonArray(), jRow;
jRow = JsonArray();
{
json jSubCol, jSubRow;
jSubCol = JsonArray();
jSubCol = TTT_InsertGridCell(jSubCol, 0);
jSubCol = TTT_InsertGridLine(jSubCol, TTT_GRID_LINE_LEFT, TTT_LINE_LENGTH, TTT_LINE_THICKNESS);
jSubCol = TTT_InsertGridCell(jSubCol, 3);
jSubCol = TTT_InsertGridLine(jSubCol, TTT_GRID_LINE_LEFT, TTT_LINE_LENGTH, TTT_LINE_THICKNESS);
jSubCol = TTT_InsertGridCell(jSubCol, 6);
jRow = JsonArrayInsert(jRow, NuiMargin(NuiCol(jSubCol), 0.0f));
jSubCol = JsonArray();
jSubCol = TTT_InsertGridLine(jSubCol, TTT_GRID_LINE_TOP, TTT_LINE_THICKNESS, TTT_LINE_LENGTH);
jSubCol = TTT_InsertGridLine(jSubCol, TTT_GRID_LINE_CENTER, TTT_LINE_THICKNESS, TTT_LINE_THICKNESS);
jSubCol = TTT_InsertGridLine(jSubCol, TTT_GRID_LINE_VERTICAL, TTT_LINE_THICKNESS, TTT_LINE_LENGTH);
jSubCol = TTT_InsertGridLine(jSubCol,TTT_GRID_LINE_CENTER, TTT_LINE_THICKNESS, TTT_LINE_THICKNESS);
jSubCol = TTT_InsertGridLine(jSubCol, TTT_GRID_LINE_BOTTOM, TTT_LINE_THICKNESS, TTT_LINE_LENGTH);
jRow = JsonArrayInsert(jRow, NuiMargin(NuiCol(jSubCol), 0.0f));
jSubCol = JsonArray();
jSubCol = TTT_InsertGridCell(jSubCol, 1);
jSubCol = TTT_InsertGridLine(jSubCol, TTT_GRID_LINE_HORIZONTAL, TTT_LINE_LENGTH, TTT_LINE_THICKNESS);
jSubCol = TTT_InsertGridCell(jSubCol, 4);
jSubCol = TTT_InsertGridLine(jSubCol, TTT_GRID_LINE_HORIZONTAL, TTT_LINE_LENGTH, TTT_LINE_THICKNESS);
jSubCol = TTT_InsertGridCell(jSubCol, 7);
jRow = JsonArrayInsert(jRow, NuiMargin(NuiCol(jSubCol), 0.0f));
jSubCol = JsonArray();
jSubCol = TTT_InsertGridLine(jSubCol, TTT_GRID_LINE_TOP, TTT_LINE_THICKNESS, TTT_LINE_LENGTH);
jSubCol = TTT_InsertGridLine(jSubCol, TTT_GRID_LINE_CENTER, TTT_LINE_THICKNESS, TTT_LINE_THICKNESS);
jSubCol = TTT_InsertGridLine(jSubCol, TTT_GRID_LINE_VERTICAL, TTT_LINE_THICKNESS, TTT_LINE_LENGTH);
jSubCol = TTT_InsertGridLine(jSubCol, TTT_GRID_LINE_CENTER, TTT_LINE_THICKNESS, TTT_LINE_THICKNESS);
jSubCol = TTT_InsertGridLine(jSubCol, TTT_GRID_LINE_BOTTOM, TTT_LINE_THICKNESS, TTT_LINE_LENGTH);
jRow = JsonArrayInsert(jRow, NuiMargin(NuiCol(jSubCol), 0.0f));
jSubCol = JsonArray();
jSubCol = TTT_InsertGridCell(jSubCol, 2);
jSubCol = TTT_InsertGridLine(jSubCol, TTT_GRID_LINE_RIGHT, TTT_LINE_LENGTH, TTT_LINE_THICKNESS);
jSubCol = TTT_InsertGridCell(jSubCol, 5);
jSubCol = TTT_InsertGridLine(jSubCol, TTT_GRID_LINE_RIGHT, TTT_LINE_LENGTH, TTT_LINE_THICKNESS);
jSubCol = TTT_InsertGridCell(jSubCol, 8);
jRow = JsonArrayInsert(jRow, NuiMargin(NuiCol(jSubCol), 0.0f));
}
jCol = NuiInsertRow(jCol, jRow);
return NuiCol(jCol);
}
json TTT_GetWindowJson()
{
json jWindow = GetLocalJson(GetModule(), TTT_WINDOW_JSON);
if (jWindow == JsonNull())
{
json jCol;
json jRow;
jCol = JsonArray();
jRow = JsonArray();
{
json jHeader = NuiHeader(NuiBind(TTT_BIND_HEADER_TEXT));
jRow = JsonArrayInsert(jRow, jHeader);
}
jCol = NuiInsertRow(jCol, jRow);
jRow = JsonArray();
{
jRow = JsonArrayInsert(jRow, NuiSpacer());
json jPlayer1 = NuiImage(NuiBind(TTT_BIND_PORTRAIT_ONE), JsonInt(NUI_ASPECT_EXACT), JsonInt(NUI_HALIGN_CENTER), JsonInt(NUI_VALIGN_TOP));
jPlayer1 = NuiMargin(jPlayer1, 0.0f);
jPlayer1 = NuiGroup(jPlayer1, TRUE, NUI_SCROLLBARS_NONE);
jPlayer1 = NuiWidth(jPlayer1, 64.0f);
jPlayer1 = NuiHeight(jPlayer1, 100.0f);
jRow = JsonArrayInsert(jRow, jPlayer1);
jRow = JsonArrayInsert(jRow, NuiSpacer());
json jTicTacToe = TTT_GetTicTacToeGridJson();
jTicTacToe = NuiGroup(jTicTacToe, FALSE, NUI_SCROLLBARS_NONE);
jTicTacToe = NuiWidth(jTicTacToe, 182.0f);
jTicTacToe = NuiHeight(jTicTacToe, 182.0f);
jRow = JsonArrayInsert(jRow, jTicTacToe);
jRow = JsonArrayInsert(jRow, NuiSpacer());
json jPlayer2 = NuiImage(NuiBind(TTT_BIND_PORTRAIT_TWO), JsonInt(NUI_ASPECT_EXACT), JsonInt(NUI_HALIGN_CENTER), JsonInt(NUI_VALIGN_TOP));
jPlayer2 = NuiMargin(jPlayer2, 0.0f);
jPlayer2 = NuiGroup(jPlayer2, TRUE, NUI_SCROLLBARS_NONE);
jPlayer2 = NuiWidth(jPlayer2, 64.0f);
jPlayer2 = NuiHeight(jPlayer2, 100.0f);
jRow = JsonArrayInsert(jRow, jPlayer2);
jRow = JsonArrayInsert(jRow, NuiSpacer());
}
jCol = NuiInsertRow(jCol, jRow);
jRow = JsonArray();
{
json jHeader = NuiHeader(NuiBind(TTT_BIND_INFO_TEXT));
jRow = JsonArrayInsert(jRow, jHeader);
}
jCol = NuiInsertRow(jCol, jRow);
jRow = JsonArray();
{
jRow = JsonArrayInsert(jRow, NuiSpacer());
json jButton = NuiButton(JsonString("Restart"));
jButton = NuiId(jButton, TTT_BIND_BUTTON_RESTART);
jButton = NuiEnabled(jButton, NuiBind(TTT_BIND_BUTTON_RESTART));
jButton = NuiHeight(jButton, 30.0f);
jRow = JsonArrayInsert(jRow, jButton);
jRow = JsonArrayInsert(jRow, NuiSpacer());
}
jCol = NuiInsertRow(jCol, jRow);
jRow = JsonArray();
{
jRow = JsonArrayInsert(jRow, NuiSpacer());
}
jCol = NuiInsertRow(jCol, jRow);
json jRoot = NuiCol(jCol);
jWindow = NuiWindow(jRoot, JsonString("TicTacToe"), NuiBind(NUI_WINDOW_GEOMETRY_BIND), JsonBool(FALSE), JsonNull(), JsonBool(TRUE), JsonBool(FALSE), JsonBool(TRUE));
SetLocalJson(GetModule(), TTT_WINDOW_JSON, jWindow);
}
return jWindow;
}
void TTT_SetRestartButtonEnabled(object oGame, int bEnabled) { TTT_UpdateBindsForPlayers(oGame, TTT_BIND_BUTTON_RESTART, JsonBool(bEnabled)); }
int TTT_GetPlayerWindowToken(object oPlayer) { return NuiFindWindow(oPlayer, TTT_WINDOW_ID); }
void TTT_SetGame(object oPlayer, object oGame) { SetLocalObject(oPlayer, TTT_BOARD, oGame); }
object TTT_GetGame(object oPlayer) { return GetLocalObject(oPlayer, TTT_BOARD); }
void TTT_DeleteGame(object oPlayer) { DeleteLocalObject(oPlayer, TTT_BOARD); }
void TTT_SetPlayerId(object oPlayer, string sPlayerId) { SetLocalString(oPlayer, TTT_PLAYER_ID, sPlayerId); }
string TTT_GetPlayerId(object oPlayer) { return GetLocalString(oPlayer, TTT_PLAYER_ID); }
void TTT_DeletePlayerId(object oPlayer) { DeleteLocalString(oPlayer, TTT_PLAYER_ID); }
void TTT_SetPlayer(object oGame, string sPlayerId, object oPlayer) { SetLocalObject(oGame, sPlayerId, oPlayer); }
object TTT_GetPlayer(object oGame, string sPlayerId) { return GetLocalObject(oGame, sPlayerId); }
void TTT_DeletePlayer(object oGame, string sPlayerId) { DeleteLocalObject(oGame, sPlayerId); }
void TTT_SetCurrentPlayer(object oGame, object oPlayer) { SetLocalObject(oGame, TTT_CURRENT_PLAYER, oPlayer); }
object TTT_GetCurrentPlayer(object oGame) { return GetLocalObject(oGame, TTT_CURRENT_PLAYER); }
string TTT_GetCurrentPlayerSymbol(object oGame)
{
return TTT_GetPlayerId(TTT_GetCurrentPlayer(oGame)) == TTT_PLAYER_ONE ? TTT_CELL_VALUE_CROSS : TTT_CELL_VALUE_CIRCLE;
}
object TTT_GetOpponent(object oGame)
{
return TTT_GetPlayerId(TTT_GetCurrentPlayer(oGame)) == TTT_PLAYER_ONE ? TTT_GetPlayer(oGame, TTT_PLAYER_TWO) : TTT_GetPlayer(oGame, TTT_PLAYER_ONE);
}
object TTT_GetValidatedPlayer(object oGame, string sPlayerId)
{
return TTT_GetIsPlayerValid(oGame, sPlayerId) ? TTT_GetPlayer(oGame, sPlayerId) : OBJECT_INVALID;
}
int TTT_GetIsPlayerValid(object oGame, string sPlayerId)
{
object oPlayer = TTT_GetPlayer(oGame, sPlayerId);
return GetIsObjectValid(oPlayer) && TTT_GetPlayerWindowToken(oPlayer);
}
int TTT_GetNumPlayers(object oGame)
{
return TTT_GetIsPlayerValid(oGame, TTT_PLAYER_ONE) + TTT_GetIsPlayerValid(oGame, TTT_PLAYER_TWO);
}
string TTT_GetFreePlayerId(object oGame)
{
if (!TTT_GetIsPlayerValid(oGame, TTT_PLAYER_ONE))
return TTT_PLAYER_ONE;
else if (!TTT_GetIsPlayerValid(oGame, TTT_PLAYER_TWO))
return TTT_PLAYER_TWO;
else
return "IF_THIS_HAPPENS_YOU_DID_SOMETHING_WRONG";
}
object TTT_GetSinglePlayer(object oGame)
{
object oPlayer = TTT_GetValidatedPlayer(oGame, TTT_PLAYER_ONE);
if (oPlayer != OBJECT_INVALID)
return oPlayer;
else
{
oPlayer = TTT_GetValidatedPlayer(oGame, TTT_PLAYER_TWO);
if (oPlayer != OBJECT_INVALID)
return oPlayer;
}
return OBJECT_INVALID;
}
void TTT_UpdateBind(object oPlayer, string sBindName, json jValue)
{
if (GetIsObjectValid(oPlayer))
{
int nToken = TTT_GetPlayerWindowToken(oPlayer);
if (nToken)
NuiSetBind(oPlayer, nToken, sBindName, jValue);
}
}
void TTT_UpdateBindsForPlayers(object oGame, string sBindName, json jValue)
{
TTT_UpdateBind(TTT_GetValidatedPlayer(oGame, TTT_PLAYER_ONE), sBindName, jValue);
TTT_UpdateBind(TTT_GetValidatedPlayer(oGame, TTT_PLAYER_TWO), sBindName, jValue);
}
int TTT_CreateGameWindow(object oPlayer)
{
int nToken = NuiCreate(oPlayer, TTT_GetWindowJson(), TTT_WINDOW_ID);
json jGeometry = GetLocalJson(oPlayer, TTT_WINDOW_GEOMETRY);
if (jGeometry == JsonNull())
jGeometry = NuiRect(100.0f, 100.0f, TTT_WINDOW_WIDTH, TTT_WINDOW_HEIGHT);
NuiSetBindWatch(oPlayer, nToken, NUI_WINDOW_GEOMETRY_BIND, TRUE);
NuiSetBind(oPlayer, nToken, NUI_WINDOW_GEOMETRY_BIND, jGeometry);
return nToken;
}
void TTT_UpdateStaticBinds(object oGame)
{
object oPlayerOne = TTT_GetValidatedPlayer(oGame, TTT_PLAYER_ONE);
object oPlayerTwo = TTT_GetValidatedPlayer(oGame, TTT_PLAYER_TWO);
string sNamePlayerOne = oPlayerOne == OBJECT_INVALID ? "???" : GetName(oPlayerOne);
string sNamePlayerTwo = oPlayerTwo == OBJECT_INVALID ? "???" : GetName(oPlayerTwo);
string sHeader = sNamePlayerOne + " vs. " + sNamePlayerTwo;
TTT_UpdateBindsForPlayers(oGame, TTT_BIND_HEADER_TEXT, JsonString(sHeader));
string sPortraitPlayerOne = oPlayerOne == OBJECT_INVALID ? "po_hu_m_99_m" : GetPortraitResRef(oPlayerOne) + "m";
string sPortraitPlayerTwo = oPlayerTwo == OBJECT_INVALID ? "po_hu_m_99_m" : GetPortraitResRef(oPlayerTwo) + "m";
TTT_UpdateBindsForPlayers(oGame, TTT_BIND_PORTRAIT_ONE, JsonString(sPortraitPlayerOne));
TTT_UpdateBindsForPlayers(oGame, TTT_BIND_PORTRAIT_TWO, JsonString(sPortraitPlayerTwo));
}
void TTT_UpdateGridCellBind(object oGame, int nCell, json jImage)
{
TTT_UpdateBindsForPlayers(oGame, TTT_IntToCellString(nCell), jImage);
}
string TTT_GetImageFromSymbol(string sSymbol)
{
return sSymbol == TTT_CELL_VALUE_BLANK ? TTT_IMAGE_BLANK : sSymbol == TTT_CELL_VALUE_CIRCLE ? TTT_IMAGE_CIRCLE : TTT_IMAGE_CROSS;
}
void TTT_UpdateGridBinds(object oGame)
{
json jGridState = TTT_GetGridState(oGame);
int nCell, nNumCells = JsonGetLength(jGridState);
for (nCell = 0; nCell < nNumCells; nCell++)
{
string sImage = TTT_GetImageFromSymbol(JsonGetString(JsonArrayGet(jGridState, nCell)));
TTT_UpdateGridCellBind(oGame, nCell, JsonString(sImage));
}
}
void TTT_UpdateInfoTextBind(object oGame, string sText)
{
TTT_UpdateBindsForPlayers(oGame, TTT_BIND_INFO_TEXT, JsonString(sText));
}
void TTT_AddPlayerToGame(object oPlayer, object oGame = OBJECT_SELF)
{
if (TTT_GetPlayerWindowToken(oPlayer))
{
FloatingTextStringOnCreature("TicTacToe: Player Already In Game", oPlayer, FALSE);
return;
}
int nNumPlayers = TTT_GetNumPlayers(oGame);
if (nNumPlayers == 2)
{
FloatingTextStringOnCreature("TicTacToe: Max Number Of Players Reached", oPlayer, FALSE);
return;
}
if (!nNumPlayers)
{
TTT_ClearGridState(oGame);
TTT_SetGameState(oGame, TTT_GAME_STATE_NONE, "");
TTT_DeletePlayer(oGame, TTT_PLAYER_ONE);
TTT_DeletePlayer(oGame, TTT_PLAYER_TWO);
}
string sPlayerId = TTT_GetFreePlayerId(oGame);
TTT_SetPlayer(oGame, sPlayerId, oPlayer);
TTT_SetPlayerId(oPlayer, sPlayerId);
TTT_SetGame(oPlayer, oGame);
TTT_CreateGameWindow(oPlayer);
TTT_UpdateStaticBinds(oGame);
TTT_UpdateGridBinds(oGame);
TTT_UpdateGameState(oGame);
}
void TTT_HandleNUIEvents(object oPlayer, int nToken, string sType, string sElement, int nArrayIndex, json jPayload)
{
if (sType == NUI_EVENT_MOUSEUP)
{
if (GetStringLeft(sElement, GetStringLength(TTT_CELL_PREFIX)) == TTT_CELL_PREFIX)
{
object oGame = TTT_GetGame(oPlayer);
object oCurrentPlayer = TTT_GetCurrentPlayer(oGame);
int nCell = StringToInt(GetStringRight(sElement, 1));
int nGameState = TTT_GetGameState(oGame);
if (nGameState != TTT_GAME_STATE_PLAYING ||
oCurrentPlayer != oPlayer ||
TTT_GetGridStateCell(oGame, nCell) != TTT_CELL_VALUE_BLANK)
return;
string sSymbol = TTT_GetCurrentPlayerSymbol(oGame);
TTT_SetGridStateCell(oGame, nCell, sSymbol);
TTT_UpdateGridCellBind(oGame, nCell, JsonString(TTT_GetImageFromSymbol(sSymbol)));
if (TTT_GetIsWin(oGame))
TTT_SetGameState(oGame, TTT_GAME_STATE_GAME_OVER, GetName(oCurrentPlayer) + " won!");
else if (TTT_GetIsDraw(oGame))
TTT_SetGameState(oGame, TTT_GAME_STATE_GAME_OVER, "Draw!");
else
{
object oOpponent = TTT_GetOpponent(oGame);
TTT_SetGameState(oGame, TTT_GAME_STATE_PLAYING, GetName(oOpponent) + "'s turn!");
TTT_SetCurrentPlayer(oGame, oOpponent);
}
}
}
else if (sType == NUI_EVENT_CLICK)
{
if (sElement == TTT_BIND_BUTTON_RESTART)
{
object oGame = TTT_GetGame(oPlayer);
if (TTT_GetGameState(oGame) == TTT_GAME_STATE_GAME_OVER)
TTT_RestartGame(oGame);
}
}
else if (sType == NUI_EVENT_CLOSE)
{
if (sElement == NUI_WINDOW_ROOT_GROUP)
{
object oGame = TTT_GetGame(oPlayer);
TTT_RemovePlayerFromGame(oGame, oPlayer);
TTT_RestartGame(oGame);
}
}
else if (sType == NUI_EVENT_WATCH)
{
if (sElement == NUI_WINDOW_GEOMETRY_BIND)
{
SetLocalJson(oPlayer, TTT_WINDOW_GEOMETRY, NuiGetBind(oPlayer, nToken, NUI_WINDOW_GEOMETRY_BIND));
}
}
}
json TTT_InsertWinCondition(json jWinConditions, int nValueA, int nValueB, int nValueC)
{
json jWinCondition = JsonArray();
jWinCondition = JsonArrayInsert(jWinCondition, JsonInt(nValueA));
jWinCondition = JsonArrayInsert(jWinCondition, JsonInt(nValueB));
jWinCondition = JsonArrayInsert(jWinCondition, JsonInt(nValueC));
return JsonArrayInsert(jWinConditions, jWinCondition);
}
json TTT_GetWinConditions()
{
json jWinConditions = GetLocalJson(GetModule(), TTT_WIN_CONDITIONS);
if (jWinConditions == JsonNull())
{
jWinConditions = JsonArray();
jWinConditions = TTT_InsertWinCondition(jWinConditions, 0, 1, 2);
jWinConditions = TTT_InsertWinCondition(jWinConditions, 3, 4, 5);
jWinConditions = TTT_InsertWinCondition(jWinConditions, 6, 7, 8);
jWinConditions = TTT_InsertWinCondition(jWinConditions, 0, 3, 6);
jWinConditions = TTT_InsertWinCondition(jWinConditions, 1, 4, 7);
jWinConditions = TTT_InsertWinCondition(jWinConditions, 2, 5, 8);
jWinConditions = TTT_InsertWinCondition(jWinConditions, 0, 4, 8);
jWinConditions = TTT_InsertWinCondition(jWinConditions, 2, 4, 6);
SetLocalJson(GetModule(), TTT_WIN_CONDITIONS, jWinConditions);
}
return jWinConditions;
}
json TTT_GetGridState(object oGame)
{
return GetLocalJson(oGame, TTT_GRID_STATE);
}
void TTT_SetGridState(object oGame, json jGridState)
{
SetLocalJson(oGame, TTT_GRID_STATE, jGridState);
}
void TTT_ClearGridState(object oGame)
{
json jGridState = JsonArray();
int nCell;
for (nCell = 0; nCell < TTT_NUM_CELLS; nCell++)
{
jGridState = JsonArrayInsert(jGridState, JsonString(TTT_CELL_VALUE_BLANK));
}
TTT_SetGridState(oGame, jGridState);
}
string TTT_GetGridStateCell(object oGame, int nCell)
{
json jGridState = TTT_GetGridState(oGame);
return JsonGetString(JsonArrayGet(jGridState, nCell));
}
void TTT_SetGridStateCell(object oGame, int nCell, string sValue)
{
json jGridState = TTT_GetGridState(oGame);
jGridState = JsonArraySet(jGridState, nCell, JsonString(sValue));
TTT_SetGridState(oGame, jGridState);
}
int TTT_GetGameState(object oGame)
{
return GetLocalInt(oGame, TTT_GAME_STATE);
}
void TTT_SetGameState(object oGame, int nGameState, string sInfoText)
{
SetLocalInt(oGame, TTT_GAME_STATE, nGameState);
TTT_UpdateInfoTextBind(oGame, sInfoText);
if (nGameState == TTT_GAME_STATE_GAME_OVER)
TTT_SetRestartButtonEnabled(oGame, TRUE);
else
TTT_SetRestartButtonEnabled(oGame, FALSE);
}
void TTT_UpdateGameState(object oGame)
{
int nNumPlayers = TTT_GetNumPlayers(oGame);
if (nNumPlayers == 1)
{
TTT_SetGameState(oGame, TTT_GAME_STATE_WAITING, "Waiting for opponent...");
TTT_SetCurrentPlayer(oGame, TTT_GetSinglePlayer(oGame));
}
else if (nNumPlayers == 2)
{
TTT_SetGameState(oGame, TTT_GAME_STATE_PLAYING, GetName(TTT_GetCurrentPlayer(oGame)) + "'s turn!");
}
}
int TTT_GetIsDraw(object oGame)
{
json jGridState = TTT_GetGridState(oGame);
int nCell, nNumCells = JsonGetLength(jGridState);
for (nCell = 0; nCell < nNumCells; nCell++)
{
if (JsonGetString(JsonArrayGet(jGridState, nCell)) == TTT_CELL_VALUE_BLANK)
return FALSE;
}
return TRUE;
}
int TTT_GetIsWin(object oGame)
{
json jGridState = TTT_GetGridState(oGame);
json jWinConditions = TTT_GetWinConditions();
int nWinCondition, nNumWinConditions = JsonGetLength(jWinConditions);
for(nWinCondition = 0; nWinCondition < nNumWinConditions; nWinCondition++)
{
json jWinCondition = JsonArrayGet(jWinConditions, nWinCondition);
string sValueA = JsonGetString(JsonArrayGet(jGridState, JsonGetInt(JsonArrayGet(jWinCondition, 0))));
string sValueB = JsonGetString(JsonArrayGet(jGridState, JsonGetInt(JsonArrayGet(jWinCondition, 1))));
string sValueC = JsonGetString(JsonArrayGet(jGridState, JsonGetInt(JsonArrayGet(jWinCondition, 2))));
if (sValueA == TTT_CELL_VALUE_BLANK || sValueB == TTT_CELL_VALUE_BLANK ||sValueC == TTT_CELL_VALUE_BLANK)
continue;
if (sValueA == sValueB && sValueB == sValueC)
return TRUE;
}
return FALSE;
}
void TTT_RestartGame(object oGame)
{
TTT_SetGameState(oGame, TTT_GAME_STATE_NONE, "");
TTT_ClearGridState(oGame);
TTT_UpdateStaticBinds(oGame);
TTT_UpdateGridBinds(oGame);
TTT_UpdateGameState(oGame);
}
void TTT_RemovePlayerFromGame(object oGame, object oPlayer)
{
NuiDestroy(oPlayer, TTT_GetPlayerWindowToken(oPlayer));
TTT_DeletePlayer(oGame, TTT_GetPlayerId(oPlayer));
TTT_DeleteGame(oPlayer);
TTT_DeletePlayerId(oPlayer);
}
void TTT_HandlePlayerExit(object oPlayer)
{
if (TTT_GetPlayerWindowToken(oPlayer))
{
object oGame = TTT_GetGame(oPlayer);
TTT_RemovePlayerFromGame(oGame, oPlayer);
TTT_RestartGame(oGame);
}
}

@ -0,0 +1,305 @@
/*
Visual Transform NUI Window
Created By: Daz
*/
#include "inc_nui"
const string VT_WINDOW_ID = "VT";
const string VT_WINDOW_JSON = "VT_WINDOW_JSON";
const string VT_WINDOW_GEOMETRY = "VT_WINDOW_GEOMETRY";
const string VT_VALUE_BIND_PREFIX = "vt_value_";
const string VT_DISPLAY_BIND_PREFIX = "vt_display_";
const string VT_CLEAR_BUTTON_ID_PREFIX = "vt_btn_clear_";
const string VT_TARGET_BUTTON_ID = "vt_btn_target";
const string VT_CURRENT_TARGET = "VT_CURRENT_TARGET";
const string VT_TARGETING_MODE = "VT_TARGETING_MODE";
const float VT_SCALE_MIN = 1.0f;
const float VT_SCALE_MAX = 10.0f;
const float VT_SCALE_STEP = 0.1f;
const float VT_SCALE_DEFAULT = 1.0f;
const float VT_ROTATE_MIN = 0.0f;
const float VT_ROTATE_MAX = 359.0f;
const float VT_ROTATE_STEP = 1.0f;
const float VT_TRANSLATE_MIN = -10.0f;
const float VT_TRANSLATE_MAX = 10.0f;
const float VT_TRANSLATE_STEP = 0.1f;
void VT_HandleNUIEvents(object oPlayer, int nToken, string sType, string sElement, int nArrayIndex, json jPayload);
string VT_GetValueBind(int nType);
string VT_GetDisplayBind(int nType);
string VT_GetClearButtonId(int nType);
json VT_CreateVisualTransformRow(string sName, int nType, float fMin, float fMax, float fStep);
void VT_SetValueBindToCurrentValue(object oPlayer, int nToken, int nType);
void VT_ShowWindow(object oPlayer);
void VT_SetCurrentTarget(object oPlayer, object oTarget);
object VT_GetCurrentTarget(object oPlayer);
void VT_DeleteCurrentTarget(object oPlayer);
void VT_EnterTargetMode(object oPlayer);
void VT_HandleTargetEvent(object oPlayer, object oTarget, vector vPosition);
void VT_HandleNUIEvents(object oPlayer, int nToken, string sType, string sElement, int nArrayIndex, json jPayload)
{
if (sType == NUI_EVENT_CLICK)
{
if (sElement == VT_TARGET_BUTTON_ID)
{
VT_EnterTargetMode(oPlayer);
}
else if (GetStringLeft(sElement, GetStringLength(VT_CLEAR_BUTTON_ID_PREFIX)) == VT_CLEAR_BUTTON_ID_PREFIX)
{
int nType = StringToInt(GetStringRight(sElement, 2));
NuiSetBind(oPlayer, nToken, VT_GetValueBind(nType), JsonFloat(nType == OBJECT_VISUAL_TRANSFORM_SCALE ? VT_SCALE_DEFAULT : 0.0f));
}
}
else if (sType == NUI_EVENT_WATCH)
{
if (GetStringLeft(sElement, GetStringLength(VT_VALUE_BIND_PREFIX)) == VT_VALUE_BIND_PREFIX)
{
int nType = StringToInt(GetStringRight(sElement, 2));
float fValue = JsonGetFloat(NuiGetBind(oPlayer, nToken, VT_GetValueBind(nType)));
object oTarget = VT_GetCurrentTarget(oPlayer);
SetObjectVisualTransform(oTarget, nType, fValue);
NuiSetBind(oPlayer, nToken, VT_GetDisplayBind(nType), JsonString(FloatToString(fValue, 2, 1)));
}
else if (sElement == NUI_WINDOW_GEOMETRY_BIND)
{
SetLocalJson(oPlayer, VT_WINDOW_GEOMETRY, NuiGetBind(oPlayer, nToken, NUI_WINDOW_GEOMETRY_BIND));
}
}
else if (sType == NUI_EVENT_MOUSESCROLL)
{
if (GetStringLeft(sElement, GetStringLength(VT_VALUE_BIND_PREFIX)) == VT_VALUE_BIND_PREFIX)
{
int nType = StringToInt(GetStringRight(sElement, 2));
float fDelta = NuiGetMouseScrollDelta(jPayload);
float fStep;
switch (nType)
{
case OBJECT_VISUAL_TRANSFORM_SCALE:
fStep = VT_SCALE_STEP;
break;
case OBJECT_VISUAL_TRANSFORM_ROTATE_X:
case OBJECT_VISUAL_TRANSFORM_ROTATE_Y:
case OBJECT_VISUAL_TRANSFORM_ROTATE_Z:
fStep = VT_ROTATE_STEP;
break;
case OBJECT_VISUAL_TRANSFORM_TRANSLATE_X:
case OBJECT_VISUAL_TRANSFORM_TRANSLATE_Y:
case OBJECT_VISUAL_TRANSFORM_TRANSLATE_Z:
fStep = VT_TRANSLATE_STEP;
break;
}
float fCurrentValue = JsonGetFloat(NuiGetBind(oPlayer, nToken, sElement));
NuiSetBind(oPlayer, nToken, sElement, JsonFloat(fCurrentValue + (fDelta > 0.0f ? fStep : -fStep)));
}
}
else if (sType == NUI_EVENT_CLOSE)
{
if (sElement == NUI_WINDOW_ROOT_GROUP)
{
VT_DeleteCurrentTarget(oPlayer);
}
}
}
string VT_GetValueBind(int nType)
{
return VT_VALUE_BIND_PREFIX + IntToString(nType);
}
string VT_GetDisplayBind(int nType)
{
return VT_DISPLAY_BIND_PREFIX + IntToString(nType);
}
string VT_GetClearButtonId(int nType)
{
return VT_CLEAR_BUTTON_ID_PREFIX + IntToString(nType);
}
json VT_CreateVisualTransformRow(string sName, int nType, float fMin, float fMax, float fStep)
{
json jRow = JsonArray();
json jLabel = NuiLabel(JsonString(sName), JsonInt(NUI_HALIGN_LEFT), JsonInt(NUI_VALIGN_MIDDLE));
jLabel = NuiWidth(jLabel, 100.0f);
jRow = JsonArrayInsert(jRow, jLabel);
jRow = JsonArrayInsert(jRow, NuiSpacer());
json jSlider = NuiSliderFloat(NuiBind(VT_GetValueBind(nType)), JsonFloat(fMin), JsonFloat(fMax), JsonFloat(fStep));
jSlider = NuiId(jSlider, VT_GetValueBind(nType));
jSlider = NuiWidth(jSlider, 175.0f);
jRow = JsonArrayInsert(jRow, jSlider);
json jText = NuiTextEdit(JsonString(""), NuiBind(VT_GetDisplayBind(nType)), 10, FALSE);
jText = NuiEnabled(jText, JsonBool(FALSE));
jText = NuiWidth(jText, 75.0f);
jRow = JsonArrayInsert(jRow, jText);
json jButtonClear = NuiButton(JsonString("X"));
jButtonClear = NuiId(jButtonClear, VT_GetClearButtonId(nType));
jButtonClear = NuiWidth(jButtonClear, 35.0f);
jButtonClear = NuiHeight(jButtonClear, 35.0f);
jRow = JsonArrayInsert(jRow, jButtonClear);
return NuiRow(jRow);
}
void VT_SetValueBindToCurrentValue(object oPlayer, int nToken, int nType)
{
object oTarget = VT_GetCurrentTarget(oPlayer);
NuiSetBind(oPlayer, nToken, VT_GetValueBind(nType), JsonFloat(GetObjectVisualTransform(oTarget, nType)));
}
void VT_ShowWindow(object oPlayer)
{
int nToken = NuiFindWindow(oPlayer, VT_WINDOW_ID);
if (nToken)
return;
object oModule = GetModule();
json jWindow = GetLocalJson(oModule, VT_WINDOW_JSON);
if (!JsonGetType(jWindow))
{
json jCol;
json jRow;
jCol = JsonArray();
jRow = JsonArray();
{
jRow = JsonArrayInsert(jRow, NuiSpacer());
json jButtonTarget = NuiButton(JsonString("Target"));
jButtonTarget = NuiId(jButtonTarget, VT_TARGET_BUTTON_ID);
jButtonTarget = NuiWidth(jButtonTarget, 100.0f);
jButtonTarget = NuiHeight(jButtonTarget, 35.0f);
jRow = JsonArrayInsert(jRow, jButtonTarget);
}
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
jCol = JsonArrayInsert(jCol, VT_CreateVisualTransformRow("Scale", OBJECT_VISUAL_TRANSFORM_SCALE, VT_SCALE_MIN, VT_SCALE_MAX, VT_SCALE_STEP));
jCol = JsonArrayInsert(jCol, VT_CreateVisualTransformRow("Rotate X", OBJECT_VISUAL_TRANSFORM_ROTATE_X, VT_ROTATE_MIN, VT_ROTATE_MAX, VT_ROTATE_STEP));
jCol = JsonArrayInsert(jCol, VT_CreateVisualTransformRow("Rotate Y", OBJECT_VISUAL_TRANSFORM_ROTATE_Y, VT_ROTATE_MIN, VT_ROTATE_MAX, VT_ROTATE_STEP));
jCol = JsonArrayInsert(jCol, VT_CreateVisualTransformRow("Rotate Z", OBJECT_VISUAL_TRANSFORM_ROTATE_Z, VT_ROTATE_MIN, VT_ROTATE_MAX, VT_ROTATE_STEP));
jCol = JsonArrayInsert(jCol, VT_CreateVisualTransformRow("Translate X", OBJECT_VISUAL_TRANSFORM_TRANSLATE_X, VT_TRANSLATE_MIN, VT_TRANSLATE_MAX, VT_TRANSLATE_STEP));
jCol = JsonArrayInsert(jCol, VT_CreateVisualTransformRow("Translate Y", OBJECT_VISUAL_TRANSFORM_TRANSLATE_Y, VT_TRANSLATE_MIN, VT_TRANSLATE_MAX, VT_TRANSLATE_STEP));
jCol = JsonArrayInsert(jCol, VT_CreateVisualTransformRow("Translate Z", OBJECT_VISUAL_TRANSFORM_TRANSLATE_Z, VT_TRANSLATE_MIN, VT_TRANSLATE_MAX, VT_TRANSLATE_STEP));
jRow = JsonArray();
{
jRow = JsonArrayInsert(jRow, NuiSpacer());
}
jCol = JsonArrayInsert(jCol, NuiRow(jRow));
json jRoot = NuiCol(jCol);
jWindow = NuiWindow(jRoot, NuiBind(NUI_WINDOW_TITLE_BIND), NuiBind(NUI_WINDOW_GEOMETRY_BIND), JsonBool(FALSE), JsonNull(), JsonBool(TRUE), JsonBool(FALSE), JsonBool(TRUE));
SetLocalJson(oModule, VT_WINDOW_JSON, jWindow);
}
nToken = NuiCreate(oPlayer, jWindow, VT_WINDOW_ID);
json jGeometry = GetLocalJson(oPlayer, VT_WINDOW_GEOMETRY);
if (!JsonGetType(jGeometry))
jGeometry = NuiGetCenteredGeometryRect(oPlayer, 450.0f, 425.0f);
VT_SetCurrentTarget(oPlayer, oPlayer);
NuiSetBindWatch(oPlayer, nToken, VT_GetValueBind(OBJECT_VISUAL_TRANSFORM_SCALE), TRUE);
NuiSetBindWatch(oPlayer, nToken, VT_GetValueBind(OBJECT_VISUAL_TRANSFORM_ROTATE_X), TRUE);
NuiSetBindWatch(oPlayer, nToken, VT_GetValueBind(OBJECT_VISUAL_TRANSFORM_ROTATE_Y), TRUE);
NuiSetBindWatch(oPlayer, nToken, VT_GetValueBind(OBJECT_VISUAL_TRANSFORM_ROTATE_Z), TRUE);
NuiSetBindWatch(oPlayer, nToken, VT_GetValueBind(OBJECT_VISUAL_TRANSFORM_TRANSLATE_X), TRUE);
NuiSetBindWatch(oPlayer, nToken, VT_GetValueBind(OBJECT_VISUAL_TRANSFORM_TRANSLATE_Y), TRUE);
NuiSetBindWatch(oPlayer, nToken, VT_GetValueBind(OBJECT_VISUAL_TRANSFORM_TRANSLATE_Z), TRUE);
VT_SetValueBindToCurrentValue(oPlayer, nToken, OBJECT_VISUAL_TRANSFORM_SCALE);
VT_SetValueBindToCurrentValue(oPlayer, nToken, OBJECT_VISUAL_TRANSFORM_ROTATE_X);
VT_SetValueBindToCurrentValue(oPlayer, nToken, OBJECT_VISUAL_TRANSFORM_ROTATE_Y);
VT_SetValueBindToCurrentValue(oPlayer, nToken, OBJECT_VISUAL_TRANSFORM_ROTATE_Z);
VT_SetValueBindToCurrentValue(oPlayer, nToken, OBJECT_VISUAL_TRANSFORM_TRANSLATE_X);
VT_SetValueBindToCurrentValue(oPlayer, nToken, OBJECT_VISUAL_TRANSFORM_TRANSLATE_Y);
VT_SetValueBindToCurrentValue(oPlayer, nToken, OBJECT_VISUAL_TRANSFORM_TRANSLATE_Z);
NuiSetBindWatch(oPlayer, nToken, NUI_WINDOW_GEOMETRY_BIND, TRUE);
NuiSetBind(oPlayer, nToken, NUI_WINDOW_GEOMETRY_BIND, jGeometry);
NuiSetBind(oPlayer, nToken, NUI_WINDOW_TITLE_BIND, JsonString("Visually Transforming: " + GetName(oPlayer)));
}
void VT_SetCurrentTarget(object oPlayer, object oTarget)
{
SetLocalObject(oPlayer, VT_CURRENT_TARGET, oTarget);
}
object VT_GetCurrentTarget(object oPlayer)
{
return GetLocalObject(oPlayer, VT_CURRENT_TARGET);
}
void VT_DeleteCurrentTarget(object oPlayer)
{
DeleteLocalObject(oPlayer, VT_CURRENT_TARGET);
}
void VT_EnterTargetMode(object oPlayer)
{
SetLocalInt(oPlayer, VT_TARGETING_MODE, TRUE);
EnterTargetingMode(oPlayer, OBJECT_TYPE_CREATURE | OBJECT_TYPE_PLACEABLE | OBJECT_TYPE_DOOR | OBJECT_TYPE_TILE);
}
void VT_HandleTargetEvent(object oPlayer, object oTarget, vector vPosition)
{
if (!GetLocalInt(oPlayer, VT_TARGETING_MODE))
return;
DeleteLocalInt(oPlayer, VT_TARGETING_MODE);
if (!GetIsObjectValid(oTarget))
return;
if (GetArea(oPlayer) == oTarget)
{
oTarget = GetNearestObjectToLocation(OBJECT_TYPE_CREATURE | OBJECT_TYPE_PLACEABLE | OBJECT_TYPE_DOOR, Location(oTarget, vPosition, 0.0f));
if (!GetIsObjectValid(oTarget))
return;
}
else
{
int nObjectType = GetObjectType(oTarget);
if (nObjectType != OBJECT_TYPE_CREATURE &&
nObjectType != OBJECT_TYPE_PLACEABLE &&
nObjectType != OBJECT_TYPE_DOOR)
return;
}
int nToken = NuiFindWindow(oPlayer, VT_WINDOW_ID);
if (!nToken)
return;
VT_SetCurrentTarget(oPlayer, oTarget);
VT_SetValueBindToCurrentValue(oPlayer, nToken, OBJECT_VISUAL_TRANSFORM_SCALE);
VT_SetValueBindToCurrentValue(oPlayer, nToken, OBJECT_VISUAL_TRANSFORM_ROTATE_X);
VT_SetValueBindToCurrentValue(oPlayer, nToken, OBJECT_VISUAL_TRANSFORM_ROTATE_Y);
VT_SetValueBindToCurrentValue(oPlayer, nToken, OBJECT_VISUAL_TRANSFORM_ROTATE_Z);
VT_SetValueBindToCurrentValue(oPlayer, nToken, OBJECT_VISUAL_TRANSFORM_TRANSLATE_X);
VT_SetValueBindToCurrentValue(oPlayer, nToken, OBJECT_VISUAL_TRANSFORM_TRANSLATE_Y);
VT_SetValueBindToCurrentValue(oPlayer, nToken, OBJECT_VISUAL_TRANSFORM_TRANSLATE_Z);
NuiSetBind(oPlayer, nToken, NUI_WINDOW_TITLE_BIND, JsonString("Visually Transforming: " + GetName(oTarget)));
}

129
_module/nss/inc_util.nss Normal file

@ -0,0 +1,129 @@
/*
Utility Functions
Created By: Daz
*/
#include "nw_inc_gff"
#include "nw_inc_nui"
string Util_GetIconResref(object oItem, json jItem, int nBaseItem);
string Util_GetIconResref(object oItem, json jItem, int nBaseItem)
{
if (nBaseItem == BASE_ITEM_CLOAK) // Cloaks use PLTs so their default icon doesn't really work
return "iit_cloak";
else if (nBaseItem == BASE_ITEM_SPELLSCROLL || nBaseItem == BASE_ITEM_ENCHANTED_SCROLL)
{// Scrolls get their icon from the cast spell property
if (GetItemHasItemProperty(oItem, ITEM_PROPERTY_CAST_SPELL))
{
itemproperty ip = GetFirstItemProperty(oItem);
while (GetIsItemPropertyValid(ip))
{
if (GetItemPropertyType(ip) == ITEM_PROPERTY_CAST_SPELL)
return Get2DAString("iprp_spells", "Icon", GetItemPropertySubType(ip));
ip = GetNextItemProperty(oItem);
}
}
}
else if (Get2DAString("baseitems", "ModelType", nBaseItem) == "0")
{// Create the icon resref for simple modeltype items
json jSimpleModel = GffGetByte(jItem, "ModelPart1");
if (JsonGetType(jSimpleModel) == JSON_TYPE_INTEGER)
{
string sSimpleModelId = IntToString(JsonGetInt(jSimpleModel));
while (GetStringLength(sSimpleModelId) < 3)// Padding...
{
sSimpleModelId = "0" + sSimpleModelId;
}
string sDefaultIcon = Get2DAString("baseitems", "DefaultIcon", nBaseItem);
switch (nBaseItem)
{
case BASE_ITEM_MISCSMALL:
case BASE_ITEM_CRAFTMATERIALSML:
sDefaultIcon = "iit_smlmisc_" + sSimpleModelId;
break;
case BASE_ITEM_MISCMEDIUM:
case BASE_ITEM_CRAFTMATERIALMED:
case 112:/* Crafting Base Material */
sDefaultIcon = "iit_midmisc_" + sSimpleModelId;
break;
case BASE_ITEM_MISCLARGE:
sDefaultIcon = "iit_talmisc_" + sSimpleModelId;
break;
case BASE_ITEM_MISCTHIN:
sDefaultIcon = "iit_thnmisc_" + sSimpleModelId;
break;
}
int nLength = GetStringLength(sDefaultIcon);
if (GetSubString(sDefaultIcon, nLength - 4, 1) == "_")// Some items have a default icon of xx_yyy_001, we strip the last 4 symbols if that is the case
sDefaultIcon = GetStringLeft(sDefaultIcon, nLength - 4);
string sIcon = sDefaultIcon + "_" + sSimpleModelId;
if (ResManGetAliasFor(sIcon, RESTYPE_TGA) != "")// Check if the icon actually exists, if not, we'll fall through and return the default icon
return sIcon;
}
}
// For everything else use the item's default icon
return Get2DAString("baseitems", "DefaultIcon", nBaseItem);
}
json Util_GetModelPart(string sDefaultIcon, string sType, json jPart)
{
if (JsonGetType(jPart) == JSON_TYPE_INTEGER)
{
string sModelPart = IntToString(JsonGetInt(jPart));
while (GetStringLength(sModelPart) < 3)
{
sModelPart = "0" + sModelPart;
}
string sIcon = sDefaultIcon + sType + sModelPart;
if (ResManGetAliasFor(sIcon, RESTYPE_TGA) != "")
return JsonString(sIcon);
}
return JsonString("");
}
json Util_GetComplexIconData(json jItem, int nBaseItem);
json Util_GetComplexIconData(json jItem, int nBaseItem)
{
if (Get2DAString("baseitems", "ModelType", nBaseItem) == "2")
{
string sDefaultIcon = Get2DAString("baseitems", "DefaultIcon", nBaseItem);
json jComplexIcon = JsonObject();
jComplexIcon = JsonObjectSet(jComplexIcon, "top", Util_GetModelPart(sDefaultIcon, "_t_", GffGetByte(jItem, "ModelPart3")));
jComplexIcon = JsonObjectSet(jComplexIcon, "middle", Util_GetModelPart(sDefaultIcon, "_m_", GffGetByte(jItem, "ModelPart2")));
jComplexIcon = JsonObjectSet(jComplexIcon, "bottom", Util_GetModelPart(sDefaultIcon, "_b_", GffGetByte(jItem, "ModelPart1")));
return jComplexIcon;
}
return JsonNull();
}
string Util_Get2DAStringByStrRef(string s2DA, string sColumn, int nRow);
string Util_Get2DAStringByStrRef(string s2DA, string sColumn, int nRow)
{
return GetStringByStrRef(StringToInt(Get2DAString(s2DA, sColumn, nRow)));
}
string Util_GetItemName(object oItem, int bIdentified);
string Util_GetItemName(object oItem, int bIdentified)
{
return bIdentified ? GetName(oItem) : Util_Get2DAStringByStrRef("baseitems", "Name", GetBaseItemType(oItem)) + " (Unidentified)";
}
void Util_SendDebugMessage(string sMessage);
void Util_SendDebugMessage(string sMessage)
{
object oPlayer = GetFirstPC();
while (oPlayer != OBJECT_INVALID)
{
SendMessageToPC(oPlayer, sMessage);
oPlayer = GetNextPC();
}
}

@ -0,0 +1,6 @@
#include "nui_i_main"
void main()
{
NUI();
}

@ -0,0 +1,11 @@
#include "nui_i_main"
void main()
{
// Get the last player to use targeting mode
object oPC = GetLastPlayerToSelectTarget();
NUI_HandleEvents(oPC);
ExecuteScript("prc_onplaytarget", oPC);
}

33
_module/nss/mod_nui.nss Normal file

@ -0,0 +1,33 @@
#include "inc_perchest"
#include "inc_gennui"
#include "inc_examine"
#include "inc_tictactoe"
#include "inc_blackjack"
#include "inc_transform"
void main()
{
object oPlayer = NuiGetEventPlayer();
int nToken = NuiGetEventWindow();
string sWindowId = NuiGetWindowId(oPlayer, nToken);
string sType = NuiGetEventType();
string sElement = NuiGetEventElement();
int nArrayIndex = NuiGetEventArrayIndex();
json jPayload = NuiGetEventPayload();
//SendMessageToPC(oPlayer, "(" + IntToString(nToken) + ":" + sWindowId + ") T: " + sType + ", E: " + sElement + ", AI: " + IntToString(nArrayIndex) + ", P: " + JsonDump(jPayload));
if (sWindowId == PC_NUI_WINDOW_ID || sWindowId == PC_NUI_GOLD_WINDOW_ID)
PC_HandleNUIEvents(oPlayer, sWindowId, nToken, sType, sElement, nArrayIndex);
else if (sWindowId == EXAMINE_NUI_WINDOW_ID)
Examine_HandleNUIEvents(oPlayer, nToken, sType, sElement, nArrayIndex);
else if (sWindowId == TTT_WINDOW_ID)
TTT_HandleNUIEvents(oPlayer, nToken, sType, sElement, nArrayIndex, jPayload);
else if (sWindowId == BJ_WINDOW_ID)
BJ_HandleNUIEvents(oPlayer, nToken, sType, sElement, nArrayIndex, jPayload);
else if (sWindowId == VT_WINDOW_ID)
VT_HandleNUIEvents(oPlayer, nToken, sType, sElement, nArrayIndex, jPayload);
else
GNW_HandleNUIEvents();
}

@ -0,0 +1,12 @@
#include "inc_perchest"
#include "inc_transform"
void main()
{
object oPlayer = GetLastPlayerToSelectTarget();
object oTarget = GetTargetingModeSelectedObject();
vector vPosition = GetTargetingModeSelectedPosition();
PC_HandleDepositEvent(oPlayer, oTarget, vPosition);
VT_HandleTargetEvent(oPlayer, oTarget, vPosition);
}

@ -0,0 +1,50 @@
/// ----------------------------------------------------------------------------
/// @file nui_c_config.nss
/// @author Ed Burke (tinygiant98) <af.hog.pilot@gmail.com>
/// @brief NUI Form Creation and Management System Configuration
/// ----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// FORM INSPECTOR
// -----------------------------------------------------------------------------
// The form inspection capability allows you to record data about a form's status,
// including bind values and how various events affect them. To use the inspection
// capability, you must include the `nui_f_inspector` formfile in your module and
// set NUI_FI_RECORD_DATA to the desired value.
// *** WARNING *** Form inspection is very expensive. Is it recommended that
// you only use the form inspection capability during debug or set this
// value to NUI_FI_WHEN_OPEN to prevent unnecessary traffic.
const int NUI_FI_NEVER = 0;
const int NUI_FI_ALWAYS = 1;
const int NUI_FI_WHEN_OPEN = 2;
const int NUI_FI_RECORD_DATA = NUI_FI_WHEN_OPEN;
// -----------------------------------------------------------------------------
// Custom Functions
// MODIFY THESE TO ENSURE COMPATIBILTY WITH YOUR MODULE'S SYSTEMS
// -----------------------------------------------------------------------------
// This system has some basic debugging functionality. In order to make this system work
// under multiple modules without collision, the following function is provided to
// allow you to call whatever debugging system you'd like to call. If you use
// squattingmonk's debug utility, no changes need to be made. The primary system does
// not provide any organic debug calls, but this function is available to all formfiles
// for debugging purposes.
//
const int NUI_DEBUG_SEVERITY_NONE = 0;
const int NUI_DEBUG_SEVERITY_CRITICAL = 1;
const int NUI_DEBUG_SEVERITY_ERROR = 2;
const int NUI_DEBUG_SEVERITY_WARNING = 3;
const int NUI_DEBUG_SEVERITY_NOTICE = 4;
const int NUI_DEBUG_SEVERITY_DEBUG = 5;
//#include "util_i_debug"
void NUI_Debug(string sMessage, int nSeverity = 4)
{
//Debug(sMessage, nSeverity);
}

@ -0,0 +1,225 @@
/// ----------------------------------------------------------------------------
/// @file nui_c_storage.nss
/// @author Ed Burke (tinygiant98) <af.hog.pilot@gmail.com>
/// @brief Persistent Storage formfile configuration settings
/// ----------------------------------------------------------------------------
/// @note Most of the following global/default settings can be overriden on a
/// per-container basis by setting a local variable on the container
/// object as noted in the setting descriptions below. Constants, such as
/// PS_TRUE, PS_NONE, etc. should be used in this configuration file, however,
/// actual values must be used when setting local overrides. Those values
/// are provided below.
/// @warning This system uses player character UUIDs. This can cause issues in
/// single-player modules if the player-character is not exported and the
/// UUID is not saved to the .bic file.
/// @brief By default, containers will be saved to a database table referenced
/// by the container object's tag. The saved item data includes the UUID
/// and CD Key of the PC that deposited the item so the same container can
/// be used for multiple PCs. To set a specific (unique) name to use as the
/// table name instead, set a local string called `PS_UNIQUE_ID` on the
/// container object and set it to any unique string.
/// @brief Determines usage of the `Search` button.
/// Configuration File:
/// PS_TRUE to force players to click the `Search` button
/// before an inventory search will commence. This is a good idea
/// for containers that you expect will have large inventories.
/// PS_FALSE to allow real-time searching as the player types
/// characters into the `Search` textbox.
/// Local Override (int): PS_FORCE_SEARCH_BUTTON
/// 1 = PS_TRUE
/// -1 = PS_FALSE
const int PS_FORCE_SEARCH_BUTTON_DEFAULT = PS_TRUE;
/// @brief Determines whether item object state is saved to the database. The
/// object state includes variables and effects.
/// Configuration File:
/// PS_TRUE saves the object state
/// PS_FALSE does not save the object state
/// Local Override (int): PS_FORCE_OBJECT_STATE
/// 1 = PS_TRUE
/// -1 = PS_FALSE
const int PS_FORCE_OBJECT_STATE_DEFAULT = PS_TRUE;
/// @brief Sets the item storage limit.
/// Configuration File:
/// PS_UNLIMITED to allow unlimited item storage.
/// Set to any positive integer to limit item storage to that amount.
/// Local Override (int): PS_STORAGE_LIMIT
/// -1 = PS_UNLIMITED
/// Set to any positive integer to limit item storage to that amount.
const int PS_STORAGE_LIMIT_DEFAULT = 500;
/// @brief Set the maximum distance (meters) a PC can travel from the container
/// before the form will auto-close.
/// Configuration File:
/// PS_UNLIMITED_DISTANCE to never auto-close the form
/// Set to any positive float to limit distance to that amount.
/// Local Override (float): PS_DISTANCE
/// -1.0 = PS_UNLIMITED_DISTANCE
/// Set to any positive float to limit distance to that amount.
const float PS_DISTANCE_DEFAULT = 5.0;
/// @brief Set the container access type. Container inventories can be accessed
/// by two methods: exclusive and contentious.
/// - Exclusive: Multiple players may open the same container, but each
/// player will only see items they've previously deposited. Players
/// may only withdraw items they've previously deposited.
/// - Contentious: Multiple players may open the same container. All
/// players will see all items deposited by any player. Any player
/// can remove any item, regardless of who originally deposited the
/// item.
///
/// Configuration File:
/// PS_ACCESS_EXCLUSIVE for exclusive access
/// PS_ACCESS_CONTENTIOUS for contentious access
/// Local Override (int): PS_ACCESS_TYPE
/// 1 = PS_ACCESS_EXCLUSIVE
/// 2 = PS_ACCESS_CONTENTIOUS
const int PS_ACCESS_TYPE_DEFAULT = PS_ACCESS_EXCLUSIVE;
/// @brief Set the container type. Containers can be of multiple types:
/// - Public: Any player can open, deposit and withdraw items from this
/// container. Whether they are limited to specific items is dependant
/// on the container's access setting.
/// - Character: Creates a 'portable' storage container for any player
/// character. Any container of this type will hold the same inventory
/// for any specific player.
/// - CD Key: Creates a 'portable' storage container for any characters
/// owned by cd-key associated with the player character. Any container
/// of this type will hold the inventory desposited by any character
/// sharing the player's cd key.
///
/// Configuration File:
/// PS_CONTAINER_PUBLIC for public.
/// PS_CONTAINER_CHARACTER for per-character.
/// PS_CONTAINER_CD_KEY for per-cdkey.
/// Local Override (int): PS_CONTAINER_TYPE
/// 1 = PS_CONTAINER_PUBLIC
/// 2 = PS_CONTAINER_CHARACTER
/// 3 = PS_CONTAINER_CDKEY
const int PS_CONTAINER_TYPE_DEFAULT = PS_CONTAINER_CDKEY;
/// @brief Set the default container type, if the container is an item. Containers
/// can be of multiple types:
/// - Public: Any player can open, deposit and withdraw items from this
/// container. Whether they are limited to specific items is dependant
/// on the container's access setting.
/// - Character: Creates a 'portable' storage container for any player
/// character. Any container of this type will hold the same inventory
/// for any specific player.
/// - CD Key: Creates a 'portable' storage container for any characters
/// owned by cd-key associated with the player character. Any container
/// of this type will hold the inventory desposited by any character
/// sharing the player's cd key.
///
/// Configuration File:
/// PS_CONTAINER_PUBLIC for public.
/// PS_CONTAINER_CHARACTER for per-character.
/// PS_CONTAINER_CD_KEY for per-cdkey.
/// Local Override (int): PS_CONTAINER_TYPE
/// 1 = PS_CONTAINER_PUBLIC
/// 2 = PS_CONTAINER_CHARACTER
/// 3 = PS_CONTAINER_CDKEY
const int PS_CONTAINER_ITEM_TYPE_DEFAULT = PS_CONTAINER_CHARACTER;
/// @brief Determines whether the player's inventory window will be opened
/// when a container is opened.
/// Configuration File:
/// PS_TRUE to open the inventory window.
/// PS_FALSE to prevent the window from opening. If the inventory
/// window is already open, this will not close it.
/// Local Override (int): PS_OPEN_INVENTORY
/// 1 = PS_TRUE
/// -1 = PS_FALSE
const int PS_OPEN_INVENTORY_DEFAULT = PS_TRUE;
/// @brief Determines the maximum amount of gold a container can store.
/// If the container is set to store no gold, the form controls that
/// manipulate gold storage will not be visible on the form.
/// Configuration File:
/// PS_UNLIMITED to allow unlimited gold storage.
/// PS_NONE to prevent gold storage.
/// Set to any positive integer to limit gold to that amount.
/// Local Override (int): PS_MAX_GOLD
/// -1 = PS_UNLIMITED
/// -2 = PS_NONE
/// Set to any positive integer to limit gold to that amount.
const int PS_MAX_GOLD_DEFAULT = 1500000;
/// @note Reference these terms for the following option:
/// Container: A persistent storage object in the game, such as a chest.
/// Container Item: An item which:
/// Can have its own inventory
/// Can be carried in a player's inventory
/// @brief Determines handling for container objects. Containers can optionally
/// store container items.
/// Configuration File:
/// PS_UNLIMITED to allow storage of an unlimited number of container items.
/// PS_NONE to prevent storage of any container items.
/// Set to any positive integer to limit storage to that number of container
/// items.
/// Local Override (int): PS_MAX_CONTAINER_TIMES
/// -1 = PS_UNLIMITED
/// -2 = PS_NONE
/// Set to any positive integer to limit storage to that number of container
/// items.
const int PS_MAX_CONTAINER_ITEMS_DEFAULT = 100;
/// @brief Determines how many items can be stored in stored container items.
/// Configuration File:
/// PS_UNLIMITED to allow storage of any number of items within a container
/// item's inventory. This will be naturally limited by the size of
/// the container item's inventory.
/// PS_NONE to prevent any items from being stored in a container item. If
/// container item storage is allow and PS_NONE is used, only empty
/// container items can be stored.
/// Set to any positive integer to limit the number of items stored in
/// the inventory of a container item.
/// Local Override (int): PS_MAX_CONTAINER_ITEMS_INVENTORY
/// -1 = PS_UNLIMITED
/// -2 = PS_NONE
/// Set to any positive integer to limit the number of items stored in
/// the inventory of a container item.
///
/// @note This configuration option has no effect if PS_MAX_CONTAINER_ITEMS_DEFAULT
/// is set to PS_NONE or its local override is set to -1.
/// @warning Items that fail check involved with container item limitations do
/// not have default messages reported to the player. The item will simply fail
/// to be stored.
const int PS_MAX_CONTAINER_ITEMS_INVENTORY_DEFAULT = 1000;
/// @brief Creates the form's title.
/// @param oContainer The container object being used.
/// @param oPC The player using oContainer.
/// @note A local string called `PS_TITLE` may be set on the object for easy
/// reference in this function. The function below is an example and may
/// be modified in any way. The returned value will be displayed as the
/// form's title.
string ps_GetFormTitle(object oContainer, object oPC, int nAccess, int nType)
{
string sTitle;
if ((sTitle = GetLocalString(oContainer, PS_TITLE)) != "")
return sTitle;
else
{
switch (nType)
{
case PS_CONTAINER_PUBLIC:
return GetTag(oContainer);
case PS_CONTAINER_CDKEY:
return GetName(oPC) + "'s Player-Specific Storage";
case PS_CONTAINER_CHARACTER:
return GetName(oPC) + "'s Character-Specific Storage";
}
if (GetIsPC(OBJECT_SELF))
return GetName(OBJECT_SELF) + "'s Storage";
}
return "Persistent Storage";
}

File diff suppressed because it is too large Load Diff

2741
_module/nss/nui_i_main.nss Normal file

File diff suppressed because it is too large Load Diff

@ -0,0 +1,8 @@
#include "inc_perchest"
void main()
{
object oPlayer = GetLastUsedBy();
PC_CreateNUIWindow(oPlayer);
}

@ -1,3 +1,5 @@
#include "inc_gennui"
void main()
{
//:: establishes PC current grid coordinates
@ -10,13 +12,18 @@ void main()
SetLocalString(oPC,"ss_t_chest_1","100003");
ExecuteScript("ss_treasure",oPC);
//:: NUI Magic by Daz
//Examine_DisablePanels(oPC);
PrintString(GetObjectUUID(oPC));
if (iXP < 1 && iGP < 300) //:: Gold for new players
{
int iRand = d100(3)+50;
GiveGoldToCreature(oPC,iRand);
}
//:: Add system journal entries
AddJournalQuestEntry("JRNL_XPCHART", 1, oPC, FALSE, FALSE, FALSE);
AddJournalQuestEntry("JRNL_LA_BUYOFF", 1, oPC, FALSE, FALSE, FALSE);
}

@ -23,8 +23,15 @@ else if (GetLastRestEventType()==REST_EVENTTYPE_REST_FINISHED||REST_EVENTTYPE_RE
int nMillisecond = GetTimeMillisecond();
// Advance the time 8 hours.
nHour += 8;
// Set the new time
SetTime(nHour, nMinute, nSecond, nMillisecond);
int iPW = GetLocalInt(GetModule(), "PW_MODE");
//:: Skip if running as a Persistant World MP module
if (!iPW)
{
SetTime(nHour, nMinute, nSecond, nMillisecond);
}
// See how hungry and thirsty PC is
int ibHungry = GetLocalInt(oPC,"ate");

@ -0,0 +1,17 @@
#include "inc_perchest"
void main()
{
object oPlayer = GetExitingObject();
int nToken = NuiFindWindow(oPlayer, PC_NUI_WINDOW_ID);
//:: Murder the poor window
NuiDestroy(oPlayer, nToken);
nToken = NuiFindWindow(oPlayer, PC_NUI_GOLD_WINDOW_ID);
if (nToken)
NuiDestroy(oPlayer, nToken);
}

@ -0,0 +1,6 @@
//Closes door if it is open
void main()
{
DelayCommand(13.0f,ActionCloseDoor(OBJECT_SELF));
}

@ -0,0 +1,86 @@
//::////////////////////////////////////////////////////////////////////////////
//:: Name Respawn Door/s v1.1
//:: FileName se_door_death
//:: Copyright (c) 2001 Bioware Corp.
//::////////////////////////////////////////////////////////////////////////////
/*
Respawn a door after a set delay
Set a float on the door ie. RESPAWN_TIMER = xx else the default is used
Thanks to Craig Welburn for the insight
Cheers to Zarathustra217
*/
//::////////////////////////////////////////////////////////////////////////////
//:: Created By: Sir Elric
//:: Created On: 8th May, 2006
//:: Modified On: 16th August, 2007
//:: Event Used: OnDeath event of a door
//::////////////////////////////////////////////////////////////////////////////
#include "x2_inc_compon"
// -----------------------------------------------------------------------------
// CONSTANTS - Settings below
// -----------------------------------------------------------------------------
const float RESPAWN_TIMER_DEFAULT = 600.0; // Default respawn delay
const int DO_CRAFT_DROP = TRUE; // Drop default Bioware crafting item?
// -----------------------------------------------------------------------------
// PROTOTYPES
// -----------------------------------------------------------------------------
// Respawn a door after a set delay
// If no float is set on the door ie. RESPAWN_TIMER = xx
// The default delay will be used ie. RESPAWN_TIMER_DEFAULT = xx
// oSelf: - Object calling the script
void SE_RespawnDoor(object oSelf);
// -----------------------------------------------------------------------------
// FUNCTIONS
// -----------------------------------------------------------------------------
void SE_RespawnDoor(object oSelf)
{
PlayAnimation(ANIMATION_DOOR_CLOSE);
int nHealAmount = GetMaxHitPoints(oSelf) - GetCurrentHitPoints(oSelf);
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHeal(nHealAmount), oSelf);
}
// -----------------------------------------------------------------------------
// MAIN
// -----------------------------------------------------------------------------
void main()
{
object oSelf = OBJECT_SELF;
object oKiller = GetLastKiller();
SetIsDestroyable(FALSE);
float fDelay = GetLocalFloat(oSelf, "RESPAWN_TIMER");
if(fDelay == 0.0)
fDelay = RESPAWN_TIMER_DEFAULT;
DelayCommand(fDelay, SE_RespawnDoor(oSelf));
if (!GetIsPC(oKiller))
return;
while (GetIsObjectValid(GetMaster(oKiller)))
{
oKiller=GetMaster(oKiller);
}
if(GetIsObjectValid(oKiller))
{
AdjustReputation(oKiller, OBJECT_SELF, -35);
AdjustAlignment (oKiller, ALIGNMENT_CHAOTIC, 10);
}
if(DO_CRAFT_DROP)
craft_drop_placeable();
}

34
_module/nss/sei_sit.nss Normal file

@ -0,0 +1,34 @@
//
// NWSit
//
// Script to make the PC using the object sit on it.
//
// (c) Shir'le E. Illios, 2002 (shirle@drowwanderer.com)
//
////////////////////////////////////////////////////////
void main()
{
// Get the character using the object.
object oPlayer = GetLastUsedBy();
// Make certain that the character is a PC.
if( GetIsPC( oPlayer ) )
{
// Get the object being sat on.
object oChair = OBJECT_SELF;
// If the object is valid and nobody else is currently sitting on it.
if( GetIsObjectValid( oChair ) &&
!GetIsObjectValid( GetSittingCreature( oChair ) ) )
{
// Let the player sit on the object.
AssignCommand( oPlayer, ActionSit( oChair ) );
}
} // End if
} // End main

@ -0,0 +1,7 @@
//Allow PC to see his description.
void main()
{
object oPC=GetLastUsedBy();
AssignCommand(oPC,ActionExamine(OBJECT_SELF));
}

@ -0,0 +1,225 @@
/// ----------------------------------------------------------------------------
/// @file util_c_color.nss
/// @author Ed Burke (tinygiant98) <af.hog.pilot@gmail.com>
/// @brief Configuration file for util_i_color.nss.
/// @details
/// These color codes are used with the functions from util_i_color.nss. These
/// are hex color codes, the same as you'd use in web design and may other
/// areas, so they are easy to look up and to copy-paste into other programs.
///
/// You can change the values of any of constants below, but do not change the
/// names of the constants themselves. You can also add your own constants for
/// use in your module.
///
/// ## Acknowledgement
/// - Function colors copied from https://nwn.wiki/display/NWN1/Colour+Tokens.
/// ----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// X11 Color Palette
// -----------------------------------------------------------------------------
// ----- Whites ----------------------------------------------------------------
const int COLOR_AZURE = 0xf0ffff;
const int COLOR_BEIGE = 0xf5f5dc;
const int COLOR_BLUE_ALICE = 0xf0f8ff;
const int COLOR_HONEYDEW = 0xf0fff0;
const int COLOR_IVORY = 0xfffff0;
const int COLOR_LAVENDERBLUSH = 0xfff0f5;
const int COLOR_LINEN = 0xfaf0e6;
const int COLOR_MINTCREAM = 0xf5fffa;
const int COLOR_MISTYROSE = 0xffe4e1;
const int COLOR_OLDLACE = 0xfdf5e6;
const int COLOR_SEASHELL = 0xfff5ee;
const int COLOR_SNOW = 0xfffafa;
const int COLOR_WHITE = 0xffffff;
const int COLOR_WHITE_ANTIQUE = 0xfaebd7;
const int COLOR_WHITE_FLORAL = 0xfffaf0;
const int COLOR_WHITE_GHOST = 0xf8f8ff;
const int COLOR_WHITE_SMOKE = 0xf5f5f5;
// ----- Blues -----------------------------------------------------------------
const int COLOR_AQUA = 0x00ffff;
const int COLOR_AQUAMARINE = 0x7fffd4;
const int COLOR_BLUE = 0x0000ff;
const int COLOR_BLUE_CORNFLOWER = 0x6495ed;
const int COLOR_BLUE_DARK = 0x00008b;
const int COLOR_BLUE_DODGER = 0x1e90ff;
const int COLOR_BLUE_LIGHT = 0xadd8e6;
const int COLOR_BLUE_MEDIUM = 0x0000cd;
const int COLOR_BLUE_MIDNIGHT = 0x191970;
const int COLOR_BLUE_POWDER = 0xb0e0e6;
const int COLOR_BLUE_ROYAL = 0x4169e1;
const int COLOR_BLUE_SKY = 0x87ceeb;
const int COLOR_BLUE_SKY_DEEP = 0x00bfff;
const int COLOR_BLUE_SKY_LIGHT = 0x87cefa;
const int COLOR_BLUE_SLATE = 0x6a5acd;
const int COLOR_BLUE_SLATE_MEDIUM = 0x7b68ee;
const int COLOR_BLUE_STEEL = 0x4682b4;
const int COLOR_BLUE_STEEL_LIGHT = 0xb0c4de;
const int COLOR_CYAN = 0x00ffff;
const int COLOR_CYAN_LIGHT = 0xe0ffff;
const int COLOR_NAVY = 0x000080;
const int COLOR_TURQUOISE = 0x40e0d0;
const int COLOR_TURQUOISE_DARK = 0x00ced1;
const int COLOR_TURQUOISE_MEDIUM = 0x48d1cc;
const int COLOR_TURQUOISE_PALE = 0xafeeee;
// ----- Browns ----------------------------------------------------------------
const int COLOR_BISQUE = 0xffe4c4;
const int COLOR_BLANCHED_ALMOND = 0xffebcd;
const int COLOR_BROWN = 0xa52a2a;
const int COLOR_BROWN_LIGHT = 0xd0814b;
const int COLOR_BROWN_ROSY = 0xbc8f8f;
const int COLOR_BROWN_SADDLE = 0x8b4513;
const int COLOR_BROWN_SANDY = 0xf4a460;
const int COLOR_BURLYWOOD = 0xdeb887;
const int COLOR_CHOCOLATE = 0xd2691e;
const int COLOR_CORNSILK = 0xfff8dc;
const int COLOR_GOLDENROD = 0xdaa520;
const int COLOR_GOLDENROD_DARK = 0xb8860b;
const int COLOR_MAROON = 0x800000;
const int COLOR_PERU = 0xcd853f;
const int COLOR_SIENNA = 0xa0522d;
const int COLOR_TAN = 0xd2b48c;
const int COLOR_WHEAT = 0xf5deb3;
const int COLOR_WHITE_NAVAJO = 0xffdead;
// ----- Purples ---------------------------------------------------------------
const int COLOR_BLUE_SLATE_DARK = 0x483d8b;
const int COLOR_BLUE_VIOLET = 0x8a2be2;
const int COLOR_FUCHSIA = 0xff00ff;
const int COLOR_INDIGO = 0x4b0082;
const int COLOR_LAVENDER = 0xe6e6fa;
const int COLOR_MAGENTA = 0xff00ff;
const int COLOR_MAGENTA_DARK = 0x8b008b;
const int COLOR_ORCHID = 0xda70d6;
const int COLOR_ORCHID_DARK = 0x9932cc;
const int COLOR_ORCHID_MEDIUM = 0xba55d3;
const int COLOR_PLUM = 0xdda0dd;
const int COLOR_PURPLE = 0x800080;
const int COLOR_PURPLE_MEDIUM = 0x9370d8;
const int COLOR_THISTLE = 0xd8bfd8;
const int COLOR_VIOLET = 0xee82ee;
const int COLOR_VIOLET_DARK = 0x9400d3;
const int COLOR_VIOLET_LIGHT = 0xf397f8;
// ----- Oranges ---------------------------------------------------------------
const int COLOR_CORAL = 0xff7f50;
const int COLOR_ORANGE = 0xffa500;
const int COLOR_ORANGE_DARK = 0xff8c00;
const int COLOR_ORANGE_LIGHT = 0xf3b800;
const int COLOR_ORANGE_RED = 0xff4500;
const int COLOR_SALMON_LIGHT = 0xffa07a;
const int COLOR_TOMATO = 0xff6347;
// ----- Reds ------------------------------------------------------------------
const int COLOR_CORAL_LIGHT = 0xf08080;
const int COLOR_CRIMSON = 0xdc143c;
const int COLOR_FIREBRICK = 0xb22222;
const int COLOR_RED = 0xff0000;
const int COLOR_RED_DARK = 0x8b0000;
const int COLOR_RED_INDIAN = 0xcd5c4c;
const int COLOR_RED_LIGHT = 0xfa6155;
const int COLOR_SALMON = 0xfa8072;
const int COLOR_SALMON_DARK = 0xe9967a;
// ----- Pinks -----------------------------------------------------------------
const int COLOR_PINK = 0xffc0cb;
const int COLOR_PINK_DEEP = 0xff1493;
const int COLOR_PINK_HOT = 0xff69b4;
const int COLOR_PINK_LIGHT = 0xffb6c1;
const int COLOR_VIOLET_RED_MEDIUM = 0xc71585;
const int COLOR_VIOLET_RED_PALE = 0xdb7093;
// ----- Grays -----------------------------------------------------------------
const int COLOR_BLACK = 0x000000;
const int COLOR_GAINSBORO = 0xdcdcdc;
const int COLOR_GRAY = 0x808080;
const int COLOR_GRAY_DARK = 0xa9a9a9;
const int COLOR_GRAY_DIM = 0x696969;
const int COLOR_GRAY_LIGHT = 0xd3d3d3;
const int COLOR_GRAY_SLATE = 0x708090;
const int COLOR_GRAY_SLATE_DARK = 0x2f4f4f;
const int COLOR_GRAY_SLATE_LIGHT = 0x778899;
const int COLOR_SILVER = 0xc0c0c0;
// ----- Greens ----------------------------------------------------------------
const int COLOR_AQUAMARINE_MEDIUM = 0x66cdaa;
const int COLOR_CHARTREUSE = 0x7fff00;
const int COLOR_CYAN_DARK = 0x008b8b;
const int COLOR_GREEN = 0x008000;
const int COLOR_GREEN_DARK = 0x006400;
const int COLOR_GREEN_FOREST = 0x228b22;
const int COLOR_GREEN_LAWN = 0x7cfc00;
const int COLOR_GREEN_LIGHT = 0x90ee90;
const int COLOR_GREEN_LIME = 0x32cd32;
const int COLOR_GREEN_OLIVE_DARK = 0x556b2f;
const int COLOR_GREEN_PALE = 0x98fb98;
const int COLOR_GREEN_SEA = 0x2e8b57;
const int COLOR_GREEN_SEA_DARK = 0x8fbc8f;
const int COLOR_GREEN_SEA_LIGHT = 0x20b2aa;
const int COLOR_GREEN_SEA_MEDIUM = 0x3cb371;
const int COLOR_GREEN_SPRING = 0x00ff7f;
const int COLOR_GREEN_SPRING_MEDIUM = 0x00fa9a;
const int COLOR_GREEN_YELLOW = 0xadff2f;
const int COLOR_LIME = 0x00ff00;
const int COLOR_OLIVE = 0x808000;
const int COLOR_OLIVE_DRAB = 0x6b8e23;
const int COLOR_TEAL = 0x008080;
const int COLOR_YELLOW_GREEN = 0x9acd32;
// ----- Yellows ---------------------------------------------------------------
const int COLOR_GOLD = 0xffd700;
const int COLOR_GOLDENROD_LIGHT = 0xfafad2;
const int COLOR_GOLDENROD_PALE = 0xeee8aa;
const int COLOR_KHAKI = 0xf0e68c;
const int COLOR_KHAKI_DARK = 0xbdb76b;
const int COLOR_LEMON_CHIFFON = 0xfffacd;
const int COLOR_MOCCASIN = 0xffe4b5;
const int COLOR_PAPAYA_WHIP = 0xffefd5;
const int COLOR_PEACH_PUFF = 0xffdab9;
const int COLOR_YELLOW = 0xffff00;
const int COLOR_YELLOW_DARK = 0xd0ce00;
const int COLOR_YELLOW_LIGHT = 0xffffe0;
// -----------------------------------------------------------------------------
// Colors By Function
// -----------------------------------------------------------------------------
const int COLOR_DEFAULT = 0xfefefe;
const int COLOR_ATTENTION = 0xfea400;
const int COLOR_BUG = 0x660000;
const int COLOR_FAIL = 0xff0000;
const int COLOR_SUCCESS = 0x3dc93d;
const int COLOR_DEBUG = 0xb4b4b4;
const int COLOR_INFO = 0xd0814b;
// ----- Damage Types ----------------------------------------------------------
const int COLOR_DAMAGE_MAGICAL = 0xcc77ff;
const int COLOR_DAMAGE_ACID = 0x01ff01;
const int COLOR_DAMAGE_COLD = 0x99ffff;
const int COLOR_DAMAGE_DIVINE = 0xffff01;
const int COLOR_DAMAGE_ELECTRICAL = 0x0166ff;
const int COLOR_DAMAGE_FIRE = 0xff0101;
const int COLOR_DAMAGE_NEGATIVE = 0x999999;
const int COLOR_DAMAGE_POSITIVE = 0xffffff;
const int COLOR_DAMAGE_SONIC = 0xff9901;
// ----- Chat Log Messages -----------------------------------------------------
const int COLOR_MESSAGE_FEEDBACK = 0xffff01;
const int COLOR_MESSAGE_COMBAT = 0xff6601;
const int COLOR_MESSAGE_MAGIC = 0xcc77ff;
const int COLOR_MESSAGE_SKILLS = 0x0166ff;
const int COLOR_MESSAGE_SAVING = 0x66ccff;
const int COLOR_SAVE_STATUS = 0x20ff20;
const int COLOR_PAUSE_STATE = 0xff0101;
const int COLOR_NAME_CLIENT = 0x99ffff;
const int COLOR_NAME_OTHER = 0xcc99cc;
// -----------------------------------------------------------------------------
// Custom Colors
// -----------------------------------------------------------------------------
// You can add any custom colors you need for your functions below this line.
// -----------------------------------------------------------------------------

@ -0,0 +1,364 @@
/// ----------------------------------------------------------------------------
/// @file util_i_color.nss
/// @author Michael A. Sinclair (Squatting Monk) <squattingmonk@gmail.com>
/// @brief Functions to handle colors.
/// @details
/// NWN normally uses color codes to color strings. These codes take the format
/// `<cRGB>`, where RGB are ALT codes (0-0255) for colors.
///
/// Because color codes are arcane and can't be easily looked up, the functions
/// in this file prefer to use hex color codes. These codes are the same as
/// you'd use in web design and many other areas, so they are easy to look up
/// and can be copied and pasted into other programs. util_c_color.nss provides
/// some hex codes for common uses.
///
/// This file also contains functions to represent colors as RGB or HSV
/// triplets. HSV (Hue, Saturation, Value) may be particularly useful if you
/// want to play around with shifting colors.
///
/// ## Acknowledgements
/// - `GetColorCode()` function by rdjparadis.
/// - RGB <-> HSV colors adapted from NWShacker's Named Color Token System.
/// ----------------------------------------------------------------------------
#include "x3_inc_string"
#include "util_i_math"
#include "util_c_color"
// -----------------------------------------------------------------------------
// Constants
// -----------------------------------------------------------------------------
/// Used to generate colors from RGB values. NEVER modify this string.
/// @see https://nwn.wiki/display/NWN1/Colour+Tokens
/// @note First character is "nearest to 00" since we can't use `\x00` itself
/// @note COLOR_TOKEN originally by rdjparadis. Converted to NWN:EE escaped
/// characters by Jasperre.
const string COLOR_TOKEN = "\x01\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF";
// -----------------------------------------------------------------------------
// Types
// -----------------------------------------------------------------------------
struct RGB
{
int r;
int g;
int b;
};
struct HSV
{
float h;
float s;
float v;
};
// -----------------------------------------------------------------------------
// Function Prototypes
// -----------------------------------------------------------------------------
// ----- Type Creation ---------------------------------------------------------
/// @brief Create an RBG color struct.
/// @param nRed The value of the red channel (0..255).
/// @param nGreen The value of the green channel (0..255).
/// @param nBlue The value of the blue channel (0..255).
struct RGB GetRGB(int nRed, int nGreen, int nBlue);
/// @brief Create an HSV color struct.
/// @details The ranges are as follows:
/// 0.0 <= H < 360.0
/// 0.0 <= S <= 1.0
/// 0.0 <= V <= 1.0
/// @param fHue The hue (i.e. location on color wheel).
/// @param fSaturation The saturation (i.e., distance from white/black).
/// @param fValue The value (i.e., brightness of color).
struct HSV GetHSV(float fHue, float fSaturation, float fValue);
// ----- Type Conversion -------------------------------------------------------
/// @brief Convert a hexadecimal color to an RGB struct.
/// @param nColor Hexadecimal to convert to RGB.
struct RGB HexToRGB(int nColor);
/// @brief Convert an RGB struct to a hexadecimal color.
/// @param rgb RGB to convert to hexadecimal.
int RGBToHex(struct RGB rgb);
/// @brief Convert an RGB struct to an HSV struct.
/// @param rgb RGB to convert to HSV.
struct HSV RGBToHSV(struct RGB rgb);
/// @brief Convert an HSV struct to an RGB struct.
/// @param hsv HSV to convert to RGB.
struct RGB HSVToRGB(struct HSV hsv);
/// @brief Converts a hexadecimal color to an HSV struct.
/// @param nColor Hexadecimal to convert to HSV.
struct HSV HexToHSV(int nColor);
/// @brief Converts an HSV struct to a hexadecial color.
/// @param hsv HSV to convert to hexadecimal.
int HSVToHex(struct HSV hsv);
// ----- Coloring Functions ----------------------------------------------------
/// @brief Construct a color code that can be used to color a string.
/// @param nRed The intensity of the red channel (0..255).
/// @param nGreen The intensity of the green channel (0..255).
/// @param nBlue The intensity of the blue channel (0..255).
/// @returns A string color code in `<cRBG>` form.
string GetColorCode(int nRed, int nGreen, int nBlue);
/// @brief Convert a hexadecimal color to a color code.
/// @param nColor Hexadecimal representation of an RGB color.
/// @returns A string color code in `<cRBG>` form.
string HexToColor(int nColor);
/// @brief Convert a color code prefix to a hexadecimal
/// @param sColor A string color code in `<cRBG>` form.
int ColorToHex(string sColor);
/// @brief Color a string with a color code.
/// @param sString The string to color.
/// @param sColor A string color code in `<cRBG>` form.
string ColorString(string sString, string sColor);
/// @brief Color a string with a hexadecimal color.
/// @param sString The string to color.
/// @param nColor A hexadecimal color.
string HexColorString(string sString, int nColor);
/// @brief Color a string with an RGB color.
/// @param sString The string to color.
/// @param rgb The RGB color struct.
string RGBColorString(string sString, struct RGB rgb);
/// @brief Color a string with a struct HSV color
/// @param sString The string to color.
/// @param hsv The HSV color struct.
string HSVColorString(string sString, struct HSV hsv);
/// @brief Remove color codes from a string.
/// @param sString The string to uncolor.
/// @returns sString with color codes removed.
string UnColorString(string sString);
// -----------------------------------------------------------------------------
// Function Definitions
// -----------------------------------------------------------------------------
// ----- Type Creation ---------------------------------------------------------
struct RGB GetRGB(int nRed, int nGreen, int nBlue)
{
struct RGB rgb;
rgb.r = clamp(nRed, 0, 255);
rgb.g = clamp(nGreen, 0, 255);
rgb.b = clamp(nBlue, 0, 255);
return rgb;
}
struct HSV GetHSV(float fHue, float fSat, float fVal)
{
struct HSV hsv;
hsv.h = fclamp(fHue, 0.0, 360.0);
hsv.s = fclamp(fSat, 0.0, 1.0);
hsv.v = fclamp(fVal, 0.0, 1.0);
if (hsv.h == 360.0)
hsv.h = 0.0;
return hsv;
}
// ----- Type Conversion -------------------------------------------------------
struct RGB HexToRGB(int nColor)
{
int nRed = (nColor & 0xff0000) >> 16;
int nGreen = (nColor & 0x00ff00) >> 8;
int nBlue = (nColor & 0x0000ff);
return GetRGB(nRed, nGreen, nBlue);
}
int RGBToHex(struct RGB rgb)
{
int nRed = (clamp(rgb.r, 0, 255) << 16);
int nGreen = (clamp(rgb.g, 0, 255) << 8);
int nBlue = clamp(rgb.b, 0, 255);
return nRed + nGreen + nBlue;
}
struct HSV RGBToHSV(struct RGB rgb)
{
// Ensure the RGB values are within defined limits
rgb = GetRGB(rgb.r, rgb.g, rgb.b);
struct HSV hsv;
// Convert RGB to a range from 0 - 1
float fRed = IntToFloat(rgb.r) / 255.0;
float fGreen = IntToFloat(rgb.g) / 255.0;
float fBlue = IntToFloat(rgb.b) / 255.0;
float fMax = fmax(fRed, fmax(fGreen, fBlue));
float fMin = fmin(fRed, fmin(fGreen, fBlue));
float fChroma = fMax - fMin;
if (fMax > fMin)
{
if (fMax == fRed)
hsv.h = 60.0 * ((fGreen - fBlue) / fChroma);
else if (fMax == fGreen)
hsv.h = 60.0 * ((fBlue - fRed) / fChroma + 2.0);
else
hsv.h = 60.0 * ((fRed - fGreen) / fChroma + 4.0);
if (hsv.h < 0.0)
hsv.h += 360.0;
}
if (fMax > 0.0)
hsv.s = fChroma / fMax;
hsv.v = fMax;
return hsv;
}
struct RGB HSVToRGB(struct HSV hsv)
{
// Ensure the HSV values are within defined limits
hsv = GetHSV(hsv.h, hsv.s, hsv.v);
struct RGB rgb;
// If value is 0, the resulting color will always be black
if (hsv.v == 0.0)
return rgb;
// If the saturation is 0, the resulting color will be a shade of grey
if (hsv.s == 0.0)
{
// Scale from white to black based on value
int nValue = FloatToInt(hsv.v * 255.0);
return GetRGB(nValue, nValue, nValue);
}
float h = hsv.h / 60.0;
float f = frac(h);
int v = FloatToInt(hsv.v * 255.0);
int p = FloatToInt(v * (1.0 - hsv.s));
int q = FloatToInt(v * (1.0 - hsv.s * f));
int t = FloatToInt(v * (1.0 - hsv.s * (1.0 - f)));
int i = FloatToInt(h);
switch (i % 6)
{
case 0: rgb = GetRGB(v, t, p); break;
case 1: rgb = GetRGB(q, v, p); break;
case 2: rgb = GetRGB(p, v, t); break;
case 3: rgb = GetRGB(p, q, v); break;
case 4: rgb = GetRGB(t, p, v); break;
case 5: rgb = GetRGB(v, p, q); break;
}
return rgb;
}
struct HSV HexToHSV(int nColor)
{
return RGBToHSV(HexToRGB(nColor));
}
int HSVToHex(struct HSV hsv)
{
return RGBToHex(HSVToRGB(hsv));
}
// ----- Coloring Functions ----------------------------------------------------
string GetColorCode(int nRed, int nGreen, int nBlue)
{
return "<c" + GetSubString(COLOR_TOKEN, nRed, 1) +
GetSubString(COLOR_TOKEN, nGreen, 1) +
GetSubString(COLOR_TOKEN, nBlue, 1) + ">";
}
string HexToColor(int nColor)
{
if (nColor < 0 || nColor > 0xffffff)
return "";
int nRed = (nColor & 0xff0000) >> 16;
int nGreen = (nColor & 0x00ff00) >> 8;
int nBlue = (nColor & 0x0000ff);
return GetColorCode(nRed, nGreen, nBlue);
}
int ColorToHex(string sColor)
{
if (sColor == "")
return -1;
string sRed = GetSubString(sColor, 2, 1);
string sGreen = GetSubString(sColor, 3, 1);
string sBlue = GetSubString(sColor, 4, 1);
int nRed = FindSubString(COLOR_TOKEN, sRed) << 16;
int nGreen = FindSubString(COLOR_TOKEN, sGreen) << 8;
int nBlue = FindSubString(COLOR_TOKEN, sBlue);
return nRed + nGreen + nBlue;
}
string ColorString(string sString, string sColor)
{
if (sColor != "")
sString = sColor + sString + "</c>";
return sString;
}
string HexColorString(string sString, int nColor)
{
string sColor = HexToColor(nColor);
return ColorString(sString, sColor);
}
string RGBColorString(string sString, struct RGB rgb)
{
string sColor = GetColorCode(rgb.r, rgb.g, rgb.b);
return ColorString(sString, sColor);
}
string HSVColorString(string sString, struct HSV hsv)
{
struct RGB rgb = HSVToRGB(hsv);
return RGBColorString(sString, rgb);
}
string UnColorString(string sString)
{
sString = StringReplace(sString, "</c>", "");
int nOpen = FindSubString(sString, "<c");
int nClose = FindSubString(sString, ">", nOpen);
int nLength;
string sPrefix, sSuffix;
while (nOpen != -1 && nClose != -1)
{
nLength = GetStringLength(sString);
sPrefix = GetStringLeft(sString, nOpen);
sSuffix = GetStringRight(sString, nLength - nClose - 1);
sString = sPrefix + sSuffix;
nOpen = FindSubString(sString, "<c");
nClose = FindSubString(sString, ">", nOpen);
}
return sString;
}

@ -0,0 +1,338 @@
/// ----------------------------------------------------------------------------
/// @file util_i_csvlists.nss
/// @author Michael A. Sinclair (Squatting Monk) <squattingmonk@gmail.com>
/// @author Ed Burke (tinygiant98) <af.hog.pilot@gmail.com>
/// @brief Functions for manipulating comma-separated value (CSV) lists.
/// @details
///
/// ## Usage:
///
/// ```nwscript
/// string sKnight, sKnights = "Lancelot, Galahad, Robin";
/// int i, nCount = CountList(sKnights);
/// for (i = 0; i < nCount; i++)
/// {
/// sKnight = GetListItem(sKnights, i);
/// SpeakString("Sir " + sKnight);
/// }
///
/// int bBedivere = HasListItem(sKnights, "Bedivere");
/// SpeakString("Bedivere " + (bBedivere ? "is" : "is not") + " in the party.");
///
/// sKnights = AddListItem(sKnights, "Bedivere");
/// bBedivere = HasListItem(sKnights, "Bedivere");
/// SpeakString("Bedivere " + (bBedivere ? "is" : "is not") + " in the party.");
///
/// int nRobin = FindListItem(sKnights, "Robin");
/// SpeakString("Robin is knight " + IntToString(nRobin) + " in the party.");
/// ```
/// ----------------------------------------------------------------------------
#include "x3_inc_string"
#include "util_i_math"
#include "util_i_strings"
// -----------------------------------------------------------------------------
// Function Prototypes
// -----------------------------------------------------------------------------
/// @brief Return the number of items in a CSV list.
/// @param sList The CSV list to count.
int CountList(string sList);
/// @brief Add an item to a CSV list.
/// @param sList The CSV list to add the item to.
/// @param sListItem The item to add to sList.
/// @param bAddUnique If TRUE, will only add the item to the list if it is not
/// already there.
/// @returns A modified copy of sList with sListItem added.
string AddListItem(string sList, string sListItem, int bAddUnique = FALSE);
/// @brief Return the item at an index in a CSV list.
/// @param sList The CSV list to get the item from.
/// @param nIndex The index of the item to get (0-based).
string GetListItem(string sList, int nIndex = 0);
/// @brief Return the index of a value in a CSV list.
/// @param sList The CSV list to search.
/// @param sListItem The value to search for.
/// @returns -1 if the item was not found in the list.
int FindListItem(string sList, string sListItem);
/// @brief Return whether a CSV list contains a value.
/// @param sList The CSV list to search.
/// @param sListItem The value to search for.
/// @returns TRUE if the item is in the list, otherwise FALSE.
int HasListItem(string sList, string sListItem);
/// @brief Delete the item at an index in a CSV list.
/// @param sList The CSV list to delete the item from.
/// @param nIndex The index of the item to delete (0-based).
/// @returns A modified copy of sList with the item deleted.
string DeleteListItem(string sList, int nIndex = 0);
/// @brief Delete the first occurrence of an item in a CSV list.
/// @param sList The CSV list to remove the item from.
/// @param sListItem The value to remove from the list.
/// @returns A modified copy of sList with the item removed.
string RemoveListItem(string sList, string sListItem);
/// @brief Copy items from one CSV list to another.
/// @param sSource The CSV list to copy items from.
/// @param sTarget The CSV list to copy items to.
/// @param nIndex The index to begin copying from.
/// @param nRange The number of items to copy.
/// @param bAddUnique If TRUE, will only copy items to sTarget if they are not
/// already there.
/// @returns A modified copy of sTarget with the items added to the end.
string CopyListItem(string sSource, string sTarget, int nIndex, int nRange = 1, int bAddUnique = FALSE);
/// @brief Merge the contents of two CSV lists.
/// @param sList1 The first CSV list.
/// @param sList2 The second CSV list.
/// @param bAddUnique If TRUE, will only put items in the returned list if they
/// are not already there.
/// @returns A CSV list containing the items from each list.
string MergeLists(string sList1, string sList2, int bAddUnique = FALSE);
/// @brief Add an item to a CSV list saved as a local variable on an object.
/// @param oObject The object on which the local variable is saved.
/// @param sListName The varname for the local variable.
/// @param sListItem The item to add to the list.
/// @param bAddUnique If TRUE, will only add the item to the list if it is not
/// already there.
/// @returns The updated copy of the list with sListItem added.
string AddLocalListItem(object oObject, string sListName, string sListItem, int bAddUnique = FALSE);
/// @brief Delete an item in a CSV list saved as a local variable on an object.
/// @param oObject The object on which the local variable is saved.
/// @param sListName The varname for the local variable.
/// @param nIndex The index of the item to delete (0-based).
/// @returns The updated copy of the list with the item at nIndex deleted.
string DeleteLocalListItem(object oObject, string sListName, int nNth = 0);
/// @brief Remove an item in a CSV list saved as a local variable on an object.
/// @param oObject The object on which the local variable is saved.
/// @param sListName The varname for the local variable.
/// @param sListItem The value to remove from the list.
/// @returns The updated copy of the list with the first instance of sListItem
/// removed.
string RemoveLocalListItem(object oObject, string sListName, string sListItem);
/// @brief Merge the contents of a CSV list with those of a CSV list stored as a
/// local variable on an object.
/// @param oObject The object on which the local variable is saved.
/// @param sListName The varname for the local variable.
/// @param sListToMerge The CSV list to merge into the saved list.
/// @param bAddUnique If TRUE, will only put items in the returned list if they
/// are not already there.
/// @returns The updated copy of the list with all items from sListToMerge
/// added.
string MergeLocalList(object oObject, string sListName, string sListToMerge, int bAddUnique = FALSE);
/// @brief Convert a comma-separated value list to a JSON array.
/// @param sList Source CSV list.
/// @returns JSON array representation of CSV list.
json ListToJson(string sList);
/// @brief Convert a JSON array to a comma-separate value list.
/// @param jArray JSON array list.
/// @returns CSV list of JSON array values.
string JsonToList(json jArray);
// -----------------------------------------------------------------------------
// Function Implementations
// -----------------------------------------------------------------------------
int CountList(string sList)
{
if (sList == "")
return 0;
return GetSubStringCount(sList, ",") + 1;
}
string AddListItem(string sList, string sListItem, int bAddUnique = FALSE)
{
if (bAddUnique && HasListItem(sList, sListItem))
return sList;
if (sList != "")
return sList + ", " + sListItem;
return sListItem;
}
string GetListItem(string sList, int nIndex = 0)
{
if (nIndex < 0 || sList == "")
return "";
// Loop through the elements until we find the one we want.
int nCount, nLeft, nRight = FindSubString(sList, ",");
while (nRight != -1 && nCount < nIndex)
{
nCount++;
nLeft = nRight + 1;
nRight = FindSubString(sList, ",", nLeft);
}
// If there were not enough elements, return a null string.
if (nCount < nIndex)
return "";
// Get the element
return TrimString(GetStringSlice(sList, nLeft, nRight - 1));
}
int FindListItem(string sList, string sListItem)
{
sList = TrimString(sList);
sListItem = TrimString(sListItem);
if (sList == "")
return -1;
int nItem, nStart, nEnd;
do
{
nEnd = FindSubString(sList, ",", nStart);
if (TrimString(GetStringSlice(sList, nStart, nEnd - 1)) == sListItem)
return nItem;
nItem++;
nStart = nEnd + 1;
}
while (nEnd >= 0);
return -1;
}
int HasListItem(string sList, string sListItem)
{
return (FindListItem(sList, sListItem) > -1);
}
string DeleteListItem(string sList, int nIndex = 0)
{
if (nIndex < 0 || sList == "")
return sList;
int nPos = FindSubStringN(sList, ",", nIndex);
if (nPos < 0)
{
if (nIndex)
{
nPos = FindSubStringN(sList, ",", nIndex - 1);
return TrimStringRight(GetStringSlice(sList, 0, nPos - 1));
}
return "";
}
string sRight = GetStringSlice(sList, nPos + 1);
if (!nIndex)
return sRight;
nPos = FindSubStringN(sList, ",", nIndex - 1);
sRight = nPos < 0 ? TrimStringLeft(sRight) : sRight;
return GetStringSlice(sList, 0, nPos) + sRight;
}
string RemoveListItem(string sList, string sListItem)
{
return DeleteListItem(sList, FindListItem(sList, sListItem));
}
string CopyListItem(string sSource, string sTarget, int nIndex, int nRange = 1, int bAddUnique = FALSE)
{
string sValue;
int i, nCount = CountList(sSource);
if (nIndex < 0 || nIndex >= nCount || !nCount)
return sSource;
nRange = clamp(nRange, 1, nCount - nIndex);
for (i = 0; i < nRange; i++)
{
sValue = GetListItem(sSource, nIndex + i);
sTarget = AddListItem(sTarget, sValue, bAddUnique);
}
return sTarget;
}
string MergeLists(string sList1, string sList2, int bAddUnique = FALSE)
{
int i, nCount = CountList(sList2);
for (i = 0; i < nCount; i++)
sList1 = AddListItem(sList1, GetListItem(sList2, i), bAddUnique);
return sList1;
}
string AddLocalListItem(object oObject, string sListName, string sListItem, int bAddUnique = FALSE)
{
string sList = GetLocalString(oObject, sListName);
sList = AddListItem(sList, sListItem, bAddUnique);
SetLocalString(oObject, sListName, sList);
return sList;
}
string DeleteLocalListItem(object oObject, string sListName, int nNth = 0)
{
string sList = GetLocalString(oObject, sListName);
sList = DeleteListItem(sList, nNth);
SetLocalString(oObject, sListName, sList);
return sList;
}
string RemoveLocalListItem(object oObject, string sListName, string sListItem)
{
string sList = GetLocalString(oObject, sListName);
sList = RemoveListItem(sList, sListItem);
SetLocalString(oObject, sListName, sList);
return sList;
}
string MergeLocalList(object oObject, string sListName, string sListToMerge, int bAddUnique = FALSE)
{
string sList = GetLocalString(oObject, sListName);
sList = MergeLists(sList, sListToMerge, bAddUnique);
SetLocalString(oObject, sListName, sList);
return sList;
}
json ListToJson(string sList)
{
json jRet = JsonArray();
if (sList == "")
return jRet;
string sItem;
int nStart, nEnd;
do
{
nEnd = FindSubString(sList, ",", nStart);
sItem = TrimString(GetStringSlice(sList, nStart, nEnd - 1));
jRet = JsonArrayInsert(jRet, JsonString(sItem));
nStart = nEnd + 1;
} while (nEnd != -1);
return jRet;
}
string JsonToList(json jArray)
{
if (JsonGetType(jArray) != JSON_TYPE_ARRAY)
return "";
string sList;
int i, nCount = JsonGetLength(jArray);
for (i; i < nCount; i++)
{
if (i > 0)
sList += ", ";
sList += JsonGetString(JsonArrayGet(jArray, i));
}
return sList;
}

177
_module/nss/util_i_math.nss Normal file

@ -0,0 +1,177 @@
/// ----------------------------------------------------------------------------
/// @file util_i_math.nss
/// @author Michael A. Sinclair (Squatting Monk) <squattingmonk@gmail.com>
/// @brief Useful math utility functions.
/// ----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// Function Prototypes
// -----------------------------------------------------------------------------
/// @brief Return the closest integer to the binary logarithm of a number.
int log2(int n);
/// @brief Restrict an integer to a range.
/// @param nValue The number to evaluate.
/// @param nMin The minimum value for the number.
/// @param nMax The maximum value for the number.
/// @returns nValue if it is between nMin and nMax. Otherwise returns the
/// closest of nMin or nMax.
int clamp(int nValue, int nMin, int nMax);
/// @brief Restrict a float to a range.
/// @param fValue The number to evaluate.
/// @param fMin The minimum value for the number.
/// @param fMax The maximum value for the number.
/// @returns fValue if it is between fMin and fMax. Otherwise returns the
/// closest of fMin or fMax.
float fclamp(float fValue, float fMin, float fMax);
/// @brief Return the larger of two integers.
int max(int a, int b);
/// @brief Return the smaller of two integers.
int min(int a, int b);
/// @brief Return the sign of an integer.
/// @returns -1 if n is negative, 0 if 0, or 1 if positive.
int sign(int n);
/// @brief Return the larger of two floats.
float fmax(float a, float b);
/// @brief Return the smaller of two floats.
float fmin(float a, float b);
/// @brief Return the sign of a float.
/// @returns -1 if f is negative, 0 if 0, or 1 if positive.
int fsign(float f);
/// @brief Truncate a float (i.e., remove numbers to the right of the decimal
/// point).
float trunc(float f);
/// @brief Return the fractional part of a float (i.e., numbers to the right of
/// the decimal point).
float frac(float f);
/// @brief Return a % b (modulo function).
/// @param a The dividend
/// @param b The divisor
/// @note For consistency with NWN's integer modulo operator, the result has the
/// same sign as a (i.e., fmod(-1, 2) == -1).
float fmod(float a, float b);
/// @brief Round a float down to the nearest whole number.
float floor(float f);
/// @brief Round a float up to the nearest whole number.
float ceil(float f);
/// @brief Round a float towards to the nearest whole number.
/// @note In case of a tie (i.e., +/- 0.5), rounds away from 0.
float round(float f);
/// @brief Determine if x is in [a..b]
/// @param x Value to compare
/// @param a Low end of range
/// @param b High end of range
int between(int x, int a, int b);
/// @brief Determine if x is in [a..b]
/// @param x Value to compare
/// @param a Low end of range
/// @param b High end of range
int fbetween(float x, float a, float b);
// -----------------------------------------------------------------------------
// Function Definitions
// -----------------------------------------------------------------------------
int log2(int n)
{
int nResult;
while (n >>= 1)
nResult++;
return nResult;
}
int clamp(int nValue, int nMin, int nMax)
{
return (nValue < nMin) ? nMin : ((nValue > nMax) ? nMax : nValue);
}
float fclamp(float fValue, float fMin, float fMax)
{
return (fValue < fMin) ? fMin : ((fValue > fMax) ? fMax : fValue);
}
int max(int a, int b)
{
return (b > a) ? b : a;
}
int min(int a, int b)
{
return (b > a) ? a : b;
}
int sign(int n)
{
return (n > 0) ? 1 : (n < 0) ? -1 : 0;
}
float fmax(float a, float b)
{
return (b > a) ? b : a;
}
float fmin(float a, float b)
{
return (b > a) ? a : b;
}
int fsign(float f)
{
return f > 0.0 ? 1 : f < 0.0 ? -1 : 0;
}
float trunc(float f)
{
return IntToFloat(FloatToInt(f));
}
float frac(float f)
{
return f - trunc(f);
}
float fmod(float a, float b)
{
return a - b * trunc(a / b);
}
float floor(float f)
{
return IntToFloat(FloatToInt(f) - (f < 0.0));
}
float ceil(float f)
{
return IntToFloat(FloatToInt(f) + (trunc(f) < f));
}
float round(float f)
{
return IntToFloat(FloatToInt(f + (f < 0.0 ? -0.5 : 0.5)));
}
int between(int x, int a, int b)
{
return ((x - a) * (x - b)) <= 0;
}
int fbetween(float x, float a, float b)
{
return ((x - a) * (x - b)) <= 0.0;
}

@ -0,0 +1,428 @@
/// ----------------------------------------------------------------------------
/// @file util_i_strings.nss
/// @author Michael A. Sinclair (Squatting Monk) <squattingmonk@gmail.com>
/// @author Ed Burke (tinygiant98) <af.hog.pilot@gmail.com>
/// @brief Functions for formatting times
/// ----------------------------------------------------------------------------
/// @details This file holds utility functions for manipulating strings.
/// ----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// Constants
// -----------------------------------------------------------------------------
const string CHARSET_NUMERIC = "0123456789";
const string CHARSET_ALPHA = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string CHARSET_ALPHA_LOWER = "abcdefghijklmnopqrstuvwxyz";
const string CHARSET_ALPHA_UPPER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// -----------------------------------------------------------------------------
// Function Prototypes
// -----------------------------------------------------------------------------
/// @brief Return the number of occurrences of a substring within a string.
/// @param sString The string to search.
/// @param sSubString The substring to search for.
int GetSubStringCount(string sString, string sSubString);
/// @brief Return the position of a given occurrence of a substring within a
/// string.
/// @param sString The string to search.
/// @param sSubString The substring to search for.
/// @param nNth The occurrence to search for. Uses a zero-based index.
/// @returns The position of the start of the nNth occurrence of the substring,
/// or -1 if the substring did not occur at least nNth + 1 times.
int FindSubStringN(string sString, string sSubString, int nNth = 0);
/// @brief Return the character at a position in a string.
/// @param sString The string to search.
/// @param nPos The position to check.
/// @returns "" if sString is not nPos + 1 characters long.
string GetChar(string sString, int nPos);
/// @brief Return the substring of a string bounded by a start and end position.
/// @param sString The string to search.
/// @param nStart The starting position of the substring to return.
/// @param nEnd The ending position of the substring to return. If -1, will
/// return to the end of the string.
/// @returns "" if nStart is not at least nStart + 1 characters long or if nEnd
/// is < nStart and not -1.
/// @note Both nStart and nEnd are inclusive, so if nStart == nEnd, the
/// character at that index will be returned.
string GetStringSlice(string sString, int nStart, int nEnd = -1);
/// @brief Replace the substring bounded by a string slice with another string.
/// @param sString The string to search.
/// @param sSub The substring to replace with.
/// @param nStart The starting position in sString of the substring to replace.
/// @param nEnd The ending position in sString of the substring to replace.
string ReplaceSubString(string sString, string sSub, int nStart, int nEnd);
/// @brief Replace a substring in a string with another string.
/// @param sString The string to search.
/// @param sToken The substring to search for.
/// @param sSub The substring to replace with.
string SubstituteSubString(string sString, string sToken, string sSub);
/// @brief Replace all substrings in a string with another string.
/// @param sString The string to search.
/// @param sToken The substring to search for.
/// @param sSub The substring to replace with.
string SubstituteSubStrings(string sString, string sToken, string sSub);
/// @brief Return whether a string contains a substring.
/// @param sString The string to search.
/// @param sSubString The substring to search for.
/// @param nStart The position in sString to begin searching from (0-based).
/// @returns TRUE if sSubString is in sString, FALSE otherwise.
int HasSubString(string sString, string sSubString, int nStart = 0);
/// @brief Return whether any of a string's characters are in a character set.
/// @param sString The string to search.
/// @param sSet The set of characters to search for.
/// @returns TRUE if any characters are in the set; FALSE otherwise.
int GetAnyCharsInSet(string sString, string sSet);
/// @brief Return whether all of a string's characters are in a character set.
/// @param sString The string to search.
/// @param sSet The set of characters to search for.
/// @returns TRUE if all characters are in the set; FALSE otherwise.
int GetAllCharsInSet(string sString, string sSet);
/// @brief Return whether all letters in a string are upper-case.
/// @param sString The string to check.
int GetIsUpperCase(string sString);
/// @brief Return whether all letters in a string are lower-case.
/// @param sString The string to check.
int GetIsLowerCase(string sString);
/// @brief Return whether all characters in sString are letters.
/// @param sString The string to check.
int GetIsAlpha(string sString);
/// @brief Return whether all characters in sString are digits.
/// @param sString The string to check.
int GetIsNumeric(string sString);
/// @brief Return whether all characters in sString are letters or digits.
/// @param sString The string to check.
int GetIsAlphaNumeric(string sString);
/// @brief Trim characters from the left side of a string.
/// @param sString The string to trim.
/// @param sRemove The set of characters to remove.
string TrimStringLeft(string sString, string sRemove = " ");
/// @brief Trim characters from the right side of a string.
/// @param sString The string to trim.
/// @param sRemove The set of characters to remove.
string TrimStringRight(string sString, string sRemove = " ");
/// @brief Trim characters from both sides of a string.
/// @param sString The string to trim.
/// @param sRemove The set of characters to remove.
string TrimString(string sString, string sRemove = " ");
/// @brief Interpolate values from a json array into a string using sqlite's
/// printf().
/// @param jArray A json array containing float, int, or string elements to
/// interpolate. The number of elements must match the number of format
/// specifiers in sFormat.
/// @param sFormat The string to interpolate the values into. Must contain
/// format specifiers that correspond to the elements in jArray. For details
/// on format specifiers, see https://sqlite.org/printf.html.
/// @example
/// FormatValues(JsonParse("[\"Blue\", 255]"), "%s: #%06X"); // "Blue: #0000FF"
string FormatValues(json jArray, string sFormat);
/// @brief Interpolate a float into a string using sqlite's printf().
/// @param f A float to interpolate. Will be passed as an argument to the query
/// as many times as necessary to cover all format specifiers.
/// @param sFormat The string to interpolate the value into. For details on
/// format specifiers, see https://sqlite.org/printf.html.
/// @example
/// FormatFloat(15.0, "%d"); // "15"
/// FormatFloat(15.0, "%.2f"); // "15.00"
/// FormatFloat(15.0, "%05.1f"); // "015.0"
string FormatFloat(float f, string sFormat);
/// @brief Interpolate an int into a string using sqlite's printf().
/// @param n An int to interpolate. Will be passed as an argument to the query
/// as many times as necessary to cover all format specifiers.
/// @param sFormat The string to interpolate the value into. For details on
/// format specifiers, see https://sqlite.org/printf.html.
/// @example
/// FormatInt(15, "%d"); // "15"
/// FormatInt(15, "%04d"); // "0015"
/// FormatInt(15, "In hexadecimal, %d is %#x"); // "In hexadecimal, 15 is 0xf"
/// FormatInt(1000, "%,d"); // "1,000"
string FormatInt(int n, string sFormat);
/// @brief Interpolate a string into another string using sqlite's printf().
/// @param s A string to interpolate. Will be passed as an argument to the query
/// as many times as necessary to cover all format specifiers.
/// @param sFormat The string to interpolate the value into. For details on
/// format specifiers, see https://sqlite.org/printf.html.
/// @example
/// FormatString("foo", "%sbar"); // "foobar"
/// FormatString("foo", "%5sbar"); // " foobar"
/// FormatString("foo", "%-5sbar"); // "foo bar"
string FormatString(string s, string sFormat);
/// @brief Substitute tokens in a string with values from a json array.
/// @param s The string to interpolate the values into. Should have tokens wich
/// contain sDesignator followed by a number denoting the position of the
/// value in jArray (1-based index).
/// @param jArray An array of values to interpolate. May be any combination of
/// strings, floats, decimals, or booleans.
/// @param sDesignator The character denoting the beginning of a token.
/// @example
/// // Assumes jArray = ["Today", 34, 2.5299999999, true];
/// SubstituteString("$1, I ran $2 miles.", jArray); // "Today, I ran 34 miles."
/// SubstituteString("The circle's radius is $3.", jArray); // "The circle's radius is 2.53."
/// SubstituteString("The applicant answered: $4", jArray); // "The applicant answered: true"
string SubstituteString(string s, json jArray, string sDesignator = "$");
/// @brief Repeats a string multiple times.
/// @param s The string to repeat.
/// @param n The number of times to repeat s.
/// @returns The repeated string.
string RepeatString(string s, int n);
// -----------------------------------------------------------------------------
// Function Implementations
// -----------------------------------------------------------------------------
int GetSubStringCount(string sString, string sSubString)
{
if (sString == "" || sSubString == "")
return 0;
int nLength = GetStringLength(sSubString);
int nCount, nPos = FindSubString(sString, sSubString);
while (nPos != -1)
{
nCount++;
nPos = FindSubString(sString, sSubString, nPos + nLength);
}
return nCount;
}
int FindSubStringN(string sString, string sSubString, int nNth = 0)
{
if (nNth < 0 || sString == "" || sSubString == "")
return -1;
int nLength = GetStringLength(sSubString);
int nPos = FindSubString(sString, sSubString);
while (--nNth >= 0 && nPos != -1)
nPos = FindSubString(sString, sSubString, nPos + nLength);
return nPos;
}
string GetChar(string sString, int nPos)
{
return GetSubString(sString, nPos, 1);
}
string GetStringSlice(string sString, int nStart, int nEnd = -1)
{
int nLength = GetStringLength(sString);
if (nEnd < 0 || nEnd > nLength)
nEnd = nLength;
if (nStart < 0 || nStart > nEnd)
return "";
return GetSubString(sString, nStart, nEnd - nStart + 1);
}
string ReplaceSubString(string sString, string sSub, int nStart, int nEnd)
{
int nLength = GetStringLength(sString);
if (nStart < 0 || nStart >= nLength || nStart > nEnd)
return sString;
return GetSubString(sString, 0, nStart) + sSub +
GetSubString(sString, nEnd + 1, nLength - nEnd);
}
string SubstituteSubString(string sString, string sToken, string sSub)
{
int nPos;
if ((nPos = FindSubString(sString, sToken)) == -1)
return sString;
return ReplaceSubString(sString, sSub, nPos, nPos + GetStringLength(sToken) - 1);
}
string SubstituteSubStrings(string sString, string sToken, string sSub)
{
while (FindSubString(sString, sToken) >= 0)
sString = SubstituteSubString(sString, sToken, sSub);
return sString;
}
int HasSubString(string sString, string sSubString, int nStart = 0)
{
return FindSubString(sString, sSubString, nStart) >= 0;
}
int GetAnyCharsInSet(string sString, string sSet)
{
int i, nLength = GetStringLength(sString);
for (i = 0; i < nLength; i++)
{
if (HasSubString(sSet, GetChar(sString, i)))
return TRUE;
}
return FALSE;
}
int GetAllCharsInSet(string sString, string sSet)
{
int i, nLength = GetStringLength(sString);
for (i = 0; i < nLength; i++)
{
if (!HasSubString(sSet, GetChar(sString, i)))
return FALSE;
}
return TRUE;
}
int GetIsUpperCase(string sString)
{
return GetAllCharsInSet(sString, CHARSET_ALPHA_UPPER + CHARSET_NUMERIC);
}
int GetIsLowerCase(string sString)
{
return GetAllCharsInSet(sString, CHARSET_ALPHA_LOWER + CHARSET_NUMERIC);
}
int GetIsAlpha(string sString)
{
return GetAllCharsInSet(sString, CHARSET_ALPHA);
}
int GetIsNumeric(string sString)
{
return GetAllCharsInSet(sString, CHARSET_NUMERIC);
}
int GetIsAlphaNumeric(string sString)
{
return GetAllCharsInSet(sString, CHARSET_ALPHA + CHARSET_NUMERIC);
}
string TrimStringLeft(string sString, string sRemove = " ")
{
while (FindSubString(sRemove, GetStringLeft(sString, 1)) != -1)
sString = GetStringRight(sString, GetStringLength(sString) - 1);
return sString;
}
string TrimStringRight(string sString, string sRemove = " ")
{
while (FindSubString(sRemove, GetStringRight(sString, 1)) != -1)
sString = GetStringLeft(sString, GetStringLength(sString) - 1);
return sString;
}
string TrimString(string sString, string sRemove = " ")
{
return TrimStringRight(TrimStringLeft(sString, sRemove), sRemove);
}
string FormatValues(json jArray, string sFormat)
{
if (JsonGetType(jArray) != JSON_TYPE_ARRAY)
return "";
string sArgs;
int i, nLength = JsonGetLength(jArray);
for (i = 0; i < nLength; i++)
sArgs += ", @" + IntToString(i);
sqlquery q = SqlPrepareQueryObject(GetModule(), "SELECT printf(@format" + sArgs + ");");
SqlBindString(q, "@format", sFormat);
for (i = 0; i < nLength; i++)
{
string sParam = "@" + IntToString(i);
json jValue = JsonArrayGet(jArray, i);
switch (JsonGetType(jValue))
{
case JSON_TYPE_FLOAT: SqlBindFloat (q, sParam, JsonGetFloat (jValue)); break;
case JSON_TYPE_INTEGER: SqlBindInt (q, sParam, JsonGetInt (jValue)); break;
case JSON_TYPE_STRING: SqlBindString(q, sParam, JsonGetString(jValue)); break;
default: break;
}
}
return SqlStep(q) ? SqlGetString(q, 0) : "";
}
string FormatFloat(float f, string sFormat)
{
json jArray = JsonArray();
int i, nCount = GetSubStringCount(sFormat, "%");
for (i = 0; i < nCount; i++)
jArray = JsonArrayInsert(jArray, JsonFloat(f));
return FormatValues(jArray, sFormat);
}
string FormatInt(int n, string sFormat)
{
json jArray = JsonArray();
int i, nCount = GetSubStringCount(sFormat, "%");
for (i = 0; i < nCount; i++)
jArray = JsonArrayInsert(jArray, JsonInt(n));
return FormatValues(jArray, sFormat);
}
string FormatString(string s, string sFormat)
{
json jArray = JsonArray();
int i, nCount = GetSubStringCount(sFormat, "%");
for (i = 0; i < nCount; i++)
jArray = JsonArrayInsert(jArray, JsonString(s));
return FormatValues(jArray, sFormat);
}
string SubstituteString(string s, json jArray, string sDesignator = "$")
{
if (JsonGetType(jArray) != JSON_TYPE_ARRAY)
return s;
int n; for (n = JsonGetLength(jArray) - 1; n >= 0; n--)
{
string sValue;
json jValue = JsonArrayGet(jArray, n);
int nType = JsonGetType(jValue);
if (nType == JSON_TYPE_STRING) sValue = JsonGetString(jValue);
else if (nType == JSON_TYPE_INTEGER) sValue = IntToString(JsonGetInt(jValue));
else if (nType == JSON_TYPE_FLOAT) sValue = FormatFloat(JsonGetFloat(jValue), "%!f");
else if (nType == JSON_TYPE_BOOL) sValue = JsonGetInt(jValue) == 1 ? "true" : "false";
else continue;
s = SubstituteSubStrings(s, sDesignator + IntToString(n + 1), sValue);
}
return s;
}
string RepeatString(string s, int n)
{
string sResult;
while (n-- > 0)
sResult += s;
return sResult;
}

File diff suppressed because it is too large Load Diff

@ -33,11 +33,18 @@
//:: Created By: Georg Zoeller
//:: Created On: 2003-07-16
//:://////////////////////////////////////////////
#include "nui_i_main"
#include "x2_inc_switches"
#include "x2_inc_restsys"
void main()
{
SetEventScript(GetModule(), EVENT_SCRIPT_MODULE_ON_NUI_EVENT, "mod_nui");
SetEventScript(GetModule(), EVENT_SCRIPT_MODULE_ON_PLAYER_TARGET, "mod_target");
SetEventScript(GetModule(), EVENT_SCRIPT_MODULE_ON_PLAYER_GUIEVENT, "mod_gui");
NUI();
if (GetGameDifficulty() == GAME_DIFFICULTY_CORE_RULES || GetGameDifficulty() == GAME_DIFFICULTY_DIFFICULT)
{
// * Setting the switch below will enable a seperate Use Magic Device Skillcheck for

@ -712,6 +712,21 @@
"type": "int",
"value": 1
}
},
{
"__struct_id": 0,
"Name": {
"type": "cexostring",
"value": "SET_NAME"
},
"Type": {
"type": "dword",
"value": 3
},
"Value": {
"type": "cexostring",
"value": "Goblin"
}
}
]
},

@ -0,0 +1,213 @@
{
"__data_type": "UTD ",
"AnimationState": {
"type": "byte",
"value": 0
},
"Appearance": {
"type": "dword",
"value": 0
},
"AutoRemoveKey": {
"type": "byte",
"value": 0
},
"CloseLockDC": {
"type": "byte",
"value": 0
},
"Comment": {
"type": "cexostring",
"value": "\"Create Area\" Door"
},
"Conversation": {
"type": "resref",
"value": "doorcv_inn_room"
},
"CurrentHP": {
"type": "short",
"value": 15
},
"Description": {
"type": "cexolocstring",
"value": {
"0": "This door leads to the inn rooms above.",
"id": 9078
}
},
"DisarmDC": {
"type": "byte",
"value": 15
},
"Faction": {
"type": "dword",
"value": 1
},
"Fort": {
"type": "byte",
"value": 16
},
"GenericType_New": {
"type": "dword",
"value": 12
},
"Hardness": {
"type": "byte",
"value": 5
},
"HP": {
"type": "short",
"value": 15
},
"Interruptable": {
"type": "byte",
"value": 1
},
"KeyName": {
"type": "cexostring",
"value": ""
},
"KeyRequired": {
"type": "byte",
"value": 1
},
"LinkedTo": {
"type": "cexostring",
"value": ""
},
"LinkedToFlags": {
"type": "byte",
"value": 0
},
"LoadScreenID": {
"type": "word",
"value": 0
},
"Lockable": {
"type": "byte",
"value": 0
},
"Locked": {
"type": "byte",
"value": 1
},
"LocName": {
"type": "cexolocstring",
"value": {
"0": "\"Create Area\" Door",
"id": 5349
}
},
"OnClick": {
"type": "resref",
"value": ""
},
"OnClosed": {
"type": "resref",
"value": ""
},
"OnDamaged": {
"type": "resref",
"value": ""
},
"OnDeath": {
"type": "resref",
"value": "x2_door_death"
},
"OnDisarm": {
"type": "resref",
"value": ""
},
"OnFailToOpen": {
"type": "resref",
"value": "cv_inn_door"
},
"OnHeartbeat": {
"type": "resref",
"value": ""
},
"OnLock": {
"type": "resref",
"value": ""
},
"OnMeleeAttacked": {
"type": "resref",
"value": ""
},
"OnOpen": {
"type": "resref",
"value": ""
},
"OnSpellCastAt": {
"type": "resref",
"value": ""
},
"OnTrapTriggered": {
"type": "resref",
"value": ""
},
"OnUnlock": {
"type": "resref",
"value": ""
},
"OnUserDefined": {
"type": "resref",
"value": ""
},
"OpenLockDC": {
"type": "byte",
"value": 18
},
"PaletteID": {
"type": "byte",
"value": 0
},
"Plot": {
"type": "byte",
"value": 1
},
"PortraitId": {
"type": "word",
"value": 2624
},
"Ref": {
"type": "byte",
"value": 0
},
"Tag": {
"type": "cexostring",
"value": "inn2pcrooms"
},
"TemplateResRef": {
"type": "resref",
"value": "inn2pcrooms"
},
"TrapDetectable": {
"type": "byte",
"value": 1
},
"TrapDetectDC": {
"type": "byte",
"value": 0
},
"TrapDisarmable": {
"type": "byte",
"value": 1
},
"TrapFlag": {
"type": "byte",
"value": 0
},
"TrapOneShot": {
"type": "byte",
"value": 1
},
"TrapType": {
"type": "byte",
"value": 0
},
"Will": {
"type": "byte",
"value": 0
}
}