Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - Monsieur OUXX

#261
I'm still interested in the MacOS executable though, even with the colors issue  :=
I can act as a tester if you guys wish.
#262
In case I didn't make it clear, I'm trying to address my needs with my own hacky solutions precisely because I know you're already giving 200% to AGS and it would not be very sport to whine to you about what I consider missing features. Or at least more than once a year ;) the flow of releases is already outstanding for an open-source project of this size.

Leave this be for now.
#263
Well you do have the C++ experience and the understanding of the AGS virtual instructions that I'm lacking to implement an actual Array object, or to allow managed structs inside managed structs. But you said that an actual object for dynamic arrays was not really needed. Verbatim. You gave me that standard C++ talk of "there are so many ways of implementing arrays of arrays if you're smart".
I tried fixing AGS it in C++ several times, but never got to the point where I understood its virtual memory space well enough. Then my last resort is to address my needs in native AGS.
#264
Quote from: Crimson Wizard on Wed 13/05/2020 15:02:13
I would just write a narrow specialized type meant to be used with dedicated functions
That's the complicated stuff. Hundreds and hundreds of copy-and-paste of the same array allocation and deallocation, over the last 15 years. The thing is that people who come from the C++ and C world are so used to it that they don't see it anymore. They accept that 90% of any code is "allocate array, expand array, insert item into array, remove item from array, shrink array". I haven't given up yet.

Anyways I got my answer. The idea of making the reference a managed type clears 90% of the question. Thanks, guys.
#265
Quote from: Crimson Wizard on Wed 13/05/2020 14:38:02
Quote from: Monsieur OUXX on Wed 13/05/2020 14:32:07
managed struct Pointer {
  DynamicSprite* someCompositeDataThatNeedsToHaveACustomDestructor;
};

You won't be able to do exactly this because AGS still does not allow managed pointers inside managed struct.
That was a shortcut. It would actually be the index of an element stored in an external array of managed structs. Therefore, an int.

Quote from: Crimson Wizard on Wed 13/05/2020 14:38:02
But still, what kind of actual object that needs custom destructor you are talking about? Can you give an actual example, allowing to understand why AGS's own garbage collection is not suitable?
How about this : An array of arrays of custom structs, each struct containing an array of arrays of int. All of that mess being represented only as ints (that int being the index in the actual array of structs, or array of ints, or array of arrays of ints) since, as you pointed out, AGS won't let you do any of that using pointers.
In other words : I want arbitrarily complex data structures, and I want automated garbage collection for them.
#266
How about this :

Code: ags

#define ArbitrarilyComplexType DynamicSprite*
#define ArbitrarilyComplexType_Index int

//Some basic array to store data externally, as AGS doesn't allow managed structs in managed structs
ArbitrarilyComplexType rawData[9999];

#define PointerType int

managed struct Pointer {
  PointerType ptrId;
  ArbitrarilyComplexType_Index someCompositeDataThatNeedsToHaveACustomDestructor;
};

Pointer* pointers[];


struct PtrFactory {
  import static PointerType Constructor(DynamicSprite* data);
  import static void Destructor(PointerType ptr);
};

PointerType PtrFactory::Constructor(DynamicSprite* data)
{
  Pointer* p = new Pointer;
  pointers[index] = p; //(not detailed : create entry in array 'pointers' and get the index)
  p.ptrId = index;

  rawData[dataIndex] = data; //(not detailed : create entry in array 'rawData' ad get the index)
  p.someCompositeDataThatNeedsToHaveACustomDestructor = dataIndex;
  
  return p.ptrId;
}

void PtrFactory::Destructor(PointerType ptr)
{
  //Destructor stuff
  ArbitrarilyComplexType objectToDestroy = rawData[pointers[ptr].someCompositeDataThatNeedsToHaveACustomDestructor];
  objectToDestroy .Delete(); //Whatever needs to be done
  pointers[ptr].ptrId = -1;
  
  pointers[ptr] = null;
}

//////////////////////////////////

managed struct Reference {
  int count;
  PointerType ptr;
};

Reference* refs[];


struct RefFactory {
  import static Reference* CreateRef(PointerType ptr);
  import static void DestroyRef(Reference*);
  import static Reference* CopyRef(Reference*);
};

