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 - eri0o

#2841
Thanks for the write up Fitz, I really liked reading through. And thanks for the how you did the cat eye pupils, that was very interesting :] Lots of ideas for cutscenes now. (laugh)
#2842
This is amazing. I love this. Is there any part of the code where you did a smart trick to get a specific effect, that would be cool to mention? And when developing, how did you go to not have to play whatever you developed before over and over?
#2843
Hey @Eric Matyas! I love your Virtual Cinema, with the ocean. If you ever have time, can you do some quick panoramic shoots of cityscapes? Thanks :]
#2844
Thinking about the Blue Cup as an actual item in game, or maybe some item in the background.

What uses would you guys give to it in game, or what have you seem done in a game? :)

Edit: Well, this is actually a topic for Adventure Related Talk & Chat, can't find the delete button...
#2845
AGS Games in Production / Re: Future Flashback
Sun 29/10/2017 15:25:37
Hey thanks ClickClickClick and Cassiebsg! About the nitpick, I agree with you, I did a small adjustment... :-\

Spoiler
[close]
#2846
AGS Games in Production / Re: Future Flashback
Sat 28/10/2017 21:45:10
Theme music updated!

Hey small update, just wanted to show the Title Screen with the new version of the theme music. If anyone has the habit of listening to music through YouTube on TV, you may want to listen to the following video.

If you haven't subscribed, please do, if we get to 100 subscribers we can have a proper channel URL. 8-)


#2847
Question, does tween module and timer module expose the loopcounter they use? I guess they would also be important to save - just remembered I use both with GUIs in lots of room puzzles.

I wouldn't mind saving stuff like isWalking, but stuff like this usually isn't writable, so they wouldn't be recoverable.

I like your approach Snarky.
#2848
Hey Monsieur OUXX, the goal isn't being able to survive AGS upgrades, this goal is already achieved by the current implementation. The goal would be surving additional content or bugfix for the Game (made in AGS).
#2849
I remember RPGMaker2000 having a big table of numbers and you would take stuff from this predefined table, so everything, even variables, had a fixed id.

Maybe if ints, floats and Strings also had a saveable_int type for instance, where you pass an additional index on creation to use as id? So only specified variables would be saved. I know this is maybe a bad idea, but I am thinking that maybe there would be a way to autofill this table with ids and not use previously used id even if variable is removed from script.
#2850
I don't understand why not restart game and once it starts it checks if it's expected to load a save or just go on.
#2851
Hey Crimson Wizard, this is a good read. My idea to do it as module was: I feel in the AGS community today more people are knowledgeable in AGS Script than C, and have it easily transferable to existing games. But if there is existing code for this in C, this is definitely something worth investigating.

One thing, if I understood, you said that object.ID==i isn't always true, and so matching would require checking object.ID==save_object[j].ID (for all positive integers i and j smaller than MAX_OBJECT) ?

I didn't understand what a reflection mechanism means.

I will take a look on this at night, right now I am not on my computer and the necessary tasks are looking too abstract, I am not sure on the atomic tasks necessary.
#2852
@Monsieur OUXX, I have no idea of how hard this is, I just stated that for updating the game (without taking all the cares listed in this thread), the only way around I saw was to implement something.

I started a discussion thread with some code here, maybe someone who has done this can shed a light.
#2853
Hey,

I have no idea if this is possible to do, the idea would be to create a module to do a custom save game. I will start the thread with some incomplete code (I have no idea how to read and parse yet) to try to gasp what's doable. Also I am looking into the most generic as possible code so the most people can benefit from it.

My design idea would be having an object to hold all rooms information, and update it when the player visits the room. Also have other object to hold other relevant information - I think this is maybe not needed but I like to have it clear which kind of thing is available to be saved. These objects would have handler to convert then to String and also have some way to parse a text file, and find the objects and recover then.

Also it would be necessary to have a way to store global variables - this would mean that for this to work, all room variables would be global, and on room variable state would be discouraged. I have no idea how to go on this.

A plus idea would be some form of text compression before storage and decompression after reading - nothing fancy, stuff as light as text compression on SNES cartridges.

PortableSaveGame.asc
Spoiler
Code: ags

// new module script
#define MAX_REGIONS 15
#define MAX_HOTSPOTS 49
#define MAX_POSSIBLE_ROOMS 100
#define MAX_POSSIBLE_CHARACTERS 100

