Go Back   The PokéCommunity Forums > ROM Hacking > Research & Development

Notices
For all updates, view the main page.

Research & Development Got a well-founded knack with ROM hacking? Love reverse-engineering the Pokémon games? Or perhaps you love your assembly language. This is the spot for polling and gathering your ideas, and then implementing them! Share your hypothesis, get ideas from others, and collaborate to create!
Research & Development programs in this forum are subject to moderator approval before they are displayed.



Closed Thread
Click here to go to the first staff post in this thread.  
Thread Tools
  #1    
Old 1 Week Ago (04:55 PM).
itsBailey
 
Join Date: Dec 2014
Gender: Male
Nature: Hasty
Hi guys, I'm new to the forums but I'm hoping this will be one of many places I'm able to hold a real discussion on something I've been working on for a little while now. As a note going in this topic, I'm a developer not a writer so please excuse my less than perfect writing style. If there's anything I can explain better or is left misunderstood after reading please ask any and all questions

What if the process of creating Pokémon based game content could be simplified in a way that it became enjoyable for everyone? Would it be possible to create an entirely new scripting language with a single purpose of being easy to learn, earn to read for those which understand English but also provide enough mechanisms for creators to make exciting content time after time?

Now, if you're anything like me you'll be reading this and grimacing already, "We've got one of these again!" Everyone wants the easy way right? Well I'm very much interested in providing it for them. I'm the head developer of an online Pokémon project where the aim is to have the community build their environment. We've had loads of creative people join the project over the years, but very little genuine interest in the scripting of game content which is absolutely vital. So how to simplify the process further and ensure that the system can be as intuitive as possible for a non-programming mindset, a real challenge.

In the last few months I've spent a great deal of time working with our game editing tool itself, creating our own version of a coding IDE although much less sophisticated of course. It does however provide in depth function templates, tutorial materials, a text editor with error checking/highlighting and even some tools to create some aspects of the scripts for you - copied to the clipboard so you can paste to as many scripts as you like. Still, this is not enough.

Unfortunately I've reached quite a catch 22 type of situation now. In my aims to keep the language as simple to read/write as possible for the vast majority of functions, applying these sample principles to more complex condition checking or parsing of values at runtime becomes very ugly and really against the core design goals.

Let me first talk about some of the limitations and boundaries at play here:

- the scripting system provides no means for variable declaration, controlled string manipulation, multi-language support.
- Every game map has it's own set of scripting files which are independent and unaware of the contents of any other map.
- The scripting language isn't object orientated and we divide our available scripts in to usable blocks available to be called by number. We call these ChatID's, although they can be used for a magnitude of other purposes.
- Players have saved storage which is referenced in bits, this enables us to make use of boolean and/or integer values, although these are defined in the number of bits and not the normal naming convention of byte/int/long or char/int16/int32 depending on the language you're used to. This means we only use the amount of storage we require, to keep player account processing as efficient as possible. We call each bit a Flag.

So let me begin by providing an example of the scripting syntax.

[1]
// This is a comment line so we can explain our scripts, <char> is a keyword which is replaced by our players username at runtime.
CHARSAY Now that I've kicked your butt you can call me <char>
SAY <char> it is
// For general scripts like this, we're 100% successful in our ease of use. I don't think anyone can have any confusion here.
[/1]
[2]
// This script is going to be a bit more complex. As this script is run every time we speak to a NPC, we've got to make sure that the items aren't provided every single time.
IF {isFlag} {1} {} {SAY I've given you everything I've got, try someone else!} {GIVEITEM Pokéball 1\SETFLAG 1 TRUE\SAY Here take this}
// I think for the most part I've managed to be successful with the goal too.
[/2]
[3]
// We have something called a pre-parser, this is effectively a script handler which processes are scripts quickly before they're passed to the main handler which actually executes functions.
// This is so that we can insert some values in to our scripts at runtime, sometimes just to randomise parts of dialogue to make the experience more enjoyable.
SAY RANDPICK[Hi/Hello/Hey you!]
// Simple enough example, here we've selected a single greeting at random from the provided selection.
// Above I mentioned that the scripting language enables us to make use of integers. So here's an example of saving and accessing one of those numbers.
SETBINARY 1 8 100
// What we've done here is allocate 8 bits for an integer and then store the value 100 in this memory space. So now we can recall it in a usable form as simple as possible:
SAY Number stored: READBINARY[1/8]
// would be displayed in a NPC conversation as 'Number Stored: 100'
[/3]

