Multi_Slot_Example Code

Documentation, usage tips and configuration guides for Titan Two scripts and bytecodes published by the community users.

Multi_Slot_Example Code

Postby Scachi » Wed Sep 20, 2017 1:55 pm

Hello,

this is a rather big / complex example on how to use a second slot to store a lot of weapon presets.

Bloating up the data script to contain 255 data presets results in around 50% bytecode usage.
So there should be enough space left if you need more weapon specific options (anti recoil left/right/verical, rapid fire on/of....) than I have put into this example.

I haven't tested if a combobox can hold more than 255 items to select from if I change its bitsize from 8 to 16.

The three weapon slots of this example are pointing to the same weapon preset data, the combobox item to weapon preset translation can be used to only allow some weapons for a specific combobox.
To get rid of this translation step, you can create different sets of arrays for each available weapon slots.

What this example does:
  • * Working (somewhat) stand alone script
  • * Sanity checking
  • * Interactive configuration for the main and data script.
  • * Loading of weapon preset data from the main/data script slot into the main script slot.
  • * All loaded data is available in the main script through the cfg arrays (filled by the WeaponLoad function),
    where index 0 = primary weapon, 1 = secondary, 2 = power :
    Code: Select all
     
    bool  cfgAntiRecoil[]
    uint8 cfgAntiRecoilV[]
    int8  cfgAntiRecoilH[]
    uint8 cfgRapidFireMode[]
    uint8 cfgRapidFirePressure[]
    uint8 cfgRapidFireSPM[]
    uint8 cfgRapidFireBPS[]
    uint8 cfgRapidFireHold[]
    uint8 cfgRapidFireRelease[]
    uint8 cfgRapidAntiRecoilMode[]
    uint8 cfgRapidAntiRecoilV[]
    int8  cfgRapidAntiRecoilH[]
    uint8 cfgSensitivity[]

    Making use of this available data shouldn't be a problem for you.


What this example lacks:
  • * While data loading if fully working, there is no game logic programmed. The main loop is empty...it is an example after all.


How to install/use this scripts:
Download "MultiSlot_DataScript" and "MultiSlot_MainScript" from the online resource or use the attached .zip and put each script in a memory slot.
Configure each script to point to the other script slot number, always using the "Save & Run" button !

Now you should be ready to open the interactive configuration of the data script, select the checkboxes of the weapon slots to load (primary/secondary/power) and the weapon to load into that slot.
Hit the "Save and Run" button.
No open up the Interactive Configuration of the Main script and hit the "Save & Run" button, this will load the selected data into the main script and you're done.

Some of the above steps can be done automatically too, by extending the code to switch to the main script after hitting save and run in the data script.

Some more information:
My first choice would have been to use the data script to write into the pmem space of the master script, but I couldn't get it working. For me it always write to the active memory slot, not sure if this is a bug or I am not using it correctly.
As a workaround I save the choosen dataset into the pmem space of the data scripts slot and set there a flag for the main script to watch for if it is supposed to load some data from the pmem space of the data slot.
Reading from a different slots pmem works fine and saving this data to local slots pmem storage works fine too.
Github entry: https://github.com/J2Kbr/GtunerIV/issues/175


The main script is fully working without the second script/slot.
This will let the user the choice if they just want to have the default features (and data presets) of the script while only using up one Memory Slot, or have access too up to 255 (and more) data/weapon presets to choose from.

The script can placed on any slot number, there is a combobox for each script to select the main/data scripts slot to reference to the correct slot.

It does some sanity checking via predefined pmem_ entries to check if the slot number selected is really the data/main script in question. It will tell the user via a "State" combobox in the interactive configuration if it is setup correctly.

The available weapon preset data options are loosely base on what I use for "Destiny 2" (code heavily borrowed from antithesis destiny2 script) to define things like anti recoil, rapid fire and stuff.

Screenshot of the master scripts Interactive Configuration:
ic-main.png
ic-main.png (31.89 KiB) Viewed 3283 times