struct RoomSaveData{
  bool exists;
  bool load_from_save;
  int ObjectCount;
  bool object_isnull[MAX_ROOM_OBJECTS];
  int object_X[MAX_ROOM_OBJECTS];
  int object_Y[MAX_ROOM_OBJECTS];
  bool object_Visible[MAX_ROOM_OBJECTS];
  bool object_Clickable[MAX_ROOM_OBJECTS];
  int object_Transparency[MAX_ROOM_OBJECTS];
  int object_Graphic[MAX_ROOM_OBJECTS];
  int object_View[MAX_ROOM_OBJECTS];
  int object_Loop[MAX_ROOM_OBJECTS];
  int object_Frame[MAX_ROOM_OBJECTS];
  bool hotspot_Enabled[MAX_HOTSPOTS];
  bool region_Enabled[MAX_REGIONS];
};

struct CharacterSaveData{
  bool exists;
  String Name;
  int Room;
  int x;
  int y;
  int z;
  int Transparency;
  bool Clickable;
  int View;
  int Frame;
  int Loop;
  int inventoryQuantity[MAX_GAME_ITEMS];
};

struct GameSaveData{
  int character_count;
  int invetoryitem_count;
  int player_ID;
};


GameSaveData save_data_game;
RoomSaveData save_data_rooms[MAX_POSSIBLE_ROOMS];
CharacterSaveData save_data_charas[MAX_POSSIBLE_CHARACTERS];

//------------------------------------------------------------------------
// PRIVATE FUNCTIONS
//-------o-----------------------------------------------------------------
void storeCharacterData(){
  int i;
  int j;
  i=0;
  save_data_game.character_count = Game.CharacterCount;
  save_data_game.invetoryitem_count = Game.InventoryItemCount+1;
  save_data_game.player_ID = player.ID;
  
  while(i<save_data_game.character_count){
    if(character[i]!=null){
      save_data_charas[i].exists=true;
      save_data_charas[i].Name = character[i].Name;
      save_data_charas[i].Room = character[i].Room;
      save_data_charas[i].x = character[i].x;
      save_data_charas[i].y = character[i].y;
      save_data_charas[i].z = character[i].z;
      save_data_charas[i].Transparency = character[i].Transparency;
      save_data_charas[i].Clickable = character[i].Clickable;
      save_data_charas[i].View = character[i].View;
      save_data_charas[i].Frame = character[i].Frame;
      save_data_charas[i].Loop = character[i].Loop;
      j=1;
      while(j<save_data_game.invetoryitem_count){
        save_data_charas[i].inventoryQuantity[j] = character[i].InventoryQuantity[j];
        j++;
      }
    } else {
      save_data_charas[i].exists=false;
    }
    
    i++;
  }
}

String CharacterSaveData_toString(){
  String rstr="{\"characters\": {[";
  int i;
  int j;
  i=0;
  while(i<save_data_game.character_count){
    if(save_data_charas[i].exists){
      rstr=rstr.Append(String.Format("  \"%d\":{[",i));
      rstr=rstr.Append(String.Format("    \"exists\": %d,[",save_data_charas[i].exists));
      rstr=rstr.Append(String.Format("    \"Name\": \"%s\",[",save_data_charas[i].Name));
      rstr=rstr.Append(String.Format("    \"Room\": %d,[",save_data_charas[i].Room));
      rstr=rstr.Append(String.Format("    \"x\": %d,[",save_data_charas[i].x));
      rstr=rstr.Append(String.Format("    \"y\": %d,[",save_data_charas[i].y));
      rstr=rstr.Append(String.Format("    \"z\": %d,[",save_data_charas[i].z));
      rstr=rstr.Append(String.Format("    \"Transparency\": %d,[",save_data_charas[i].Transparency));
      rstr=rstr.Append(String.Format("    \"Clickable\": %d,[",save_data_charas[i].Clickable));
      rstr=rstr.Append(String.Format("    \"View\": %d,[",save_data_charas[i].View));
      rstr=rstr.Append(String.Format("    \"Frame\": %d,[",save_data_charas[i].Frame));
      rstr=rstr.Append(String.Format("    \"Loop\": %d,[",save_data_charas[i].Loop));
      
      
      rstr=rstr.Append(String.Format("    \"inventoryQuantity\":{["));
      j=1;
      while(j<save_data_game.invetoryitem_count-1){
        rstr=rstr.Append(String.Format("      \"%d\": %d,[",j, save_data_charas[i].inventoryQuantity[j]));
        j++;
      }
      rstr=rstr.Append(String.Format("      \"%d\": %d[",j, save_data_charas[i].inventoryQuantity[j]));
      
      rstr=rstr.Append(String.Format("    }[  },["));
    }
    i++;
  }
  rstr=rstr.Append(String.Format("    }[  }["));
  return rstr;
}

