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.