Reference* RefFactory::CreateRef(PointerType ptr)
{
  // find if there's a ref contining 'ptr' in 'refs'.
  if (yes) // increase count
    refs[existingRef].count ++;
    return refs[existingRef];
  if (not) //create new ref
    refs[newRef] = new Reference;
    refs[newRef].count = 1;
    refs[newRef].ptr = ptr;
    return refs[newRef];
}

void RefFactory::DestroyRef(Reference* ref)
{
  for (int i=0; i< refs.length; i++) {
    if (refs[i] == ref) {
      if (refs[i].count > 1) {
        refs[i].count--;
      } else if (refs[i].count == 1) {
        PtrFactory.Destructor(refs[i].ptr);
        refs[i].count = 0;
        refs[i] = null;
      } else { // 0
         AbortGame("All the references to that pointer have already been destroyed. Did you do an illegal copy, you punk?");
      }
    }
  }
}

Reference* RefFactory::CopyRef(Reference* ref)
{
  for (int i=0; i< refs.length; i++) {
    if (refs[i] == ref) {
      refs[i].count++;
      return refs[i];
    }
  }
  
  AbortGame("Cannot copy illegal reference");
}

/////////////////////////////////////////////////////////

void game_start() {
    DynamicSprite* someCompositeData = DynamicSprite.Create(); // In the final product, the user would not be allowed to manipulate pointers, they'd be given the factory to create references directly.
    PointerType ptr = PtrFactory.Constructor(someCompositeData);
    Reference* someLegalRef1 = RefFactory.CreateRef(ptr);
    Reference* someLegalRef2 = RefFactory.CreateRef(ptr);
    Reference* someLegalRef3 = RefFactory.CopyRef(someLegalRef2);
    
    Reference* someIllegalRef = someLegalRef1; //Allowed syntactically, but shady
    
    RefFactory.DestroyRef(someLegalRef1);
    RefFactory.DestroyRef(someLegalRef2);
    RefFactory.DestroyRef(someIllegalRef); // Will work because this is technically someLegalRef3. This calls the Destructor of ptr, as expected.
    RefFactory.DestroyRef(someLegalRef3); // Was already destroyed just before. Causes an AbortGame;
  
}



#267
Quote from: Snarky on Wed 13/05/2020 13:18:40
To be more explicit: the "references" could be instances of a managed type.

Are you saying it's not allowed to assign an instance of a managed type? If yes, then it's exactly the kind of syntactic trick I as looking for.


EDIT  I don't see how that addressed my issue :

Code: ags
managed struct Reference {
  int pointer;
};

Reference* ref1 = Factory.CreateReference(); //Side-note: What stops me from using "new" and messing up things?
Reference* ref2 = ref1 ; //I now have a copy out there in the wilderness and the garbage collector doesn't know about it.
#268
Yes, same. I want to control the number of references, in order to implement some sort of garbage collection. If the user copies the pointers around, then it breaks everything.
#269
OK bear with me here. I'm looking to imitate what's done in C++ with ptr_unique, except in AGS. More generally I want to control every time a certain type of variable gets assigned, i.e. potentially copied.

I'll start with the "forbid copy" case and work on the other cases later. The idea is that you have a variable of some type (it doesn't matter, it can be a custom type) and the developer just cannot copy it. He/she has to work with the original instance and copying it is illegal.

As a naive solution, I could do a #define ASSIGN MyCustomFunctionThatCreatesACopyOfThePointer. Then the syntax would be clunky, but work :
Code: ags

VariableType copy = ASSIGN(originalVariable);


However what bothers me is that I could still do an "=" by mistake if I'm distracted.
Code: ags

VariableType copy = originalVariable; //I want this to be forbidden


So, the riddle :
- Can you think of any sort of mechanism (Think out of the box!) that would force a copy, or an assignment to go through an exceptional function somehow? Let me worry about the implementation. I'm looking for a clever concept to ignite it. Aren't there some obscure types in AGS that you cannot assign? Views or whatnot.
#270
Quote from: Crimson Wizard on Fri 08/05/2020 10:29:24
So, we need to write a page in the manual explaining all this, ok.