void storeCurrentRoomData(){
  int i;
  int r = player.Room;
  save_data_rooms[r].load_from_save = false;
  save_data_rooms[r].exists = true;
  save_data_rooms[r].ObjectCount = Room.ObjectCount;
  i=0;
  while(i<save_data_rooms[r].ObjectCount){
    if(object[i] != null){
      save_data_rooms[r].object_isnull[i] = false;
      save_data_rooms[r].object_X[i] = object[i].X;
      save_data_rooms[r].object_Y[i] = object[i].Y;
      save_data_rooms[r].object_Visible[i] = object[i].Visible;
      save_data_rooms[r].object_Clickable[i] = object[i].Clickable;
      save_data_rooms[r].object_Transparency[i] = object[i].Transparency;
      save_data_rooms[r].object_Graphic[i] = object[i].Graphic;
      save_data_rooms[r].object_View[i] = object[i].View;
      save_data_rooms[r].object_Loop[i] = object[i].Loop;
      save_data_rooms[r].object_Frame[i] = object[i].Frame;
    }  else {
      save_data_rooms[r].object_isnull[i] = true;
    }
    i++;
  }
  
  i=0;
  while(i<MAX_HOTSPOTS){
    save_data_rooms[r].hotspot_Enabled[i] = hotspot[i].Enabled;
    i++;
  }
  
  i=0;
  while(i<MAX_REGIONS){
    save_data_rooms[r].region_Enabled[i] = region[i].Enabled;
    i++;
  }
}

String RoomSaveData_toString(){
  String rstr="{\"rooms\": {[";
  int i;
  int j;
  i=0;
  while(i<MAX_POSSIBLE_ROOMS){
    if(save_data_rooms[i].exists){
      rstr=rstr.Append(String.Format("  \"%d\":{[",i));
      rstr=rstr.Append(String.Format("    \"exists\": %d,[",save_data_rooms[i].exists));
      rstr=rstr.Append(String.Format("    \"load_from_save\": \"%d\",[",save_data_rooms[i].load_from_save));
      rstr=rstr.Append(String.Format("    \"ObjectCount\": \"%d\",[",save_data_rooms[i].ObjectCount));
      
      
      rstr=rstr.Append(String.Format("    \"objects\":{["));
      j=0;
      while(j<save_data_rooms[i].ObjectCount){
        rstr=rstr.Append(String.Format("      \"%d\": {",j));
        
        rstr=rstr.Append(String.Format("        \"isnull\": %d,[", save_data_rooms[i].object_isnull[j]));
        rstr=rstr.Append(String.Format("        \"X\": %d,[", save_data_rooms[i].object_X[j]));
        rstr=rstr.Append(String.Format("        \"Y\": %d,[", save_data_rooms[i].object_Y[j]));
        rstr=rstr.Append(String.Format("        \"Visible\": %d,[", save_data_rooms[i].object_Visible[j]));
        rstr=rstr.Append(String.Format("        \"Clickable\": %d,[", save_data_rooms[i].object_Clickable[j]));
        rstr=rstr.Append(String.Format("        \"Transparency\": %d,[", save_data_rooms[i].object_Transparency[j]));
        rstr=rstr.Append(String.Format("        \"Graphic\": %d,[", save_data_rooms[i].object_Graphic[j]));
        rstr=rstr.Append(String.Format("        \"View\": %d,[", save_data_rooms[i].object_View[j]));
        rstr=rstr.Append(String.Format("        \"Loop\": %d,[", save_data_rooms[i].object_Loop[j]));
        rstr=rstr.Append(String.Format("        \"Frame\": %d,[", save_data_rooms[i].object_Frame[j]));
        
        if(j<save_data_rooms[i].ObjectCount-1){
          rstr=rstr.Append(String.Format("      },"));
        } else {
          rstr=rstr.Append(String.Format("      }"));
        }
        j++;        
      }
      rstr=rstr.Append(String.Format("    },"));
      
      
      rstr=rstr.Append(String.Format("    \"regions\":{["));
      j=0;
      while(j<MAX_REGIONS){
        rstr=rstr.Append(String.Format("      \"%d\": {  \"Enabled\": %d }, [",j,save_data_rooms[i].region_Enabled[j]));
        j++;
      }
      rstr=rstr.Append(String.Format("    },"));
      
     
      rstr=rstr.Append(String.Format("    \"hotspot\":{["));
      j=0;
      while(j<MAX_HOTSPOTS){
        rstr=rstr.Append(String.Format("      \"%d\": {  \"Enabled\": %d }, [",j,save_data_rooms[i].hotspot_Enabled[j]));
        j++;
      }
      rstr=rstr.Append(String.Format("    },"));
      
    }
    i++;
  }
  rstr=rstr.Append(String.Format("  }[}["));
  return rstr;
  
}

