class LK_SeqFlow_Loop extends LK_SeqAct_FlowControl abstract; var const int InternalLoopInputIdx; var const int MainInputIdx; var const int CompletedOutputIdx; var const int LoopBodyIdx; var const int BreakInputIdx; var bool bHasProcessedChain; public event Activated() { if(InputLinks[MainInputIdx].bHasImpulse && !bHasProcessedChain) { ProcessLoopBody(); bHasProcessedChain = true; } } function ProcessLoopBody() { local int i; for(i = 0; i < OutputLinks[LoopBodyIdx].Links.Length; i++) { RecursiveProcessChain(OutputLinks[LoopBodyIdx].Links[i].LinkedOp, self); } } function RecursiveProcessChain(SequenceOp Op, LK_SeqFlow_Loop UpperCaller) { local int i, j; local SeqOpOutputInputLink l; if(LK_SeqAct_FlowControl(Op) != None && Op != self) { LK_SeqAct_FlowControl(Op).NotifiedByUpper(self); return; } for(i = 0; i < Op.OutputLinks.Length; i++) { if(Op.OutputLinks[i].Links.Length == 0) { l.LinkedOp = UpperCaller; l.InputLinkIdx = UpperCaller.InternalLoopInputIdx; Op.OutputLinks[i].Links.AddItem(l); continue; } for(j = 0; j < Op.OutputLinks[i].Links.Length; j++) { RecursiveProcessChain(Op.OutputLinks[i].Links[j].LinkedOp, UpperCaller); } } } public function NotifiedByUpper(LK_SeqFlow_Loop Op) { local SeqOpOutputInputLink l; local int i; Super.NotifiedByUpper(Op); ProcessLoopBody(); bHasProcessedChain = true; if(OutputLinks[CompletedOutputIdx].Links.Length == 0) { l.LinkedOp = Op; l.InputLinkIdx = Op.InternalLoopInputIdx; OutputLinks[CompletedOutputIdx].Links.AddItem(l); } else { for(i = 0; i < OutputLinks[CompletedOutputIdx].Links.Length; i++) { RecursiveProcessChain(OutputLinks[CompletedOutputIdx].Links[i].LinkedOp, UpperNode); } } } defaultproperties { OutputLinks.Empty OutputLinks(0) = (LinkDesc="Loop Body") OutputLinks(1) = (LinkDesc="Completed") LoopBodyIdx = 0; CompletedOutputIdx = 1; InputLinks.Empty; InputLinks(0) = (LinkDesc="In") InputLinks(1) = (LinkDesc="Loop Input (DO NOT USE)", bHidden=true) InputLinks(2) = (LinkDesc="Break", bHidden=true) // Don't connect to this, use the Break node instead. (Or do and experience the pain of kismetti) InternalLoopInputIdx = 1; MainInputIdx = 0; BreakInputIdx = 2; ObjComment = "Use the Continue and Break nodes for additional control within this scope." }