I can write it if you give me hints, especially the first part regarding Linux. Or if you point me to the right post (the threads seem to talk mostly about compiling)(and weirdly the Linux thread stops at AGS 3.4)
#271
How I would proceed :
- clone the WoaMAGS repo somehwere on your hard drive
- Run the custom version of the Editor at least once to see if you visually spot the customizations. New native objects in the scripting language? New nodes in the editor? Maybe try to identify what is now natively offered in AGS 3.5 since AGS 3.3. Do you need any of that?
- clone the AGS 3.5.0.x repo
- find a way of comparing the to repos (I don't think you can do a merge because the WoaMAGS is no longer a branch of AGS, but you can find tools that do recursive diffs on all the files of all the subfolders)
- Assert the degree of customization. Compare with what you saw in step #2. My guess : They mostly added stuff. And wherever they did that, it's probably easy to spot and see how it's still relevant in 3.5.
- Do the merge.
- Enjoy AGS 3.5.0 on Linux
- You won't need to keep up with the newer version of AGS before quite some time, and even if you do, now that you've upgraded to 3.5 you'll probably only need to do a merge from master from tie to time in order to upgrade.
#273
Hello,

I've got this : https://github.com/adventuregamestudio/ags/releases/tag/v.3.5.0.24
On that page I can download ready-to-use stuff like : AGS-3.5.0.24-android-libs.zip, ags_3.5.0.24_linux.tar.gz

If I understand properly, everything else is for debug (in particular : AGS-3.5.0.24-debug.apk, AGS-3.5.0.24-pdb.zip)

My questions :
a) Does ags_3.5.0.24_linux.tar.gz contain the executables of the engine, and, if yes, are these the same as in the "Linux" subfolder of the AGS engine, and if yes, do I just need to copy that alongside the .ags file to make it work? (no need to detail the procedure, I just need a theoretical "yes"). Do I need to provide the compiled libraries too (allegro, etc.)
b) Similarly, does AGS-3.5.0.24-android-libs.zip contain the executables of the engine? If not, do I also need AGS-3.5.0.24-debug.apk? (which would surprise me as it sounds like a debug package). Talk to me like a 5-years-old, as my understanding of phones goes as far as APK GOOD, APK BE LIKE EXE or YOU SCREWED ANYWAYS BECAUSE YOU NO HAVE CERTIFICATE.

#274
Time to beg!  :=
Do you think you guys could upload the 3.5.0.x engine executable for MacOS somewhere? And since you're there, maybe also the Linux one? (I'm guessing they're not too different but maybe I'm wrong).
Asking for my personal sanity. The learning curve for compiling on Mac is just too much.
#275
A small improvement but very convenient :

VerbsGui.ash

Code: ags

enum eObjectType {
  eGizmo, //use this type for regular-sized objects. Usually, objects that the player could physically pick up but doesn't need.
  eHeavy,  //use this type for objects that are too heavy to pickup/push/pull
  eCharacter, //appropriate responses to silly attempts like "opening" a human being.
  eDoor //similar to eHeavy but slightly more specific in regards to open/close/use
};

  // START MODIFICATION
  //import static void Unhandled(int door_script=0);
  import static void Unhandled(eObjectType objType = eGizmo,  int door_script=0); //I've put the new parameter first because you use it much more often
  // END



VerbsGui.asc
Code: ags