Screenshot of the data scripts Interactive Configuration:
ic-data.png
ic-data.png (36.65 KiB) Viewed 3283 times
Attachments
Multi_Slot_Example.zip
Zip containing both scripts and referenced .gph files in a single folder.
(73.35 KiB) Downloaded 205 times
Last edited by Scachi on Mon Sep 25, 2017 11:55 am, edited 5 times in total.
User avatar
Scachi
Brigadier General
Brigadier General
 
Posts: 3044
Joined: Wed May 11, 2016 6:25 am
Location: Germany

Re: Multi_Slot_Example Code

Postby antithesis » Wed Sep 20, 2017 2:08 pm

You bloody ripper! The final piece of the puzzle :smile0208:
Official Australian retailer for Titan One, Titan Two and XIM APEX at Mod Squad
User avatar
antithesis
Colonel
Colonel
 
Posts: 1912
Joined: Sat May 28, 2016 10:45 pm

Re: Multi_Slot_Example Code

Postby J2Kbr » Wed Sep 20, 2017 3:50 pm

Great work, not only for the script, but also for this very detailed page. :smile0517:

Scachi wrote:My first choice would have been to use the data script to write into the pmem space of the master script, but I couldn't get it working. For me it always write to the active memory slot, not sure if this is a bug or I am not using it correctly. As a workaround I save the choosen dataset into the pmem space of the data scripts slot and set there a flag for the main script to watch for if it is supposed to load some data from the pmem space of the data slot.
Reading from a different slots pmem works fine and saving this data to local slots pmem storage works fine too.
Github entry: https://github.com/J2Kbr/GtunerIV/issues/175

I found the bug that was causing this, it is already fixed and a firmware update should be out soon. thank you for reporting.
ConsoleTuner Support Team
User avatar
J2Kbr
General of the Army
General of the Army
 
Posts: 20323
Joined: Tue Mar 18, 2014 1:39 pm

Re: Multi_Slot_Example Code

Postby monty34 » Tue Feb 27, 2018 12:23 pm

Hi, i have currently my weapon setups saved in a .gph file. Is there a possibility to load the data from the .gph file from a different memory slot to my main script? And can i pre-define the Memory and Data slot inside the script to use it without the interactive configuration menu when the T2 is not connected to the PC?
User avatar
monty34
Command Sergeant Major
Command Sergeant Major
 
Posts: 165
Joined: Wed Jun 28, 2017 7:25 pm

Re: Multi_Slot_Example Code

Postby antithesis » Wed Feb 28, 2018 5:14 am

monty34 wrote:Hi, i have currently my weapon setups saved in a .gph file. Is there a possibility to load the data from the .gph file from a different memory slot to my main script? And can i pre-define the Memory and Data slot inside the script to use it without the interactive configuration menu when the T2 is not connected to the PC?

An external gph file can't be loaded into a GBC, it all gets packaged up together. It should be fine in a GPC, but then the source code is exposed.

There was discussion about the possibility of loading external files late last year, but I don't think anything has happened yet.
Official Australian retailer for Titan One, Titan Two and XIM APEX at Mod Squad
User avatar
antithesis
Colonel
Colonel
 
Posts: 1912
Joined: Sat May 28, 2016 10:45 pm

Re: Multi_Slot_Example Code

Postby Scachi » Wed Feb 28, 2018 8:37 am

monty34 wrote:Hi, i have currently my weapon setups saved in a .gph file. Is there a possibility to load the data from the .gph file from a different memory slot to my main script? And can i pre-define the Memory and Data slot inside the script to use it without the interactive configuration menu when the T2 is not connected to the PC?

You need some code (gpc) to handle your data from gph in the same slot you put your gph on, write it from there into the pmem offset in a slot your main code slot can access.

Your man script can't access the variables/declarations directly from another slot. It has to get them from pmem space.
It is up to you if you access the data in pmem slot 2 from slot 1 or if you write in your data script in slot2 to the pmem of slot 1 directly. It doesn't matter much as you still need some script in slot 2 to write the specific data for your weapon in use from your weapon data list into the pmem space, switch memory slot and use it in your main script.

