View Single Post
Old 03-11-17, 19:34   #24
AkyV
Moderator
 
Joined: Dec 2011
Posts: 4,881
Default

23. Data conversions

You can do data conversion in the code in these situations:

a, Index conversion:
There are three sequences of NGLE/tomb indices:
- Moveable object (plus camera/sink/sound),
- Static objects,
- rooms

Previously I have already talked about Moveable object (plus camera/sink/sound) NGLE/tomb indices. Supposedly this list will refresh your reminiscences:

Index slot 0: NGLE Index 0 – Tomb Index 0
Index slot 1: NGLE Index 1 – Tomb Index 1
Index slot 2: empty
Index slot 3: empty
Index slot 4: NGLE Index 4 – Tomb Index 2
Index slot 5: empty
Index slot 6: NGLE Index 6 – Tomb Index 3

The sequence of room indices is absolutely similar – see eg. this room list:

Room0 (0:0) – room name (NGLE index:tomb index)
Room1 (1:1)
Empty
Empty
Room4 (4:2)
Empty
Room6 (6:3)

The indices of Static objects are a bit different. An NGLE Static index is naturally the object ID you can read from the map in NGLE. But its tomb index has two parts: the room tomb index, where the Static is, plus the Static index only for that room.

b, Absolute/relative value conversion:
“Absolute” indices are used for animations and animation frames in the code, but only their “relative” versions are easily understandable for the level builders.

Let’s see for example a basic WAD, where LARA object has the usual 444 animations. LARA is the first object in the WAD, PISTOLS_ANIM is the second one. The first animation of PISTOLS_ANIM is naturally Animation0. But it is the relative index – the index which can be identified only with the slot together, because naturally LARA object Animation0 and PISTOLS_ANIM Animation0 are not the same.
An absolute index is always the “previous absolute animation index of the WAD, plus 1”. As the animation indices of the first object, the relative and absolute indices of LARA object are the same. The animation just before the second object PISTOLS_ANIM Animation0 is the last (444) animation of the first object LARA. So the absolute index of PISTOLS_ANIM Animation0 is Animation445. There is no other absolute Animation445 in the WAD, naturally. (But other WADs can also have their own absolute Animation445.)

As for frame indices, the theory is similar. I mean, you have different Frame0 frames eg. for the different animations of LARA object. Which means those are relative indices, you can identify an index only with its animation (and slot) together, i.e. Frame0 of LARA object Animation0 and Frame0 of LARA object Animation1 are not the same.
An absolute index is always the “previous absolute frame index of the WAD object slot, plus 1”. As the frame indices of the first animation (0 - running), the relative and absolute indices of LARA object Animation0 are the same. The frame just before the second animation (1 - walking) is the last (21, by default) frame of the first animation (0). So the absolute index of LARA Animation1 Frame0 is Frame22. There is no other absolute Frame22 for LARA object, naturally. (But other object slots in the WAD can also have their own absolute Frame22.)

Note:
There are also some other (not so important) conversions, you can read about them in this tutorial. (You don’t need them now.)

The conversion is needed in the code:

1. From NGLE index to tomb index:
- If you type the room/Moveable object NGLE ID manually. (Mostly if you ask the ID in Parameters Script commands.) If you got tomb indices manually, out of the code, that would be wrong (see the explanation just below), so you will always type NGLE room/Moveable indices in the code, also asking the conversion: “convert NGLE X code into tomb Y code”, because the plugin always work with tomb indices.
- Always, if you work with Static object indices. The plugin always work with tomb indices, but you can know only NGLE Static indices from the Level Editor, so you will always type NGLE indices in the code, also asking the conversion: “convert NGLE X code into tomb Y code”.

2. From relative index to absolute index:
- Always, if you work with animation indices.
- Always, if you work with animation frame indices.

The cause in both cases is: if you got absolute indices manually, out of the code, that would be wrong (see the explanation just below), so you will always type relative animation/frame indices in the code, also asking the conversion: “convert relative X code into absolute Y code”, because the plugin always work with absolue indices.

3. From tomb index to NGLE index / from absolute index to relative index:
If you would like to print the index (coming from the code) with Statistic Script commands or in the log. Because the tomb/absolute index of the code doesn’t mean anything when level building, only NGLE/relative indices can be identified easily.