So far so good right? To me at this point I'm not sure we could really make things any easier, if you see something different when reading this please do let me know! But this isn't really where things go crazy, above is just so you can loosely see how things come together, it all falls to pieces when we try to create more variable content, specifically in content generated at runtime based on the players circumstances.

Take this one such example, which is an exert from a script used within a sprite selection shop. This is a good example because it has to refresh the map with NPCs based on the users selection in dialogue, so the available sprites can be displayed and made to do a small moving animation so the user is able to see the sprite from all sides.

Code:
CREATENPC (instAvatarREADBINARY[1197/1199])|Avatar,ADD[8+READBINARY[1197/1199]],3,ADD[378+-86+READBINARY[ADD[1170+MULT[READBINARY[1197/1199]*7]]/ADD[1176+MULT[READBINARY[1197/1199]*7]]]],2,0,0,READBINARY[ADD[1170+MULT[READBINARY[1197/1199]*7]]/ADD[1176+MULT[READBINARY[1197/1199]*7]]],300,,0,
What an ugly line of script, impossible to really understand what's going on without a paragraph of notes to accompany it! This is only the tip of the iceberg too, if you're able, take a minute to digest the following set of scripts.
(probably worth copying to notepad for easy reading)
Spoiler:
Code:
[73]
// THIS IS MUCH EASIER TO READ WITHIN THE EDITOR, it will be colour formatted correctly for the most part. Anything it may list as an issue, isn't an issue.
// This will be the start of the sprite shop for the halloween event.
// It's going to work slightly different than last time, although it will share some common principles.
// Reset our variable data.
SETBINARY 1170 1199 0
// We're basically going to let the players see 3 sprites at a time, and store the sprite ids within the temp flags. We need 7 flags (0-127) per spriteid.
// SpriteID 1 Flags 1170-1176
// SpriteID 2 Flags 1177-1183
// SpriteID 3 Flags 1184-1190
// PageID     Flags 1191-1196 - will be a number between like 0 and 7.
// OptionID Flags 1197- 1199 - will be number between 0 and 2
SAY So I may have a few more options available than I'd mentioned...
//Load up the page handler.
GOTO 74
[/73]
[74]
// This is the page handler for the witch/sprite handler.
// PageID is stored in Flags 1191-1196
// Reset all Sprite FlagIDs and Sprite optionID
SETBINARY 1170 1190 0
SETBINARY 1197 1199 3
//We mark the OptionID for the creation/destruction loops
// PageID 1. Sprites: 86,87,88
//Destroy Previous instanced NPCs
EXECUTEC 76
// Let's make sure player faces the sprites we create while they're moving around.
RESETPLAYERMOVEQUEUE TRUE
PLAYERSETDIR RIGHT
DELAYPLAYERMOVEMENT 6000
PLAYERSETDIR LEFT
// Page 0
EXECUTEB IF {Compare} {=} {READBINARY[1191/1196]:0} {SETBINARY 1170 1176 86@@@SETBINARY 1177 1183 87@@@SETBINARY 1184 1190 88@@@EXECUTEC 77@@@STARTASK Which option interests you? Page ADD[1+READBINARY[1191/1196]] of 8.|Previous#IF {Compare} {=} {0:READBINARY[1191/1196]} {SETBINARY 1191 1196 7@@@GOTO 74} {INCREMENT 1191 1196 -1@@@GOTO 74}|Sprite 1#SETBINARY 1197 1199 0~GOTO 75|Sprite 2#SETBINARY 1197 1199 1~GOTO 75|Sprite 3#SETBINARY 1197 1199 2~GOTO 75|More#IF {Compare} {=} {7:READBINARY[1191/1196]} {GOTO 74} {INCREMENT 1191 1196 1@@@GOTO 74}} {}
// Page 1
EXECUTEB IF {Compare} {=} {READBINARY[1191/1196]:1} {SETBINARY 1170 1176 89@@@SETBINARY 1177 1183 90@@@SETBINARY 1184 1190 91@@@EXECUTEC 77@@@STARTASK Which option interests you? Page ADD[1+READBINARY[1191/1196]] of 8.|Previous#IF {Compare} {=} {0:READBINARY[1191/1196]} {GOTO 74} {INCREMENT 1191 1196 -1@@@GOTO 74}|Sprite 1#SETBINARY 1197 1199 0~GOTO 75|Sprite 2#SETBINARY 1197 1199 1~GOTO 75|Sprite 3#SETBINARY 1197 1199 2~GOTO 75|More#IF {Compare} {=} {7:READBINARY[1191/1196]} {GOTO 74} {INCREMENT 1191 1196 1@@@GOTO 74}} {}
// Page 2
EXECUTEB IF {Compare} {=} {READBINARY[1191/1196]:2} {SETBINARY 1170 1176 92@@@SETBINARY 1177 1183 93@@@SETBINARY 1184 1190 94@@@EXECUTEC 77@@@STARTASK Which option interests you? Page ADD[1+READBINARY[1191/1196]] of 8.|Previous#IF {Compare} {=} {0:READBINARY[1191/1196]} {GOTO 74} {INCREMENT 1191 1196 -1@@@GOTO 74}|Sprite 1#SETBINARY 1197 1199 0~GOTO 75|Sprite 2#SETBINARY 1197 1199 1~GOTO 75|Sprite 3#SETBINARY 1197 1199 2~GOTO 75|More#IF {Compare} {=} {7:READBINARY[1191/1196]} {GOTO 74} {INCREMENT 1191 1196 1@@@GOTO 74}} {}
// Page 3
EXECUTEB IF {Compare} {=} {READBINARY[1191/1196]:3} {SETBINARY 1170 1176 98@@@SETBINARY 1177 1183 99@@@SETBINARY 1184 1190 100@@@EXECUTEC 77@@@STARTASK Which option interests you? Page ADD[1+READBINARY[1191/1196]] of 8.|Previous#IF {Compare} {=} {0:READBINARY[1191/1196]} {GOTO 74} {INCREMENT 1191 1196 -1@@@GOTO 74}|Sprite 1#SETBINARY 1197 1199 0~GOTO 75|Sprite 2#SETBINARY 1197 1199 1~GOTO 75|Sprite 3#SETBINARY 1197 1199 2~GOTO 75|More#IF {Compare} {=} {7:READBINARY[1191/1196]} {GOTO 74} {INCREMENT 1191 1196 1@@@GOTO 74}} {}
// Page 4
EXECUTEB IF {Compare} {=} {READBINARY[1191/1196]:4} {SETBINARY 1170 1176 101@@@SETBINARY 1177 1183 102@@@SETBINARY 1184 1190 103@@@EXECUTEC 77@@@STARTASK Which option interests you? Page ADD[1+READBINARY[1191/1196]] of 8.|Previous#IF {Compare} {=} {0:READBINARY[1191/1196]} {GOTO 74} {INCREMENT 1191 1196 -1@@@GOTO 74}|Sprite 1#SETBINARY 1197 1199 0~GOTO 75|Sprite 2#SETBINARY 1197 1199 1~GOTO 75|Sprite 3#SETBINARY 1197 1199 2~GOTO 75|More#IF {Compare} {=} {7:READBINARY[1191/1196]} {GOTO 74} {INCREMENT 1191 1196 1@@@GOTO 74}} {}
// Page 5
EXECUTEB IF {Compare} {=} {READBINARY[1191/1196]:5} {SETBINARY 1170 1176 104@@@SETBINARY 1177 1183 105@@@SETBINARY 1184 1190 106@@@EXECUTEC 77@@@STARTASK Which option interests you? Page ADD[1+READBINARY[1191/1196]] of 8.|Previous#IF {Compare} {=} {0:READBINARY[1191/1196]} {GOTO 74} {INCREMENT 1191 1196 -1@@@GOTO 74}|Sprite 1#SETBINARY 1197 1199 0~GOTO 75|Sprite 2#SETBINARY 1197 1199 1~GOTO 75|Sprite 3#SETBINARY 1197 1199 2~GOTO 75|More#IF {Compare} {=} {7:READBINARY[1191/1196]} {GOTO 74} {INCREMENT 1191 1196 1@@@GOTO 74}} {}
// Page 6
EXECUTEB IF {Compare} {=} {READBINARY[1191/1196]:6} {SETBINARY 1170 1176 106@@@SETBINARY 1177 1183 107@@@SETBINARY 1184 1190 108@@@EXECUTEC 77@@@STARTASK Which option interests you? Page ADD[1+READBINARY[1191/1196]] of 8.|Previous#IF {Compare} {=} {0:READBINARY[1191/1196]} {GOTO 74} {INCREMENT 1191 1196 -1@@@GOTO 74}|Sprite 1#SETBINARY 1197 1199 0~GOTO 75|Sprite 2#SETBINARY 1197 1199 1~GOTO 75|Sprite 3#SETBINARY 1197 1199 2~GOTO 75|More#IF {Compare} {=} {7:READBINARY[1191/1196]} {GOTO 74} {INCREMENT 1191 1196 1@@@GOTO 74}} {}
// Page 7
EXECUTEB IF {Compare} {=} {READBINARY[1191/1196]:7} {SETBINARY 1170 1176 109@@@SETBINARY 1177 1183 110@@@SETBINARY 1184 1190 0@@@EXECUTEC 77@@@STARTASK Which option interests you? Page ADD[1+READBINARY[1191/1196]] of 8.|Previous#IF {Compare} {=} {0:READBINARY[1191/1196]} {GOTO 74} {INCREMENT 1191 1196 -1@@@GOTO 74}|Sprite 1#SETBINARY 1197 1199 0~GOTO 75|Sprite 2#SETBINARY 1197 1199 1~GOTO 75|Sprite 3#SETBINARY 1197 1199 2~GOTO 75|More#IF {Compare} {=} {7:READBINARY[1191/1196]} {GOTO 74} {INCREMENT 1191 1196 1@@@GOTO 74}} {}
[/74]
[75]
//Player is interested in one of the player sprites.
// We'll be creating their instanced names based on the OptionID stored in
// Flags 1197-1199
MOVENPC (instAvatarREADBINARY[1197/1199]) DOWN 1
MOVENPC (instAvatarREADBINARY[1197/1199]) UP 1
NPCSETDIR (instAvatarREADBINARY[1197/1199]) LEFT
DELAYNPCMOVEMENT (instAvatarREADBINARY[1197/1199]) 200
NPCSETDIR (instAvatarREADBINARY[1197/1199]) RIGHT
DELAYNPCMOVEMENT (instAvatarREADBINARY[1197/1199]) 200
NPCSETDIR (instAvatarREADBINARY[1197/1199]) DOWN
DELAYNPCMOVEMENT (instAvatarREADBINARY[1197/1199]) 500
MOVENPC (instAvatarREADBINARY[1197/1199]) DOWN 1
WAITNPCMOVE (instAvatarREADBINARY[1197/1199])
STARTASK So is this the one you were after?|Yes#GOTO 78|Back#74|Leave#EXECUTEC 76~CHARSAY I'll probably be back..
[/75]
[76]
// This is our ChatID for clearing up any previously created instanced NPCs for
// Avatar selection. Must be called in the instant handler!
IF {doesINPCExist} {(instAvatar0)} {} {DESTROYNPC (instAvatar0)} {}
IF {doesINPCExist} {(instAvatar1)} {} {DESTROYNPC (instAvatar1)} {}
IF {doesINPCExist} {(instAvatar2)} {} {DESTROYNPC (instAvatar2)} {}
[/76]
[77]
// This ChatID will create each of our instanced NPCs for the avatar shop.
// This is called within the instant handler!
INCREMENT 1197 1199 -1
CREATENPC (instAvatarREADBINARY[1197/1199])|Avatar,ADD[8+READBINARY[1197/1199]],3,ADD[378+-86+READBINARY[ADD[1170+MULT[READBINARY[1197/1199]*7]]/ADD[1176+MULT[READBINARY[1197/1199]*7]]]],2,0,0,READBINARY[ADD[1170+MULT[READBINARY[1197/1199]*7]]/ADD[1176+MULT[READBINARY[1197/1199]*7]]],300,,0,
// We can read the SpriteID from the following FlagIDs: 1170/1176 1177/1183 1184/1190
// Using maths we can determine the FlagIDs from the OptionID using the following:
// Range Min/Max: 1170 + OprionsID * 7 / 1170 + (OptionID*7) + 6
// Written in script as ADD[1170+MULT[READBINARY[1197/1199]*7]] / ADD[1176+MULT[READBINARY[1197/1199]*7]]
// The whole thing becomes pretty ugly lol:
// READBINARY[ADD[1170+MULT[READBINARY[1197/1199]*7]]/ADD[1176+MULT[READBINARY[1197/1199]*7]]]
// Now for this function to work properly, it must call itself again. This is important and is called a recursive loop, it will continue to call itself untill all
// work has been done.
IF {compare} {=} {READBINARY[1197/1199]:0} {} {DELAYNPCMOVEMENT (instAvatarREADBINARY[1197/1199]) MULT[READBINARY[1197/1199]*800]}
// The above line creates a delay before we let the instanced NPC move. We're actually creating the sprites from right to left, but make them start their animations from left to right.
MOVENPC (instAvatarREADBINARY[1197/1199]) DOWN 1
DELAYNPCMOVEMENT (instAvatarREADBINARY[1197/1199]) 150
MOVENPC (instAvatarREADBINARY[1197/1199]) UP 1
NPCSETDIR (instAvatarREADBINARY[1197/1199]) LEFT
DELAYNPCMOVEMENT (instAvatarREADBINARY[1197/1199]) 150
NPCSETDIR (instAvatarREADBINARY[1197/1199]) RIGHT
DELAYNPCMOVEMENT (instAvatarREADBINARY[1197/1199]) 150
NPCSETDIR (instAvatarREADBINARY[1197/1199]) DOWN
IF {Compare} {=} {READBINARY[1197/1199]:0} {} {EXECUTEC 77}
[/77]
[78]
// player is confirming their choice.
//SAY SpriteID: READBINARY[ADD[1170+MULT[READBINARY[1197/1199]*7]]/ADD[1176+MULT[READBINARY[1197/1199]*7]]]
// This query is to make sure the player has enough of the Chocolate item.
EXECUTEB IF {hasItem} {189x400} {} {} {DELAYEDB SAY You need at least 400 chocolates for the real magic to begin!}
EXECUTEB IF {compare} {=} {0:READBINARY[ADD[1170+MULT[READBINARY[1197/1199]*7]]/ADD[1176+MULT[READBINARY[1197/1199]*7]]]} {DELAYEDB SAY Unfortunately there an issue with your selection. Please try again\GOTO 74} {}
// we're good to go.
EXECUTEC 76
STARTASK So if you're certain, that will be 400 Chocolates please?|Yes#REMOVEITEM 189 400~UPDATEPLAYERSPRITEID READBINARY[ADD[1170+MULT[READBINARY[1197/1199]*7]]/ADD[1176+MULT[READBINARY[1197/1199]*7]]]|Back#74|Leave#0
[/78]


If you've not switched off after starting to read through that mammoth I think you can really start to see some of the problems we face around dynamic content. This is a very simple example in the scheme of things, imagine a random quest generator which can select random maps to fill with a random number of computer opponents which are set to roam the map seeking out the player. We need to be able to create these challenges and re-create them based on the players progress through the challenge at any time they re-enter the map, re-logging in to the game included.

This is where we have the real separation from single player and multi-player experiences, both for players and content creators. In a single player environment we do have to give a little thought to cheat prevention and glitch abuse, but nothing compared to a multi-player environment where a level playing field for everyone is absolutely vital to the projects success. The existing wealth of players can be jeopardised by faulty scripts giving an unfair advantage for those which found an unfair advantage and these kind of things can have long lasting impacts on economy and balance. This makes encouraging playing with scripts like those seen in my last snippet pretty unappealing as the room for error is pretty high, with the possibility of broken scripts disrupting existing player saved data.

So my questions are this:

- Do you see any faults with the way we layout our query structure? Do you have any suggestions for optimising it? Especially with regards to querying multiple pieces of information at once.
- What features of the tools that you guys use to create content do you find most useful?
- Are there any things you wish your tools could do to help speed up the process of creating content?
- Do you have any suggestions for improving the syntax and structure available as a whole?
- As a side point: I'm also interested to know what you guys do to learn a new scripting language or toolset, from the perspective of people who enjoy this kind of thing it's important to make sure we have the appropriate learning resources available. I've been trying determine if the time required to make quality video tutorials would be a worthwhile task.


I've tried to keep project specific information away from the discussion, although if anyone is interested I have no issues with sharing a download link to the editor software in question. However, this is a downloadable executable file which will requires installation. If posting a link to such software is within the rules of the forums I will make one available in place of this sentence, I've not found anything formal to suggest this is acceptable yet though and don't want it to get in the way of starting a discussion.
  #2    
Old 1 Week Ago (03:28 AM).
Magic's Avatar
Magic
キュウコン
 
Join Date: Jan 2009
Location: UK
Age: 23
Gender: Male
A few questions before I can respond in any productive way:

What game is this scripting envisioned for? If your answer is generation 3 (FR/RSE) or another?
Do you have any videos/screenshots of these scripts in action? Preferably of the editor and what it does in game.
  #3    
Old 1 Week Ago (05:53 AM).
itsBailey
 
Join Date: Dec 2014
Gender: Male
Nature: Hasty
Quote originally posted by Magic:
A few questions before I can respond in any productive way:

What game is this scripting envisioned for? If your answer is generation 3 (FR/RSE) or another?
Do you have any videos/screenshots of these scripts in action? Preferably of the editor and what it does in game.
My environment is styled to RSE graphically, although we do have 4th generation Pokémon and movesets available. PDoD is the game that this tool is intended to support. The game engine and all tools are in-house creations.

I misread the forum rules for this section when first posting and so I understand that I am able to link to the software in question. I do not have the post count though!
If you google 'PDoD' my website should be the first in the list, then there's a menu option for the game editors. You may also check out the media section for a video and dozens of pictures of our game world.

Once the editor is installed, you will be able to open it up to find a few examples of game scripts including the first 2-3 gyms if you choose to play the game to experience them. Copying and pasting the code snippets from above in to the text editor would also make understanding the mess a LOT easier A big problem I face is that my energy is invested solely in the tools which enable others to make content, the vast majority of our game content doesn't make use of the more complex features available at all. It's usually limited time game events which I write myself and the next isn't going to be available until Easter

There is a small multi path starting quest which makes use of some instanced NPCs (created on a per client basis, not globally) to provide the player with a small cutscene and introduction in to the game. You can choose to help out the Prof or sell off his goods to be on your way.


I would be happy to create some small purpose built examples around some key ideas/issues if you believe it would help your understanding
Attached Images
File Type: png NPCSS1.png‎ (211.5 KB, 33 views) (Save to Dropbox)
File Type: png npctexteditor2.png‎ (73.1 KB, 18 views) (Save to Dropbox)
  #4    
Old 1 Week Ago (06:16 AM).
Spherical Ice's Avatar
Spherical Ice
 
Join Date: Nov 2007
Location: UK
Send a message via Skype™ to Spherical Ice
As far as I can tell, none of this actually involves ROM hacking, and so I think it would be better suited for the Game Development forum. Perhaps you should check out the rules there, and repost? Sorry!

__________________
Closed Thread
Quick Reply

Sponsored Links
Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Minimum Characters Per Post: 25



All times are UTC -8. The time now is 11:08 AM.