How to implement scripting correctly?

So a while ago I asked a question about how to handle and abundance of events that happen in games like explosions. Someone replied to me saying that Scripts would be best used for stuff like this and npcs. I know how to actually script in LUA but I’m dumbfounded on how to implement it into a game correctly.

Here’s my problems:

*If I wanted many many npcs with dialogue would I have a script for each npc?
*Would I create the NPC using the script or would I create it in the java code itself and then somehow give it it’s dialogue through the script.
*For events, would I just have the script create instances of an object that I defined in Java and have a move method in my npcs for the cinematic movement of npcs?

Short answer - whatever’s easiest. The whole point of scripts in games is to make something that would take a long time in your core language take less time by “outsourcing” it to a scripting language. It means things are quicker (in the long run), more organized (easier to find / modify specific things) and generally more modifiable and less problem prone. So just jump into it, make an implementation. If you think it could be made easier to use, make it so.

I think I may have been the one who suggested scripting in your other thread :slight_smile: So, I’ll offer a few ideas here as well (in addition to what quew8 said).

I don’t know much about Java-Lua integration. A quick Google search suggests there are some good solutions available, but JavaScript is extremely well-integrated with Java (via Nashorn or Rhino), which makes it a tempting option. And, Lua and JavaScript are pretty similar paradigmatically, so if you’re familiar with Lua, you might find JavaScript pretty easy to pick up. I’m not necessarily advocating for any particular solution, but just be aware Lua isn’t your only option.

Following on what quew8 said, there’s no one right way to incorporate scripting in a game, so don’t feel like you have to do things a certain way. There’s a wide range of ways scripting can be used. Some games provide only a basic framework in the base language (Java in this case), and write pretty much the entire game itself in the scripting language. Other games put almost everything in the base language and just outsource a few things (like UI event handling and so on) to a scripting system. The main purpose of scripting is to make things easier for the developers (you in this case), so the only real metric here is whether your use of scripting makes it easier for you (in the long run) to develop the game.

[quote]*If I wanted many many npcs with dialogue would I have a script for each npc?
*Would I create the NPC using the script or would I create it in the java code itself and then somehow give it it’s dialogue through the script.
*For events, would I just have the script create instances of an object that I defined in Java and have a move method in my npcs for the cinematic movement of npcs?
[/quote]
As noted above, there aren’t really single ‘right’ answers to the above questions. But, here’s a suggestion for how you might get started. Pick one thing in your game that’s currently hard-coded (or maybe driven by a config file or something), and move it to scripting. Just doing that will get you through the steps of choosing a scripting language and framework, getting it integrated, and getting the basics of communication with Java working. Once you’ve done that, you can then start moving other things to scripting as seems reasonable.

In order to use scripting successfully, you first need to have a problem. What immediate problem is scripting going to solve?

I’ve played with LUA and it seems a bit primitive to me. Why not go higher-level with something like Groovy? Or just stick to the default JS scripting available in the JRE?

I expect I will be using scripting in my game too, but I’m not going to jump into scripting until I absolutely need to. I anticipate I will mostly need it to define custom behaviors for creatures and custom rules for items. So all the code to create and run the entities is Java, but sometimes the entity will have one or more ScriptableRule or ScriptableBehavior instances attached to it, and these will be loaded from the data file where I define them.

I want a way to handle dialogue. I just have no idea how to actually implement it for a NPC class I have created in Java. Currently trying to figure that out :clue:

Wouldn’t some XML files holding dialogue that you retrieve by an internal reference that’s hardcoded in work as well?

A typically dialogue system can look like this. You have a root set of “opening” dialog as a list and each player response leads to the next list. To make it interesting you simply need to allow each element to be conditionally shown based on a boolean response.

My own system for scripting works as follows.

The format I’ve created is

Command#parameter1,parameter2,…

It is the same format for two potential script items: Actions and Conditions. Both actions and conditions have just two fields: type and data. Type is an enum that identifies what kind of action or condition is, and data is where the unparsed parameters after the “#” are stored for later use.

Some examples of Conditions:

PlayerHasItem#2507
PlayerIsLevel#2
NPCInParty#Adaon

Some examples of actions:

NPCSpawn#bandit,230,46
PlayerGainXP#300
TravelTo#grey_mountains,7,12

Actions have an execute() method, that check what kind of action it is, and then does things in the game depending on the params. Conditions have an evaulate() method that return true or false depending on the type or params.

Here’s a very simplified version of my classes. I have removed most types and a few utilities I did for debugging (toString, etc). I will also omit my condition class because it’s almost identycal to the action, only has an evaluate() instead of a execute().

ScriptedAction class

public class ScriptedAction {
	
	public enum ActionType {	//actually I have like 30 types, removed for clarity.
                 GainItem,LoseItem,GainXP      }   

private ActionType type;
private String data;

public ScriptedAction(String _type,String _data){
	this(parseActionType(_type),_data);	
}

private ScriptedAction(ActionType _type,String _data){		
	type=_type;
	data=_data;
}

private static ActionType parseActionType(String _action) {	
	if (_action.toLowerCase().trim().equals("gainitem")) return ActionType.GainItem;
	if (_action.toLowerCase().trim().equals("loseitem"))	return ActionType.LoseItem;	
	if (_action.toLowerCase().trim().equals("gainxp"))	return ActionType.GainXP;		
}

public void execute(){
	
	//System.out.println(toString());
	
	String parsed=FDUtils.replaceSmartTags(data);
	
	
	switch (type){			
		
		case GainXP:{
			//make player gain XP
		}

                //implement all other type cases.
        }

}

}

As normally you have to run several conditions or actions at once, I have created two “container” classes, ActionSet and ConditionsSet that can be created by parsing a list of items separated by “;”, hold them inside a list, and allow you to evaluate() or execute() them all at once.

ActionsSet class

public class ActionsSet {
	
	public ArrayList<ScriptedAction> actions= new ArrayList<ScriptedAction>();
	
	public ActionsSet(){		
	}
	
	public ActionsSet(String str){
		
		
		List<String> items = FDUtils.splitScript(str);
		
		for (String a:items){
			String[] splitAction= new String[2];
			splitAction= a.split("#",-1);
			actions.add(new ScriptedAction(splitAction[0],splitAction[1]));			
		}
				
	}
	
	public void execute(){
		//System.out.println("ActionSet executing:"+toString());
		for (ScriptedAction a:actions){
			 a.execute();
		}
		
	}
}

So how does this work in practice?

I have added in my game string fields that can hold actions and conditions.

A container may have this in conditions field: VariableLower#ng_enraged_mino,1;PlayerIsLevel#6

My conversations are held in text files, based in lines. Each conversation line (be it NPC sentence or your possible replies) has attached to them conditions and actions, too. A reply may not appear, for instance, if you don’w have certain item. Or the sentence the NPC was going to say may be skipped and he’ll instead say the one below.

Even loot tables have a field for conditions, and my “bestiary” file has fields called OnDieActions, items have an OnTakeActions field too.