Notes:
- On the other hand, the NGLE=>tomb conversion is not needed for Moveable object (plus camera/sink/sound) indices:

> If you use preset arguments in your own Action or Condition triggers, and if the list of the argument has the actual Moveable object (camera/sink/sound) indices, like in the case of #MOVEABLES#.
The reason is this time you won’t type the index manually - the object list in the trigger “Object to trigger” box shows NGLE indices, though. But the conversion will be made automatically in the code: “Object to trigger” box values of Action or Condition triggers are always handled as “ItemIndex” variable values in the code. So if you type “ItemIndex” in the code, having those preset arguments, then it means “the tomb index of Moveable object (camera/sink/sound), that you chose in »Object to trigger« box”.
> If the index is defined by the code, because that index is naturally a tomb index. See eg. *Trng.pGlobTomb4->pVetMemorySavegame[0].pShort to get the last found item index.

- The code uses tomb indices, and the code uses absolute indices. That is why an animation/frame index defined by a code is always absolute. For example, GET.pItem->AnimationNow is the absolute index of the animation that the object is just performing, you don’t need relative=>absolute conversions.
- You should avoid conversions out of the code, if the conversion is needed. There are more possibilities for that, in many cases of the NGLE/tomb, absolute/relative indices. For example, you can find Animation Watcher in NG Center. Load the WAD, choose “Show Present Animations” in the “Show” box, and choose “PISTOLS_ANIM” in the “Slot” box. Now you can identify easily in the bigger window below that PISTOLS_ANIM Animation0 has 445 as the absolute ID – as I said above.
But it is bad idea to use that 445 in the code. – This example will explain why:

The only enemies in your WAD are CROCODILE (slot ID 51) and DEMIGOD1 (slot ID 77). Then you add a new enemy to your WAD. Eg. this is the WILD_BOAR (slot ID 73). Up to now, the absolute index of DEMIGOD1 first animation was the absolute index of CROCODILE last animation, plus one. But that index goes to the WILD_BOAR first animation now.
So Absolute Index X (meaning DEMIGOD1 first animation before) means WILD_BOAR first animation, after adding WILD_BOAR, you should change the absolute animation ID, typed manually, which is wrong now (not referring any more to DEMIGOD1), in the code.

So what I say is (when you need a conversion): even if you can get a tomb/absolute index in other ways, always type an NGLE/relative index (or a variable having that index) into the code, and the proper conversion (in the code) will be made by the conversion methods that are listed below.

- You need to be careful, if this animation/frame is for Lara, but not for Lara object – for example, if it is VEHICLE_EXTRA or PISTOLS_ANIM etc.:
a, In the case of vehicle animation slots, unfortunately, the only useful way to identify an animation in the code is with a conversion out of the code – eg. getting the proper absolute animation code of VEHICLE_EXTRA from Animation Watcher. - So you should check this absolute animation value (if it is still the proper one) when you add/remove an animation or an object slot to/from your WAD later!
However, these animations and frames are still handled as the animations/frames of Lara object, in other aspects.
b, In the case of flare, torch or weapon animations, you need to identify the absolute animation/frame ID’s NOT as Lara object’s animations/frames, but the values of these Savegame Memory Zone fields:

WeaponAnim. Current animation of torch-flare-weapon animation (Short)
WeaponAnim. Current frame of torch-flare-weapon animation (Short)

Conversion methods:

1. If the Moveable index comes from another trigger (i.e. if you export an Action/Condition trigger as a function into your code), then you need the NGLE=>tomb conversion. As I said above, it is very easy, just hit the Export Function button to get the proper values:

; Set Trigger Type - ACTION 43
; Exporting: TRIGGER(43:0) for ACTION(152) {Tomb_NextGeneration}
; <#> : ANIMATING2 ID 152 in sector (8,6) of First Room
; <&> : Trigger. (Moveable) Activate <#>Object with (E)Timer value
; (E) : Timer= +00

PerformActionTrigger(NULL, 43, 152 | NGLE_INDEX, 0);

A special example – activate the object which is the last found item:

Code:
  PerformActionTrigger(NULL, 43, ReadMemVariable (0 | enumMEMT.SAVEGAME), 0);
2. As I said above, items for “Get (GET_ITEM...” structure needs an NGLE=>tomb conversion, if it is an NGLE index:

Code:
  Get (GET_ITEM, 97+NGLE_INDEX, 0);
But if it is a tomb index (eg. if this item is coming from the “Object to trigger” box of the Condition trigger, as a preset argumnt), then you don’t need the conversion:

Code:
  Get (GET_ITEM, ItemIndex, 0);
3. If the room/Moveable index is in Current Value TRNG variable, then there are some “Variables. Convert” Flipeffect triggers, to do NGLE=>tomb or tomb=>NGLE conversion. You can export those Flipeffects as functions, into your code.

4. The basic NGLE=>tomb or tomb=>NGLE conversion for Moveables (NGLE index = X variable, tomb index= Y variable this time), with these functions:

Y = FromNgleIndexToTomb4Index (X);
X = FromTomb4IndexToNgleIndex (Y);

It looks this way eg. in the case of GET_ITEM:

Code:
  Y = FromNgleIndexToTomb4Index (X);
  Get (GET_ITEM, Y, 0);
or, if you don’t want an Y variable:

Code:
  Get (GET_ITEM, FromNgleIndexToTomb4Index (X), 0);
5. The basic NGLE=>tomb or tomb=>NGLE conversion for Statics (eg. if the NGLE index is in Z variable this time), with FromNgleStaticIndexToTomb4Indices function – an example when you check if the OCB of the required Static has OCB flag 1:

Code:
  {
  int Z;
  int RoomIndex;
  int StaticIndexForRoom;
  
  FromNgleStaticIndexToTomb4Indices (Z, & RoomIndex, & StaticIndexForRoom);
  
  Get (enumGET.STATIC, RoomIndex, StaticIndexForRoom);
  if (GET.pStatic ->OCB & 1) {
  
  }
  }
As I said above, a Static tomb index is double: you get a room index and the Static index only for that room, with a NGLE=>tomb conversion.
As I also said, a single & means “part of something”, so “& RoomIndex, & StaticIndexForRoom” means now “they are both parts of the tomb index”.

The back conversion is similar - but this time without a &:

Code:
Z = FromStaticIndicesToNgleIndex (RoomIndex, StaticIndexForRoom);
6. The Convert function is the “ultimate tool” for the converisons.
The general syntax of the function is:

Convert (CONVERT constant for the conversion type, First Input Value, Second Input Value, Pointer)

Let’s see one example for each case:

- Conversion from Moveable 107 NGLE index into tomb index (no second input value and pointer), storing the value in TombItemIndex variable:

Code:
TombItemIndex = Convert (enumCONV.ItemIndexFromNgleToTomb, 107, 0,NULL);
- Conversion from the Moveable tomb index (having the tomb index in TombItemIndex variable) into NGLE index (no second input value and pointer), storing the value in NgleItemIndex variable:

Code:
NgleItemIndex = Convert (enumCONV.ItemIndexFromTombToNgle, TombItemIndex,0,NULL);
- Conversion from Static 258 NGLE index into room/static double tomb index (no second input value), storing the value in RoomIndex and StaticIndex variable:

Code:
RoomIndex = Convert (enumCONV.StaticIndexFromNgleToTomb, 258, 0, &StaticIndex);
Yes, a &, without p, but it is a pointer.

- Conversion from the Static tomb indices (having tomb indices in RoomIndex and StaticIndex variables) into NGLE index (no pointer), storing the value in NgleStaticIndex variable:

Code:
  NgleStaticIndex = Convert (enumCONV.StaticIndexFromTombToNgle, RoomIndex, StaticIndex,NULL);
- Conversion from Room 75 NGLE index into tomb index (no second input value and pointer), storing the value in TombRoomIndex variable:

Code:
  TombRoomIndex = Convert (enumCONV.RoomIndexFromNgleToTomb, 75, 0, NULL);
- Conversion from the room tomb index (having the tomb index in TombRoomIndex variable) into NGLE index (no second input value and pointer), storing the value in NgleRoomIndex variable:

Code:
  NgleRoomIndex = Convert (enumCONV.RoomIndexFromTombToNgle, TombRoomIndex, 0, NULL);
- Conversion from Animation 5 relative index of BADDY_1 enemy of GET.pItem into the absolute WAD animation index (no second input value), storing the value in AbsAnimationIndex variable:

Code:
  Get (enumGET.ITEM, ItemIndex, 0);
  AbsAnimationIndex = Convert(enumCONV.AnimIndexFromRelativeToAbs, 5, 0, GET.pItem);
- Conversion from the WAD absolute animation index (having the absolute index in AbsAnimationIndex variable) into the relative index of BADDY_1 enemy of GET.pItem (no second input value and pointer), storing the value in RelAnimIndex variable:

Code:
  Get (enumGET.ITEM, ItemIndex, 0);
  RelAnimIndex = Convert (enumCONV.AnimIndexFromAbsToRelative, AbsAnimationIndex, 0, GET.pItem);
- Conversion from Frame2 relative index of the absolute animation (being in AbsAnimationIndex variable), into the absolute frame index of the object slot (no pointer), storing the value in FrameAbs variable:

Code:
  FrameAbs = Convert (enumCONV.FrameIndexFromRelativeToAbs, 2, AbsAnimationIndex, NULL);
- Conversion from the absolute frame index of the object slot (having the absolute index in FrameAbs variable) into the relative frame index of AbsAnimationIndex animation (no pointer), storing the value in FrameRel variable:

Code:
  FrameRel = Convert (enumCONV.FrameIndexFromAbsToRelative, FrameAbs, AbsAnimationIndex, NULL);
7. Animation and frame indices without any conversion – with some easy tricks:
For example, to identify and examine Frame2 of Animation5 of a BADDY_1 object in a Condition trigger, as his actual animation and frame, without knowing and searching for its absolute animation/frame ID:

Code:
  Get (enumGET.ITEM, ItemIndex, 0);
  if (GET.pItem->SlotID == SLOT_BADDY_1) {
        Get (enumGET.SLOT, GET.pItem->SlotID, 0);
        if (GET.pItem->AnimationNow == 5 + GET.pSlot->IndexFirstAnim) {
              Get (enumGET.ANIMATION, 5 + GET.pSlot->IndexFirstAnim, 0);
              if (GET.pItem->FrameNow == 2 + GET.pAnimation->FrameStart) {
  
              }
        }
  }
I mean, the absolute ID in “IndexFirstAnim” could be any number, it doesn’t matter now, but we now surely it has Animation 0 relative ID for its objects slot (hence the name “first”). So “5 + GET.pSlot->IndexFirstAnim” is surely refers to Animation5 (0+5=5) relative animation index of the slot.
So if this animation is just being performed by that enemy (“AnimationNow”, defined by the code, absolute value), then we examine the animation with the GET_ANIMATION constant.
The absolute ID in “FrameStart” could be any number, it doesn’t matter now, but we now surely it has Frame 0 relative ID for its animation (hence the name “start”). So “2 + GET.pAnimation->FrameStart” is surely refers to Frame2 (0+2=2) relative frame index of the animation.
So if this frame is just being performed by that enemy (“FrameNow”, defined by the code, absolute value), then we know the whole condition is true.

This is a very useful method, if you can’t do a conversion, because that doesn’t work in these cases:

WeaponAnim. Current animation of torch-flare-weapon animation (Short)
WeaponAnim. Current frame of torch-flare-weapon animation (Short)

For example:

Code:
  Get (enumGET.SLOT, SLOT_PISTOLS_ANIM, 0);
  if (*Trng.pGlobTomb4->pVetMemorySavegame[91].pShort == 3 + GET.pSlot->IndexFirstAnim) {
        Get (enumGET.ANIMATION, 3 + GET.pSlot->IndexFirstAnim, 0);
        if (*Trng.pGlobTomb4->pVetMemorySavegame[90].pShort == 2 + GET.pAnimation->FrameStart) {
  
        }
  }
means „if it is Frame2 of Animation 3 of PISTOLS_ANIM”, because 91 is the memory zone field ID for the animations and 90 is for frames.
AkyV is online now