void storeCurrentData(){
  storeCharacterData();
  storeCurrentRoomData();
}

void writeToFile(String content, String filename){
  File *output = File.Open(filename, eFileWrite);
  if (output == null) {
    Display("Error opening file.");
  } else {
    String lineToWrite;
    String restOfContent;
    
    restOfContent = content.Copy();
    
    while(restOfContent.Length > 0 && restOfContent.IndexOf("[")>0){
      lineToWrite = restOfContent.Substring(0, restOfContent.IndexOf("["));
      restOfContent = restOfContent.Substring(restOfContent.IndexOf("[")+1, restOfContent.Length- restOfContent.IndexOf("[")-1);
      output.WriteRawLine(lineToWrite);
    }
    
    
    output.Close();
  }
}

String readFile(String filename){
  
}


//------------------------------------------------------------------------
// PUBLIC FUNCTIONS
//------------------------------------------------------------------------
static void PortableSaveGame::save(int slot, String description){
  storeCurrentData();
  String fstr;
  fstr=CharacterSaveData_toString();
  fstr=fstr.Append(RoomSaveData_toString());
  writeToFile(fstr, "atemp.json");
}

static void PortableSaveGame::restore(int slot){
  
}

//------------------------------------------------------------------------
//
//------------------------------------------------------------------------
function on_event (EventType event, int data)
{
  if(event == eEventLeaveRoom){
    storeCurrentRoomData();
  } else if(event == eEventEnterRoomBeforeFadein){
    //do necessary loading from save
  }
}
[close]

PortableSaveGame.ash
Spoiler
Code: ags

struct PortableSaveGame{
  import static void save(int slot, String description);
  import static void restore(int slot);
};
[close]

#2854
Thank you all for all the insightful ideas. I like the being able to click on each side and arrow indications on cursor - my box is actually a hospital bed with wheels, so the gesture idea doesn't work as great, but I will have this idea in mind for other things.

One question, I usually have lots of "how to design x" questions when I am making a game, does these type of questions belong here in the technical questions? (this a bit offtopic but I am not sure where to go for these meta questions).
#2855
AGS Games in Production / Re: Unavowed
Tue 24/10/2017 23:14:39
Hey Dave! Lovely art! This is beautiful. I love this!

I have some minor things I noticed, since they will be shown only once and quick in the game, they are very minor and probably a bad return on investment to pursue. But still, thought would mention.

The first shot, the rain though looks a bit wrong? This is a quick reverse close-up from Singing in the Rain (around 1:42). In the gif the rain is falling from up to down, but from the angle the rain looks to be going horizontal, instead the drops should falling in front of the camera.

I love the train and the dude meditating.

On the last shot, I don't know how you are doing the panning, but in the gif the movement doesn't look smooth. If the game is 60fps and you are tweening y position of the objects/GUIs it will probably look smooth, but in the gif it doesn't look smooth.
#2856
Hey Wyz, found a repo in github that may contain interesting code github.com/ThemsAllTook/libstem_gamepad

my storage suggestion is Google Drive if you already have gmail.
#2857
A* (a star) pathfinding isn't impossible to implement, you could do your own algorithm, which means you would also need to take care of the walking animation for your character. There are lots of resources on the subject online. It will probably eat you two weeks on development.
#2858
For which part, the save or the distrbution platform? If you are going for Steam as distribution platform read the Steam Developer documentation. For the save part I advise you to ask around since I haven't tried it myself.
#2859
Hey,

There's a scene where we wanted our character to push a box, which he will use to climb on top and reach something that's normally out of reach. How would you design such a scene? Our first design idea is that interacting with the box reveals a GUI with forward and backward arrows.
#2860
The distribution platform you are making your game available can usually handle this, but you are probably going to need to implement your own save module since the save game as is usually breaks when you update an existing room.
SMF spam blocked by CleanTalk