-
Notifications
You must be signed in to change notification settings - Fork 1
/
Scripting Notes.txt
960 lines (718 loc) · 31.1 KB
/
Scripting Notes.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
Notes
=====
Misc notes and script snippets.
Limits:
Tag names are limited to 32 characters.
Script file names are limited to 16 characters and all lowercase.
I think i saw something in the lexicon about an action queue limit of 75?
Speed runs of original game to make sure minimal plot can play through
----------------------------------------------------------------------
https://www.youtube.com/watch?v=0UgAImlNjmM
https://www.youtube.com/watch?v=dnzjpw7H3Dg
Things to figure out and/or confirm before getting in to deep
-------------------------------------------------------------
* Can NPCs waypoint through area transitions?
* If i need an NPC from other areas for cut scenes or locations during time schedule should I:
teleport them, walk them, or spawn a clone? (depends on above if NPCs can transition).
* Script file name encoding to fit into the 16 character limit. Names must be lowercase.
- Everything begins with "u8" if possible to namespace.
- Module scripts prefix with "mod".
+ "u8_mod_act_item" or "u8_mod_onactitem"
- Area scripts
+ "u8_ar_plat_ent" // OnEnter
+ "u8_ar_plat_exit" // OnExit
+ "u8_ar_plat_beat" // OnHeartbeat
+ "u8_ar_plat_user" // OnUserDefined
- Creatures (characters/mobs) OnUserDefined prefix with "cr".
+ "u8_cr_devon"
+ "u8_cr_mythran"
+ "u8_cr_hydros"
+ "u8_cr_skeleton"
+ "u8_cr_ghoul"
- Triggers prefix with "tr".
+ "u8_tr_docks_cs1" // docks cutscene 1: Toran exe
+ "u8_tr_docks_cs2" // docks cutscene 2: Devon exe
+ "u8_tr_recallpad" // find recall pad. Trigger tag name is used for specific pad logic.
+ "u8_tr_redshroom" // red mushroom trigger trap
- Placeable prefix with "pl".
+ "u8_pl_dartboard"
+ "u8_pl_lever"
+ "u8_pl_pltcavelvr" or "u8_pl_pclv" // Plateau cave levers, they all share same script like tut.
- Conversation action prefix with "ca".
+ "u8_ca_recallxxxx" // where xxxx is: tene, plat, isle, crag, lake, cata, hall, vale.
+ "u8_ca_myt_grec" // 3 digit character/creature, 'g' to give, 3 digit thing. eg. mythran give recall
+ "u8_ca_dev_gkey"
- Libraries (use as includes) prefix with "lib". Might need these for Items since they merge into Module scripts.
+ "u8_lib_earth" // Magic library. Spell creation and casting.
+ "u8_lib_air" // Magic library. Spell creation and casting.
+ "u8_lib_water" // Magic library. Spell creation and casting.
+ "u8_lib_fire" // Magic library. Spell creation and casting.
+ "u8_lib_ether" // Magic library. Spell creation and casting.
+ "u8_lib_recallgem"
+ "u8_lib_slayer" // If custom scripting needed for the 1 in 10 fatal chance.
+ "u8_lib_flamestng" // If custom thing needed to create fire on ground after strike.
Variable Naming Conventions
---------------------------
https://nwnlexicon.com/index.php?title=Naming_Conventions
+---------------+--------+-------------+
| Type | Prefix | Example |
+---------------+--------+-------------+
| action | a | aKill |
| effect | e | eConPenalty |
| event | ev | evAttacked |
| float | f | fResult |
| int | n | nAge |
| int (boolean) | b | bIsSpell |
| itemproperty | ip | ipProperty |
| location | loc | locJumpTo |
| object | o | oPC |
| string | s | sName |
| struct | str | strPerson |
| talent | t | tSkillHide |
| vector | v | vVelocity |
+---------------+--------+-------------+
Credits
-------
- Lord British, Origin and Electronic Arts for Ultima 8
- Bioware for Neverwinter Nights
- Beamdog for Neverwinter Nights Enhanced Edition
- Celowin for scripting tutorials
- Ultima Codex for keeping Ultima alive
- http://gigi.nullneuron.net/ultima/ for keeping Ultima alive
- Exile remake for inspiration and music
Gameplay Goals For Remake
-------------------------
Standard NWN character classes and leveling. This might help it feel more like the older Ultima's where you had classes, even U9.
Aiming for play through of U8 story. Including learning the spells of Pagan and maybe visiting the Lost Vale.
The ghost side quest. Apparently the herdsman family and Kilandra are involed in the ghost side quest.
Kilandra's daughter has/had the key for the door. Her grave is in the cemetery.
Tutorials
---------
https://nwnlexicon.com/index.php?title=Category:Tutorials
Debugging
---------
https://nwnlexicon.com/index.php?title=Category:Debug_Functions
Debug Message Helper
--------------------
https://nwnlexicon.com/index.php?title=PrintString
https://nwnlexicon.com/index.php?title=WriteTimestampedLogEntry
Records a message to the log file.
void PrintString(
string sString
);
// sample debug call, covers many testing bases:
void debug(string sMessage)
{
SendMessageToPC(GetFirstPC(), sMessage);
SendMessageToAllDMs(sMessage);
PrintString(sMessage);
}
Records a string in the log file along with a date-time stamp.
void WriteTimestampedLogEntry(
string sLogEntry
);
Example:
// This call would produce "[Fri Jul 12 12:08:03] Test" in the log file
WriteTimestampedLogEntry("Test");
Debug Logic Helper (runscript)
------------------------------
KM: Apparently there is some kind of console mode and you can run custom scripts?
Mentioned here: https://nwnlexicon.com/index.php?title=An_Introduction_To_Tile_Magic
"Start your module, enter the area, enable debugmode, and run your script using the runscript command."
This will allow me to build in some plot skipper tools to jump ahead in the plot and test things better.
One of the main things to skip would be the docks scene so that the chracters are all in place for the regular game.
Script Events
-------------
Module Events:
- OnAcquireItem (has a default)
- ObActivateItem (has a default)
- OnClientEnter (has a default)
- OnClientLeave
- OnCutsceneAbort
- OnHeartbeat
- OnModuleLoad (has a default)
- OnPlayerChat
- OnPlayerDeath (has a default)
- OnPlayerDying (has a default)
- OnPlayerEquipItem (has a default)
- OnPlayerLevelUp
- OnPlayerRespawn (has a default)
- OnPlayerRest (has a default)
- OnPlayerUnEquipItem (has a default)
- OnUnAcquireItem (has a default)
- OnUserDefined
Area Events:
- OnEnter
- OnExit
- OnHeartbeat
- OnUserDefined
Creature Scripts:
- OnBlocked (has a default)
- OnCombatRoundEnd (has a default)
- OnConversation (has a default)
- OnDamaged (has a default)
- OnDeath (has a default)
- OnDisturbed (has a default)
- OnHeartbeat (has a default)
- OnPerception (has a default)
- OnPhysicalAttacked (has a default)
- OnRested (has a default)
- OnSpawn (has a default)
- OnSpellCastAt (has a default)
- OnUserDefined (has a default)
Modules, Areas and Creatures all have option for setting initial variables.
Constants
---------
Constants can be defined in an include file. This will make working with things like tags much nicer in many files.
Each file can just import the/a constant definition file.
Constants can be: int, float, string.
// KM: The constant makes it strict, the string value can be what ever, but may as well match. Length limit 32 characters?
const string U8_IT_THING = "U8_IT_THING";
Cut Scenes
----------
https://nwnlexicon.com/index.php?title=X1_inc_cutscene
https://nwnlexicon.com/index.php?title=X2_inc_cutscene
KM: Sounds like awesome stuff! :D
CutDisableAbort
CutSetCutsceneMode
GetActiveCutsceneNum
CutStoreMusic
CutRestoreMusic
CutSetAmbient
CutSetMusic
CutStoreCameraFacing
CutRestoreCameraFacing
CutSetCamera
CutSetFacingPoint
CutSetActiveCutsceneForObject
CutSetWeather
CutSpeakString
CutSetPlotFlag
CutPlaySound
CutPlayAnimation
CutActionCastFakeSpellAtLocation
CutActionCastFakeSpellAtObject
CutActionCastSpellAtLocation
CutActionCastSpellAtObject
CutKnockdown
CutDeath
CutActionSit
CutActionMoveToLocation
CutActionMoveToObject
CutJumpToLocation
CutJumpAssociateToLocation
CutJumpToObject
CutFadeFromBlack
CutFadeToBlack
CutFadeOutAndIn
CutBeginConversation
CutActionStartConversation
CutActionEquipItem
CutActionUnequipItem
// visual effects
effect eShake = EffectVisualEffect(VFX_FNF_SCREEN_SHAKE);
effect eLightning = EffectVisualEffect(VFX_IMP_LIGHTNING_M);
effect ePortal = EffectVisualEffect(VFX_IMP_UNSUMMON);
Cut Scene Tutorial
------------------
https://nwnlexicon.com/index.php?title=Category:Cut_Scenes
KM: Hmm they might be old now though? The first tutorial in that series says this:
"Note: these tutorials were written prior to the new cut-scene functionality added by BioWare in patch 1.30."
Cut Scene NPC Control
---------------------
https://nwnlexicon.com/index.php?title=ActionMoveToLocation
void ActionMoveToLocation(
location locDestination,
int bRun = FALSE
);
KM: I will probably want to also disable regular AI so they only act as told.
I think i saw some functions related to AI that might help with that. Paralyze isn't going to work for this or I can't move them.
// Make the calling object walk to a waypoint
void main()
{
object oWP = GetObjectByTag("my_waypoint");
location lDestination = GetLocation(oWP);
ActionMoveToLocation(lDestination,FALSE);
}
Also see this one:
https://nwnlexicon.com/index.php?title=MoveToNewLocation
void MoveToNewLocation(
location lNewLocation = none,
object oTarget = OBJECT_SELF
);
This is a convenience function that places two commands in the target objects queue using two AssignCommand calls. The first wraps
ActionMoveToLocation(lNewLocation, FALSE).
The second wraps
ActionDoCommand(SetFacing(GetFacingFromLocation(lNewLocation))
These two commands effectively command the target to move to the new location, then instructs the target to face the correct way once they get there.
The default target is OBJECT_SELF. Note that the restrictions to AssignCommand, ActionMoveToLocation, and SetFacing still apply.
Cut Scene Creature Paralyze (mainly the Player)
-----------------------------------------------
https://nwnlexicon.com/index.php?title=EffectCutsceneParalyze
Returns an effect that is guranteed to paralyze a creature; this effect is identical to EffectParalyze except that it cannot be resisted.
See notes for EffectParalyze for more remarks, code and description.
The target this effect is applied to must be a creature for it to work. This effect should not be applied instantly, only temporarily or permanently.
KM: Need this for cut scenes like the docks where the player can watch but not interact.
KM: Also look for something about "cutscene dominate", for taking control during cut scenes?
effect EffectCutsceneParalyze();
Coloured Text
-------------
https://nwnlexicon.com/index.php?title=StringToRGBString
string StringToRGBString(
string sString,
string sRGB
);
...
string sNewItemName = "Sir Elric's Bulletproof Plate Mail";
SetName(oItem, StringToRGBString(sNewItemName, STRING_COLOR_RED));
if(GetName(oItem) == "Sir Elric's Bulletproof Plate Mail")
{ // this will never happen
}
else if(GetName(oItem) == sNewItemName)
{ // this will never happen either
}
else
{ // this will always happen
}
if(GetName(oItem) == StringToRGBString(sNewItemName, STRING_COLOR_RED))
{ // this will always happen
}
...
Guardian Taunts
---------------
Should be able to do these by making the Player or some hidden entity yell some text when the player crosses a trigger.
The trigger should fire once only when certain plot progress is reached.
Not sure if a yell appears above a head, if so i guess do it on the Player (as per U9 plot). Pretty sure yell text is red also.
Stone of Recall (from Mythran)
------------------------------
http://nwn.wikia.com/wiki/Stone_of_recall_system
KM: This is like the one in the official NWN game, but with some changes this can work like U8.
KM: Not sure why these script snippets from the tutorials have extra braces. It should be easy to clean when ready to import.
Create your item. Be sure to give it a unique tag name and that you remember that tagname.
Make it "magical". Edit the properties of the item and click the "Properties" tab.
There, you should see a whole bunch of effects. Go down to "Cast Spell" and click that to open that, then go down to "Unique Power".
Decide if it's a power that you will cast on others, or only on the wielder, then double-click the appropriate decision.
When you double-clicked, that added that Unique Power to the right-hand pane of the window. Double-click the power there, to determine how many charges per day it gets.
When done, click OK/Done to get back to the editor.
Now you have your item, you need to get it to work. Here's what you do:
Go to Edit->Module Properties->Events
For the OnActivateItem click Edit.
Paste this script and save as "StoneRecall01" (or whatever you want)
void main()
{
object oActivated = GetItemActivated();
switch (2);
{
// Item 1 = Stone of Recall type item.
case 1:
if (GetTag(oActivated) == "item1")
{
object oObject = GetItemActivator();
object oTarget = GetItemActivator();
location lLocation = GetLocation(oObject);
{
// Object 1 = A Placeable object (invisible object works best). Must be the blueprint name NOT TAG!!
CreateObject(OBJECT_TYPE_PLACEABLE, "object1", lLocation, FALSE);
}
{
// stonerecall02 = name of second script
ExecuteScript("stonerecall02", oTarget);
}
}
break;
}
}
Create a new placeable object and give it a unique tag. Make sure its appearance is set to Invisible Object. This is your object1 in the script above.
Create a new waypoint and give it a unique name. Place this where you want the player to appear after activating the item.
Go to the Script Editor, paste this in and save as "stonerecall02".
void main()
{
object oActivated = GetItemActivated();
switch (2);
{
case 1:
if (GetTag(oActivated) == "item1")
{
object oPC = GetItemActivator();
// waypoint1 = Tag of waypoint where the player will be taken to when they activate the stone
object oTarget = GetWaypointByTag("waypoint1");
AssignCommand(oPC,JumpToObject(oTarget));
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect (VFX_IMP_HOLY_AID), oPC);
}
break;
}
}
Create a Recall Portal near the waypoint you just made.
Go to the Advanced Tab and edit the conversation.
Create a new conversation, with just a simple line like "This will take you back to where you activated the Stone of Recall".
Add a PC line such as "Step in to the Portal" and then add this script to the Actions Taken part.
void main()
{
location lLocation;
object oObject, oActionSubject, oPC, oDestroy;
{
// object1 = TAG name of the placeable created in the first script
oObject = GetObjectByTag("object1", 0);
oDestroy = GetObjectByTag("object1", 0);
oActionSubject = GetPCSpeaker();
oPC = GetPCSpeaker();
lLocation = GetLocation(oObject);
{
AssignCommand(oActionSubject, ActionJumpToLocation(lLocation));
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect (VFX_IMP_UNSUMMON), oPC);
}
{
DestroyObject(oDestroy, 3.0);
}
}
}
NPC Door closing
----------------
https://nwnlexicon.com/index.php?title=AnimActionCloseRandomDoor
Causes an NPC to close a nearby open door.
KM: The NPC's used to close their house doors every so often if left open. "Who left this open?"
int AnimActionCloseRandomDoor();
Pagan Time and Calendar System
------------------------------
http://wiki.ultimacodex.com/wiki/Pagan_Calendar
The Pagan day consists of 6 times, each equaling four hours:
* Bloodwatch - 00:00-04:00
* Firstebb - 04:00-08:00
* Daytide - 08:00-12:00
* Threemoons - 12:00-16:00
* Lastebb - 16:00-20:00
* Eventide - 20:00-00:00
The Pagan week is divided into 6 days:
* Guarday - To honor the Guardian (Who they think is a benevolent being)
* Earthday - To honor Lithos
* Waterday - To honor Hydros
* Airday - To honor Stratos
* Fireday - To honor Pyros
* Blackday - To remember the war and the Destroyer
The Pagan year is divided into 6 months:
* Stonemark
* Skyrock
* Windbreak
* Stormpeak
* Firefall
* DarkFlame
KM: Not sure how to handle time of day with NWN. I need to prevent daylight from happening to keep the twilight theme of Pagan.
I could try run the clock as normal but only over a 6 hour range and reset it to the start range each time?
NPC Schedules
-------------
https://nwnlexicon.com/index.php?title=Category:Animation_Functions
AnimActionGoHome
AnimActionLeaveHome
AnimActionSitInChair
AnimActionGetUpFromChair
Waypoints for schedules?
This talks about some automatic waypoint helper function: https://nwnlexicon.com/index.php?title=CheckWayPoints
This function takes oWalker's tag, and looks for waypoint tags with matching names: "POST_<tag>" and "WP_<tag>_01" (always checked).
If the NW_FLAG_DAY_NIGHT_POSTING spawn-in condition has been set in oWalker's OnSpawn script, then "NIGHT_<tag>" and "WN_<tag>" are also sought.
The NPC can have multiples of the WP_ and WN_ waypoints, but only one POST_ and one NIGHT_ waypoint.
KM: I guess i could build something similar for the Pagan time system that works generic based on tag concat for each NPC.
// Source for CheckWayPoints():
int CheckWayPoints(object oWalker = OBJECT_SELF)
{
object oWay1;
object oWay2;
object oWay3;
object oWay4;
string sTag = GetTag(oWalker);
if(GetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING))
{
oWay2 = GetWaypointByTag("NIGHT_" + sTag);
oWay4 = GetWaypointByTag("WN_" + sTag + "_01");
}
oWay1 = GetWaypointByTag("POST_" + sTag);
oWay3 = GetWaypointByTag("WP_" + sTag + "_01");
if(GetIsObjectValid(oWay2) || GetIsObjectValid(oWay4) || GetIsObjectValid(oWay1) || GetIsObjectValid(oWay3))
{
return TRUE;
}
return FALSE;
}
City Guards
-----------
https://nwnlexicon.com/index.php?title=WalkWayPoints
void WalkWayPoints(
int nRun = FALSE,
float fPause = 1.0
);
The waypoints to walk must have tags in the format "WP_" + NPC's tag name + "_0#".
Example: WP_CITYGUARD_01. The # determines what order the NPC walks the waypoints in.
You may also have up to one "POST_" + NPC's tag name waypoint tagged; if so the NPC will return to this waypoint after a combat.
Waypoint names are case-sensitive.
KM: They should do their waypoint walk patrol with pause or their stand guard and comment.
Comments like "Watch for undead." and "Boy this weapon gets heavy!" (with weapon animation).
Weather
-------
https://nwnlexicon.com/index.php?title=SetWeather
Allows you to set the weather for an area or the entire module.
void SetWeather(
object oTarget,
int nWeather
);
KM: When Hydros is free, this will cause all outdoor areas to rain non stop:
KM: Fog can be set also i think. I remember there being fog after Hydros free.
SetWeather(GetModule(), WEATHER_RAIN);
Change Ground Tiles (Tile Magic)
--------------------------------
https://nwnlexicon.com/index.php?title=TLChangeAreaGroundTiles
https://nwnlexicon.com/index.php?title=An_Introduction_To_Tile_Magic
This function will flood the entire area with the tile in question. nColumns and nRows indicate the size of the area. For instance, a 4 * 6 area will have 4 columns and 6 rows.
You may not want to flood your entire area, but this function will give you a pretty good idea how to use the tile magic (tm). Basically, you just create an invisible object in the center of a tile, and apply a permanent visual effect to that invisible object.
void TLChangeAreaGroundTiles(
object oArea,
int nGroundTileConst,
int nColumns,
int nRows,
float fZOffset = -0.4f
);
KM: Not sure if this is a visual effect only? Might be able to use for Devon to walk on water?
KM: Flood Hydros lair (Carthax lake) after freed. Probably better than swapping transition areas?
// Create a Small (4x4) Rural or City Exterior area, place the Start Location
// in the area and add this script to the area's OnEnter event. When the first
// player (or creature) enters the area the TileMagic effect will be created.
// This script will actually work from any object event except the module events.
#include "x2_inc_toollib"
void main()
{
object oArea = GetArea(OBJECT_SELF);
// We only want to apply tilemagic if it does not already exist.
if (GetLocalInt(oArea, "TILEMAGIC_APPLIED") == FALSE)
{
// Cover a 3x3 square with knee-high water: the square starts in the
// area's bottom left corner and extends x columns right and y rows up.
// NOTE: the water tile has a built in z-offset of -1m, so to make it
// it knee-high for a human (about 0.5m) we have to raise it by 1.5m.
TLChangeAreaGroundTiles(oArea, X2_TL_GROUNDTILE_WATER, 3, 3, 1.5);
// Set a variable to indicate the tilemagic exists.
SetLocalInt(oArea, "TILEMAGIC_APPLIED", TRUE);
}
}
Deity's
------------------
NWN (D&D) has the option to set a deity. I should set each titan as the deity for each town.
Some are specific like Berren though. Even know he is in Tenebrae most of the time, he still follows Pyros.
The titans themselves could set The Guardian as their deity though.
Creature: Titans
----------------
Use dragons as the visual interaction thing. Coloured to their element.
After "defeating" them in the Ethereal Void, I could strip them of their power and have them appear as human again.
Creatures/Characters
--------------------
The ultima wikia has lots of small rarely known details about each character.
Apparently you can set local vars directly on creatures in the toolset.
This will be good for setting some initial values like state.
Might be able to set the "bMetPC" flag there, but that won't work for multiplayer and the NPC meeting each individually.
Probably fine, but if needed that would have to be fully dynamic and concat the PC name into the var flag. eg. "bMet<FirstName>".
If setting flags and other state on a runtime created crature, then use the queued action so it safely does it after spawn is completed.
ActionDoCommand(SetLocal<T>(object oObject, string sVarName, T tValue))
ActionDoCommand(SetLocalInt(object oObject, string sVarName, int nValue))
ActionDoCommand(SetLocalString(object oObject, string sVarName, string sValue))
U8 School = NWN Class+School
They won't actually use the spells from the NWN classes, its just for their identity.
- Earth/Necromancer = Wizard+Necromancy
- Air/Theurgist = Wizard+Conjuration
- Water/Tempest = Wizard+Evocation
- Fire/Sorcerer = Wizard+Evocation
- Zealan = Druid?
Tavern drunk
------------
https://nwnlexicon.com/index.php?title=GetEnteringObject
Gets the object that last opened or entered the calling object.
object GetEnteringObject();
// Greet any Players that come into a trigger set around a drunk in a tavern.
void main()
{
if (GetIsPC(GetEnteringObject()))
{
AssignCommand(GetNearestObjectByTag("TavernPatron"), SpeakOneLinerConversation("DrunkGreeting"));
AssignCommand(GetNearestObjectByTag("TavernPatron"), ActionPlayAnimation(ANIMATION_LOOPING_PAUSE_DRUNK));
}
}
Creature: Mythran
-----------------
http://ultima.wikia.com/wiki/Mythran
Trivia:
He gives a potion once a day. He is visited by Shaana.
Creature: Changling
-------------------
By default could use a gnome with gray clothes?
There was some function to copy a creature. That could be used to mimic its target player.
Tavern joining to the other 2 houses
------------------------------------
I don't think the rural tileset had options for houses to join for those, but what i can do
is make them join through a basement tunnel thing. Just drop in a exit low and either do the
joiner room or just port between each directly. Not sure about putting them in the same
internal area or having 3 separate areas. I don't want path finders to go through the houses
to get into the tavern, which they might do when using those common generic path finding points.
So its probalby worth doing them as 3 separate ones.
Traps and dangers in U8
-----------------------
Electric Gateways - 5-10 electric damage
Exploding Chests - 5-20 fire damage
Exploding Books - 5-20 fire damage
Fire Mortar - 5-20 fire damage
Fire Shrooms (red mushroom) - 5-20 fire damage
Fire Shooters (wall) - 5-20 fire damage
Fire Spouts (ground) - 5-20 fire damage
Floor Spikes - 3-5 piercing damage
Force Fields (blue) - 5-10 (sonic?) damage
Spiked Roller - 2-5 piercing damage
Stalactites - 15 (bludgeon?) damage (could mark with water drop effect?)
Meteor - 10-30 fire damage
Lightning - death / 100 electirc damage
Fire - 5-10 fire damage
Red Lava - 1-2 fire damage
Green Potion - 10-20 damage
Electric Traps
--------------
https://nwnlexicon.com/index.php?title=TrapDoElectricalDamage
Function for doing electrical traps.
void TrapDoElectricalDamage(
int ngDamageMaster,
int nSaveDC,
int nSecondary
);
Zealan Gods/Goddesses
---------------------
Use statues, add some spell particle effects to make them stand out.
Maybe different colours for each one? I remember some red and blue sparkles.
For the trapped ones in the Lost Value, use different coloured spell particle effects.
Screenshots of the Lost Value show them trapped in some kind of yellow crystals, so maybe use yellow.
Carthax Lake
------------
Might use the "Underdark" tileset for this area, i think it allows raised areas to make the dry lake?
Lost Vale
---------
Read the kind of finally released story docs and see if it mentions how to get there. eg. through
the plateau double doors.
What unlocks them? If not mentioned, then consider using the unnamed ring like item from the
waterfall cave, which is below the plateau lake; and/or use the EAC item in Mythran's house, which
is related to the Ultima 7 power generators in the Guardian questline? It was the Guardian who gave
power to the Titan's on Pagan afterall, which allowed them to fight the Zealan gods.
I think the Lost Vale is a dry desolate area, the water was removed by Hydros. All the remaining
screenshots show the ground areas as dirt and rock. There are cloud areas, yellow stone areas and
white marble structures.
Inventory Scripts
-----------------
https://nwnlexicon.com/index.php?title=Globals
If there is a need to loop through inventory slots, this is a constant that can be used to limit it:
NUM_INVENTORY_SLOTS
Item scripts based on Tags
--------------------------
See file: x2_mod_def_load (Look in "All Modules")
// * Item Event Scripts: The game's default event scripts allow routing of all item related events
// * into a single file, based on the tag of that item. If an item's tag is "test", it will fire a
// * script called "test" when an item based event (equip, unequip, acquire, unacquire, activate,...)
// * is triggered. Check "x2_it_example.nss" for an example.
// * This feature is disabled by default.
SetModuleSwitch (MODULE_SWITCH_ENABLE_TAGBASED_SCRIPTS, TRUE);
if (GetModuleSwitchValue (MODULE_SWITCH_ENABLE_TAGBASED_SCRIPTS) == TRUE)
{
// * If Tagbased scripts are enabled, and you are running a Local Vault Server
// * you should use the line below to add a layer of security to your server, preventing
// * people to execute script you don't want them to. If you use the feature below,
// * all called item scrips will be the prefix + the Tag of the item you want to execute, up to a
// * maximum of 16 chars, instead of the pure tag of the object.
// * i.e. without the line below a user activating an item with the tag "test",
// * will result in the execution of a script called "test". If you uncomment the line below
// * the script called will be "1_test.nss"
// SetUserDefinedItemEventPrefix("1_");
}
So "IT_RecallGem" will auto link to script: "it_recallgem".
Some nice script guides for NPC features
----------------------------------------
https://www.gamefaqs.com/pc/188666-neverwinter-nights/faqs/22932
For example, it has a nice blacksmith script. The blacksmith will work and make comments until
the player comes close, at which point he will stop and wait for interaction.
Books and scrolls of Pagan
--------------------------
http://gigi.nullneuron.net/ultima/u8/u8writ.php
They are presented as scrolls and books just as they appear in the game.
This will be a good reference for formatting to match the new lines and paragraphs.
Hidden Items
------------
http://gigi.nullneuron.net/ultima/u8/u8hidden.php
The Key Blank might be difficult to implement if door unlocking is based on tags.
Maybe this will be a targeted action useable item to unlock doors?
Item Prices
-----------
http://infinitron.nullneuron.net/u8eco.html
Weapons at Korick shop:
Dagger - 5 Obsidian Coins
Mace - 15 Obsidian Coins
Axe - 25 Obsidian Coins
Sabre - 75 Obsidian Coins
Scimitar - 90 Obsidian Coins
Long Sword - 125 Obsidian Coins
Armour at Korick shop:
Plate Arm Guards - 11 Obsidian Coins
Plate Leggings - 12 Obsidian Coins
Triangle Shield - 12 Obsidian Coins
Great Helm - 13 Obsidian Coins
Armour at Darion training room:
Leather Arm Guards - 5 Obsidian Coins
Leather Leggings - 10 Obsidian Coins
Iron Helm - 2 Obsidian Coins
Leather Armor - 6 Obsidian Coins
Training at Darion training room:
A few minutes of training - 50 Obsidian Coins
Spells at Mythran house (must be brought in order to unlock next):
Confusion Blast - 50 Obsidian Coins
Meteor Shower - 100 Obsidian Coins
Summon Creature - 100 Obsidian Coins
Call Destruction - 150 Obsidian Coins
Devastation - 1000 Obsidian Coins
Ethereal Travel - 250 Obsidian Coins
Necromancy Reagents at Mythran house:
Bone - 10 Obsidian Coins
Executioner's Hood - 10 Obsidian Coins
Blackmoor - 10 Obsidian Coins
Sorcery Reagents at Mythran house:
Obsidian - 15 Obsidian Coins
Brimstone - 15 Obsidian Coins
Pumice - 15 Obsidian Coins
Ash - 15 Obsidian Coins
Pig Iron - 15 Obsidian Coins
Thaumaturgy Reagents at Mythran house:
Eye of Newt - 25 Obsidian Coins
Bat Wing - 30 Obsidian Coins
Serpent Scale - 25 Obsidian Coins
Dragon Blood - 40 Obsidian Coins
Scrolls at Mythran house:
Scroll of Dispelling Magical Portals - 50 Obsidian Coins
Jewelery at Rhian house East Tenebrae:
[ Jewel - Buying Price - Selling Price ]
Dark Diamond - 45 Obsidian Coins - 12 Obsidian Coins
Dancing Ruby - 20 Obsidian Coins - 18 Obsidian Coins
Gemstone Necklace - 36 Obsidian Coins - 6 Obsidian Coins
Gemstone Ring - 22 Obsidian Coins - 3 Obsidian Coins
Amethyst Gem - n/a - 9 Obsidian Coins
Stone Amber - n/a - 15 Obsidian Coins
Obsidian Starstone - n/a - 21 Obsidian Coins
Bright Diamond - n/a - 24 Obsidian Coin
Clothes at Rhian house East Tenebrae:
Cloak - 6 Obsidian Coins
Shirt - 4 Obsidian Coins
Vest - 7 Obsidian Coins
Food at Jenna in West Tenebrae tavern:
Fish - 1 Obsidian Coin
Toraxen Jerky - 3 Obsidian Coins
Kith Filet - 8 Obsidian Coins
Bread - 1 Obsidian Coin
Mushroom - 1 Obsidian Coin
Tuber - 1 Obsidian Coin
Toraxen Cheese - 1 Obsidian Coin
Drinks at Orlock/Jenna in West Tenebrae tavern (a bar tab is also available):
Tenebraen Ale - 2/1 Obsidian Coins (Orlock 2, Jenna 1)
Blackwine - 3 Obsidian Coins
Hurricane - 2 Obsidian Coins
Breath o' Spirit - 2 Obsidian Coins
Cloven Hoof - 5 Obsidian Coins
Virtues?
--------
It would be good to track the Virtues of the player during the game without them knowing and present
them at the end. Read up on how Ultima 4 tracked the virtues.