// START MODIFICATION
//static void Verbs::Unhandled(int door_script) 
static void Verbs::Unhandled(eObjectType objType, int door_script) 
// END
{


Then of course don't forget to update any call to Verbs.Unhandled in the template. When in doubt use eGizmo.
And of course don't forget to add all the new strings to verbsData.unhandled_strings. To sort them easily, you may get inspiration from these values :

Your own module
Code: ags

bool moduleInitialized = false;


String defaultSentence_Pull     ;
String defaultSentence_Push     ;
String defaultSentence_Give     ;
String defaultSentence_Interact ;
String defaultSentence_Look     ;
String defaultSentence_PickUp   ;
String defaultSentence_Talk     ;
String defaultSentence_UseInv   ;
String defaultSentence_Open     ;
String defaultSentence_Close    ;


function InitializeModule() {

  //unfortunately AGS script does not allow to initialize a default
  //String's value at declaration. We are forced to do it here
  
  //universal sentences for any object in the entire game
  defaultSentence_Pull     = "I can't pull that.";
  defaultSentence_Push     = "I can't push that.";
  defaultSentence_Give     = "That just won't work.";
  defaultSentence_Interact = "I don't know what to do.";
  defaultSentence_Look     = "I see nothing special about it.";
  defaultSentence_PickUp   = "Why would I want to pick that up?";
  defaultSentence_Talk     = "I shouldn't start talking to things.";
  defaultSentence_UseInv   = "That won't work.";
  defaultSentence_Open     = "I can't open that.";
  defaultSentence_Close    = "I can't close that."; 
    
  moduleInitialized = true; //make sure we don't call it again
}


//makes sure that all the relevant module stuff is initialized
function checkInitialized() {
   //at first call
  if (!moduleInitialized) 
    InitializeModule();
  
}

String FindWontWorkSentence() {
  String wontWork[10];
  wontWork[0] = "That won't work.";
  wontWork[1] = "I don't think that will work.";
  wontWork[2] = "Nu-uh.";
  wontWork[3] = "No.";
  wontWork[4] = "Nope.";
  wontWork[5] = "That's silly.";
  wontWork[6] = "Why would I try that?";
  wontWork[7] = "I'll have to think of something more useful.";
  wontWork[8] = "No way.";
  wontWork[9] = "I can't figure it out.";  
  
  return wontWork[Random(9)];
}


String FindWontGiveSentence() {
  String wontGive[4];
  wontGive[0] = "I'd rather keep that to myself.";
  wontGive[1] = "I won't give that away.";
  wontGive[2] = "Bad idea.";
  wontGive[3] = "Let's keep that to myself.";
  
  return wontGive[Random(3)];
}

String Sentence(Action_7CoG mode, eObjectType objectType) {
  checkInitialized();
  
  String sentence = "ERROR : no sentence returned.";
  
  if (objectType == eGizmo) { //See the definition of "eGizmo" in the Enum declaration
    if (mode == eGA_7CoG_Pull) sentence = defaultSentence_Pull;               //Pull
    else if (mode == eGA_7CoG_Push) sentence = defaultSentence_Push;          //Push
    else if (mode == eGA_7CoG_GiveTo) sentence = FindWontGiveSentence();          // Give
    else if (mode == eGA_7CoG_Use) sentence = FindWontWorkSentence();  // Interact
    else if (mode == eGA_7CoG_LookAt) sentence = defaultSentence_Look;        // Look
    else if (mode == eGA_7CoG_PickUp) sentence = "I don't need that.";        // Pickup
    else if (mode == eGA_7CoG_TalkTo) sentence = defaultSentence_Talk;        // Talk
    else if (mode == eGA_7CoG_UseInv) sentence = FindWontWorkSentence();      // Useinv   
    else if (mode == eGA_7CoG_Open) sentence = defaultSentence_Open;          // Useinv   
    else if (mode == eGA_7CoG_Close) sentence = defaultSentence_Close;        // Useinv  
    else sentence = String.Format("Unknown mode : %d",mode);
  } else if   (objectType == eHeavy) { //See the definition of "eHeavy" in the Enum declaration
    if (mode == eGA_7CoG_Pull) sentence = "It's too heavy to pull it";                  //Pull
    else if (mode == eGA_7CoG_Push) sentence = "It's too heavy to push it";             //Push
    else if (mode == eGA_7CoG_GiveTo) sentence = FindWontGiveSentence();                    // Give
    else if (mode == eGA_7CoG_Use) sentence = "Let it be.";                        // Interact
    else if (mode == eGA_7CoG_LookAt) sentence = defaultSentence_Look;                  // Look
    else if (mode == eGA_7CoG_PickUp) sentence = "I can't pick up something that big!"; // Pickup
    else if (mode == eGA_7CoG_TalkTo) sentence = defaultSentence_Talk;                  // Talk
    else if (mode == eGA_7CoG_UseInv) sentence = defaultSentence_UseInv;                // Useinv   
    else if (mode == eGA_7CoG_Open) sentence = defaultSentence_Open;                    // Useinv   
    else if (mode == eGA_7CoG_Close) sentence = defaultSentence_Close;                  // Useinv   
    else sentence = String.Format("Unknown mode : %d",mode); 
  } else if   (objectType == eCharacter) { //See the definition of "eHeavy" in the Enum declaration
    if (mode == eGA_7CoG_Pull) sentence = "Violence is not a solution here.";               //Pull
    else if (mode == eGA_7CoG_Push) sentence = "I don't just push people around.";          //Push
    else if (mode == eGA_7CoG_GiveTo) sentence = FindWontGiveSentence();                      // Give
    else if (mode == eGA_7CoG_Use) sentence = "I don't randomly touch people.";        // Interact
    else if (mode == eGA_7CoG_LookAt) sentence = defaultSentence_Look;                      // Look
    else if (mode == eGA_7CoG_PickUp) sentence = "Yes, why don't I just carry everybody around on my back?";      // Pickup
    else if (mode == eGA_7CoG_TalkTo) sentence = defaultSentence_Talk;                      // Talk
    else if (mode == eGA_7CoG_UseInv) sentence = defaultSentence_UseInv;                    // Useinv   
    else if (mode == eGA_7CoG_Open) sentence = "You mean, open that person with a knife or something?";      // Useinv   
    else if (mode == eGA_7CoG_Close) sentence = "That doesn't make sense.";                 // Useinv   
    else sentence = String.Format("Unknown mode : %d",mode);
  } else if   (objectType == eDoor) { //See the definition of "eDoor" in the Enum declaration
    if (mode == eGA_7CoG_Pull) sentence = "It's too heavy to pull it";                  //Pull
    else if (mode == eGA_7CoG_Push) sentence = "It's too heavy to push it";             //Push
    else if (mode == eGA_7CoG_GiveTo) sentence = FindWontGiveSentence();                    // Give
    else if (mode == eGA_7CoG_Use) sentence = "Let it be.";                        // Interact
    else if (mode == eGA_7CoG_LookAt) sentence = defaultSentence_Look;                  // Look
    else if (mode == eGA_7CoG_PickUp) sentence = "I can't pick up something that big!"; // Pickup
    else if (mode == eGA_7CoG_TalkTo) sentence = defaultSentence_Talk;                  // Talk
    else if (mode == eGA_7CoG_UseInv) sentence = defaultSentence_UseInv;                // Useinv   
    else if (mode == eGA_7CoG_Open) sentence = defaultSentence_Open;                    // Useinv   
    else if (mode == eGA_7CoG_Close) sentence = defaultSentence_Close;                  // Useinv   
    else sentence = String.Format("Unknown mode : %d",mode); 
  } else { //the most possible generic sentences
    if (mode == eGA_7CoG_Pull) sentence = defaultSentence_Pull;               //Pull
    else if (mode == eGA_7CoG_Push) sentence = defaultSentence_Push;          //Push
    else if (mode == eGA_7CoG_GiveTo) sentence = FindWontGiveSentence();          // Give
    else if (mode == eGA_7CoG_Use) sentence = defaultSentence_Interact;  // Interact
    else if (mode == eGA_7CoG_LookAt) sentence = defaultSentence_Look;        // Look
    else if (mode == eGA_7CoG_PickUp) sentence = FindWontWorkSentence();      // Pickup
    else if (mode == eGA_7CoG_TalkTo) sentence = defaultSentence_Talk;        // Talk
    else if (mode == eGA_7CoG_UseInv) sentence = FindWontWorkSentence();      // Useinv   
    else if (mode == eGA_7CoG_Open) sentence = defaultSentence_Open;          // Useinv   
    else if (mode == eGA_7CoG_Close) sentence = defaultSentence_Close;        // Useinv   
    else sentence = String.Format("Unknown mode : %d",mode);
  }
  
  return sentence;
}




#276
A minor bug in the custom dialogs : There's no "scroll to top" after selecting a dialog option. Which means that if you click on, let's say, option 5, then the next time some options are displayed they will still be scrolled down. It's a bit awkward.

I fixed it like this (by the way, somehow the RunActiveOption was filtered out for the mouse wheel scrolling but not the plain old mouse click scrolling. I changed that too)

Code: ags

function dialog_options_mouse_click(DialogOptionsRenderingInfo *info, MouseButton button)
{

  CDG_Arrow uparrow;
  CDG_Arrow downarrow;
  int i;

  // Up-Arrow coordinates
  uparrow.x1 = info.X + CDG_options.uparrow_xpos;
  uparrow.y1 = info.Y + CDG_options.uparrow_ypos ;
  uparrow.x2 = uparrow.x1 + Game.SpriteWidth[CDG_options.uparrow_img];
  uparrow.y2 = uparrow.y1 + Game.SpriteHeight[CDG_options.uparrow_img];

  // Down-Arrow coordinates
  downarrow.x1 = info.X + CDG_options.downarrow_xpos;
  downarrow.y1 = info.Y + CDG_options.downarrow_ypos ;
  downarrow.x2 = downarrow.x1 + Game.SpriteWidth[CDG_options.downarrow_img];
  downarrow.y2 = downarrow.y1 + Game.SpriteHeight[CDG_options.downarrow_img];
  
//MODIFIED BY SEVEN CITIES - START
  bool isClickScrollUp = ((mouse.x >= uparrow.x1 && mouse.y >= uparrow.y1) &&
                         (mouse.x <= uparrow.x2 && mouse.y <= uparrow.y2))||
                         (button == eMouseWheelNorth && CDG_options.mousewheel);
       
  bool isClickScrollDown = ((mouse.x >= downarrow.x1 && mouse.y >= downarrow.y1) &&
                          (mouse.x <= downarrow.x2 && mouse.y <= downarrow.y2)) ||
                          (button == eMouseWheelSouth && CDG_options.mousewheel);
//MODIFIED BY SEVEN CITIES - END

  // scroll up
  if (isClickScrollUp) {
        i=0;
        
        while (i<CDG_options.scroll_rows)
        {
          if (CDG_options.scroll_from >1) CDG_options.scroll_from --;
          dialog_options_render(info);          
          i++;
        }
  } 
  // scroll down
  else if (isClickScrollDown) {
      
      i=0; 
      while (i<CDG_options.scroll_rows)
      {      
        if (CDG_options.scroll_to != CDG_options.active_options_count-1) {
          dialog_options_render(info); 
          CDG_options.scroll_from ++;
        }
        i++;
      }
  }

  info.Update();
  
  
//MODIFIED BY SEVEN CITIES - START
  //if (button != eMouseWheelSouth && button != eMouseWheelNorth) info.RunActiveOption();
  
  if (!isClickScrollDown && !isClickScrollUp){
    CDG_options.scroll_from = 0; // Scroll to top
    info.Update();
    info.RunActiveOption();
  }
  
//MODIFIED BY SEVEN CITIES - END
}

#277
Encoding issue.

So, I know that the .TRS of AGS are supposed to be ANSI. But somehow at some point I f***ed up and my file probably did a little trip to UTF-8 and back.
And now it's "corrupt".

Consider this as a riddle :

My file contains this sequence of characters (in hexadecimal ) :  EF BF BD and I know for a fact that it's supposed to be Ö (capital ö, decimal ascii : 214)

Can you :
- find an automated process to restore it properly to ANSI? (at the moment I cant figure out how to display it as Ö even by toying around with the encodings) (by automated, I mean fix an entire file with just a few clicks in Notepad++ or Visual Studio Code or whatnot)
- maybe guess what bad encoding/actions could have led to the faulty encoding? (so that I don't do it again). Did I do that by saving an ANSI file to UTF8?


=== EDIT ===

So apparently I have this issue : https://www.w3.org/International/questions/qa-utf8-bom.en.html
I'm still not sure what I did wrong, or how to fix it.


=== EDIT ===

I've given up and luckily found a backup.
On a general note I think the TRS files should now be UTF-8 from the start, and then throw an error message at translation-compile time if they contain a character that's too fancy.
#278
Has something changed with the encoding of translation files between 3.4.x and 3.5.0 patch 2? All my special characters in all my translations (French, Italian , Spanish...) are now displayed as several random characters. For example, è is now displayed as ï¿Ö even though I do have è in my font. Did we switch to full-blown Unicode or something?
#279
May I suggest that you put the recorded video in the very first post?
#280
Beginners' Technical Questions / Greek font?
Sun 05/04/2020 22:08:35
Anyone knows if there's a pixel font in Greek?
We would use both for dialogs and the GUI, so it would need to be about the same size as the default AGS in-game font.
We'd use automated outline, so no sweat on that side of business.
SMF spam blocked by CleanTalk