2016-07-06 05:03:02 +00:00
/* User action execution handler */
// Handles actions set in editor e.g. for dialogues, switches, etc.
// An object is sometimes needed to show a menu or start a timer, so this definition is created whenever a user action is run
local Name = " UserAction " ;
local Plane = 0 ;
2016-07-21 04:22:53 +00:00
/* UserAction definition */
2016-07-06 05:03:02 +00:00
// Base classes for EditorProps using actions
local Evaluator ;
// EditorProps for generic user action callbacks
local Prop , PropProgressMode , PropParallel ;
// Base props for action execution conditions
local ActionEvaluation ;
// Proplist containing callback function. Indexed by option names.
local EvaluatorCallbacks ;
2016-07-10 18:11:23 +00:00
// Proplist containing option definitions. Indexed by option names.
local EvaluatorDefs ;
2016-07-06 05:03:02 +00:00
// Call this definition early (but after EditorBase) to allow EditorProp initialization
local DefinitionPriority = 99 ;
2016-07-30 17:21:38 +00:00
// Localized group names
local GroupNames = { Structure = " $Structure$ " } ;
2016-07-31 02:39:22 +00:00
// Storage for global user variables
static g_UserAction_global_vars ;
// Localized evaluator names
local EvaluatorTypeNames = {
Action = " $UserAction$ " ,
Object = " $UserObject$ " ,
Definition = " $UserDefinition$ " ,
Player = " $UserPlayer$ " ,
PlayerList = " $UserPlayerList$ " ,
Boolean = " $UserBoolean$ " ,
Integer = " $UserInteger$ " ,
String = " $UserString$ " ,
Condition = " $UserCondition$ " ,
Position = " $UserPosition$ " ,
Offset = " $UserOffset$ "
} ;
2016-07-06 05:03:02 +00:00
func Definition ( def )
{
// Typed evaluator base definitions
Evaluator = { } ;
2016-07-21 04:47:43 +00:00
Evaluator . Action = { Name = " $UserAction$ " , Type = " enum " , OptionKey = " Function " , Options = [ { Name = " $None$ " } ] } ;
Evaluator . Object = { Name = " $UserObject$ " , Type = " enum " , OptionKey = " Function " , Options = [ { Name = " $None$ " } ] } ;
2016-07-29 05:43:35 +00:00
Evaluator . Definition = { Name = " $UserDefinition$ " , Type = " enum " , OptionKey = " Function " , Options = [ { Name = " $None$ " } ] } ;
2016-07-21 04:47:43 +00:00
Evaluator . Player = { Name = " $UserPlayer$ " , Type = " enum " , OptionKey = " Function " , Options = [ { Name = " $Noone$ " } ] } ;
Evaluator . PlayerList = { Name = " $UserPlayerList$ " , Type = " enum " , OptionKey = " Function " , Options = [ { Name = " $Noone$ " } ] } ;
Evaluator . Boolean = { Name = " $UserBoolean$ " , Type = " enum " , OptionKey = " Function " , Options = [ ] } ;
2016-07-30 06:06:54 +00:00
Evaluator . Integer = { Name = " $UserInteger$ " , Type = " enum " , OptionKey = " Function " , Options = [ { Name = " 0 " } ] } ;
2016-07-30 21:39:15 +00:00
Evaluator . String = { Name = " $UserString$ " , Type = " enum " , OptionKey = " Function " , Options = [ ] } ;
2016-07-21 04:47:43 +00:00
Evaluator . Condition = { Name = " $UserCondition$ " , Type = " enum " , OptionKey = " Function " , Options = [ { Name = " $None$ " } ] } ;
2016-07-29 05:43:35 +00:00
Evaluator . Position = { Name = " $UserPosition$ " , Type = " enum " , OptionKey = " Function " , Options = [ { Name = " $Here$ " } ] } ;
2016-07-30 06:06:54 +00:00
Evaluator . Offset = { Name = " $UserOffset$ " , Type = " enum " , OptionKey = " Function " , Options = [ { Name = " $None$ " } ] } ;
2016-07-31 02:39:22 +00:00
Evaluator . Any = { Name = " $UserAny$ " , Type = " enum " , OptionKey = " Function " , Options = [ { Name = " $None$ " } ] } ;
2016-07-06 05:03:02 +00:00
// Action evaluators
EvaluatorCallbacks = { } ;
2016-07-10 18:11:23 +00:00
EvaluatorDefs = { } ;
2016-07-25 05:42:23 +00:00
AddEvaluator ( " Action " , " $Sequence$ " , " $Sequence$ " , " $SequenceHelp$ " , " sequence " , [ def , def . EvalAct_Sequence ] , { Actions = [ ] } , { Type = " proplist " , DescendPath = " Actions " , Display = " {{Actions}} " , EditorProps = {
2016-07-13 21:18:08 +00:00
Actions = { Name = " $Actions$ " , Type = " array " , Elements = Evaluator . Action } ,
2016-07-06 05:03:02 +00:00
} } ) ;
2016-07-25 05:42:23 +00:00
AddEvaluator ( " Action " , " $Sequence$ " , " $Goto$ " , " $GotoHelp$ " , " goto " , [ def , def . EvalAct_Goto ] , { Index = 0 } , { Type = " proplist " , Display = " {{Index}} " , EditorProps = {
2016-07-13 21:18:08 +00:00
Index = { Name = " $Index$ " , Type = " int " , Min = 0 }
2016-07-06 05:03:02 +00:00
} } ) ;
2016-07-25 05:42:23 +00:00
AddEvaluator ( " Action " , " $Sequence$ " , " $StopSequence$ " , " $StopSequenceHelp$ " , " stop_sequence " , [ def , def . EvalAct_StopSequence ] ) ;
AddEvaluator ( " Action " , " $Sequence$ " , " $SuspendSequence$ " , " $SuspendSequenceHelp$ " , " suspend_sequence " , [ def , def . EvalAct_SuspendSequence ] ) ;
AddEvaluator ( " Action " , " $Sequence$ " , " $Wait$ " , " $WaitHelp$ " , " wait " , [ def , def . EvalAct_Wait ] , { Time = 60 } , { Type = " proplist " , Display = " {{Time}} " , EditorProps = {
2016-07-13 21:18:08 +00:00
Time = { Name = " $Time$ " , Type = " int " , Min = 1 }
2016-07-06 05:03:02 +00:00
} } ) ;
2016-07-29 03:44:10 +00:00
AddEvaluator ( " Action " , " $Ambience$ " , " $Sound$ " , " $SoundHelp$ " , " sound " , [ def , def . EvalAct_Sound ] , { Pitch = { Function = " int_constant " , Value = 0 } , Volume = { Function = " int_constant " , Value = 100 } , TargetPlayers = { Function = " all_players " } } , { Type = " proplist " , Display = " {{Sound}} " , EditorProps = {
Sound = { Name = " $SoundName$ " , EditorHelp = " $SoundNameHelp$ " , Type = " sound " , AllowEditing = true } ,
Pitch = new Evaluator . Integer { Name = " $SoundPitch$ " , EditorHelp = " $SoundPitchHelp$ " } ,
Volume = new Evaluator . Integer { Name = " $SoundVolume$ " , EditorHelp = " $SoundVolumeHelp$ " } ,
Loop = { Name = " $SoundLoop$ " , EditorHelp = " $SoundLoopHelp$ " , Type = " enum " , Options = [
{ Name = " $SoundLoopNone$ " } ,
{ Name = " $SoundLoopOn$ " , Value = + 1 } ,
{ Name = " $SoundLoopOff$ " , Value = - 1 }
] } ,
TargetPlayers = new Evaluator . PlayerList { EditorHelp = " $SoundTargetPlayersHelp$ " } ,
2016-07-30 18:14:09 +00:00
SourceObject = new Evaluator . Object { Name = " $SoundSourceObject$ " , EditorHelp = " $SoundSourceObjectHelp$ " , EmptyName = " $Global$ " }
2016-07-29 03:44:10 +00:00
} } ) ;
2016-07-30 20:51:57 +00:00
AddEvaluator ( " Action " , " $Object$ " , " $CreateObject$ " , " $CreateObjectHelp$ " , " create_object " , [ def , def . EvalAct_CreateObject ] , { SpeedX = { Function = " int_constant " , Value = 0 } , SpeedY = { Function = " int_constant " , Value = 0 } } , { Type = " proplist " , Display = " {{ID}} " , ShowFullName = true , EditorProps = {
2016-07-29 05:43:35 +00:00
ID = new Evaluator . Definition { EditorHelp = " $CreateObjectDefinitionHelp$ " } ,
Position = new Evaluator . Position { EditorHelp = " $CreateObjectPositionHelp$ " } ,
CreateAbove = { Name = " $CreateObjectCreationOffset$ " , EditorHelp = " $CreateObjectCreationOffsetHelp$ " , Type = " enum " , Options = [
{ Name = " $Center$ " } ,
{ Name = " $Bottom$ " , Value = true }
] } ,
Owner = new Evaluator . Player { Name = " $Owner$ " , EditorHelp = " $CreateObjectOwnerHelp$ " } ,
Container = new Evaluator . Object { Name = " $Container$ " , EditorHelp = " $CreateObjectContainerHelp$ " } ,
SpeedX = new Evaluator . Integer { Name = " $SpeedX$ " , EditorHelp = " $CreateObjectSpeedXHelp$ " } ,
SpeedY = new Evaluator . Integer { Name = " $SpeedY$ " , EditorHelp = " $CreateObjectSpeedYHelp$ " }
} } ) ;
2016-07-30 20:51:57 +00:00
AddEvaluator ( " Action " , " $Object$ " , " $CastObjects$ " , " $CastObjectsHelp$ " , " cast_objects " , [ def , def . EvalAct_CastObjects ] , { Amount = { Function = " int_constant " , Value = 8 } , Speed = { Function = " int_constant " , Value = 20 } , AngleDeviation = { Function = " int_constant " , Value = 360 } } , { Type = " proplist " , Display = " {{Amount}}x{{ID}} " , ShowFullName = true , EditorProps = {
ID = new Evaluator . Definition { EditorHelp = " $CastObjectsDefinitionHelp$ " } ,
Position = new Evaluator . Position { EditorHelp = " $CastObjectsPositionHelp$ " } ,
Amount = new Evaluator . Integer { Name = " $Amount$ " , EditorHelp = " $CastObjectsAmountHelp$ " } ,
Speed = new Evaluator . Integer { Name = " $SpeedY$ " , EditorHelp = " $CastObjectsSpeedHelp$ " } ,
MeanAngle = new Evaluator . Integer { Name = " $MeanAngle$ " , EditorHelp = " $CastObjectsMeanAngleHelp$ " } ,
AngleDeviation = new Evaluator . Integer { Name = " $AngleDeviation$ " , EditorHelp = " $CastObjectsAngleDeviationHelp$ " } ,
Owner = new Evaluator . Player { Name = " $Owner$ " , EditorHelp = " $CastObjectsOwnerHelp$ " }
} } ) ;
2016-07-31 04:05:58 +00:00
AddEvaluator ( " Action " , " $Object$ " , " $RemoveObject$ " , " $RemoveObjectHelp$ " , " remove_object " , [ def , def . EvalAct_RemoveObject ] , { } , { Type = " proplist " , Display = " {{Object}} " , ShowFullName = true , EditorProps = {
2016-07-29 06:06:20 +00:00
Object = new Evaluator . Object { EditorHelp = " $RemoveObjectObject$ " } ,
EjectContents = { Name = " $EjectContents$ " , EditorHelp = " $EjectContentsHelp$ " , Type = " enum " , Options = [
{ Name = " $EjectContentsNo$ " } ,
{ Name = " $EjectContentsYes$ " , Value = true }
] } ,
} } ) ;
2016-07-31 02:39:22 +00:00
AddEvaluator ( " Action " , " $Script$ " , " $SetVariable$ " , " $SetVariableHelp$ " , " set_variable " , [ def , def . EvalAct_SetVariable ] , { VariableName = { Function = " string_constant " , Value = " " } } , { Type = " proplist " , Display = " {{Context}}::{{VariableName}}={{Value}} " , EditorProps = {
Context = new Evaluator . Object { Name = " $Context$ " , EditorHelp = " $VariableContextHelp$ " , EmptyName = " $Global$ " } ,
VariableName = new Evaluator . String { Name = " $VariableName$ " , EditorHelp = " $VariableNameHelp$ " } ,
Value = new Evaluator . Any { Name = " $Value$ " , EditorHelp = " $SetVariableValueHelp$ " }
} } ) ;
var variable_delegate = { Type = " proplist " , Display = " {{Context}}::{{VariableName}} " , EditorProps = {
Context = new Evaluator . Object { Name = " $Context$ " , EditorHelp = " $VariableContextHelp$ " , EmptyName = " $Global$ " } ,
VariableName = new Evaluator . String { Name = " $VariableName$ " , EditorHelp = " $VariableNameHelp$ " } } } ;
2016-07-31 04:05:58 +00:00
AddEvaluator ( " Action " , " $Script$ " , " $Log$ " , " $LogHelp$ " , " log " , [ def , def . EvalAct_Log ] , { Message = { Function = " string_constant " , Value = " " } } , { Type = " proplist " , Display = " {{Message}} " , ShowFullName = true , EditorProps = {
Message = new Evaluator . String { Name = " $LogMessage$ " , EditorHelp = " $LogMessageHelp$ " } ,
} } ) ;
2016-07-06 05:03:02 +00:00
// Object evaluators
2016-07-25 05:42:23 +00:00
AddEvaluator ( " Object " , nil , " $ActionObject$ " , " $ActionObjectHelp$ " , " action_object " , [ def , def . EvalObj_ActionObject ] ) ;
AddEvaluator ( " Object " , nil , " $TriggerClonk$ " , " $TriggerClonkHelp$ " , " triggering_clonk " , [ def , def . EvalObj_TriggeringClonk ] ) ;
AddEvaluator ( " Object " , nil , " $TriggerObject$ " , " $TriggerObjectHelp$ " , " triggering_object " , [ def , def . EvalObj_TriggeringObject ] ) ;
2016-07-30 18:50:22 +00:00
AddEvaluator ( " Object " , nil , [ " $ConstantObject$ " , " " ] , " $ConstantObjectHelp$ " , " object_constant " , [ def , def . EvalConstant ] , { Value = nil } , { Type = " object " , Name = " $Value$ " } ) ;
2016-07-29 05:43:35 +00:00
AddEvaluator ( " Object " , nil , " $LastCreatedObject$ " , " $LastCreatedObjectHelp$ " , " last_created_object " , [ def , def . EvalObj_LastCreatedObject ] ) ;
2016-07-31 02:39:22 +00:00
AddEvaluator ( " Object " , nil , " $Variable$ " , " $VariableHelp$ " , " object_variable " , [ def , def . EvalVariable , C4V_C4Object ] , { VariableName = { Function = " string_constant " , Value = " " } } , variable_delegate ) ;
2016-07-29 05:43:35 +00:00
// Definition evaluators
2016-07-30 18:50:22 +00:00
AddEvaluator ( " Definition " , nil , [ " $Constant$ " , " " ] , " $ConstantHelp$ " , " def_constant " , [ def , def . EvalConstant ] , { Value = nil } , { Type = " def " , Name = " $Value$ " } ) ;
2016-07-30 22:00:04 +00:00
AddEvaluator ( " Definition " , nil , " $TypeOfObject$ " , " $TypeOfObjectHelp$ " , " type_of_object " , [ def , def . EvalDef_TypeOfObject ] , { } , new Evaluator . Object { } , " Object " ) ;
2016-07-31 02:39:22 +00:00
AddEvaluator ( " Definition " , nil , " $Variable$ " , " $VariableHelp$ " , " def_variable " , [ def , def . EvalVariable , C4V_Def ] , { VariableName = { Function = " string_constant " , Value = " " } } , variable_delegate ) ;
2016-07-06 05:03:02 +00:00
// Player evaluators
2016-07-25 05:42:23 +00:00
AddEvaluator ( " Player " , nil , " $TriggeringPlayer$ " , " $TriggeringPlayerHelp$ " , " triggering_player " , [ def , def . EvalPlr_Trigger ] ) ;
2016-07-31 02:39:22 +00:00
AddEvaluator ( " Player " , nil , " $Variable$ " , " $VariableHelp$ " , " player_variable " , [ def , def . EvalVariable , C4V_Int ] , { VariableName = { Function = " string_constant " , Value = " " } } , variable_delegate ) ;
2016-07-25 05:42:23 +00:00
AddEvaluator ( " PlayerList " , nil , " $TriggeringPlayer$ " , " $TriggeringPlayerHelp$ " , " triggering_player_list " , [ def , def . EvalPlrList_Single , def . EvalPlr_Trigger ] ) ;
AddEvaluator ( " PlayerList " , nil , " $AllPlayers$ " , " $AllPlayersHelp$ " , " all_players " , [ def , def . EvalPlrList_All ] ) ;
2016-07-31 02:39:22 +00:00
AddEvaluator ( " PlayerList " , nil , " $Variable$ " , " $VariableHelp$ " , " player_list_variable " , [ def , def . EvalVariable , [ C4V_Int ] ] , { VariableName = { Function = " string_constant " , Value = " " } } , variable_delegate ) ;
2016-07-13 06:17:12 +00:00
// Boolean (condition) evaluators
2016-07-30 18:50:22 +00:00
AddEvaluator ( " Boolean " , nil , [ " $Constant$ " , " " ] , " $ConstantHelp$ " , " bool_constant " , [ def , def . EvalConstant ] , { Value = true } , { Type = " bool " , Name = " $Value$ " } ) ;
2016-07-30 21:39:15 +00:00
AddEvaluator ( " Boolean " , " $Comparison$ " , " $CompareInteger$ " , " $ComparisonHelp$ " , " compare_int " , [ def , def . EvalComparison , " Integer " ] , { } , { Type = " proplist " , Display = " {{LeftOperand}}{{Operator}}{{RightOperand}} " , ShowFullName = true , EditorProps = {
LeftOperand = new Evaluator . Integer { Name = " $LeftOperand$ " , EditorHelp = " $LeftOperandHelp$ " } ,
Operator = { Type = " enum " , Name = " $Operator$ " , EditorHelp = " $OperatorHelp$ " , Options = [
{ Name = " == " , EditorHelp = " $EqualHelp$ " } ,
{ Name = " != " , EditorHelp = " $NotEqualHelp$ " , Value = " ne " } ,
{ Name = " < " , EditorHelp = " $LessThanHelp$ " , Value = " lt " } ,
{ Name = " > " , EditorHelp = " $GreaterThanHelp$ " , Value = " gt " } ,
{ Name = " <= " , EditorHelp = " $LessOrEqualHelp$ " , Value = " le " } ,
{ Name = " >= " , EditorHelp = " $GreaterOrEqualHelp$ " , Value = " ge " }
] } ,
RightOperand = new Evaluator . Integer { Name = " $RightOperand$ " , EditorHelp = " $RightOperandHelp$ " }
} } ) ;
AddEvaluator ( " Boolean " , " $Comparison$ " , " $CompareObject$ " , " $ComparisonHelp$ " , " compare_object " , [ def , def . EvalComparison , " Object " ] , { } , { Type = " proplist " , Display = " {{LeftOperand}}{{Operator}}{{RightOperand}} " , ShowFullName = true , EditorProps = {
LeftOperand = new Evaluator . Object { Name = " $LeftOperand$ " , EditorHelp = " $LeftOperandHelp$ " } ,
Operator = { Type = " enum " , Name = " $Operator$ " , EditorHelp = " $OperatorHelp$ " , Options = [
{ Name = " == " , EditorHelp = " $EqualHelp$ " } ,
{ Name = " != " , EditorHelp = " $NotEqualHelp$ " , Value = " ne " } ,
] } ,
RightOperand = new Evaluator . Object { Name = " $RightOperand$ " , EditorHelp = " $RightOperandHelp$ " }
} } ) ;
AddEvaluator ( " Boolean " , " $Comparison$ " , " $CompareString$ " , " $ComparisonHelp$ " , " compare_string " , [ def , def . EvalComparison , " String " ] , { LeftOperand = { Function = " string_constant " , Value = " " } , RightOperand = { Function = " string_constant " , Value = " " } } , { Type = " proplist " , Display = " {{LeftOperand}}{{Operator}}{{RightOperand}} " , ShowFullName = true , EditorProps = {
LeftOperand = new Evaluator . String { Name = " $LeftOperand$ " , EditorHelp = " $LeftOperandHelp$ " } ,
Operator = { Type = " enum " , Name = " $Operator$ " , EditorHelp = " $OperatorHelp$ " , Options = [
{ Name = " == " , EditorHelp = " $EqualHelp$ " } ,
{ Name = " != " , EditorHelp = " $NotEqualHelp$ " , Value = " ne " } ,
] } ,
RightOperand = new Evaluator . String { Name = " $RightOperand$ " , EditorHelp = " $RightOperandHelp$ " }
} } ) ;
AddEvaluator ( " Boolean " , " $Comparison$ " , " $CompareDefinition$ " , " $ComparisonHelp$ " , " compare_definition " , [ def , def . EvalComparison , " Definition " ] , { } , { Type = " proplist " , Display = " {{LeftOperand}}{{Operator}}{{RightOperand}} " , ShowFullName = true , EditorProps = {
LeftOperand = new Evaluator . Definition { Name = " $LeftOperand$ " , EditorHelp = " $LeftOperandHelp$ " } ,
Operator = { Type = " enum " , Name = " $Operator$ " , EditorHelp = " $OperatorHelp$ " , Options = [
{ Name = " == " , EditorHelp = " $EqualHelp$ " } ,
{ Name = " != " , EditorHelp = " $NotEqualHelp$ " , Value = " ne " } ,
] } ,
RightOperand = new Evaluator . Definition { Name = " $RightOperand$ " , EditorHelp = " $RightOperandHelp$ " }
} } ) ;
AddEvaluator ( " Boolean " , " $Comparison$ " , " $ComparePlayer$ " , " $ComparisonHelp$ " , " compare_player " , [ def , def . EvalComparison , " Player " ] , { } , { Type = " proplist " , Display = " {{LeftOperand}}{{Operator}}{{RightOperand}} " , ShowFullName = true , EditorProps = {
LeftOperand = new Evaluator . Player { Name = " $LeftOperand$ " , EditorHelp = " $LeftOperandHelp$ " } ,
Operator = { Type = " enum " , Name = " $Operator$ " , EditorHelp = " $OperatorHelp$ " , Options = [
{ Name = " == " , EditorHelp = " $EqualHelp$ " } ,
{ Name = " != " , EditorHelp = " $NotEqualHelp$ " , Value = " ne " } ,
] } ,
RightOperand = new Evaluator . Player { Name = " $RightOperand$ " , EditorHelp = " $RightOperandHelp$ " }
} } ) ;
2016-07-30 21:47:45 +00:00
AddEvaluator ( " Boolean " , nil , " $ObjectExists$ " , " $ObjectExistsHelp$ " , " object_exists " , [ def , def . EvalBool_ObjectExists ] , { } , new Evaluator . Object { } , " Object " ) ;
2016-07-31 02:39:22 +00:00
AddEvaluator ( " Boolean " , nil , " $Variable$ " , " $VariableHelp$ " , " bool_variable " , [ def , def . EvalVariable , C4V_Bool ] , { VariableName = { Function = " string_constant " , Value = " " } } , variable_delegate ) ;
2016-07-29 03:44:10 +00:00
// Integer evaluators
2016-07-30 18:50:22 +00:00
AddEvaluator ( " Integer " , nil , [ " $Constant$ " , " " ] , " $ConstantHelp$ " , " int_constant " , [ def , def . EvalConstant ] , { Value = 0 } , { Type = " int " , Name = " $Value$ " } ) ;
AddEvaluator ( " Integer " , nil , " $Random$ " , " $RandomIntHelp$ " , " int_random " , [ def , def . EvalIntRandom ] , { Min = { Function = " int_constant " , Value = 0 } , Max = { Function = " int_constant " , Value = 99 } } , { Type = " proplist " , Display = " Rnd({{Min}}..{{Max}}) " , EditorProps = {
2016-07-30 15:03:26 +00:00
Min = new Evaluator . Integer { Name = " $Min$ " , EditorHelp = " $RandomMinHelp$ " } ,
Max = new Evaluator . Integer { Name = " $Max$ " , EditorHelp = " $RandomMaxHelp$ " }
} } ) ;
2016-07-31 03:49:45 +00:00
AddEvaluator ( " Integer " , nil , " $Distance$ " , " $DistanceHelp$ " , " distance " , [ def , def . EvalInt_Distance ] , { } , { Type = " proplist " , Display = " d({{PositionA}}..{{PositionB}}) " , EditorProps = {
PositionA = new Evaluator . Position { Name = " $PositionA$ " , EditorHelp = " $PositionAHelp$ " } ,
PositionB = new Evaluator . Position { Name = " $PositionB$ " , EditorHelp = " $PositionBHelp$ " }
} } ) ;
2016-07-31 02:39:22 +00:00
AddEvaluator ( " Integer " , nil , " $Variable$ " , " $VariableHelp$ " , " integer_variable " , [ def , def . EvalVariable , C4V_Int ] , { VariableName = { Function = " string_constant " , Value = " " } } , variable_delegate ) ;
2016-07-30 21:39:15 +00:00
// String evaluators
AddEvaluator ( " String " , nil , [ " $Constant$ " , " " ] , " $ConstantHelp$ " , " string_constant " , [ def , def . EvalConstant ] , { Value = " " } , { Type = " string " , Name = " $Value$ " } ) ;
2016-07-31 03:59:09 +00:00
AddEvaluator ( " String " , nil , [ " $ValueToString$ " , " " ] , " $ValueToStringHelp$ " , " value_to_string " , [ def , def . EvalStr_ValueToString ] , { } , new Evaluator . Any { } ) ;
2016-07-31 04:28:02 +00:00
AddEvaluator ( " String " , nil , " $Concat$ " , " $ConcatHelp$ " , " string_concat " , [ def , def . EvalStr_Concat ] , { Substrings = [ ] } , { Type = " proplist " , DescendPath = " Substrings " , Display = " {{Substrings}} " , EditorProps = {
Substrings = { Name = " $Substrings$ " , Type = " array " , Elements = Evaluator . String , DefaultValue = { Function = " string_constant " , Value = " " } }
} } ) ;
2016-07-31 02:39:22 +00:00
AddEvaluator ( " String " , nil , " $Variable$ " , " $VariableHelp$ " , " integer_variable " , [ def , def . EvalVariable , C4V_String ] , { VariableName = { Function = " string_constant " , Value = " " } } , variable_delegate ) ;
2016-07-30 05:06:21 +00:00
// Position evaluators
2016-07-30 18:50:22 +00:00
AddEvaluator ( " Position " , nil , [ " $ConstantPositionAbsolute$ " , " " ] , " $ConstantPositionAbsoluteHelp$ " , " position_constant " , [ def , def . EvalConstant ] , def . GetDefaultPosition , { Type = " point " , Name = " $Position$ " , Relative = false , Color = 0xff2000 } ) ;
AddEvaluator ( " Position " , nil , [ " $ConstantPositionRelative$ " , " + " ] , " $ConstantPositionRelativeHelp$ " , " position_constant_rel " , [ def , def . EvalPositionRelative ] , { Value = [ 0 , 0 ] } , { Type = " point " , Name = " $Position$ " , Relative = true , Color = 0xff0050 } ) ;
2016-07-30 06:06:54 +00:00
AddEvaluator ( " Position " , nil , " $Coordinates$ " , " $CoordinatesHelp$ " , " position_coordinates " , [ def , def . EvalCoordinates ] , def . GetDefaultCoordinates , { Type = " proplist " , Display = " ({{X}},{{Y}}) " , EditorProps = {
X = new Evaluator . Integer { Name = " X " , EditorHelp = " $PosXHelp$ " } ,
Y = new Evaluator . Integer { Name = " Y " , EditorHelp = " $PosYHelp$ " }
} } ) ;
AddEvaluator ( " Position " , nil , " $PositionOffset$ " , " $PositionOffsetHelp$ " , " position_offset " , [ def , def . EvalPositionOffset ] , { } , { Type = " proplist " , Display = " {{Position}}+{{Offset}} " , EditorProps = {
Position = new Evaluator . Position { EditorHelp = " $PositionOffsetPositionHelp$ " } ,
Offset = new Evaluator . Offset { EditorHelp = " $PositionOffsetOffsetHelp$ " }
} } ) ;
2016-07-30 15:14:12 +00:00
AddEvaluator ( " Position " , nil , " $ObjectPosition$ " , " $ObjectPositionHelp$ " , " object_position " , [ def , def . EvalPositionObject ] , { Object = { Function = " triggering_object " } } , new Evaluator . Object { EditorHelp = " $ObjectPositionObjectHelp$ " } , " Object " ) ;
2016-07-30 16:29:35 +00:00
AddEvaluator ( " Position " , " $RandomPosition$ " , " $RandomRectAbs$ " , " $RandomRectAbsHelp$ " , " random_pos_rect_abs " , [ def , def . EvalPos_RandomRect , false ] , def . GetDefaultRect , { Type = " rect " , Name = " $Rectangle$ " , Relative = false , Color = 0xffff00 } , " Area " ) ;
AddEvaluator ( " Position " , " $RandomPosition$ " , " $RandomRectRel$ " , " $RandomRectRelHelp$ " , " random_pos_rect_rel " , [ def , def . EvalPos_RandomRect , true ] , { Area = [ - 30 , - 30 , 60 , 60 ] } , { Type = " rect " , Name = " $Rectangle$ " , Relative = true , Color = 0x00ffff } , " Area " ) ;
AddEvaluator ( " Position " , " $RandomPosition$ " , " $RandomCircleAbs$ " , " $RandomCircleAbsHelp$ " , " random_pos_circle_abs " , [ def , def . EvalPos_RandomCircle , false ] , def . GetDefaultCircle , { Type = " circle " , Name = " $Circle$ " , Relative = false , CanMoveCenter = true , Color = 0xff00ff } , " Area " ) ;
AddEvaluator ( " Position " , " $RandomPosition$ " , " $RandomCircleRel$ " , " $RandomCircleRelHelp$ " , " random_pos_circle_rel " , [ def , def . EvalPos_RandomCircle , true ] , { Area = [ 50 , 0 , 0 ] } , { Type = " circle " , Name = " $Circle$ " , Relative = true , CanMoveCenter = true , Color = 0xa000a0 } , " Area " ) ;
2016-07-31 02:39:22 +00:00
AddEvaluator ( " Position " , nil , " $Variable$ " , " $VariableHelp$ " , " position_variable " , [ def , def . EvalVariable , [ C4V_Int , 2 ] ] , { VariableName = { Function = " string_constant " , Value = " " } } , variable_delegate ) ;
2016-07-30 06:06:54 +00:00
// Offset evaluators
2016-07-30 18:50:22 +00:00
AddEvaluator ( " Offset " , nil , [ " $ConstantOffsetRelative$ " , " " ] , " $ConstantOffsetRelativeHelp$ " , " offset_constant " , [ def , def . EvalConstant ] , { Value = [ 0 , 0 ] } , { Type = " point " , Name = " $Position$ " , Relative = true , Color = 0xff30ff } ) ;
AddEvaluator ( " Offset " , nil , [ " $Coordinates$ " , " " ] , " $CoordinatesHelp$ " , " offset_coordinates " , [ def , def . EvalCoordinates ] , { Value = { X = 0 , Y = 0 } } , { Type = " proplist " , Display = " ({{X}},{{Y}}) " , EditorProps = {
2016-07-30 06:06:54 +00:00
X = new Evaluator . Integer { Name = " X " , EditorHelp = " $OffXHelp$ " } ,
Y = new Evaluator . Integer { Name = " Y " , EditorHelp = " $OffYHelp$ " } ,
} } ) ;
2016-07-30 15:26:34 +00:00
AddEvaluator ( " Offset " , nil , " $AddOffsets$ " , " $AddOffsetsHelp$ " , " add_offsets " , [ def , def . EvalOffsetAdd ] , { } , { Type = " proplist " , Display = " {{Offset1}}+{{Offset2}} " , EditorProps = {
Offset1 = new Evaluator . Offset { EditorHelp = " $AddOffsetOffsetHelp$ " } ,
Offset2 = new Evaluator . Offset { EditorHelp = " $AddOffsetOffsetHelp$ " }
} } ) ;
AddEvaluator ( " Offset " , nil , " $DiffPositions$ " , " $DiffPositionsHelp$ " , " diff_positions " , [ def , def . EvalOffsetDiff ] , { } , { Type = " proplist " , Display = " {{PositionB}}-{{PositionA}} " , EditorProps = {
PositionA = new Evaluator . Position { Name = " $PositionA$ " , EditorHelp = " $PositionAHelp$ " } ,
PositionB = new Evaluator . Position { Name = " $PositionB$ " , EditorHelp = " $PositionBHelp$ " }
2016-07-30 06:06:54 +00:00
} } ) ;
2016-07-30 16:29:35 +00:00
AddEvaluator ( " Offset " , nil , " $RandomOffRectRel$ " , " $RandomRectRelHelp$ " , " random_off_rect_rel " , [ def , def . EvalPos_RandomRect , " rect " , false ] , { Area = [ - 30 , - 30 , 60 , 60 ] } , { Type = " rect " , Name = " $Rectangle$ " , Relative = true , Color = 0x00ffff } , " Area " ) ;
AddEvaluator ( " Offset " , nil , " $RandomOffCircleRel$ " , " $RandomCircleRelHelp$ " , " random_off_circle_rel " , [ def , def . EvalPos_RandomCircle , " circle " , false ] , { Area = [ 0 , 0 , 50 ] } , { Type = " circle " , Name = " $Circle$ " , Relative = true , CanMoveCenter = true , Color = 0xa000a0 } , " Area " ) ;
2016-07-31 02:39:22 +00:00
AddEvaluator ( " Offset " , nil , " $Variable$ " , " $VariableHelp$ " , " offset_variable " , [ def , def . EvalVariable , [ C4V_Int , 2 ] ] , { VariableName = { Function = " string_constant " , Value = " " } } , variable_delegate ) ;
2016-07-06 05:03:02 +00:00
// User action editor props
Prop = Evaluator . Action ;
2016-07-25 05:42:23 +00:00
PropProgressMode = { Name = " $UserActionProgressMode$ " , EditorHelp = " $UserActionProgressModeHelp$ " , Type = " enum " , Options = [ { Name = " $Session$ " , Value = " session " } , { Name = " $Player$ " , Value = " player " } , { Name = " $Global$ " } ] } ;
PropParallel = { Name = " $ParallelAction$ " , EditorHelp = " $ParallelActionHelp$ " , Type = " bool " } ;
2016-07-06 05:03:02 +00:00
return true ;
}
2016-07-30 17:21:38 +00:00
public func GetObjectEvaluator ( filter_def , name , help )
2016-07-13 06:17:12 +00:00
{
// Create copy of the Evaluator.Object delegate, but with the object_constant proplist replaced by a version with filter_def
var object_options = Evaluator . Object . Options [ : ] ;
var const_option = new EvaluatorDefs [ " object_constant " ] { } ;
const_option . Delegate = new const_option . Delegate { Filter = filter_def } ;
object_options [ const_option . OptionIndex ] = const_option ;
2016-07-30 17:21:38 +00:00
return new Evaluator . Object { Name = name , Options = object_options , EditorHelp = help } ;
2016-07-13 06:17:12 +00:00
}
2016-07-30 18:50:22 +00:00
public func AddEvaluator ( string eval_type , string group , name , string help , string identifier , callback_data , default_val , proplist delegate , string delegate_storage_key )
2016-07-06 05:03:02 +00:00
{
2016-07-13 06:17:12 +00:00
// Add an evaluator for one of the data types. Evaluators allow users to write small action sequences and scripts in the editor using dropdown lists.
// eval_type: Return type of the evaluator (Action, Object, Boolean, Player, etc. as defined in UserAction.Evaluator)
// group [optional] Localized name of sub-group for larger enums (i.e. actions)
2016-07-30 18:50:22 +00:00
// name: Localized name as it appears in the dropdown list of evaluators. May also be an array [name, short_name].
2016-07-13 06:17:12 +00:00
// identifier: Unique identifier that is used to store this action in savegames and look up the action def. Identifiers must be unique among all data types.
// callback_data: Array of [definition, definition.Function, parameter (optional)]. Function to be called when this evaluator is called
// default_val [optional]: Default value to be set when this evaluator is selected. Must be a proplist. Should contain values for all properties in the delegate
// delegate: Parameters for this evaluator
2016-07-31 02:39:22 +00:00
// Copy most boolean props to condition prop
if ( eval_type = = " Boolean " & & identifier ! = " bool_constant " )
{
AddEvaluator ( " Condition " , group , name , help , identifier , callback_data , default_val , delegate ) ;
}
// Copy all value evaluations
if ( eval_type ! = " Condition " & & eval_type ! = " Action " & & eval_type ! = " Any " )
{
if ( group ) group = Format ( " %s/%s " , EvaluatorTypeNames [ eval_type ] , group ) ; else group = EvaluatorTypeNames [ eval_type ] ;
AddEvaluator ( " Any " , group , name , help , identifier , callback_data , default_val , delegate ) ;
}
// Dissect parameters
2016-07-30 17:21:38 +00:00
if ( group ) group = GroupNames [ group ] ? ? group ; // resolve localized group name
2016-07-30 18:50:22 +00:00
var short_name ;
if ( GetType ( name ) = = C4V_Array )
{
short_name = name [ 1 ] ;
name = name [ 0 ] ;
}
2016-07-30 20:51:57 +00:00
else if ( delegate & & delegate . Type = = " proplist " & & ! delegate . ShowFullName )
2016-07-30 18:50:22 +00:00
{
// Proplist delegates provide their own display string and need not show the option name
short_name = " " ;
}
2016-07-06 05:03:02 +00:00
if ( ! default_val ) default_val = { } ;
var default_get ;
if ( GetType ( default_val ) = = C4V_Function )
{
default_get = default_val ;
default_val = Call ( default_get ) ;
}
2016-07-21 04:47:43 +00:00
default_val . Function = identifier ;
2016-07-30 18:50:22 +00:00
var action_def = { Name = name , ShortName = short_name , EditorHelp = help , Group = group , Value = default_val , OptionKey = " Function " , Delegate = delegate , Get = default_get } , n ;
2016-07-13 06:17:12 +00:00
if ( delegate )
2016-07-06 05:03:02 +00:00
{
2016-07-25 05:42:23 +00:00
if ( delegate . EditorProps | | delegate . Elements )
2016-07-13 06:17:12 +00:00
{
// Proplist of array parameter for this evaluator: Descend path title should be name
2016-07-13 21:18:08 +00:00
delegate . Name = name ;
2016-07-25 05:42:23 +00:00
var child_delegate = delegate ;
if ( delegate . DescendPath ) child_delegate = delegate . EditorProps [ delegate . DescendPath ] ;
if ( ! child_delegate . EditorHelp ) child_delegate . EditorHelp = help ;
2016-07-13 06:17:12 +00:00
}
else
{
// Any other parameter type: Store in value
2016-07-30 15:14:12 +00:00
action_def . ValueKey = delegate_storage_key ? ? " Value " ;
2016-07-13 06:17:12 +00:00
}
2016-07-06 05:03:02 +00:00
}
2016-07-13 06:17:12 +00:00
Evaluator [ eval_type ] . Options [ n = GetLength ( Evaluator [ eval_type ] . Options ) ] = action_def ;
action_def . OptionIndex = n ;
2016-07-31 02:39:22 +00:00
// Remember lookup table through identifier (ignore duplicates)
if ( eval_type ! = " Condition " & & eval_type ! = " Any " )
{
EvaluatorCallbacks [ identifier ] = callback_data ;
EvaluatorDefs [ identifier ] = action_def ;
}
2016-07-06 05:03:02 +00:00
return action_def ;
}
public func EvaluateValue ( string eval_type , proplist props , proplist context )
{
//Log("EvaluateValue %v %v %v", eval_type, props, context);
if ( ! props ) return nil ;
// Finish any hold-action
if ( context . hold = = props )
{
context . hold = nil ;
return context . hold_result ;
}
// Not on hold: Perform evaluation
2016-07-21 04:47:43 +00:00
var cb = EvaluatorCallbacks [ props . Function ] ;
2016-07-30 15:03:26 +00:00
/*var rval = cb[0]->Call(cb[1], props, context, cb[2]);
Log ( " %v <- EvaluateValue %v %v %v " , rval , eval_type , props , context ) ;
return rval ; */
2016-07-06 05:03:02 +00:00
return cb [ 0 ] - > Call ( cb [ 1 ] , props , context , cb [ 2 ] ) ;
}
2016-07-21 04:22:53 +00:00
public func EvaluateAction ( proplist props , object action_object , object triggering_object , int triggering_player , string progress_mode , bool allow_parallel , finish_callback )
2016-07-06 05:03:02 +00:00
{
2016-07-24 14:50:39 +00:00
// No action
if ( ! props ) if ( finish_callback ) return action_object - > Call ( finish_callback ) ; else return ;
2016-07-06 05:03:02 +00:00
// Determine context
var context ;
if ( ! progress_mode )
{
2016-07-21 04:22:53 +00:00
if ( ! ( context = props . _context ) )
props . _context = context = CreateObject ( UserAction ) ;
2016-07-06 05:03:02 +00:00
}
else if ( progress_mode = = " player " )
{
2016-07-21 04:22:53 +00:00
if ( ! props . _contexts ) props . _contexts = [ ] ;
2016-07-06 05:03:02 +00:00
var plr_id ;
if ( action_object ) plr_id = GetPlayerID ( action_object - > GetOwner ( ) ) ;
2016-07-21 04:22:53 +00:00
if ( ! ( context = props . _contexts [ plr_id ] ) )
props . _contexts [ plr_id ] = context = CreateObject ( UserAction ) ;
2016-07-06 05:03:02 +00:00
}
else // if (progress_mode == "session")
{
// Temporary context
context = CreateObject ( UserAction ) ;
context . temp = true ;
}
// Prevent duplicate parallel execution
2016-07-22 05:51:29 +00:00
if ( ! allow_parallel & & ( context . hold & & ! context . suspended ) ) return false ;
2016-07-06 05:03:02 +00:00
// Init context settings
2016-07-21 04:22:53 +00:00
context - > InitContext ( action_object , triggering_player , triggering_object , props ) ;
2016-07-06 05:03:02 +00:00
// Execute action
EvaluateValue ( " Action " , props , context ) ;
FinishAction ( context ) ;
2016-07-22 05:51:29 +00:00
return true ;
2016-07-06 05:03:02 +00:00
}
2016-07-21 04:22:53 +00:00
public func EvaluateCondition ( proplist props , object action_object , object triggering_object , int triggering_player )
{
// Build temp context
var context = CreateObject ( UserAction ) ;
context . temp = true ;
// Init context settings
context - > InitContext ( action_object , triggering_player , triggering_object , props ) ;
// Execute condition evaluator
var result = EvaluateValue ( " Condition " , props , context ) ;
// Cleanup
if ( context ) context - > RemoveObject ( ) ;
// Done
return result ;
}
2016-07-29 05:43:35 +00:00
private func EvaluatePosition ( proplist props , object context )
{
// Execute position evaluator; fall back to position of action object
var position = EvaluateValue ( " Position " , props , context ) ;
if ( ! position )
{
if ( context . action_object ) position = [ context . action_object - > GetX ( ) , context . action_object - > GetY ( ) ] ;
else position = [ 0 , 0 ] ;
}
return position ;
}
2016-07-30 06:06:54 +00:00
private func EvaluateOffset ( proplist props , object context )
{
// Execute offset evaluator; fall back to [0, 0]
return EvaluateValue ( " Offset " , props , context ) ? ? [ 0 , 0 ] ;
}
2016-07-06 05:03:02 +00:00
private func ResumeAction ( proplist context , proplist resume_props )
{
//Log("ResumeAction %v %v", context, resume_props);
// Resume only if on hold for the same entry
if ( context . hold ! = resume_props ) return ;
2016-07-29 05:43:35 +00:00
// Not if owning object is dead
if ( ! context . action_object ) return ;
2016-07-06 05:03:02 +00:00
// Resume action
EvaluateValue ( " Action " , context . root_action , context ) ;
// Cleanup action object (unless it ran into another hold)
FinishAction ( context ) ;
}
private func FinishAction ( proplist context )
{
// Cleanup action object (unless it's kept around for callbacks or to store sequence progress)
// Note that context.root_action.contexts is checked to kill session-contexts that try to suspend
// There would be no way to resume so just kill the context
2016-07-21 04:22:53 +00:00
if ( ! context . hold | | context . temp )
{
if ( context . action_object & & context . finish_callback ) context . action_object - > Call ( context . finish_callback , context ) ;
context - > RemoveObject ( ) ;
}
2016-07-06 05:03:02 +00:00
}
2016-07-13 06:17:12 +00:00
private func EvalConstant ( proplist props , proplist context ) { return props . Value ; }
2016-07-06 05:03:02 +00:00
private func EvalObj_ActionObject ( proplist props , proplist context ) { return context . action_object ; }
private func EvalObj_TriggeringObject ( proplist props , proplist context ) { return context . triggering_object ; }
2016-07-24 14:50:39 +00:00
private func EvalObj_TriggeringClonk ( proplist props , proplist context ) { return context . triggering_clonk ; }
2016-07-29 05:43:35 +00:00
private func EvalObj_LastCreatedObject ( proplist props , proplist context ) { return context . last_created_object ; }
2016-07-21 04:22:53 +00:00
private func EvalPlr_Trigger ( proplist props , proplist context ) { return context . triggering_player ; }
2016-07-06 05:03:02 +00:00
private func EvalPlrList_Single ( proplist props , proplist context , fn ) { return [ Call ( fn , props , context ) ] ; }
private func EvalPlrList_All ( proplist props , proplist context , fn )
{
var n = GetPlayerCount ( C4PT_User ) ;
var result = CreateArray ( n ) ;
for ( var i = 0 ; i < n ; + + i ) result [ i ] = GetPlayerByIndex ( i ) ;
return result ;
}
2016-07-30 21:39:15 +00:00
private func EvalComparison ( proplist props , proplist context , data_type )
{
var left = EvaluateValue ( data_type , props . LeftOperand , context ) ;
var right = EvaluateValue ( data_type , props . RightOperand , context ) ;
if ( ! left ) left = nil ; // 0 ==nil
if ( ! right ) right = nil ; // 0 == nil
var op = props . Operator ;
if ( ! op )
return left = = right ;
else if ( op = = " ne " )
return left ! = right ;
else if ( op = = " lt " )
return left < right ;
else if ( op = = " gt " )
return left > right ;
else if ( op = = " le " )
return left < = right ;
else if ( op = = " ge " )
return left > = right ;
}
2016-07-30 21:47:45 +00:00
private func EvalBool_ObjectExists ( proplist props , proplist context ) { return ! ! EvaluateValue ( " Object " , props . Object , context ) ; }
2016-07-30 22:00:04 +00:00
private func EvalDef_TypeOfObject ( proplist props , proplist context )
{
var obj = EvaluateValue ( " Object " , props . Object , context ) ;
if ( obj ) return obj - > GetID ( ) ;
}
2016-07-06 05:03:02 +00:00
private func EvalAct_Sequence ( proplist props , proplist context )
{
// Sequence execution: Iterate over actions until one action puts the context on hold
2016-07-13 21:39:36 +00:00
var n = GetLength ( props . Actions ) , sid = props . _sequence_id ;
if ( ! sid ) sid = props . _sequence_id = Format ( " %d " , + + UserAction_SequenceIDs ) ;
for ( var progress = context . sequence_progress [ sid ] ? ? 0 ; progress < n ; + + progress )
2016-07-06 05:03:02 +00:00
{
//Log("Sequence progress exec %v %v", progress, context.hold);
// goto preparations
context . sequence_had_goto [ sid ] = false ;
context . last_sequence = props ;
// Evaluate next sequence step
EvaluateValue ( " Action " , props . Actions [ progress ] , context ) ;
if ( context . hold | | context . suspended )
{
// Execution on hold (i.e. wait action). Stop execution for now
if ( ! context . hold ) progress = 0 ; // No hold specified: Stop with sequence reset
context . sequence_progress [ sid ] = progress ;
return ;
}
// Apply jump in the sequence
if ( context . sequence_had_goto [ sid ] ) progress = context . sequence_progress [ sid ] - 1 ;
}
// Sequence finished
context . last_sequence = nil ;
// Reset for next execution.
2016-07-13 21:39:36 +00:00
context . sequence_progress [ sid ] = 0 ;
2016-07-06 05:03:02 +00:00
}
private func EvalAct_Goto ( proplist props , proplist context )
{
// Apply goto by jumping in most recently executed sequence
if ( context . last_sequence )
{
2016-07-24 14:50:39 +00:00
context . sequence_progress [ context . last_sequence . _sequence_id ] = props . Index ;
context . sequence_had_goto [ context . last_sequence . _sequence_id ] = true ;
2016-07-06 05:03:02 +00:00
}
}
private func EvalAct_StopSequence ( proplist props , proplist context )
{
// Stop: Suspend without hold props, which causes all sequences to reset
context . hold = nil ;
context . suspended = true ;
}
private func EvalAct_SuspendSequence ( proplist props , proplist context )
{
// Suspend: Remember hold position and stop action execution
context . hold = props ;
context . suspended = true ;
}
private func EvalAct_Wait ( proplist props , proplist context )
{
// Wait for specified number of frames
context . hold = props ;
ScheduleCall ( context , UserAction . ResumeAction , props . Time , 1 , context , props ) ;
}
2016-07-29 03:44:10 +00:00
private func EvalAct_Sound ( proplist props , proplist context )
{
if ( ! props . Sound ) return ;
var sound_context = props . SourceObject ? ? Global ;
var volume = EvaluateValue ( " Integer " , props . Volume , context ) ;
var pitch = EvaluateValue ( " Integer " , props . Pitch , context ) ;
if ( props . TargetPlayers = = " all_players " )
{
sound_context - > Sound ( props . Sound , true , volume , nil , props . Loop , nil , pitch ) ;
}
else
{
for ( var plr in EvaluateValue ( " PlayerList " , props . TargetPlayers , context ) )
{
sound_context - > Sound ( props . Sound , false , volume , plr , props . Loop , nil , pitch ) ;
}
}
}
2016-07-29 05:43:35 +00:00
private func EvalAct_CreateObject ( proplist props , proplist context )
{
// Create a new object
var create_id = EvaluateValue ( " Definition " , props . ID , context ) ;
if ( ! create_id ) return ;
var owner = EvaluateValue ( " Player " , props . Owner , context ) ;
var container = EvaluateValue ( " Object " , props . Container , context ) ;
var obj ;
if ( container )
{
// Contained object
obj = container - > CreateContents ( create_id ) ;
if ( obj ) obj - > SetOwner ( owner ) ;
}
else
{
// Uncontained object
var position = EvaluatePosition ( props . Position , context ) ;
var speed_x = EvaluateValue ( " Integer " , props . SpeedX , context ) ;
var speed_y = EvaluateValue ( " Integer " , props . SpeedY , context ) ;
if ( props . CreateAbove )
obj = Global - > CreateObjectAbove ( create_id , position [ 0 ] , position [ 1 ] , owner ) ;
else
obj = Global - > CreateObject ( create_id , position [ 0 ] , position [ 1 ] , owner ) ;
// Default speed
2016-07-30 20:51:57 +00:00
if ( obj ) obj - > SetXDir ( speed_x ) ;
if ( obj ) obj - > SetYDir ( speed_y ) ;
2016-07-29 05:43:35 +00:00
}
// Remember object for later access
context . last_created_object = obj ;
}
2016-07-30 20:51:57 +00:00
private func EvalAct_CastObjects ( proplist props , proplist context )
{
// Cast objects in multiple directions
var create_id = EvaluateValue ( " Definition " , props . ID , context ) ;
if ( ! create_id ) return ;
var owner = EvaluateValue ( " Player " , props . Owner , context ) ;
var amount = EvaluateValue ( " Integer " , props . Amount , context ) ;
var speed = EvaluateValue ( " Integer " , props . Speed , context ) ;
var mean_angle = EvaluateValue ( " Integer " , props . MeanAngle , context ) ;
var angle_deviation = EvaluateValue ( " Integer " , props . AngleDeviation , context ) ;
var position = EvaluatePosition ( props . Position , context ) ;
context . last_casted_objects = CastObjects ( create_id , amount , speed , position [ 0 ] , position [ 1 ] , mean_angle , angle_deviation ) ;
}
2016-07-29 06:06:20 +00:00
private func EvalAct_RemoveObject ( proplist props , proplist context )
{
var obj = EvaluateValue ( " Object " , props . Object , context ) ;
if ( ! obj ) return ;
obj - > RemoveObject ( props . EjectContents ) ;
}
2016-07-31 04:05:58 +00:00
private func EvalAct_Log ( proplist props , proplist context )
{
Log ( EvaluateValue ( " String " , props . Message , context ) ) ;
}
2016-07-31 02:39:22 +00:00
private func GetVariableContext ( proplist props , proplist context )
{
// Resolve context for variable. Global or object context.
var var_context = EvaluateValue ( " Object " , props , context ) ;
if ( ! var_context )
{
if ( ! g_UserAction_global_vars ) g_UserAction_global_vars = { } ;
var_context = g_UserAction_global_vars ;
}
else
{
if ( ! var_context . user_variables ) var_context . user_variables = { } ;
var_context = var_context . user_variables ;
}
return var_context ;
}
private func EvalAct_SetVariable ( proplist props , proplist context )
{
// Assign variable
var var_context = GetVariableContext ( props . Context , context ) ;
var var_name = StringToIdentifier ( EvaluateValue ( " String " , props . VariableName , context ) ) ;
var value = EvaluateValue ( " Any " , props . Value , context ) ;
var_context [ var_name ] = value ;
}
private func EvalVariable ( proplist props , proplist context , expected_type )
{
// Get variable value
var var_context = GetVariableContext ( props . Context , context ) ;
var var_name = StringToIdentifier ( EvaluateValue ( " String " , props . VariableName , context ) ) ;
var value = var_context [ var_name ] ;
// Check type
var val_type = GetType ( value ) ;
if ( val_type ! = expected_type )
{
// Array types have special checking
if ( GetType ( expected_type ) = = C4V_Array )
{
var expected_len = expected_type [ 1 ] ;
var valid ;
if ( val_type = = C4V_Array )
{
// Check required length
if ( ! expected_len | | GetLength ( value ) = = expected_len )
{
// Check data type of contents
var subtype = expected_type [ 0 ] ;
valid = true ;
for ( var v in value ) if ( v & & GetType ( v ) ! = subtype ) valid = false ;
}
}
// Invalid value for expected array: Return default array.
// All nil is OK because there is no string list type and nil converts to 0.
if ( ! valid ) return CreateArray ( expected_len ) ;
}
else
{
// Type not matching. Construct default.
if ( expected_type = = C4V_Int ) return 0 ;
if ( expected_type = = C4V_Bool ) return ! ! value ; // This conversion is OK
if ( expected_type = = C4V_String ) return " " ;
return nil ;
}
}
// Value OK. Return it.
return value ;
}
2016-07-30 05:06:21 +00:00
private func GetDefaultPosition ( object target_object )
{
// Default position for constant absolute position evaluator: Use selected object position
var value ;
if ( target_object )
value = [ target_object - > GetX ( ) , target_object - > GetY ( ) ] ;
else
value = [ 0 , 0 ] ;
return { Function = " position_constant " , Value = value } ;
}
2016-07-30 06:06:54 +00:00
private func GetDefaultCoordinates ( object target_object )
{
// Default position for constant absolute position evaluator: Use selected object position
var value ;
if ( target_object )
value = { X = { Function = " int_constant " , Value = target_object - > GetX ( ) } , Y = { Function = " int_constant " , Value = target_object - > GetY ( ) } } ;
else
value = { X = 0 , Y = 0 } ;
value . Function = " position_coordinates " ;
return value ;
}
2016-07-30 16:29:35 +00:00
private func GetDefaultRect ( object target_object )
{
// Default rectangle around target object
var r ;
if ( target_object ) r = [ target_object - > GetX ( ) - 30 , target_object - > GetY ( ) - 30 , 60 , 60 ] ; else r = [ 100 , 100 , 100 , 100 ] ;
return { Function = " random_pos_rect_abs " , Area = r } ;
}
private func GetDefaultCircle ( object target_object )
{
// Default circle around target object
var r ;
if ( target_object ) r = [ 50 , target_object - > GetX ( ) , target_object - > GetY ( ) ] ; else r = [ 50 , 100 , 100 ] ;
return { Function = " random_pos_circle_abs " , Area = r } ;
}
private func EvalIntRandom ( proplist props , proplist context )
2016-07-30 15:03:26 +00:00
{
// Random value between min and max. Also allow them to be swapped.
var min = EvaluateValue ( " Integer " , props . Min , context ) ;
var max = EvaluateValue ( " Integer " , props . Max , context ) ;
var rmin = Min ( min , max ) ;
return Random ( Max ( max , min ) - rmin ) + rmin ;
}
2016-07-30 05:06:21 +00:00
private func EvalPositionRelative ( proplist props , proplist context )
{
// Return position relative to action_object
if ( context . action_object )
return [ props . Value [ 0 ] + context . action_object - > GetX ( ) , props . Value [ 1 ] + context . action_object - > GetY ( ) ] ;
else
return props . Value ;
}
2016-07-30 06:06:54 +00:00
private func EvalCoordinates ( proplist props , proplist context )
{
// Coordinate evaluation: Make array [X, Y]
return [ EvaluateValue ( " Integer " , props . X , context ) , EvaluateValue ( " Integer " , props . Y , context ) ] ;
}
private func EvalPositionOffset ( proplist props , proplist context )
{
var p = EvaluatePosition ( props . Position , context ) ;
var o = EvaluateOffset ( props . Offset , context ) ;
return [ p [ 0 ] + o [ 0 ] , p [ 1 ] + o [ 1 ] ] ;
}
2016-07-30 15:14:12 +00:00
private func EvalPositionObject ( proplist props , proplist context )
{
var obj = EvaluateValue ( " Object " , props . Object , context ) ;
if ( obj ) return [ obj - > GetX ( ) , obj - > GetY ( ) ] ;
return [ 0 , 0 ] ; // undefined object: Position is 0/0 default
}
2016-07-30 16:29:35 +00:00
private func EvalPos_RandomRect ( proplist props , proplist context , bool relative )
{
// Constant random distribution in rectangle
var a = props . Area ;
var rval = [ a [ 0 ] + Random ( a [ 2 ] ) , a [ 1 ] + Random ( a [ 3 ] ) ] ;
// Apply relative offset
if ( relative & & context . action_object )
{
rval [ 0 ] + = context . action_object - > GetX ( ) ;
rval [ 1 ] + = context . action_object - > GetY ( ) ;
}
return rval ;
}
private func EvalPos_RandomCircle ( proplist props , proplist context , bool relative )
{
// Constant random distribution in circle
var a = props . Area ;
var r = a [ 0 ] ;
r = Sqrt ( Random ( r * r ) ) ;
var ang = Random ( 360 ) ;
var x = Sin ( ang , r ) , y = Cos ( ang , r ) ;
var rval = [ a [ 1 ] + x , a [ 2 ] + y ] ;
// Apply relative offset
if ( relative & & context . action_object )
{
rval [ 0 ] + = context . action_object - > GetX ( ) ;
rval [ 1 ] + = context . action_object - > GetY ( ) ;
}
return rval ;
}
2016-07-30 15:26:34 +00:00
private func EvalOffsetAdd ( proplist props , proplist context )
2016-07-30 06:06:54 +00:00
{
var o1 = EvaluateOffset ( props . Offset1 , context ) ;
var o2 = EvaluateOffset ( props . Offset2 , context ) ;
return [ o1 [ 0 ] + o2 [ 0 ] , o1 [ 1 ] + o2 [ 1 ] ] ;
}
2016-07-30 15:26:34 +00:00
private func EvalOffsetDiff ( proplist props , proplist context )
{
var pA = EvaluatePosition ( props . PositionA , context ) ;
var pB = EvaluatePosition ( props . PositionB , context ) ;
return [ pB [ 0 ] - pA [ 0 ] , pB [ 1 ] - pA [ 1 ] ] ;
}
2016-07-31 03:49:45 +00:00
private func EvalInt_Distance ( proplist props , proplist context )
{
var pA = EvaluatePosition ( props . PositionA , context ) ;
var pB = EvaluatePosition ( props . PositionB , context ) ;
return Distance ( pA [ 0 ] , pA [ 1 ] , pB [ 0 ] , pB [ 1 ] ) ;
}
2016-07-31 03:59:09 +00:00
private func EvalStr_ValueToString ( proplist props , proplist context )
{
return Format ( " %v " , EvaluateValue ( " Any " , props . Value , context ) ) ;
}
2016-07-31 04:28:02 +00:00
private func EvalStr_Concat ( proplist props , proplist context )
{
var result = " " ;
for ( var s in props . Substrings ) result = Format ( " %s%s " , result , EvaluateValue ( " String " , s , context ) ) ;
return result ;
}
2016-07-31 03:49:45 +00:00
2016-07-21 04:22:53 +00:00
/* Context instance */
// Proplist holding progress in each sequence
local sequence_progress , sequence_had_goto ;
static UserAction_SequenceIDs ;
// Set to innermost sequence (for goto)
local last_sequence ;
// If this action is paused and will be resumed by a callback or by re-execution of the action, this property is set to the props of the holding action
local hold ;
// Set to true if action is on hold but waiting for re-execution
local suspended ;
// Return value if a value-providing evaluator is held
local hold_result ;
public func Initialize ( )
{
sequence_progress = { } ;
sequence_had_goto = { } ;
return true ;
}
public func InitContext ( object action_object , int triggering_player , object triggering_object , proplist props )
{
2016-07-24 14:50:39 +00:00
// Determine triggering player+objects
var triggering_clonk ;
// Triggering player unknown? Try fallback to the controller of the triggering object
if ( ! GetType ( triggering_player ) & & triggering_object )
2016-07-21 04:22:53 +00:00
{
2016-07-24 14:50:39 +00:00
triggering_player = triggering_object - > GetController ( ) ;
2016-07-21 04:22:53 +00:00
}
2016-07-24 14:50:39 +00:00
// Triggering clonk is the selected clonk of the triggering player
if ( GetType ( triggering_player ) )
2016-07-21 04:22:53 +00:00
{
2016-07-24 14:50:39 +00:00
triggering_clonk = GetCursor ( triggering_player ) ; ;
if ( ! triggering_clonk ) triggering_clonk = GetCrew ( triggering_player ) ;
2016-07-21 04:22:53 +00:00
}
2016-07-24 14:50:39 +00:00
// Triggering object: Fallback to triggering player clonk
if ( ! triggering_object ) triggering_object = triggering_clonk ;
2016-07-21 04:22:53 +00:00
// Init context settings
this . action_object = action_object ;
this . triggering_object = triggering_object ;
2016-07-24 14:50:39 +00:00
this . triggering_clonk = triggering_clonk ;
2016-07-21 04:22:53 +00:00
this . triggering_player = triggering_player ;
this . root_action = props ;
this . suspended = false ;
return true ;
}
2016-07-06 05:03:02 +00:00
public func MenuOK ( proplist menu_id , object clonk )
{
// Pressed 'Next' in dialogue: Resume in user action
UserAction - > ResumeAction ( this , this . hold ) ;
}
public func MenuSelectOption ( int index )
{
// Selected an option in dialogue: Resume at specified position in innermost sequence
if ( ! hold | | ! hold . Options ) return ;
var opt = this . hold . Options [ index ] ;
if ( opt & & last_sequence )
{
2016-07-31 03:00:18 +00:00
sequence_progress [ last_sequence . _sequence_id ] = opt . _goto ;
2016-07-06 05:03:02 +00:00
hold = nil ;
}
UserAction - > ResumeAction ( this , hold ) ;
}
2016-07-21 04:22:53 +00:00
public func SaveScenarioObject ( props ) { return false ; } // temp. don't save.