As you need to compile your script in the second slot you still have the choice to share it as gbc or gpc.

As for selecting the data to load from the second slot without a pc connected, yes it is possible.
You can utilize the display of the T2 to show a simple menu, like writing a number for the weapon set to load into slot 1 or the weapon name (char after char).
User avatar
Scachi
Brigadier General
Brigadier General
 
Posts: 3044
Joined: Wed May 11, 2016 6:25 am
Location: Germany

Re: Multi_Slot_Example Code

Postby monty34 » Wed Feb 28, 2018 3:34 pm

Thanks for your feedback, i go now the way to store my configs in arrays like Scachi`s example in the data script. This gives me currently enough space to store all of my weapon configs inside a .gph file.
User avatar
monty34
Command Sergeant Major
Command Sergeant Major
 
Posts: 165
Joined: Wed Jun 28, 2017 7:25 pm

Re: Multi_Slot_Example Code

Postby monty34 » Fri Jul 27, 2018 5:46 am

Hi, considering the coming changes in Destiny 2 for the weapon slots, i think i need to extract my weapon DB to a seperate memory slot.

Currently the DB is stored as .gph file and looks like this:

Code: Select all
 
char *TriWeaponName[] = {"Power Weapon 0: AR-Disabled","Power Weapon 1: Hawthornes Field-Forged Shotgun","Power Weapon 2: Gunnoras Axt","Power Weapon 3: Undefined","Power Weapon 4: Undefined","Power Weapon 5: Undefined"};
const fix32 triyRecoilvalue[] = {0.0,45.0,45.0,0.0,0.0};
const fix32 trixRecoilvalue[] = {0.0,0.0,0.0,0.0,0.0};
const bool triRapidfiremodevalue[] = {0,1,0,0,0};
const uint16 triShotHoldTimeValue[] = {0,334,0,0,0};
const uint16 triShotWaitTimeValue[] = {0,334,0,0,0};
const uint16 triWeaponReloadTimeValue[] = {2500,2500,2500,2500,2500};
 



I call the data via a function:

Code: Select all
 
Powerconfig(triRecoilmode);
 


Code: Select all
 
void Powerconfig (int mode) {
    static uint8 P;
    if (mode != P) {
        triyRecoil = triyRecoilvalue[mode];
        trixRecoil = trixRecoilvalue[mode];
        triRapidFireMode =  triRapidfiremodevalue[mode];
        triShotHoldTime = triShotHoldTimeValue[mode];
        triShotWaitTime = triShotWaitTimeValue[mode];
        triWeaponReloadTime = triWeaponReloadTimeValue[mode];
        //PowerSensivity = triSensivityFactor[mode];
      P = mode;
  }
  return;
}
 


As this running well with one memory slot, how can i adapt the code to outsource the weapon DB to a different memory slot? I don´t need an interactive configuration.
User avatar
monty34
Command Sergeant Major
Command Sergeant Major
 
Posts: 165
Joined: Wed Jun 28, 2017 7:25 pm

Re: Multi_Slot_Example Code

Postby Scachi » Fri Jul 27, 2018 12:21 pm

The coolest thing would be using a script load function (feature request on github https://github.com/J2Kbr/GtunerIV/issues/237) to load the data script so you won't need a second slot at all for this.

Here is some example code how it can be done at the moment.
It got a bit complex as I added a some debug output with printf and put everything important into a shared gph file to avoid making mistakes using different byte offsets to read from than i have written to or using different variable types for the same name.

The share.gph file is read by both scripts, main_slot.gpc and data_slot.gpc
Save this as "share.gph":
Code: Select all
 
// used by both scripts
#define TRILIMIT  4  // 0..4 , to know the valid range and force it to keep this number and the actual data count in sync
 
uint8 MainSlot=0; // to know where to load the data from, configured via IC
uint8 DataSlot=0; // to know the slot to switch to from the main slot, configured via IC
 
uint8 triRecoilmode=0;
uint8 triRecoilmodeCur=0;
 
#define PO_trm 0    // byteoffset 0   uint8 triRecoilmode
#define PO_tyr 1    // byteoffset +4  fix32 triyRecoil
#define PO_txr 5    // byteoffset +4  fix32 trixRecoil
#define PO_trf 9    // byteoffset +1  bool triRapidFireMode;
#define PO_tsh 10   // byteoffset +2  uint16 triShotHoldTime,
#define PO_tsw 12   // byteoffset +2  uint16 triShotWaitTime
#define PO_twr 14   // byteoffset +2  uint16 triWeaponReloadTime
                    // byteoffset 127 uint8 DataSlot/mainslot location
 
 
fix32 triyRecoil, trixRecoil;
bool triRapidFireMode;
uint16 triShotHoldTime, triShotWaitTime, triWeaponReloadTime;
 
// LED Color 'C'olor , blink duration on , blink duration off, blink count
void ColorLEDVM(char Color, uint16 DurOn, uint16 DurOf, int Count) {
    int Color1, Color2, Color3, Color4;
 
    if(Color == 'B'){Color1 = 1; Color2 = 0; Color3 = 0; Color4 = 0;}
    if(Color == 'R'){Color1 = 0; Color2 = 1; Color3 = 0; Color4 = 0;}
    if(Color == 'G'){Color1 = 0; Color2 = 0; Color3 = 1; Color4 = 0;}
    if(Color == 'P'){Color1 = 0; Color2 = 0; Color3 = 0; Color4 = 1;}
    if(Color == 'C'){Color1 = 1; Color2 = 0; Color3 = 1; Color4 = 0;}
    if(Color == 'A'){Color1 = 0; Color2 = 1; Color3 = 1; Color4 = 0;}
    if(Color == 'W'){Color1 = 1; Color2 = 1; Color3 = 1; Color4 = 1;}
    led_reset();
  if (Color1) led_vmset(LED_1, DurOn, DurOf, Count);
    if (Color2) led_vmset(LED_2, DurOn, DurOf, Count);
    if (Color3) led_vmset(LED_3, DurOn, DurOf, Count);
    if (Color4) led_vmset(LED_4, DurOn, DurOf, Count);
}


The main_slot.gpc file contains the main script that will be used for gaming and the selection of the datablock to load.
Save this as "main_slot.gpc":
Code: Select all
#pragma METAINFO("main slot", 1, 0, "Scachi")
 
#include "share.gph"
 
/*** IC
<cfgdesc>
[Main Script]
collapsible= 1
shortdesc     = Main Scripts Settings
control   = info
 
[Data Memory Slot]
shortdesc = Select the Memory Slot where the DATA script is stored!
byteoffset= 127
bitsize        = 8
control        = combobox
default        = 0
item            = Select one !
item            = 1
item            = 2
item            = 3
item            = 4
item            = 5
item            = 6
item            = 7
item            = 8
item            = 9
 
[Last Loaded Data]
shortdesc = Show the last loaded Data or Data to load
byteoffset= 0
bitsize        = 8
control        = spinbox
default        = 0
minimum        = 0
maximum        = 255
step            = 1
 
</cfgdesc>
***/

 
 
init {
  pmem_load()// current slot
 
  pmem_read(127,&DataSlot); // to now the slot where the data is stored
  if (DataSlot == 0) {
    printf("Main: You have to select the memory slot where the DATA script is at!");
    ColorLEDVM('R',200,200,-1);
  }
 
  // uint8 triRecoilmode; // in share.gph
  pmem_read(PO_trm,&triRecoilmode); // read the last triRecoilmode used
  triRecoilmodeCur = triRecoilmode;
  printf("Main: Reading the data block %d at init",triRecoilmode);
  PowerDataLoad();
  printf("Main: Ready");
}
 
void PowerDataLoad() {
                                          // byteoffset 0   uint8 triRecoilmode
  pmem_read(PO_tyr,&triyRecoil);          // byteoffset +4  fix32 triyRecoil
  pmem_read(PO_txr,&trixRecoil);          // byteoffset +4  fix32 trixRecoil
  pmem_read(PO_trf,&triRapidFireMode);    // byteoffset +1  bool triRapidFireMode;
  pmem_read(PO_tsh,&triShotHoldTime);     // byteoffset +2  uint16 triShotHoldTime,
  pmem_read(PO_tsw,&triShotWaitTime);     // byteoffset +2  uint16 triShotWaitTime
  pmem_read(PO_twr,&triWeaponReloadTime); // byteoffset +2  uint16 triWeaponReloadTime
                                          // byteoffset 127 uint8 DataSlot location
  printf("triyRecoil %f", triyRecoil);
  printf("trixRecoil %f", trixRecoil);
 
  printf("triRapidFireMode %d", triRapidFireMode);
 
  printf("triShotHoldTime %d", triShotHoldTime);
  printf("triShotWaitTime %d", triShotWaitTime);
 
  printf("triWeaponReloadTime %d", triWeaponReloadTime);
 
}
 
main {
  // L2 + DPAD_LEFT decrease / right increase triRecoilmode to load
  if ( get_val(BUTTON_8) && event_active(BUTTON_12) ) triRecoilmode--;
  if ( get_val(BUTTON_8) && event_active(BUTTON_13) ) triRecoilmode++;
  triRecoilmode=clamp(triRecoilmode,0,TRILIMIT);
 
  // press R3 to load the data
  if ( event_active(BUTTON_6) && triRecoilmode != triRecoilmodeCur && DataSlot != 0 ) {
    pmem_write(0,triRecoilmode); pmem_save();
    printf("Main: Now switching to Data slot %d to load data block %d",DataSlot,triRecoilmode);
    mslot_load(DataSlot);
  }
}
 
 


The data_slot.gpc file contains the loading from the db header and writing the data into the pmem space of the main_slot
Save this as "data_slot.gpc":
Code: Select all
#pragma METAINFO("data slot", 1, 0, "Scachi")
 
#include "share.gph"
#include "data_slot.gph"
 
/*** IC
<cfgdesc>
 
[Data Script]
collapsible= 1
shortdesc     = Data Scripts Settings
control   = info
 
[Main Memory Slot]
shortdesc = Select the Memory Slot where the MAIN script is stored!
byteoffset= 127
bitsize        = 8
control        = combobox
default        = 0
item            = Select one !
item            = 1
item            = 2
item            = 3
item            = 4
item            = 5
item            = 6
item            = 7
item            = 8
item            = 9
 
</cfgdesc>
***/

 
init {
  printf("Data: Data Slot %d Active",mslot_get());
  pmem_load(); // load data slots pmem to read where the main slot is located
  pmem_read(127,&MainSlot);
 
  if (MainSlot == 0) {
    printf("Data: You have to select the memory slot where the MAIN script is at!");
    ColorLEDVM('R',200,200,-1);
 
  } else {
 
    pmem_load(MainSlot); // your main code is at slot 1
    // uint8 triRecoilmode; // in share.gph
    pmem_read(PO_trm,&triRecoilmode); // read from main slot the data number to load
    printf("Data: Loading data block %d",triRecoilmode);
    Powerconfig(triRecoilmode);
    printf("Data: Writing data block %d to main slot %d",triRecoilmode,MainSlot);
    PowerDataToMainSlot();
    printf("Data: Switching back to main slot %d",MainSlot);
    mslot_load(MainSlot); // back to main slot
  }
}
 
void PowerDataToMainSlot() {
                                          // byteoffset 0   uint8 triRecoilmode
  pmem_write(PO_tyr,triyRecoil);          // byteoffset +4  fix32 triyRecoil
  pmem_write(PO_txr,trixRecoil);          // byteoffset +4  fix32 trixRecoil
  pmem_write(PO_trf,triRapidFireMode);    // byteoffset +1  bool triRapidFireMode;
  pmem_write(PO_tsh,triShotHoldTime);     // byteoffset +2  uint16 triShotHoldTime,
  pmem_write(PO_tsw,triShotWaitTime);     // byteoffset +2  uint16 triShotWaitTime
  pmem_write(PO_twr,triWeaponReloadTime); // byteoffset +2  uint16 triWeaponReloadTime
                                          // byteoffset 127 uint8 DataSlot location
  pmem_save(MainSlot);
}
 
void Powerconfig (int mode) {
 
        triyRecoil = triyRecoilvalue[mode];
        trixRecoil = trixRecoilvalue[mode];
        triRapidFireMode =  triRapidfiremodevalue[mode];
        triShotHoldTime = triShotHoldTimeValue[mode];
        triShotWaitTime = triShotWaitTimeValue[mode];
        triWeaponReloadTime = triWeaponReloadTimeValue[mode];
        //PowerSensivity = triSensivityFactor[mode];
 
  return;
}
 
 
main { }
 
 


The data_slot.gph file contains your db data
Save this as "data_slot.gph":
Code: Select all
 
char *TriWeaponName[TRILIMIT] = {"Power Weapon 0: AR-Disabled","Power Weapon 1: Hawthornes Field-Forged Shotgun","Power Weapon 2: Gunnoras Axt","Power Weapon 3: Undefined","Power Weapon 4: Undefined","Power Weapon 5: Undefined"};
const fix32 triyRecoilvalue[TRILIMIT] = {0.0,45.0,45.0,0.0,0.0};
const fix32 trixRecoilvalue[TRILIMIT] = {0.0,0.0,0.0,0.0,0.0};
const bool triRapidfiremodevalue[TRILIMIT] = {0,1,0,0,0};
const uint16 triShotHoldTimeValue[TRILIMIT] = {0,334,0,0,0};
const uint16 triShotWaitTimeValue[TRILIMIT] = {0,334,0,0,0};
const uint16 triWeaponReloadTimeValue[TRILIMIT] = {2500,2500,2500,2500,2500};
 


You now should have the files all in the same directory:
share.gph
main_slot.gpc
data_slot.gpc
data_slot.gph

Put the script "main_slot.gpc" into one slot , the "data_slot.gpc" in another slot of your T2.
Use the Interactive Configuration to configure the main_slot to point to the slot of the data_slot and vice versa.
The T2 will blink red if you skip this step.

Load the main_slot.
Holding L2/LT and pressing dpad-right will change the datablock to load +1 and dpad-left -1 (no printf output for this).
Pressing R3/RS will load the data script, write the datablock to pmem space of the main script and switches back to the main script. It will only load the data script if the selected data block isn't already loaded.

If you don't want to use the Interactive Configuration you have to hard code the slot positions so you would only be able to use the script when they are placed at the correct slot.
User avatar
Scachi
Brigadier General
Brigadier General
 
Posts: 3044
Joined: Wed May 11, 2016 6:25 am
Location: Germany

Re: Multi_Slot_Example Code

Postby monty34 » Sat Jul 28, 2018 12:26 pm

Thank you very much for this detailed explanation. It works like a charme :smile0203: :smile0517: :smile0203:

I have just two questions

1) After i change the trirecoilmode and confirm it with RS, i would like to Printf also the weapon name saved in the data_slot.gph file. Which byteoffset i´ve to use for char variables?

Code: Select all
char *TriWeaponName[TRILIMIT] = {"Power Weapon 0: AR-Disabled","Power Weapon 1: Hawthornes Field-Forged Shotgun","Power Weapon 2: Gunnoras Axt","Power Weapon 3: Undefined","Power Weapon 4: Undefined","Power Weapon 5: Undefined"};


2) What´s the background and function of "TRILIMT 4"?
User avatar
monty34
Command Sergeant Major
Command Sergeant Major
 
Posts: 165
Joined: Wed Jun 28, 2017 7:25 pm

Next

Return to User's Script Documentation

Who is online

Users browsing this forum: No registered users and 92 guests