Advertisement
Guest User

Not the Unreal Source

a guest
Oct 11th, 2008
1,240
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 100.19 KB | None | 0 0
  1. /*=============================================================================
  2.     UnCorSc.cpp: UnrealScript execution and support code.
  3.     Copyright 1997-1999 Epic Games, Inc. All Rights Reserved.
  4.  
  5. Description:
  6.     UnrealScript execution and support code.
  7.  
  8. Revision history:
  9.     * Created by Tim Sweeney
  10.  
  11. =============================================================================*/
  12.  
  13. #include "CorePrivate.h"
  14. #include "OpCode.h"
  15.  
  16. /*-----------------------------------------------------------------------------
  17.     Globals.
  18. -----------------------------------------------------------------------------*/
  19.  
  20. void (UObject::*GNatives[EX_Max])( FFrame &Stack, RESULT_DECL );
  21. INT GNativeDuplicate=0;
  22.  
  23. void (UObject::*GCasts[CST_Max])( FFrame &Stack, RESULT_DECL );
  24. INT GCastDuplicate=0;
  25.  
  26. #define RUNAWAY_LIMIT 1000000
  27. #define RECURSE_LIMIT 250
  28.  
  29. #if DO_GUARD
  30.     static INT Runaway=0;
  31.     static INT Recurse=0;
  32.     #define CHECK_RUNAWAY {if( ++Runaway > RUNAWAY_LIMIT ) {if(!ParseParam(appCmdLine(),TEXT("norunaway"))&&(!GDebugger||GDebugger->NotifyInfiniteLoop())) Stack.Logf( NAME_Critical, TEXT("Runaway loop detected (over %i iterations)"), RUNAWAY_LIMIT ); Runaway=0;}}
  33.     void GInitRunaway() {Recurse=Runaway=0;}
  34. #else
  35.     #define CHECK_RUNAWAY
  36.     void GInitRunaway() {}
  37. #endif
  38.  
  39. #define IMPLEMENT_CAST_FUNCTION(cls,num,func) \
  40.         IMPLEMENT_FUNCTION(cls,-1,func); \
  41.         static BYTE cls##func##CastTemp = GRegisterCast( num, int##cls##func );
  42.  
  43. TCHAR* GetOpCodeName( BYTE OpCode )
  44. {
  45.     switch ( OpCode )
  46.     {
  47.     case DI_Let:                return TEXT("Let");
  48.     case DI_SimpleIf:           return TEXT("SimpleIf");
  49.     case DI_Switch:             return TEXT("Switch");
  50.     case DI_While:              return TEXT("While");
  51.     case DI_Assert:             return TEXT("Assert");
  52.     case DI_Return:             return TEXT("Return");
  53.     case DI_ReturnNothing:      return TEXT("ReturnNothing");
  54.     case DI_NewStack:           return TEXT("NewStack");
  55.     case DI_NewStackLatent:     return TEXT("NewStackLatent");
  56.     case DI_NewStackLabel:      return TEXT("NewStackLabel");
  57.     case DI_PrevStack:          return TEXT("PrevStack");
  58.     case DI_PrevStackLatent:    return TEXT("PrevStackLatent");
  59.     case DI_PrevStackLabel:     return TEXT("PrevStackLabel");
  60.     case DI_PrevStackState:     return TEXT("PrevStackState");
  61.     case DI_EFP:                return TEXT("EFP");
  62.     case DI_EFPOper:            return TEXT("EFPOper");
  63.     case DI_EFPIter:            return TEXT("EFPIter");
  64.     case DI_ForInit:            return TEXT("ForInit");
  65.     case DI_ForEval:            return TEXT("ForEval");
  66.     case DI_ForInc:             return TEXT("ForInc");
  67.     case DI_BreakLoop:          return TEXT("BreakLoop");
  68.     case DI_BreakFor:           return TEXT("BreakFor");
  69.     case DI_BreakForEach:       return TEXT("BreakForEach");
  70.     case DI_BreakSwitch:        return TEXT("BreakSwitch");
  71.     case DI_ContinueLoop:       return TEXT("ContinueLoop");
  72.     case DI_ContinueForeach:    return TEXT("ContinueForeach");
  73.     case DI_ContinueFor:        return TEXT("ContinueFor");
  74.     }
  75.  
  76.     return NULL;
  77. }
  78.  
  79. /*-----------------------------------------------------------------------------
  80.     FFrame implementation.
  81. -----------------------------------------------------------------------------*/
  82.  
  83. //
  84. // Error or warning handler.
  85. //
  86. void FFrame::Serialize( const TCHAR* V, EName Event )
  87. {
  88.     if( Event==NAME_Critical ) appErrorf
  89.     (
  90.         TEXT("%s (%s:%04X) %s"),
  91.         *Object->GetFullName(),
  92.         *Node->GetFullName(),
  93.         Code - &Node->Script(0),
  94.         V
  95.     );
  96.     else debugf
  97.     (
  98.         NAME_ScriptWarning,
  99.         TEXT("%s (%s:%04X) %s"),
  100.         *Object->GetFullName(),
  101.         *Node->GetFullName(),
  102.         Code - &Node->Script(0),
  103.         V
  104.     );
  105. }
  106.  
  107. /*-----------------------------------------------------------------------------
  108.     Global script execution functions.
  109. -----------------------------------------------------------------------------*/
  110.  
  111. //
  112. // Have an object go to a named state, and idle at no label.
  113. // If state is NAME_None or was not found, goes to no state.
  114. // Returns 1 if we went to a state, 0 if went to no state.
  115. //
  116. EGotoState UObject::GotoState( FName NewState, UBOOL bForceEvents )
  117. {
  118.     // check to see if this object even supports states
  119.     if (StateFrame == NULL)
  120.     {
  121.         return GOTOSTATE_NotFound;
  122.     }
  123.     // find the new state
  124.     UState* StateNode = NULL;
  125.     FName OldStateName = StateFrame->StateNode != Class ? StateFrame->StateNode->GetFName() : FName(NAME_None);
  126.     if (NewState != NAME_Auto)
  127.     {
  128.         // Find regular state.
  129.         StateNode = FindState( NewState );
  130.     }
  131.     else
  132.     {
  133.         // find the auto state.
  134.         for( TFieldIterator<UState,CLASS_IsAUState> It(GetClass()); It && !StateNode; ++It )
  135.         {
  136.             if( It->StateFlags & STATE_Auto )
  137.             {
  138.                 StateNode = *It;
  139.             }
  140.         }
  141.     }
  142.     // if no state was found, then go to the default class state
  143.     if (!StateNode)
  144.     {
  145.         NewState  = NAME_None;
  146.         StateNode = GetClass();
  147.     }
  148.     else
  149.     if (NewState == NAME_Auto)
  150.     {
  151.         // going to auto state.
  152.         NewState = StateNode->GetFName();
  153.     }
  154.     // Send EndState notification.
  155.     if (bForceEvents ||
  156.         (OldStateName!=NAME_None &&
  157.          NewState!=OldStateName &&
  158.          IsProbing(NAME_EndState) &&
  159.          !(GetFlags() & RF_InEndState)))
  160.     {
  161.         ClearFlags( RF_StateChanged );
  162.         SetFlags( RF_InEndState );
  163.         eventEndState();
  164.         ClearFlags( RF_InEndState );
  165.         if( GetFlags() & RF_StateChanged )
  166.         {
  167.             return GOTOSTATE_Preempted;
  168.         }
  169.     }
  170.     // clear the nested state stack
  171.     StateFrame->StateStack.Empty();
  172.     // clear the previous latent action if any
  173.     StateFrame->LatentAction = 0;
  174.     // set the new state
  175.     StateFrame->Node = StateNode;
  176.     StateFrame->StateNode = StateNode;
  177.     StateFrame->Code = NULL;
  178.     StateFrame->ProbeMask = (StateNode->ProbeMask | GetClass()->ProbeMask) & StateNode->IgnoreMask;
  179.     // Send BeginState notification.
  180.     if (bForceEvents ||
  181.         (NewState!=NAME_None &&
  182.          NewState!=OldStateName &&
  183.          IsProbing(NAME_BeginState)))
  184.     {
  185.         ClearFlags( RF_StateChanged );
  186.         eventBeginState();
  187.         // check to see if a new state change was instigated
  188.         if (GetFlags() & RF_StateChanged)
  189.         {
  190.             return GOTOSTATE_Preempted;
  191.         }
  192.     }
  193.     // Return result.
  194.     if( NewState != NAME_None )
  195.     {
  196.         SetFlags(RF_StateChanged);
  197.         return GOTOSTATE_Success;
  198.     }
  199.     return GOTOSTATE_NotFound;
  200. }
  201.  
  202. //
  203. // Goto a label in the current state.
  204. // Returns 1 if went, 0 if not found.
  205. //
  206. UBOOL UObject::GotoLabel( FName FindLabel )
  207. {
  208.     if( StateFrame )
  209.     {
  210.         StateFrame->LatentAction = 0;
  211.         if( FindLabel != NAME_None )
  212.         {
  213.             for( UState* SourceState=StateFrame->StateNode; SourceState; SourceState=SourceState->GetSuperState() )
  214.             {
  215.                 if( SourceState->LabelTableOffset != MAXWORD )
  216.                 {
  217.                     for( FLabelEntry* Label = (FLabelEntry *)&SourceState->Script(SourceState->LabelTableOffset); Label->Name!=NAME_None; Label++ )
  218.                     {
  219.                         if( Label->Name==FindLabel )
  220.                         {
  221.                             StateFrame->Node = SourceState;
  222.                             StateFrame->Code = &SourceState->Script(Label->iCode);
  223.                             return 1;
  224.                         }
  225.                     }
  226.                 }
  227.             }
  228.         }
  229.         StateFrame->Code = NULL;
  230.     }
  231.     return 0;
  232. }
  233.  
  234. /*-----------------------------------------------------------------------------
  235.     Natives.
  236. -----------------------------------------------------------------------------*/
  237.  
  238. //////////////////////////////
  239. // Undefined native handler //
  240. //////////////////////////////
  241.  
  242. void UObject::ExecutingBadStateCode(FFrame& Stack)
  243. {
  244.     Stack.Logf( NAME_Critical, TEXT("Unknown code token %02X"), Stack.Code[-1] );
  245. }
  246.  
  247. void UObject::execUndefined( FFrame& Stack, RESULT_DECL  )
  248. {
  249.     ExecutingBadStateCode(Stack);
  250. }
  251.  
  252. ///////////////
  253. // Variables //
  254. ///////////////
  255.  
  256. void UObject::execLocalVariable( FFrame& Stack, RESULT_DECL )
  257. {
  258.     checkSlow(Stack.Object==this);
  259.     checkSlow(Stack.Locals!=NULL);
  260.     GProperty = (UProperty*)Stack.ReadObject();
  261.     GPropAddr = Stack.Locals + GProperty->Offset;
  262.     GPropObject = NULL;
  263.     if( Result )
  264.         GProperty->CopyCompleteValue( Result, GPropAddr );
  265. }
  266. IMPLEMENT_FUNCTION( UObject, EX_LocalVariable, execLocalVariable );
  267.  
  268. void UObject::execInstanceVariable( FFrame& Stack, RESULT_DECL)
  269. {
  270.     GProperty = (UProperty*)Stack.ReadObject();
  271.     GPropAddr = (BYTE*)this + GProperty->Offset;
  272.     GPropObject = this;
  273.     if( Result )
  274.         GProperty->CopyCompleteValue( Result, GPropAddr );
  275. }
  276. IMPLEMENT_FUNCTION( UObject, EX_InstanceVariable, execInstanceVariable );
  277.  
  278. void UObject::execDefaultVariable( FFrame& Stack, RESULT_DECL )
  279. {
  280.     GProperty = (UProperty*)Stack.ReadObject();
  281.     GPropAddr = &GetClass()->Defaults(GProperty->Offset);
  282.     GPropObject = NULL;
  283.     if( Result )
  284.         GProperty->CopyCompleteValue( Result, GPropAddr );
  285. }
  286. IMPLEMENT_FUNCTION( UObject, EX_DefaultVariable, execDefaultVariable );
  287.  
  288. void UObject::execClassContext( FFrame& Stack, RESULT_DECL )
  289. {
  290.     // Get class expression.
  291.     UClass* ClassContext=NULL;
  292.     Stack.Step( Stack.Object, &ClassContext );
  293.  
  294.     // Execute expression in class context.
  295.     if( ClassContext )
  296.     {
  297.         Stack.Code += 3;
  298.         Stack.Step( ClassContext->GetDefaultObject(), Result );
  299.     }
  300.     else
  301.     {
  302.         if ( GProperty )
  303.         {
  304.             Stack.Logf( NAME_Error, TEXT("Accessed null class context '%s'"), GProperty->GetName() );
  305.         }
  306.         else
  307.         {
  308.             Stack.Logf( NAME_Error, TEXT("Accessed null class context") );
  309.         }
  310.  
  311.         if ( GDebugger )
  312.             GDebugger->NotifyAccessedNone();
  313.  
  314.         INT wSkip = Stack.ReadWord();
  315.         BYTE bSize = *Stack.Code++;
  316.         Stack.Code += wSkip;
  317.         GPropAddr = NULL;
  318.         GPropObject = NULL;
  319.         GProperty = NULL;
  320.         if( Result )
  321.             appMemzero( Result, bSize );
  322.     }
  323. }
  324. IMPLEMENT_FUNCTION( UObject, EX_ClassContext, execClassContext );
  325.  
  326. void UObject::execArrayElement( FFrame& Stack, RESULT_DECL )
  327. {
  328.     // Get array index expression.
  329.     INT Index=0;
  330.     Stack.Step( Stack.Object, &Index );
  331.  
  332.     // Get base element (must be a variable!!).
  333.     GProperty = NULL;
  334.     Stack.Step( this, NULL );
  335.     GPropObject = this;
  336.  
  337.     // Add scaled offset to base pointer.
  338.     if( GProperty && GPropAddr )
  339.     {
  340.         // Bounds check.
  341.         if( Index>=GProperty->ArrayDim || Index<0 )
  342.         {
  343.             // Display out-of-bounds warning and continue on with index clamped to valid range.
  344.             Stack.Logf( NAME_Error, TEXT("Accessed array '%s' out of bounds (%i/%i)"), GProperty->GetName(), Index, GProperty->ArrayDim );
  345.             Index = Clamp( Index, 0, GProperty->ArrayDim - 1 );
  346.         }
  347.  
  348.         // Update address.
  349.         GPropAddr += Index * GProperty->ElementSize;
  350.         if( Result )//!!
  351.             GProperty->CopySingleValue( Result, GPropAddr );
  352.     }
  353. }
  354. IMPLEMENT_FUNCTION( UObject, EX_ArrayElement, execArrayElement );
  355.  
  356. void UObject::execDebugInfo( FFrame& Stack, RESULT_DECL ) //DEBUGGER
  357. {
  358.     INT GVER        = Stack.ReadInt();
  359.    
  360.     // Correct version?
  361.     if( GVER != 100 )
  362.     {
  363.         Stack.Code -= sizeof(INT);
  364.         Stack.Code--;
  365.         return;
  366.     }
  367.    
  368.     INT LineNumber  = Stack.ReadInt();
  369.     INT InputPos    = Stack.ReadInt();
  370.     BYTE OpCode     = *Stack.Code++;
  371.  
  372.     // Only valid when the debugger is running.
  373.     if ( GDebugger != NULL )
  374.         GDebugger->DebugInfo( this, &Stack, OpCode, LineNumber, InputPos );
  375. }
  376. IMPLEMENT_FUNCTION( UObject, EX_DebugInfo, execDebugInfo );
  377.  
  378. void UObject::execDynArrayElement( FFrame& Stack, RESULT_DECL )
  379. {
  380.     // Get array index expression.
  381.     INT Index=0;
  382.     Stack.Step( Stack.Object, &Index );
  383.  
  384.     GProperty = NULL;
  385.     Stack.Step( this, NULL );
  386.     GPropObject = this;
  387.  
  388.     checkSlow(GProperty);
  389.     checkSlow(GProperty->IsA(UArrayProperty::StaticClass()));
  390.  
  391.     // Add scaled offset to base pointer.
  392.     if( GProperty && GPropAddr )
  393.     {
  394.         FArray* Array=(FArray*)GPropAddr;
  395.         UArrayProperty* ArrayProp = (UArrayProperty*)GProperty;
  396.         if( Index>=Array->Num() || Index<0 )
  397.         {
  398.             //if we are returning a value, check for out-of-bounds
  399.             if ( Result || Index<0 )
  400.             {
  401.                 Stack.Logf( NAME_Error, TEXT("Accessed array '%s' out of bounds (%i/%i)"), ArrayProp->GetName(), Index, Array->Num() );
  402.                 GPropAddr = 0;
  403.                 GPropObject = NULL;
  404.                 if (Result) appMemzero( Result, ArrayProp->Inner->ElementSize );
  405.                 return;
  406.             }
  407.             //if we are setting a value, allow the array to be resized
  408.             else
  409.             {
  410.                 Array->AddZeroed(ArrayProp->Inner->ElementSize,Index-Array->Num()+1);
  411.             }
  412.         }
  413.  
  414.         GPropAddr = (BYTE*)Array->GetData() + Index * ArrayProp->Inner->ElementSize;
  415.  
  416.         // Add scaled offset to base pointer.
  417.         if( Result )
  418.         {
  419.             ArrayProp->Inner->CopySingleValue( Result, GPropAddr );
  420.         }
  421.     }
  422. }
  423. IMPLEMENT_FUNCTION( UObject, EX_DynArrayElement, execDynArrayElement );
  424.  
  425. void UObject::execDynArrayLength( FFrame& Stack, RESULT_DECL )
  426. {
  427.     GProperty = NULL;
  428.     Stack.Step( this, NULL );
  429.     GPropObject = this;
  430.  
  431.     if (GPropAddr)
  432.     {
  433.         FArray* Array=(FArray*)GPropAddr;
  434.         if ( !Result )
  435.             GRuntimeUCFlags |= RUC_ArrayLengthSet; //so that EX_Let knows that this is a length 'set'-ting
  436.         else
  437.             *(INT*)Result = Array->Num();
  438.     }
  439. }
  440. IMPLEMENT_FUNCTION( UObject, EX_DynArrayLength, execDynArrayLength );
  441.  
  442. void UObject::execDynArrayInsert( FFrame& Stack, RESULT_DECL )
  443. {
  444.     GPropObject = this;
  445.     GProperty = NULL;
  446.     Stack.Step( this, NULL );
  447.     UArrayProperty* ArrayProperty = Cast<UArrayProperty>(GProperty);
  448.     FArray* Array=(FArray*)GPropAddr;
  449.  
  450.     P_GET_INT(Index);
  451.     P_GET_INT(Count);
  452.     if (Array && Count)
  453.     {
  454.         if ( Count < 0 )
  455.         {
  456.             Stack.Logf( TEXT("Attempt to insert a negative number of elements '%s'"), ArrayProperty->GetName() );
  457.             return;
  458.         }
  459.         if ( Index < 0 || Index > Array->Num() )
  460.         {
  461.             Stack.Logf( TEXT("Attempt to insert %i elements at %i an %i-element array '%s'"), Count, Index, Array->Num(), ArrayProperty->GetName() );
  462.             Index = Clamp(Index, 0,Array->Num());
  463.         }
  464.         Array->InsertZeroed( Index, Count, ArrayProperty->Inner->ElementSize);
  465.     }
  466. }
  467. IMPLEMENT_FUNCTION( UObject, EX_DynArrayInsert, execDynArrayInsert );
  468.  
  469. void UObject::execDynArrayRemove( FFrame& Stack, RESULT_DECL )
  470. {  
  471.     GProperty = NULL;
  472.     GPropObject = this;
  473.     Stack.Step( this, NULL );
  474.     UArrayProperty* ArrayProperty = Cast<UArrayProperty>(GProperty);
  475.     FArray* Array=(FArray*)GPropAddr;
  476.  
  477.     P_GET_INT(Index);
  478.     P_GET_INT(Count);
  479.     if (Array && Count)
  480.     {
  481.         if ( Count < 0 )
  482.         {
  483.             Stack.Logf( TEXT("Attempt to remove a negative number of elements '%s'"), ArrayProperty->GetName() );
  484.             return;
  485.         }
  486.         if ( Index < 0 || Index >= Array->Num() || Index + Count > Array->Num() )
  487.         {
  488.             if (Count == 1)
  489.                 Stack.Logf( TEXT("Attempt to remove element %i in an %i-element array '%s'"), Index, Array->Num(), ArrayProperty->GetName() );
  490.             else
  491.                 Stack.Logf( TEXT("Attempt to remove elements %i through %i in an %i-element array '%s'"), Index, Index+Count-1, Array->Num(), ArrayProperty->GetName() );
  492.             Index = Clamp(Index, 0,Array->Num());
  493.             if ( Index + Count > Array->Num() )
  494.                 Count = Array->Num() - Index;
  495.         }
  496.  
  497.         for (INT i=Index+Count-1; i>=Index; i--)
  498.             ArrayProperty->Inner->DestroyValue((BYTE*)Array->GetData() + ArrayProperty->Inner->ElementSize*i);
  499.         Array->Remove( Index, Count, ArrayProperty->Inner->ElementSize);
  500.     }
  501. }
  502. IMPLEMENT_FUNCTION( UObject, EX_DynArrayRemove, execDynArrayRemove );
  503.  
  504. void UObject::execBoolVariable( FFrame& Stack, RESULT_DECL )
  505. {
  506.     // Get bool variable.
  507.     BYTE B = *Stack.Code++;
  508.     UBoolProperty* Property;
  509. #if SERIAL_POINTER_INDEX
  510.     INT idx = *(INT*)Stack.Code;
  511.     checkSlow(idx < GTotalSerializedPointers);
  512.     Property = (UBoolProperty*) GSerializedPointers[idx];
  513. #else
  514.     Property = *(UBoolProperty**)Stack.Code;
  515. #endif
  516.  
  517.     (this->*GNatives[B])( Stack, NULL );
  518.     GProperty = Property;
  519.     GPropObject = this;
  520.  
  521.     // Note that we're not returning an in-place pointer to to the bool, so EX_Let
  522.     // must take special precautions with bools.
  523.     if( Result )
  524.         *(BITFIELD*)Result = (GPropAddr && (*(BITFIELD*)GPropAddr & ((UBoolProperty*)GProperty)->BitMask)) ? 1 : 0;
  525. }
  526. IMPLEMENT_FUNCTION( UObject, EX_BoolVariable, execBoolVariable );
  527.  
  528. void UObject::execStructMember( FFrame& Stack, RESULT_DECL )
  529. {
  530.     // Get structure element.
  531.     UProperty* Property = (UProperty*)Stack.ReadObject();
  532.  
  533.     // Get struct expression.
  534.     UStruct* Struct = CastChecked<UStruct>(Property->GetOuter());
  535.     BYTE* Buffer = (BYTE*)appAlloca(Struct->PropertiesSize);
  536.     appMemzero( Buffer, Struct->PropertiesSize );
  537.     GPropAddr = NULL;
  538.     Stack.Step( this, Buffer );
  539.  
  540.     // Set result.
  541.     GProperty = Property;
  542.     GPropObject = this;
  543.     if( GPropAddr )
  544.         GPropAddr += Property->Offset;
  545.     if( Result )
  546.         Property->CopyCompleteValue( Result, Buffer+Property->Offset );
  547.     for( UProperty* P=Struct->ConstructorLink; P; P=P->ConstructorLinkNext )
  548.         P->DestroyValue( Buffer + P->Offset );
  549. }
  550. IMPLEMENT_FUNCTION( UObject, EX_StructMember, execStructMember );
  551.  
  552. /////////////
  553. // Nothing //
  554. /////////////
  555.  
  556. void UObject::execNothing( FFrame& Stack, RESULT_DECL )
  557. {
  558.     // Do nothing.
  559. }
  560. IMPLEMENT_FUNCTION( UObject, EX_Nothing, execNothing );
  561.  
  562. void UObject::execNativeParm( FFrame& Stack, RESULT_DECL )
  563. {
  564.     UProperty* Property = (UProperty*)Stack.ReadObject();
  565.     if( Result )
  566.     {
  567.         GPropAddr = Stack.Locals + Property->Offset;
  568.         GPropObject = NULL;  
  569.         Property->CopyCompleteValue( Result, Stack.Locals + Property->Offset );
  570.     }
  571. }
  572. IMPLEMENT_FUNCTION( UObject, EX_NativeParm, execNativeParm );
  573.  
  574. void UObject::execEndFunctionParms( FFrame& Stack, RESULT_DECL )
  575. {
  576.     // For skipping over optional function parms without values specified.
  577.     GPropObject = NULL;  
  578.     Stack.Code--;
  579. }
  580. IMPLEMENT_FUNCTION( UObject, EX_EndFunctionParms, execEndFunctionParms );
  581.  
  582. //////////////
  583. // Commands //
  584. //////////////
  585.  
  586. void UObject::execStop( FFrame& Stack, RESULT_DECL )
  587. {
  588.     Stack.Code = NULL;
  589. }
  590. IMPLEMENT_FUNCTION( UObject, EX_Stop, execStop );
  591.  
  592. //@warning: Does not support UProperty's fully, will break when TArray's are supported in UnrealScript!
  593. void UObject::execSwitch( FFrame& Stack, RESULT_DECL )
  594. {
  595.     // Get switch size.
  596.     BYTE bSize = *Stack.Code++;
  597.  
  598.     // Get switch expression.
  599.     BYTE SwitchBuffer[1024], Buffer[1024];
  600.     appMemzero( Buffer,       sizeof(FString) );
  601.     appMemzero( SwitchBuffer, sizeof(FString) );
  602.     Stack.Step( Stack.Object, SwitchBuffer );
  603.  
  604.     // Check each case clause till we find a match.
  605.     for( ; ; )
  606.     {
  607.         // Skip over case token.
  608.         checkSlow(*Stack.Code==EX_Case);
  609.         Stack.Code++;
  610.  
  611.         // Get address of next handler.
  612.         INT wNext = Stack.ReadWord();
  613.         if( wNext == MAXWORD ) // Default case or end of cases.
  614.             break;
  615.  
  616.         // Get case expression.
  617.         Stack.Step( Stack.Object, Buffer );
  618.  
  619.         // Compare.
  620.         if( bSize ? (appMemcmp(SwitchBuffer,Buffer,bSize)==0) : (*(FString*)SwitchBuffer==*(FString*)Buffer) )
  621.             break;
  622.  
  623.         // Jump to next handler.
  624.         Stack.Code = &Stack.Node->Script(wNext);
  625.     }
  626.     if( !bSize )
  627.     {
  628.         (*(FString*)SwitchBuffer).~FString();
  629.         (*(FString*)Buffer      ).~FString();
  630.     }
  631. }
  632. IMPLEMENT_FUNCTION( UObject, EX_Switch, execSwitch );
  633.  
  634. void UObject::execCase( FFrame& Stack, RESULT_DECL )
  635. {
  636.     INT wNext = Stack.ReadWord();
  637.     if( wNext != MAXWORD )
  638.     {
  639.         // Skip expression.
  640.         BYTE Buffer[1024];
  641.         appMemzero( Buffer, sizeof(FString) );
  642.         Stack.Step( Stack.Object, Buffer );
  643.     }
  644. }
  645. IMPLEMENT_FUNCTION( UObject, EX_Case, execCase );
  646.  
  647. void UObject::execJump( FFrame& Stack, RESULT_DECL )
  648. {
  649.     CHECK_RUNAWAY;
  650.  
  651.     // Jump immediate.
  652.     INT Offset = Stack.ReadWord();
  653.     Stack.Code = &Stack.Node->Script(Offset);
  654. //  Stack.Code = &Stack.Node->Script(Stack.ReadWord() );
  655. }
  656. IMPLEMENT_FUNCTION( UObject, EX_Jump, execJump );
  657.  
  658. void UObject::execJumpIfNot( FFrame& Stack, RESULT_DECL )
  659. {
  660.     CHECK_RUNAWAY;
  661.  
  662.     // Get code offset.
  663.     INT wOffset = Stack.ReadWord();
  664.  
  665.     // Get boolean test value.
  666.     UBOOL Value=0;
  667.     Stack.Step( Stack.Object, &Value );
  668.  
  669.     // Jump if false.
  670.     if( !Value )
  671.         Stack.Code = &Stack.Node->Script( wOffset );
  672. }
  673. IMPLEMENT_FUNCTION( UObject, EX_JumpIfNot, execJumpIfNot );
  674.  
  675. void UObject::execAssert( FFrame& Stack, RESULT_DECL )
  676. {
  677.     // Get line number.
  678.     INT wLine = Stack.ReadWord();
  679.  
  680.     // Get boolean assert value.
  681.     DWORD Value=0;
  682.     Stack.Step( Stack.Object, &Value );
  683.  
  684.     // Check it.
  685.     if( !Value && (!GDebugger || !GDebugger->NotifyAssertionFailed( wLine )) )
  686.     {
  687.         Stack.Logf( NAME_Critical, TEXT("Assertion failed, line %i"), wLine );
  688.     }
  689. }
  690. IMPLEMENT_FUNCTION( UObject, EX_Assert, execAssert );
  691.  
  692. void UObject::execGotoLabel( FFrame& Stack, RESULT_DECL )
  693. {
  694.     P_GET_NAME(N);
  695.     if( !GotoLabel( N ) )
  696.         Stack.Logf( NAME_Error, TEXT("GotoLabel (%s): Label not found"), *N );
  697. }
  698. IMPLEMENT_FUNCTION( UObject, EX_GotoLabel, execGotoLabel );
  699.  
  700. ////////////////
  701. // Assignment //
  702. ////////////////
  703.  
  704. void UObject::execLet( FFrame& Stack, RESULT_DECL )
  705. {
  706.     checkSlow(!IsA(UBoolProperty::StaticClass()));
  707.  
  708.     // Get variable address.
  709.     GPropAddr = NULL;
  710.     Stack.Step( Stack.Object, NULL ); // Evaluate variable.
  711.     if( !GPropAddr )
  712.     {
  713.         Stack.Logf( NAME_ScriptWarning, TEXT("Attempt to assign variable through None") );
  714.         static BYTE Crud[1024];//@temp
  715.         GPropAddr = Crud;
  716.         appMemzero( GPropAddr, sizeof(FString) );
  717.     }
  718.     else if ( GPropObject && GProperty && (GProperty->PropertyFlags & CPF_Net) )
  719.         GPropObject->NetDirty(GProperty); //FIXME - use object property instead for performance
  720.  
  721.     if (GRuntimeUCFlags & RUC_ArrayLengthSet)
  722.     {
  723.         GRuntimeUCFlags &= ~RUC_ArrayLengthSet;
  724.         FArray* Array=(FArray*)GPropAddr;
  725.         UArrayProperty* ArrayProp = (UArrayProperty*)GProperty;
  726.         INT NewSize = 0;
  727.         Stack.Step( Stack.Object, &NewSize); // Evaluate expression into variable.
  728.         if (NewSize > Array->Num())
  729.         {
  730.             Array->AddZeroed(ArrayProp->Inner->ElementSize, NewSize-Array->Num());
  731.         }
  732.         else if (NewSize < Array->Num())
  733.         {
  734.             for (INT i=Array->Num()-1; i>=NewSize; i--)
  735.                 ArrayProp->Inner->DestroyValue((BYTE*)Array->GetData() + ArrayProp->Inner->ElementSize*i);
  736.             Array->Remove(NewSize, Array->Num()-NewSize, ArrayProp->Inner->ElementSize );
  737.         }
  738.     } else
  739.         Stack.Step( Stack.Object, GPropAddr ); // Evaluate expression into variable.
  740. }
  741. IMPLEMENT_FUNCTION( UObject, EX_Let, execLet );
  742.  
  743. void UObject::execLetBool( FFrame& Stack, RESULT_DECL )
  744. {
  745.     // Get variable address.
  746.     GPropAddr = NULL;
  747.     GProperty = NULL;
  748.     GPropObject = NULL;
  749.     Stack.Step( Stack.Object, NULL ); // Variable.
  750.     BITFIELD*      BoolAddr     = (BITFIELD*)GPropAddr;
  751.     UBoolProperty* BoolProperty = (UBoolProperty*)GProperty;
  752.     INT Value=0;  // must be INT...execTrue/execFalse return 32 bits. --ryan.
  753.     if ( GPropObject && GProperty && (GProperty->PropertyFlags & CPF_Net) )
  754.         GPropObject->NetDirty(GProperty);
  755.     Stack.Step( Stack.Object, &Value );
  756.     if( BoolAddr )
  757.     {
  758.         checkSlow(BoolProperty->IsA(UBoolProperty::StaticClass()));
  759.         if( Value ) *BoolAddr |=  BoolProperty->BitMask;
  760.         else        *BoolAddr &= ~BoolProperty->BitMask;
  761.     }
  762. }
  763. IMPLEMENT_FUNCTION( UObject, EX_LetBool, execLetBool );
  764.  
  765. /////////////////////////
  766. // Context expressions //
  767. /////////////////////////
  768.  
  769. void UObject::execSelf( FFrame& Stack, RESULT_DECL )
  770. {
  771.     // Get Self actor for this context.
  772.     *(UObject**)Result = this;
  773. }
  774. IMPLEMENT_FUNCTION( UObject, EX_Self, execSelf );
  775.  
  776. void UObject::execContext( FFrame& Stack, RESULT_DECL )
  777. {
  778.     // Get actor variable.
  779.     UObject* NewContext=NULL;
  780.     Stack.Step( this, &NewContext );
  781.  
  782.     // Execute or skip the following expression in the actor's context.
  783.     if( NewContext != NULL )
  784.     {
  785.         Stack.Code += 3;
  786.         Stack.Step( NewContext, Result );
  787.     }
  788.     else
  789.     {
  790.         if ( GProperty )
  791.             Stack.Logf( NAME_Warning, TEXT("Accessed None '%s'"), GProperty->GetName() );
  792.         else
  793.             Stack.Logf( NAME_Warning, TEXT("Accessed None"));
  794.  
  795.         // DEBUGGER
  796.  
  797.         if ( GDebugger )
  798.             GDebugger->NotifyAccessedNone();    // jmw
  799.  
  800.         INT wSkip = Stack.ReadWord();
  801.         BYTE bSize = *Stack.Code++;
  802.         Stack.Code += wSkip;
  803.         GPropAddr = NULL;
  804.         GProperty = NULL;
  805.         GPropObject = NULL;
  806.         if( Result )
  807.             appMemzero( Result, bSize );
  808.     }
  809. }
  810. IMPLEMENT_FUNCTION( UObject, EX_Context, execContext );
  811.  
  812. ////////////////////
  813. // Function calls //
  814. ////////////////////
  815.  
  816. void UObject::execVirtualFunction( FFrame& Stack, RESULT_DECL )
  817. {
  818.     // read the super byte
  819.     BYTE bSuper = *(BYTE*)Stack.Code;
  820.     Stack.Code += sizeof(BYTE);
  821.     UFunction *func = NULL;
  822.     FName funcName = Stack.ReadName();
  823.     // if calling super function
  824.     if (bSuper)
  825.     {
  826.         // get the last function on stack
  827.         UFunction *searchFunc = (UFunction*)Stack.Node;
  828.         if (searchFunc != NULL)
  829.         {
  830.             // build the list of states to search through
  831.             TArray<UState*> searchStates;
  832.             UState *testState = NULL;
  833.             if (StateFrame != NULL &&
  834.                 StateFrame->StateNode != NULL &&
  835.                 StateFrame->StateNode != GetClass())
  836.             {
  837.                 UState *baseState = StateFrame->StateNode;
  838.                 // if transitioned states within the function call,
  839.                 if (StateFrame->StateNode != searchFunc->GetOuter())
  840.                 {
  841.                     // use the previous state as a base for searching
  842.                     baseState = (UState*)searchFunc->GetOuter();
  843.                 }
  844.                 // otherwise use the current state as a base
  845.                 searchStates.AddItem(baseState);
  846.                 // search the state stack
  847.                 if (StateFrame->StateStack.Num() > 0)
  848.                 {
  849.                     for (INT idx = StateFrame->StateStack.Num() - 1; idx >= 0; idx--)
  850.                     {
  851.                         searchStates.AddItem(StateFrame->StateStack(idx).State);
  852.                     }
  853.                 }
  854.                 // next search the state inheritance chain
  855.                 testState = baseState->GetSuperState();
  856.                 while (testState != NULL)
  857.                 {
  858.                     searchStates.AddItem(testState);
  859.                     testState = testState->GetSuperState();
  860.                 }
  861.             }
  862.             // and last search the class inheritance chain
  863.             testState = GetClass();
  864.             while (testState != NULL)
  865.             {
  866.                 searchStates.AddUniqueItem(testState);
  867.                 testState = testState->GetSuperState();
  868.             }
  869.             // first, find where this function is in the state/class list
  870.             // then call the next version of the function that is found
  871.             UBOOL bFoundState = 0;
  872.             UFunction *testFunc = NULL;
  873.             for (INT idx = 0; idx < searchStates.Num() && func == NULL; idx++)
  874.             {
  875.                 if (!bFoundState &&
  876.                     searchStates(idx) == searchFunc->GetOuter())
  877.                 {
  878.                     bFoundState = 1;
  879.                 }
  880.                 else
  881.                 if (bFoundState)
  882.                 {
  883.                     testFunc = searchStates(idx)->FuncMap.FindRef(funcName);
  884.                     if (testFunc != NULL)
  885.                     {
  886.                         // found the next one up the chain
  887.                         func = testFunc;
  888.                     }
  889.                 }
  890.             }
  891.         }
  892.         if (func == NULL)
  893.         {
  894.             appErrorf(TEXT("Failed to find super function %s for object %s"),*funcName,GetFullName());
  895.         }
  896.     }
  897.     // default function search
  898.     if (func == NULL)
  899.     {
  900.         func = FindFunctionChecked(funcName,0);
  901.     }
  902.     // Call the virtual function.
  903.     CallFunction( Stack, Result, func );
  904. }
  905. IMPLEMENT_FUNCTION( UObject, EX_VirtualFunction, execVirtualFunction );
  906.  
  907. void UObject::execFinalFunction( FFrame& Stack, RESULT_DECL )
  908. {
  909.     // Call the final function.
  910.     CallFunction( Stack, Result, (UFunction*)Stack.ReadObject() );
  911. }
  912. IMPLEMENT_FUNCTION( UObject, EX_FinalFunction, execFinalFunction );
  913.  
  914. void UObject::execGlobalFunction( FFrame& Stack, RESULT_DECL )
  915. {
  916.     // Call global version of virtual function.
  917.     CallFunction( Stack, Result, FindFunctionChecked(Stack.ReadName(),1) );
  918. }
  919. IMPLEMENT_FUNCTION( UObject, EX_GlobalFunction, execGlobalFunction );
  920.  
  921. ///////////////////////
  922. // Delegates         //
  923. ///////////////////////
  924.  
  925. void UObject::execDelegateFunction( FFrame& Stack, RESULT_DECL )
  926. {
  927.     BYTE bLocalProp = *(BYTE*)Stack.Code;
  928.     Stack.Code += sizeof(BYTE);
  929.     // Look up delegate property.
  930.     UProperty* DelegateProperty = (UProperty*)Stack.ReadObject();
  931.     // read the delegate info
  932.     FScriptDelegate* Delegate = NULL;
  933.     if (bLocalProp)
  934.     {
  935.         // read off the stack
  936.         Delegate = (FScriptDelegate*)(Stack.Locals + DelegateProperty->Offset);
  937.     }
  938.     else
  939.     {
  940.         // read off the object
  941.         Delegate = (FScriptDelegate*)((BYTE*)this + DelegateProperty->Offset);
  942.     }
  943.     FName DelegateName = Stack.ReadName();
  944.     if( Delegate->Object && Delegate->Object->IsPendingKill() )
  945.     {
  946.         Delegate->Object = NULL;
  947.         Delegate->FunctionName = NAME_None;
  948.     }
  949.     if( Delegate->Object )
  950.         Delegate->Object->CallFunction( Stack, Result, Delegate->Object->FindFunctionChecked(Delegate->FunctionName) );
  951.     else
  952.         CallFunction( Stack, Result, FindFunctionChecked(DelegateName) );
  953. }
  954. IMPLEMENT_FUNCTION( UObject, EX_DelegateFunction, execDelegateFunction );
  955.  
  956. void UObject::execDelegateProperty( FFrame& Stack, RESULT_DECL )
  957. {
  958.     FName FunctionName = Stack.ReadName();
  959.     ((FScriptDelegate*)Result)->FunctionName = FunctionName;
  960.     if( FunctionName == NAME_None )
  961.         ((FScriptDelegate*)Result)->Object = NULL;
  962.     else
  963.         ((FScriptDelegate*)Result)->Object = this;
  964. }
  965. IMPLEMENT_FUNCTION( UObject, EX_DelegateProperty, execDelegateProperty );
  966.  
  967. void UObject::execLetDelegate( FFrame& Stack, RESULT_DECL )
  968. {
  969.     // Get variable address.
  970.     GPropAddr = NULL;
  971.     GProperty = NULL;
  972.     GPropObject = NULL;
  973.     Stack.Step( Stack.Object, NULL ); // Variable.
  974.     FScriptDelegate* DelegateAddr = (FScriptDelegate*)GPropAddr;
  975.     FScriptDelegate Delegate;
  976.     Stack.Step( Stack.Object, &Delegate );
  977.     if( DelegateAddr )
  978.     {
  979.         DelegateAddr->FunctionName = Delegate.FunctionName;
  980.         DelegateAddr->Object       = Delegate.Object;
  981.     }
  982. }
  983. IMPLEMENT_FUNCTION( UObject, EX_LetDelegate, execLetDelegate );
  984.  
  985.  
  986. ///////////////////////
  987. // Struct comparison //
  988. ///////////////////////
  989.  
  990. void UObject::execStructCmpEq( FFrame& Stack, RESULT_DECL )
  991. {
  992.     UStruct* Struct  = (UStruct*)Stack.ReadObject();
  993.     BYTE*    Buffer1 = (BYTE*)appAlloca(Struct->PropertiesSize);
  994.     BYTE*    Buffer2 = (BYTE*)appAlloca(Struct->PropertiesSize);
  995.     appMemzero( Buffer1, Struct->PropertiesSize );
  996.     appMemzero( Buffer2, Struct->PropertiesSize );
  997.     Stack.Step( this, Buffer1 );
  998.     Stack.Step( this, Buffer2 );
  999.     *(DWORD*)Result  = Struct->StructCompare( Buffer1, Buffer2 );
  1000. }
  1001. IMPLEMENT_FUNCTION( UObject, EX_StructCmpEq, execStructCmpEq );
  1002.  
  1003. void UObject::execStructCmpNe( FFrame& Stack, RESULT_DECL )
  1004. {
  1005.     UStruct* Struct = (UStruct*)Stack.ReadObject();
  1006.     BYTE*    Buffer1 = (BYTE*)appAlloca(Struct->PropertiesSize);
  1007.     BYTE*    Buffer2 = (BYTE*)appAlloca(Struct->PropertiesSize);
  1008.     appMemzero( Buffer1, Struct->PropertiesSize );
  1009.     appMemzero( Buffer2, Struct->PropertiesSize );
  1010.     Stack.Step( this, Buffer1 );
  1011.     Stack.Step( this, Buffer2 );
  1012.     *(DWORD*)Result = !Struct->StructCompare(Buffer1,Buffer2);
  1013. }
  1014. IMPLEMENT_FUNCTION( UObject, EX_StructCmpNe, execStructCmpNe );
  1015.  
  1016. ///////////////
  1017. // Constants //
  1018. ///////////////
  1019.  
  1020. void UObject::execIntConst( FFrame& Stack, RESULT_DECL )
  1021. {
  1022.     *(INT*)Result = Stack.ReadInt();
  1023. }
  1024. IMPLEMENT_FUNCTION( UObject, EX_IntConst, execIntConst );
  1025.  
  1026. void UObject::execFloatConst( FFrame& Stack, RESULT_DECL )
  1027. {
  1028.     *(FLOAT*)Result = Stack.ReadFloat();
  1029. }
  1030. IMPLEMENT_FUNCTION( UObject, EX_FloatConst, execFloatConst );
  1031.  
  1032. void UObject::execStringConst( FFrame& Stack, RESULT_DECL )
  1033. {
  1034.     *(FString*)Result = (ANSICHAR*)Stack.Code;
  1035.     while( *Stack.Code )
  1036.         Stack.Code++;
  1037.     Stack.Code++;
  1038. }
  1039. IMPLEMENT_FUNCTION( UObject, EX_StringConst, execStringConst );
  1040.  
  1041. void UObject::execUnicodeStringConst( FFrame& Stack, RESULT_DECL )
  1042. {
  1043.     *(FString*)Result = FString((UNICHAR*)Stack.Code);
  1044.     while( *(_WORD*)Stack.Code )
  1045.         Stack.Code+=sizeof(_WORD);
  1046.     Stack.Code+=sizeof(_WORD);
  1047. }
  1048. IMPLEMENT_FUNCTION( UObject, EX_UnicodeStringConst, execUnicodeStringConst );
  1049.  
  1050. void UObject::execObjectConst( FFrame& Stack, RESULT_DECL )
  1051. {
  1052.     *(UObject**)Result = (UObject*)Stack.ReadObject();
  1053. }
  1054. IMPLEMENT_FUNCTION( UObject, EX_ObjectConst, execObjectConst );
  1055.  
  1056. void UObject::execNameConst( FFrame& Stack, RESULT_DECL )
  1057. {
  1058.     *(FName*)Result = Stack.ReadName();
  1059. }
  1060. IMPLEMENT_FUNCTION( UObject, EX_NameConst, execNameConst );
  1061.  
  1062. void UObject::execByteConst( FFrame& Stack, RESULT_DECL )
  1063. {
  1064.     *(BYTE*)Result = *Stack.Code++;
  1065. }
  1066. IMPLEMENT_FUNCTION( UObject, EX_ByteConst, execByteConst );
  1067.  
  1068. void UObject::execIntZero( FFrame& Stack, RESULT_DECL )
  1069. {
  1070.     *(INT*)Result = 0;
  1071. }
  1072. IMPLEMENT_FUNCTION( UObject, EX_IntZero, execIntZero );
  1073.  
  1074. void UObject::execIntOne( FFrame& Stack, RESULT_DECL )
  1075. {
  1076.     *(INT*)Result = 1;
  1077. }
  1078. IMPLEMENT_FUNCTION( UObject, EX_IntOne, execIntOne );
  1079.  
  1080. void UObject::execTrue( FFrame& Stack, RESULT_DECL )
  1081. {
  1082.     *(INT*)Result = 1;
  1083. }
  1084. IMPLEMENT_FUNCTION( UObject, EX_True, execTrue );
  1085.  
  1086. void UObject::execFalse( FFrame& Stack, RESULT_DECL )
  1087. {
  1088.     *(DWORD*)Result = 0;
  1089. }
  1090. IMPLEMENT_FUNCTION( UObject, EX_False, execFalse );
  1091.  
  1092. void UObject::execNoObject( FFrame& Stack, RESULT_DECL )
  1093. {
  1094.     *(UObject**)Result = NULL;
  1095. }
  1096. IMPLEMENT_FUNCTION( UObject, EX_NoObject, execNoObject );
  1097.  
  1098. void UObject::execIntConstByte( FFrame& Stack, RESULT_DECL )
  1099. {
  1100.     *(INT*)Result = *Stack.Code++;
  1101. }
  1102. IMPLEMENT_FUNCTION( UObject, EX_IntConstByte, execIntConstByte );
  1103.  
  1104. /////////////////
  1105. // Conversions //
  1106. /////////////////
  1107.  
  1108. void UObject::execDynamicCast( FFrame& Stack, RESULT_DECL )
  1109. {
  1110.     UClass* Class = (UClass *)Stack.ReadObject();
  1111.  
  1112.     // Compile object expression.
  1113.     UObject* Castee = NULL;
  1114.     Stack.Step( Stack.Object, &Castee );
  1115.     *(UObject**)Result = (Castee && Castee->IsA(Class)) ? Castee : NULL;
  1116. }
  1117. IMPLEMENT_FUNCTION( UObject, EX_DynamicCast, execDynamicCast );
  1118.  
  1119. void UObject::execMetaCast( FFrame& Stack, RESULT_DECL )
  1120. {
  1121.     UClass* MetaClass = (UClass*)Stack.ReadObject();
  1122.  
  1123.     // Compile actor expression.
  1124.     UObject* Castee=NULL;
  1125.     Stack.Step( Stack.Object, &Castee );
  1126.     *(UObject**)Result = (Castee && Castee->IsA(UClass::StaticClass()) && ((UClass*)Castee)->IsChildOf(MetaClass)) ? Castee : NULL;
  1127. }
  1128. IMPLEMENT_FUNCTION( UObject, EX_MetaCast, execMetaCast );
  1129.  
  1130. void UObject::execPrimitiveCast( FFrame& Stack, RESULT_DECL )
  1131. {
  1132.     INT B = *(Stack.Code)++;
  1133.     (Stack.Object->*GCasts[B])( Stack, Result );
  1134. }
  1135. IMPLEMENT_FUNCTION( UObject, EX_PrimitiveCast, execPrimitiveCast );
  1136.  
  1137. void UObject::execByteToInt( FFrame& Stack, RESULT_DECL )
  1138. {
  1139.     BYTE B=0;
  1140.     Stack.Step( Stack.Object, &B );
  1141.     *(INT*)Result = B;
  1142. }
  1143. IMPLEMENT_CAST_FUNCTION( UObject, CST_ByteToInt, execByteToInt );
  1144.  
  1145. void UObject::execByteToBool( FFrame& Stack, RESULT_DECL )
  1146. {
  1147.     BYTE B=0;
  1148.     Stack.Step( Stack.Object, &B );
  1149.     *(DWORD*)Result = B ? 1 : 0;
  1150. }
  1151. IMPLEMENT_CAST_FUNCTION( UObject, CST_ByteToBool, execByteToBool );
  1152.  
  1153. void UObject::execByteToFloat( FFrame& Stack, RESULT_DECL )
  1154. {
  1155.     BYTE B=0;
  1156.     Stack.Step( Stack.Object, &B );
  1157.     *(FLOAT*)Result = B;
  1158. }
  1159. IMPLEMENT_CAST_FUNCTION( UObject, CST_ByteToFloat, execByteToFloat );
  1160.  
  1161. void UObject::execByteToString( FFrame& Stack, RESULT_DECL )
  1162. {
  1163.     P_GET_BYTE(B);
  1164.     // dump the enum string if possible
  1165.     UByteProperty *ByteProp = Cast<UByteProperty>(GProperty);
  1166.     if (ByteProp != NULL &&
  1167.         ByteProp->Enum != NULL &&
  1168.         B >= 0 && B < ByteProp->Enum->Names.Num())
  1169.     {
  1170.         *(FString*)Result = *ByteProp->Enum->Names(B);
  1171.     }
  1172.     else
  1173.     {
  1174.         *(FString*)Result = FString::Printf(TEXT("%i"),B);
  1175.     }
  1176. }
  1177. IMPLEMENT_CAST_FUNCTION( UObject, CST_ByteToString, execByteToString );
  1178.  
  1179. void UObject::execIntToByte( FFrame& Stack, RESULT_DECL )
  1180. {
  1181.     INT I=0;
  1182.     Stack.Step( Stack.Object, &I );
  1183.     *(BYTE*)Result = I;
  1184. }
  1185. IMPLEMENT_CAST_FUNCTION( UObject, CST_IntToByte, execIntToByte );
  1186.  
  1187. void UObject::execIntToBool( FFrame& Stack, RESULT_DECL )
  1188. {
  1189.     INT I=0;
  1190.     Stack.Step( Stack.Object, &I );
  1191.     *(INT*)Result = I ? 1 : 0;
  1192. }
  1193. IMPLEMENT_CAST_FUNCTION( UObject, CST_IntToBool, execIntToBool );
  1194.  
  1195. void UObject::execIntToFloat( FFrame& Stack, RESULT_DECL )
  1196. {
  1197.     INT I=0;
  1198.     Stack.Step( Stack.Object, &I );
  1199.     *(FLOAT*)Result = I;
  1200. }
  1201. IMPLEMENT_CAST_FUNCTION( UObject, CST_IntToFloat, execIntToFloat );
  1202.  
  1203. void UObject::execIntToString( FFrame& Stack, RESULT_DECL )
  1204. {
  1205.     P_GET_INT(I);
  1206.     *(FString*)Result = FString::Printf(TEXT("%i"),I);
  1207. }
  1208. IMPLEMENT_CAST_FUNCTION( UObject, CST_IntToString, execIntToString );
  1209.  
  1210. void UObject::execBoolToByte( FFrame& Stack, RESULT_DECL )
  1211. {
  1212.     UBOOL B=0;
  1213.     Stack.Step( Stack.Object, &B );
  1214.     *(BYTE*)Result = B & 1;
  1215. }
  1216. IMPLEMENT_CAST_FUNCTION( UObject, CST_BoolToByte, execBoolToByte );
  1217.  
  1218. void UObject::execBoolToInt( FFrame& Stack, RESULT_DECL )
  1219. {
  1220.     UBOOL B=0;
  1221.     Stack.Step( Stack.Object, &B );
  1222.     *(INT*)Result = B & 1;
  1223. }
  1224. IMPLEMENT_CAST_FUNCTION( UObject, CST_BoolToInt, execBoolToInt );
  1225.  
  1226. void UObject::execBoolToFloat( FFrame& Stack, RESULT_DECL )
  1227. {
  1228.     UBOOL B=0;
  1229.     Stack.Step( Stack.Object, &B );
  1230.     *(FLOAT*)Result = B & 1;
  1231. }
  1232. IMPLEMENT_CAST_FUNCTION( UObject, CST_BoolToFloat, execBoolToFloat );
  1233.  
  1234. void UObject::execBoolToString( FFrame& Stack, RESULT_DECL )
  1235. {
  1236.     P_GET_UBOOL(B);
  1237.     *(FString*)Result = B ? GTrue : GFalse;
  1238. }
  1239. IMPLEMENT_CAST_FUNCTION( UObject, CST_BoolToString, execBoolToString );
  1240.  
  1241. void UObject::execFloatToByte( FFrame& Stack, RESULT_DECL )
  1242. {
  1243.     FLOAT F=0.f;
  1244.     Stack.Step( Stack.Object, &F );
  1245.     *(BYTE*)Result = (BYTE)F;
  1246. }
  1247. IMPLEMENT_CAST_FUNCTION( UObject, CST_FloatToByte, execFloatToByte );
  1248.  
  1249. void UObject::execFloatToInt( FFrame& Stack, RESULT_DECL )
  1250. {
  1251.     FLOAT F=0.f;
  1252.     Stack.Step( Stack.Object, &F );
  1253.     *(INT*)Result = (INT)F;
  1254. }
  1255. IMPLEMENT_CAST_FUNCTION( UObject, CST_FloatToInt, execFloatToInt );
  1256.  
  1257. void UObject::execFloatToBool( FFrame& Stack, RESULT_DECL )
  1258. {
  1259.     FLOAT F=0.f;
  1260.     Stack.Step( Stack.Object, &F );
  1261.     *(DWORD*)Result = F!=0.f ? 1 : 0;
  1262. }
  1263. IMPLEMENT_CAST_FUNCTION( UObject, CST_FloatToBool, execFloatToBool );
  1264.  
  1265. void UObject::execFloatToString( FFrame& Stack, RESULT_DECL )
  1266. {
  1267.     P_GET_FLOAT(F);
  1268.     *(FString*)Result = FString::Printf(TEXT("%.2f"),F);
  1269. }
  1270. IMPLEMENT_CAST_FUNCTION( UObject, CST_FloatToString, execFloatToString );
  1271.  
  1272. void UObject::execObjectToBool( FFrame& Stack, RESULT_DECL )
  1273. {
  1274.     UObject* Obj=NULL;
  1275.     Stack.Step( Stack.Object, &Obj );
  1276.     *(DWORD*)Result = Obj!=NULL;
  1277. }
  1278. IMPLEMENT_CAST_FUNCTION( UObject, CST_ObjectToBool, execObjectToBool );
  1279.  
  1280. void UObject::execObjectToString( FFrame& Stack, RESULT_DECL )
  1281. {
  1282.     P_GET_OBJECT(UObject,Obj);
  1283.     *(FString*)Result = Obj ? Obj->GetPathName() : TEXT("None");
  1284. }
  1285. IMPLEMENT_CAST_FUNCTION( UObject, CST_ObjectToString, execObjectToString );
  1286.  
  1287. void UObject::execNameToBool( FFrame& Stack, RESULT_DECL )
  1288. {
  1289.     FName N=NAME_None;
  1290.     Stack.Step( Stack.Object, &N );
  1291.     *(DWORD*)Result = N!=NAME_None ? 1 : 0;
  1292. }
  1293. IMPLEMENT_CAST_FUNCTION( UObject, CST_NameToBool, execNameToBool );
  1294.  
  1295. void UObject::execNameToString( FFrame& Stack, RESULT_DECL )
  1296. {
  1297.     P_GET_NAME(N);
  1298.     *(FString*)Result = *N;
  1299. }
  1300. IMPLEMENT_CAST_FUNCTION( UObject, CST_NameToString, execNameToString );
  1301.  
  1302. void UObject::execStringToName( FFrame& Stack, RESULT_DECL )
  1303. {
  1304.     P_GET_STR(String);
  1305.     *(FName*)Result = FName(*String);
  1306. }
  1307. IMPLEMENT_CAST_FUNCTION( UObject, CST_StringToName, execStringToName );
  1308.  
  1309. void UObject::execStringToByte( FFrame& Stack, RESULT_DECL )
  1310. {
  1311.     P_GET_STR(Str);
  1312.     *(BYTE*)Result = appAtoi( *Str );
  1313. }
  1314. IMPLEMENT_CAST_FUNCTION( UObject, CST_StringToByte, execStringToByte );
  1315.  
  1316. void UObject::execStringToInt( FFrame& Stack, RESULT_DECL )
  1317. {
  1318.     P_GET_STR(Str);
  1319.     *(INT*)Result = appAtoi( *Str );
  1320. }
  1321. IMPLEMENT_CAST_FUNCTION( UObject, CST_StringToInt, execStringToInt );
  1322.  
  1323. void UObject::execStringToBool( FFrame& Stack, RESULT_DECL )
  1324. {
  1325.     P_GET_STR(Str);
  1326.     if( appStricmp(*Str,TEXT("True") )==0 || appStricmp(*Str,GTrue)==0 )
  1327.     {
  1328.         *(INT*)Result = 1;
  1329.     }
  1330.     else if( appStricmp(*Str,TEXT("False"))==0 || appStricmp(*Str,GFalse)==0 )
  1331.     {
  1332.         *(INT*)Result = 0;
  1333.     }
  1334.     else
  1335.     {
  1336.         *(INT*)Result = appAtoi(*Str) ? 1 : 0;
  1337.     }
  1338. }
  1339. IMPLEMENT_CAST_FUNCTION( UObject, CST_StringToBool, execStringToBool );
  1340.  
  1341. void UObject::execStringToFloat( FFrame& Stack, RESULT_DECL )
  1342. {
  1343.     P_GET_STR(Str);
  1344.     *(FLOAT*)Result = appAtof( *Str );
  1345. }
  1346. IMPLEMENT_CAST_FUNCTION( UObject, CST_StringToFloat, execStringToFloat );
  1347.  
  1348. /////////////////////////////////////////
  1349. // Native bool operators and functions //
  1350. /////////////////////////////////////////
  1351.  
  1352. void UObject::execNot_PreBool( FFrame& Stack, RESULT_DECL )
  1353. {
  1354.     P_GET_UBOOL(A);
  1355.     P_FINISH;
  1356.  
  1357.     *(DWORD*)Result = !A;
  1358. }
  1359. IMPLEMENT_FUNCTION( UObject, 129, execNot_PreBool );
  1360.  
  1361. void UObject::execEqualEqual_BoolBool( FFrame& Stack, RESULT_DECL )
  1362. {
  1363.     P_GET_UBOOL(A);
  1364.     P_GET_UBOOL(B);
  1365.     P_FINISH;
  1366.  
  1367.     *(DWORD*)Result = ((!A) == (!B));
  1368. }
  1369. IMPLEMENT_FUNCTION( UObject, 242, execEqualEqual_BoolBool );
  1370.  
  1371. void UObject::execNotEqual_BoolBool( FFrame& Stack, RESULT_DECL )
  1372. {
  1373.     P_GET_UBOOL(A);
  1374.     P_GET_UBOOL(B);
  1375.     P_FINISH;
  1376.  
  1377.     *(DWORD*)Result = ((!A) != (!B));
  1378. }
  1379. IMPLEMENT_FUNCTION( UObject, 243, execNotEqual_BoolBool );
  1380.  
  1381. void UObject::execAndAnd_BoolBool( FFrame& Stack, RESULT_DECL )
  1382. {
  1383.     P_GET_UBOOL(A);
  1384.     P_GET_SKIP_OFFSET(W);
  1385.  
  1386.     if( A )
  1387.     {
  1388.         P_GET_UBOOL(B);
  1389.         *(DWORD*)Result = A && B;
  1390.         Stack.Code++; //DEBUGGER
  1391.     }
  1392.     else
  1393.     {
  1394.         *(DWORD*)Result = 0;
  1395.         Stack.Code += W;
  1396.     }
  1397. }
  1398. IMPLEMENT_FUNCTION( UObject, 130, execAndAnd_BoolBool );
  1399.  
  1400. void UObject::execXorXor_BoolBool( FFrame& Stack, RESULT_DECL )
  1401. {
  1402.     P_GET_UBOOL(A);
  1403.     P_GET_UBOOL(B);
  1404.     P_FINISH;
  1405.  
  1406.     *(DWORD*)Result = !A ^ !B;
  1407. }
  1408. IMPLEMENT_FUNCTION( UObject, 131, execXorXor_BoolBool );
  1409.  
  1410. void UObject::execOrOr_BoolBool( FFrame& Stack, RESULT_DECL )
  1411. {
  1412.     P_GET_UBOOL(A);
  1413.     P_GET_SKIP_OFFSET(W);
  1414.     if( !A )
  1415.     {
  1416.         P_GET_UBOOL(B);
  1417.         *(DWORD*)Result = A || B;
  1418.         Stack.Code++; //DEBUGGER
  1419.     }
  1420.     else
  1421.     {
  1422.         *(DWORD*)Result = 1;
  1423.         Stack.Code += W;
  1424.     }
  1425. }
  1426. IMPLEMENT_FUNCTION( UObject, 132, execOrOr_BoolBool );
  1427.  
  1428. /////////////////////////////////////////
  1429. // Native byte operators and functions //
  1430. /////////////////////////////////////////
  1431.  
  1432. void UObject::execMultiplyEqual_ByteByte( FFrame& Stack, RESULT_DECL )
  1433. {
  1434.     P_GET_BYTE_REF(A);
  1435.     P_GET_BYTE(B);
  1436.     P_FINISH;
  1437.  
  1438.     *(BYTE*)Result = (*A *= B);
  1439. }
  1440. IMPLEMENT_FUNCTION( UObject, 133, execMultiplyEqual_ByteByte );
  1441.  
  1442. void UObject::execDivideEqual_ByteByte( FFrame& Stack, RESULT_DECL )
  1443. {
  1444.     P_GET_BYTE_REF(A);
  1445.     P_GET_BYTE(B);
  1446.     P_FINISH;
  1447.  
  1448.     *(BYTE*)Result = B ? (*A /= B) : 0;
  1449. }
  1450. IMPLEMENT_FUNCTION( UObject, 134, execDivideEqual_ByteByte );
  1451.  
  1452. void UObject::execAddEqual_ByteByte( FFrame& Stack, RESULT_DECL )
  1453. {
  1454.     P_GET_BYTE_REF(A);
  1455.     P_GET_BYTE(B);
  1456.     P_FINISH;
  1457.  
  1458.     *(BYTE*)Result = (*A += B);
  1459. }
  1460. IMPLEMENT_FUNCTION( UObject, 135, execAddEqual_ByteByte );
  1461.  
  1462. void UObject::execSubtractEqual_ByteByte( FFrame& Stack, RESULT_DECL )
  1463. {
  1464.     P_GET_BYTE_REF(A);
  1465.     P_GET_BYTE(B);
  1466.     P_FINISH;
  1467.  
  1468.     *(BYTE*)Result = (*A -= B);
  1469. }
  1470. IMPLEMENT_FUNCTION( UObject, 136, execSubtractEqual_ByteByte );
  1471.  
  1472. void UObject::execAddAdd_PreByte( FFrame& Stack, RESULT_DECL )
  1473. {
  1474.     P_GET_BYTE_REF(A);
  1475.     P_FINISH;
  1476.  
  1477.     *(BYTE*)Result = ++(*A);
  1478. }
  1479. IMPLEMENT_FUNCTION( UObject, 137, execAddAdd_PreByte );
  1480.  
  1481. void UObject::execSubtractSubtract_PreByte( FFrame& Stack, RESULT_DECL )
  1482. {
  1483.     P_GET_BYTE_REF(A);
  1484.     P_FINISH;
  1485.  
  1486.     *(BYTE*)Result = --(*A);
  1487. }
  1488. IMPLEMENT_FUNCTION( UObject, 138, execSubtractSubtract_PreByte );
  1489.  
  1490. void UObject::execAddAdd_Byte( FFrame& Stack, RESULT_DECL )
  1491. {
  1492.     P_GET_BYTE_REF(A);
  1493.     P_FINISH;
  1494.  
  1495.     *(BYTE*)Result = (*A)++;
  1496. }
  1497. IMPLEMENT_FUNCTION( UObject, 139, execAddAdd_Byte );
  1498.  
  1499. void UObject::execSubtractSubtract_Byte( FFrame& Stack, RESULT_DECL )
  1500. {
  1501.     P_GET_BYTE_REF(A);
  1502.     P_FINISH;
  1503.  
  1504.     *(BYTE*)Result = (*A)--;
  1505. }
  1506. IMPLEMENT_FUNCTION( UObject, 140, execSubtractSubtract_Byte );
  1507.  
  1508. /////////////////////////////////
  1509. // Int operators and functions //
  1510. /////////////////////////////////
  1511.  
  1512. void UObject::execComplement_PreInt( FFrame& Stack, RESULT_DECL )
  1513. {
  1514.     P_GET_INT(A);
  1515.     P_FINISH;
  1516.  
  1517.     *(INT*)Result = ~A;
  1518. }
  1519. IMPLEMENT_FUNCTION( UObject, 141, execComplement_PreInt );
  1520.  
  1521. void UObject::execGreaterGreaterGreater_IntInt( FFrame& Stack, RESULT_DECL )
  1522. {
  1523.     P_GET_INT(A);
  1524.     P_GET_INT(B);
  1525.     P_FINISH;
  1526.  
  1527.     *(INT*)Result = ((DWORD)A) >> B;
  1528. }
  1529. IMPLEMENT_FUNCTION( UObject, 196, execGreaterGreaterGreater_IntInt );
  1530.  
  1531. void UObject::execSubtract_PreInt( FFrame& Stack, RESULT_DECL )
  1532. {
  1533.     P_GET_INT(A);
  1534.     P_FINISH;
  1535.  
  1536.     *(INT*)Result = -A;
  1537. }
  1538. IMPLEMENT_FUNCTION( UObject, 143, execSubtract_PreInt );
  1539.  
  1540. void UObject::execMultiply_IntInt( FFrame& Stack, RESULT_DECL )
  1541. {
  1542.     P_GET_INT(A);
  1543.     P_GET_INT(B);
  1544.     P_FINISH;
  1545.  
  1546.     *(INT*)Result = A * B;
  1547. }
  1548. IMPLEMENT_FUNCTION( UObject, 144, execMultiply_IntInt );
  1549.  
  1550. void UObject::execDivide_IntInt( FFrame& Stack, RESULT_DECL )
  1551. {
  1552.     P_GET_INT(A);
  1553.     P_GET_INT(B);
  1554.     P_FINISH;
  1555.  
  1556.     if (B == 0)
  1557.     {
  1558.         Stack.Logf(NAME_ScriptWarning,TEXT("Divide by zero"));
  1559.     }
  1560.  
  1561.     *(INT*)Result = B ? A / B : 0;
  1562. }
  1563. IMPLEMENT_FUNCTION( UObject, 145, execDivide_IntInt );
  1564.  
  1565. void UObject::execAdd_IntInt( FFrame& Stack, RESULT_DECL )
  1566. {
  1567.     P_GET_INT(A);
  1568.     P_GET_INT(B);
  1569.     P_FINISH;
  1570.  
  1571.     *(INT*)Result = A + B;
  1572. }
  1573. IMPLEMENT_FUNCTION( UObject, 146, execAdd_IntInt );
  1574.  
  1575. void UObject::execSubtract_IntInt( FFrame& Stack, RESULT_DECL )
  1576. {
  1577.     P_GET_INT(A);
  1578.     P_GET_INT(B);
  1579.     P_FINISH;
  1580.  
  1581.     *(INT*)Result = A - B;
  1582. }
  1583. IMPLEMENT_FUNCTION( UObject, 147, execSubtract_IntInt );
  1584.  
  1585. void UObject::execLessLess_IntInt( FFrame& Stack, RESULT_DECL )
  1586. {
  1587.     P_GET_INT(A);
  1588.     P_GET_INT(B);
  1589.     P_FINISH;
  1590.  
  1591.     *(INT*)Result = A << B;
  1592. }
  1593. IMPLEMENT_FUNCTION( UObject, 148, execLessLess_IntInt );
  1594.  
  1595. void UObject::execGreaterGreater_IntInt( FFrame& Stack, RESULT_DECL )
  1596. {
  1597.     P_GET_INT(A);
  1598.     P_GET_INT(B);
  1599.     P_FINISH;
  1600.  
  1601.     *(INT*)Result = A >> B;
  1602. }
  1603. IMPLEMENT_FUNCTION( UObject, 149, execGreaterGreater_IntInt );
  1604.  
  1605. void UObject::execLess_IntInt( FFrame& Stack, RESULT_DECL )
  1606. {
  1607.     P_GET_INT(A);
  1608.     P_GET_INT(B);
  1609.     P_FINISH;
  1610.  
  1611.     *(DWORD*)Result = A < B;
  1612. }
  1613. IMPLEMENT_FUNCTION( UObject, 150, execLess_IntInt );
  1614.  
  1615. void UObject::execGreater_IntInt( FFrame& Stack, RESULT_DECL )
  1616. {
  1617.     P_GET_INT(A);
  1618.     P_GET_INT(B);
  1619.     P_FINISH;
  1620.  
  1621.     *(DWORD*)Result = A > B;
  1622. }
  1623. IMPLEMENT_FUNCTION( UObject, 151, execGreater_IntInt );
  1624.  
  1625. void UObject::execLessEqual_IntInt( FFrame& Stack, RESULT_DECL )
  1626. {
  1627.     P_GET_INT(A);
  1628.     P_GET_INT(B);
  1629.     P_FINISH;
  1630.  
  1631.     *(DWORD*)Result = A <= B;
  1632. }
  1633. IMPLEMENT_FUNCTION( UObject, 152, execLessEqual_IntInt );
  1634.  
  1635. void UObject::execGreaterEqual_IntInt( FFrame& Stack, RESULT_DECL )
  1636. {
  1637.     P_GET_INT(A);
  1638.     P_GET_INT(B);
  1639.     P_FINISH;
  1640.  
  1641.     *(DWORD*)Result = A >= B;
  1642. }
  1643. IMPLEMENT_FUNCTION( UObject, 153, execGreaterEqual_IntInt );
  1644.  
  1645. void UObject::execEqualEqual_IntInt( FFrame& Stack, RESULT_DECL )
  1646. {
  1647.     P_GET_INT(A);
  1648.     P_GET_INT(B);
  1649.     P_FINISH;
  1650.  
  1651.     *(DWORD*)Result = A == B;
  1652. }
  1653. IMPLEMENT_FUNCTION( UObject, 154, execEqualEqual_IntInt );
  1654.  
  1655. void UObject::execNotEqual_IntInt( FFrame& Stack, RESULT_DECL )
  1656. {
  1657.     P_GET_INT(A);
  1658.     P_GET_INT(B);
  1659.     P_FINISH;
  1660.  
  1661.     *(DWORD*)Result = A != B;
  1662. }
  1663. IMPLEMENT_FUNCTION( UObject, 155, execNotEqual_IntInt );
  1664.  
  1665. void UObject::execAnd_IntInt( FFrame& Stack, RESULT_DECL )
  1666. {
  1667.     P_GET_INT(A);
  1668.     P_GET_INT(B);
  1669.     P_FINISH;
  1670.  
  1671.     *(INT*)Result = A & B;
  1672. }
  1673. IMPLEMENT_FUNCTION( UObject, 156, execAnd_IntInt );
  1674.  
  1675. void UObject::execXor_IntInt( FFrame& Stack, RESULT_DECL )
  1676. {
  1677.     P_GET_INT(A);
  1678.     P_GET_INT(B);
  1679.     P_FINISH;
  1680.  
  1681.     *(INT*)Result = A ^ B;
  1682. }
  1683. IMPLEMENT_FUNCTION( UObject, 157, execXor_IntInt );
  1684.  
  1685. void UObject::execOr_IntInt( FFrame& Stack, RESULT_DECL )
  1686. {
  1687.     P_GET_INT(A);
  1688.     P_GET_INT(B);
  1689.     P_FINISH;
  1690.  
  1691.     *(INT*)Result = A | B;
  1692. }
  1693. IMPLEMENT_FUNCTION( UObject, 158, execOr_IntInt );
  1694.  
  1695. void UObject::execMultiplyEqual_IntFloat( FFrame& Stack, RESULT_DECL )
  1696. {
  1697.     P_GET_INT_REF(A);
  1698.     P_GET_FLOAT(B);
  1699.     P_FINISH;
  1700.  
  1701.     *(INT*)Result = *A = (INT)(*A * B);
  1702. }
  1703. IMPLEMENT_FUNCTION( UObject, 159, execMultiplyEqual_IntFloat );
  1704.  
  1705. void UObject::execDivideEqual_IntFloat( FFrame& Stack, RESULT_DECL )
  1706. {
  1707.     P_GET_INT_REF(A);
  1708.     P_GET_FLOAT(B);
  1709.     P_FINISH;
  1710.  
  1711.     *(INT*)Result = *A = (INT)(B ? *A/B : 0.f);
  1712. }
  1713. IMPLEMENT_FUNCTION( UObject, 160, execDivideEqual_IntFloat );
  1714.  
  1715. void UObject::execAddEqual_IntInt( FFrame& Stack, RESULT_DECL )
  1716. {
  1717.     P_GET_INT_REF(A);
  1718.     P_GET_INT(B);
  1719.     P_FINISH;
  1720.  
  1721.     *(INT*)Result = (*A += B);
  1722. }
  1723. IMPLEMENT_FUNCTION( UObject, 161, execAddEqual_IntInt );
  1724.  
  1725. void UObject::execSubtractEqual_IntInt( FFrame& Stack, RESULT_DECL )
  1726. {
  1727.     P_GET_INT_REF(A);
  1728.     P_GET_INT(B);
  1729.     P_FINISH;
  1730.  
  1731.     *(INT*)Result = (*A -= B);
  1732. }
  1733. IMPLEMENT_FUNCTION( UObject, 162, execSubtractEqual_IntInt );
  1734.  
  1735. void UObject::execAddAdd_PreInt( FFrame& Stack, RESULT_DECL )
  1736. {
  1737.     P_GET_INT_REF(A);
  1738.     P_FINISH;
  1739.  
  1740.     *(INT*)Result = ++(*A);
  1741. }
  1742. IMPLEMENT_FUNCTION( UObject, 163, execAddAdd_PreInt );
  1743.  
  1744. void UObject::execSubtractSubtract_PreInt( FFrame& Stack, RESULT_DECL )
  1745. {
  1746.     P_GET_INT_REF(A);
  1747.     P_FINISH;
  1748.  
  1749.     *(INT*)Result = --(*A);
  1750. }
  1751. IMPLEMENT_FUNCTION( UObject, 164, execSubtractSubtract_PreInt );
  1752.  
  1753. void UObject::execAddAdd_Int( FFrame& Stack, RESULT_DECL )
  1754. {
  1755.     P_GET_INT_REF(A);
  1756.     P_FINISH;
  1757.  
  1758.     *(INT*)Result = (*A)++;
  1759. }
  1760. IMPLEMENT_FUNCTION( UObject, 165, execAddAdd_Int );
  1761.  
  1762. void UObject::execSubtractSubtract_Int( FFrame& Stack, RESULT_DECL )
  1763. {
  1764.     P_GET_INT_REF(A);
  1765.     P_FINISH;
  1766.  
  1767.     *(INT*)Result = (*A)--;
  1768. }
  1769. IMPLEMENT_FUNCTION( UObject, 166, execSubtractSubtract_Int );
  1770.  
  1771. void UObject::execRand( FFrame& Stack, RESULT_DECL )
  1772. {
  1773.     P_GET_INT(A);
  1774.     P_FINISH;
  1775.  
  1776.     *(INT*)Result = A>0 ? (appRand() % A) : 0;
  1777. }
  1778. IMPLEMENT_FUNCTION( UObject, 167, execRand );
  1779.  
  1780. void UObject::execMin( FFrame& Stack, RESULT_DECL )
  1781. {
  1782.     P_GET_INT(A);
  1783.     P_GET_INT(B);
  1784.     P_FINISH;
  1785.  
  1786.     *(INT*)Result = Min(A,B);
  1787. }
  1788. IMPLEMENT_FUNCTION( UObject, 249, execMin );
  1789.  
  1790. void UObject::execMax( FFrame& Stack, RESULT_DECL )
  1791. {
  1792.     P_GET_INT(A);
  1793.     P_GET_INT(B);
  1794.     P_FINISH;
  1795.  
  1796.     *(INT*)Result = Max(A,B);
  1797. }
  1798. IMPLEMENT_FUNCTION( UObject, 250, execMax );
  1799.  
  1800. void UObject::execClamp( FFrame& Stack, RESULT_DECL )
  1801. {
  1802.     P_GET_INT(V);
  1803.     P_GET_INT(A);
  1804.     P_GET_INT(B);
  1805.     P_FINISH;
  1806.  
  1807.     *(INT*)Result = Clamp(V,A,B);
  1808. }
  1809. IMPLEMENT_FUNCTION( UObject, 251, execClamp );
  1810.  
  1811. ///////////////////////////////////
  1812. // Float operators and functions //
  1813. ///////////////////////////////////
  1814.  
  1815. void UObject::execSubtract_PreFloat( FFrame& Stack, RESULT_DECL )
  1816. {
  1817.     P_GET_FLOAT(A);
  1818.     P_FINISH;
  1819.  
  1820.     *(FLOAT*)Result = -A;
  1821. }  
  1822. IMPLEMENT_FUNCTION( UObject, 169, execSubtract_PreFloat );
  1823.  
  1824. void UObject::execMultiplyMultiply_FloatFloat( FFrame& Stack, RESULT_DECL )
  1825. {
  1826.     P_GET_FLOAT(A);
  1827.     P_GET_FLOAT(B);
  1828.     P_FINISH;
  1829.  
  1830.     *(FLOAT*)Result = appPow(A,B);
  1831. }  
  1832. IMPLEMENT_FUNCTION( UObject, 170, execMultiplyMultiply_FloatFloat );
  1833.  
  1834. void UObject::execMultiply_FloatFloat( FFrame& Stack, RESULT_DECL )
  1835. {
  1836.     P_GET_FLOAT(A);
  1837.     P_GET_FLOAT(B);
  1838.     P_FINISH;
  1839.  
  1840.     *(FLOAT*)Result = A * B;
  1841. }  
  1842. IMPLEMENT_FUNCTION( UObject, 171, execMultiply_FloatFloat );
  1843.  
  1844. void UObject::execDivide_FloatFloat( FFrame& Stack, RESULT_DECL )
  1845. {
  1846.     P_GET_FLOAT(A);
  1847.     P_GET_FLOAT(B);
  1848.     P_FINISH;
  1849.  
  1850.     *(FLOAT*)Result = A / B;
  1851. }  
  1852. IMPLEMENT_FUNCTION( UObject, 172, execDivide_FloatFloat );
  1853.  
  1854. void UObject::execPercent_FloatFloat( FFrame& Stack, RESULT_DECL )
  1855. {
  1856.     P_GET_FLOAT(A);
  1857.     P_GET_FLOAT(B);
  1858.     P_FINISH;
  1859.  
  1860.     *(FLOAT*)Result = appFmod(A,B);
  1861. }  
  1862. IMPLEMENT_FUNCTION( UObject, 173, execPercent_FloatFloat );
  1863.  
  1864. void UObject::execAdd_FloatFloat( FFrame& Stack, RESULT_DECL )
  1865. {
  1866.     P_GET_FLOAT(A);
  1867.     P_GET_FLOAT(B);
  1868.     P_FINISH;
  1869.  
  1870.     *(FLOAT*)Result = A + B;
  1871. }  
  1872. IMPLEMENT_FUNCTION( UObject, 174, execAdd_FloatFloat );
  1873.  
  1874. void UObject::execSubtract_FloatFloat( FFrame& Stack, RESULT_DECL )
  1875. {
  1876.     P_GET_FLOAT(A);
  1877.     P_GET_FLOAT(B);
  1878.     P_FINISH;
  1879.  
  1880.     *(FLOAT*)Result = A - B;
  1881. }  
  1882. IMPLEMENT_FUNCTION( UObject, 175, execSubtract_FloatFloat );
  1883.  
  1884. void UObject::execLess_FloatFloat( FFrame& Stack, RESULT_DECL )
  1885. {
  1886.     P_GET_FLOAT(A);
  1887.     P_GET_FLOAT(B);
  1888.     P_FINISH;
  1889.  
  1890.     *(DWORD*)Result = A < B;
  1891. }  
  1892. IMPLEMENT_FUNCTION( UObject, 176, execLess_FloatFloat );
  1893.  
  1894. void UObject::execGreater_FloatFloat( FFrame& Stack, RESULT_DECL )
  1895. {
  1896.     P_GET_FLOAT(A);
  1897.     P_GET_FLOAT(B);
  1898.     P_FINISH;
  1899.  
  1900.     *(DWORD*)Result = A > B;
  1901. }  
  1902. IMPLEMENT_FUNCTION( UObject, 177, execGreater_FloatFloat );
  1903.  
  1904. void UObject::execLessEqual_FloatFloat( FFrame& Stack, RESULT_DECL )
  1905. {
  1906.     P_GET_FLOAT(A);
  1907.     P_GET_FLOAT(B);
  1908.     P_FINISH;
  1909.  
  1910.     *(DWORD*)Result = A <= B;
  1911. }  
  1912. IMPLEMENT_FUNCTION( UObject, 178, execLessEqual_FloatFloat );
  1913.  
  1914. void UObject::execGreaterEqual_FloatFloat( FFrame& Stack, RESULT_DECL )
  1915. {
  1916.     P_GET_FLOAT(A);
  1917.     P_GET_FLOAT(B);
  1918.     P_FINISH;
  1919.  
  1920.     *(DWORD*)Result = A >= B;
  1921. }  
  1922. IMPLEMENT_FUNCTION( UObject, 179, execGreaterEqual_FloatFloat );
  1923.  
  1924. void UObject::execEqualEqual_FloatFloat( FFrame& Stack, RESULT_DECL )
  1925. {
  1926.     P_GET_FLOAT(A);
  1927.     P_GET_FLOAT(B);
  1928.     P_FINISH;
  1929.  
  1930.     *(DWORD*)Result = A == B;
  1931. }  
  1932. IMPLEMENT_FUNCTION( UObject, 180, execEqualEqual_FloatFloat );
  1933.  
  1934. void UObject::execNotEqual_FloatFloat( FFrame& Stack, RESULT_DECL )
  1935. {
  1936.     P_GET_FLOAT(A);
  1937.     P_GET_FLOAT(B);
  1938.     P_FINISH;
  1939.  
  1940.     *(DWORD*)Result = A != B;
  1941. }  
  1942. IMPLEMENT_FUNCTION( UObject, 181, execNotEqual_FloatFloat );
  1943.  
  1944. void UObject::execComplementEqual_FloatFloat( FFrame& Stack, RESULT_DECL )
  1945. {
  1946.     P_GET_FLOAT(A);
  1947.     P_GET_FLOAT(B);
  1948.     P_FINISH;
  1949.  
  1950.     *(DWORD*)Result = Abs(A - B) < (1.e-4);
  1951. }  
  1952. IMPLEMENT_FUNCTION( UObject, 210, execComplementEqual_FloatFloat );
  1953.  
  1954. void UObject::execMultiplyEqual_FloatFloat( FFrame& Stack, RESULT_DECL )
  1955. {
  1956.     P_GET_FLOAT_REF(A);
  1957.     P_GET_FLOAT(B);
  1958.     P_FINISH;
  1959.  
  1960.     *(FLOAT*)Result = (*A *= B);
  1961. }  
  1962. IMPLEMENT_FUNCTION( UObject, 182, execMultiplyEqual_FloatFloat );
  1963.  
  1964. void UObject::execDivideEqual_FloatFloat( FFrame& Stack, RESULT_DECL )
  1965. {
  1966.     P_GET_FLOAT_REF(A);
  1967.     P_GET_FLOAT(B);
  1968.     P_FINISH;
  1969.  
  1970.     if (B == 0.f)
  1971.     {
  1972.         Stack.Logf(NAME_ScriptWarning,TEXT("Divide by zero"));
  1973.     }
  1974.  
  1975.     *(FLOAT*)Result = (*A /= B);
  1976. }  
  1977. IMPLEMENT_FUNCTION( UObject, 183, execDivideEqual_FloatFloat );
  1978.  
  1979. void UObject::execAddEqual_FloatFloat( FFrame& Stack, RESULT_DECL )
  1980. {
  1981.     P_GET_FLOAT_REF(A);
  1982.     P_GET_FLOAT(B);
  1983.     P_FINISH;
  1984.  
  1985.     *(FLOAT*)Result = (*A += B);
  1986. }  
  1987. IMPLEMENT_FUNCTION( UObject, 184, execAddEqual_FloatFloat );
  1988.  
  1989. void UObject::execSubtractEqual_FloatFloat( FFrame& Stack, RESULT_DECL )
  1990. {
  1991.     P_GET_FLOAT_REF(A);
  1992.     P_GET_FLOAT(B);
  1993.     P_FINISH;
  1994.  
  1995.     *(FLOAT*)Result = (*A -= B);
  1996. }  
  1997. IMPLEMENT_FUNCTION( UObject, 185, execSubtractEqual_FloatFloat );
  1998.  
  1999. void UObject::execAbs( FFrame& Stack, RESULT_DECL )
  2000. {
  2001.     P_GET_FLOAT(A);
  2002.     P_FINISH;
  2003.  
  2004.     *(FLOAT*)Result = Abs(A);
  2005. }  
  2006. IMPLEMENT_FUNCTION( UObject, 186, execAbs );
  2007.  
  2008. void UObject::execSin( FFrame& Stack, RESULT_DECL )
  2009. {
  2010.     P_GET_FLOAT(A);
  2011.     P_FINISH;
  2012.  
  2013.     *(FLOAT*)Result = appSin(A);
  2014. }  
  2015. IMPLEMENT_FUNCTION( UObject, 187, execSin );
  2016.  
  2017. void UObject::execAsin( FFrame& Stack, RESULT_DECL )
  2018. {
  2019.     P_GET_FLOAT(A);
  2020.     P_FINISH;
  2021.  
  2022.     *(FLOAT*)Result = appAsin(A);
  2023. }  
  2024. IMPLEMENT_FUNCTION( UObject, -1, execAsin );
  2025.  
  2026. void UObject::execCos( FFrame& Stack, RESULT_DECL )
  2027. {
  2028.     P_GET_FLOAT(A);
  2029.     P_FINISH;
  2030.  
  2031.     *(FLOAT*)Result = appCos(A);
  2032. }  
  2033. IMPLEMENT_FUNCTION( UObject, 188, execCos );
  2034.  
  2035. void UObject::execAcos( FFrame& Stack, RESULT_DECL )
  2036. {
  2037.     P_GET_FLOAT(A);
  2038.     P_FINISH;
  2039.  
  2040.     *(FLOAT*)Result = appAcos(A);
  2041. }  
  2042. IMPLEMENT_FUNCTION( UObject, -1, execAcos );
  2043.  
  2044. void UObject::execTan( FFrame& Stack, RESULT_DECL )
  2045. {
  2046.     P_GET_FLOAT(A);
  2047.     P_FINISH;
  2048.  
  2049.     *(FLOAT*)Result = appTan(A);
  2050. }  
  2051. IMPLEMENT_FUNCTION( UObject, 189, execTan );
  2052.  
  2053. void UObject::execAtan( FFrame& Stack, RESULT_DECL )
  2054. {
  2055.     P_GET_FLOAT(A);
  2056.     P_GET_FLOAT(B); //amb
  2057.     P_FINISH;
  2058.  
  2059.     *(FLOAT*)Result = appAtan2(A,B); //amb: changed to atan2
  2060. }  
  2061. IMPLEMENT_FUNCTION( UObject, 190, execAtan );
  2062.  
  2063. void UObject::execExp( FFrame& Stack, RESULT_DECL )
  2064. {
  2065.     P_GET_FLOAT(A);
  2066.     P_FINISH;
  2067.  
  2068.     *(FLOAT*)Result = appExp(A);
  2069. }  
  2070. IMPLEMENT_FUNCTION( UObject, 191, execExp );
  2071.  
  2072. void UObject::execLoge( FFrame& Stack, RESULT_DECL )
  2073. {
  2074.     P_GET_FLOAT(A);
  2075.     P_FINISH;
  2076.  
  2077.     *(FLOAT*)Result = appLoge(A);
  2078. }  
  2079. IMPLEMENT_FUNCTION( UObject, 192, execLoge );
  2080.  
  2081. void UObject::execSqrt( FFrame& Stack, RESULT_DECL )
  2082. {
  2083.     P_GET_FLOAT(A);
  2084.     P_FINISH;
  2085.  
  2086.     FLOAT Sqrt = 0.f;
  2087.     if( A > 0.f )
  2088.     {
  2089.         // Can't use appSqrt(0) as it computes it as 1 / appInvSqrt(). Not a problem as Sqrt variable defaults to 0 == sqrt(0).
  2090.         Sqrt = appSqrt( A );
  2091.     }
  2092.     else if (A < 0.f)
  2093.     {
  2094.         Stack.Logf(NAME_ScriptWarning,TEXT("Attempt to take Sqrt() of negative number - returning 0."));
  2095.     }
  2096.  
  2097.     *(FLOAT*)Result = Sqrt;
  2098. }  
  2099. IMPLEMENT_FUNCTION( UObject, 193, execSqrt );
  2100.  
  2101. void UObject::execSquare( FFrame& Stack, RESULT_DECL )
  2102. {
  2103.     P_GET_FLOAT(A);
  2104.     P_FINISH;
  2105.  
  2106.     *(FLOAT*)Result = Square(A);
  2107. }  
  2108. IMPLEMENT_FUNCTION( UObject, 194, execSquare );
  2109.  
  2110. void UObject::execFRand( FFrame& Stack, RESULT_DECL )
  2111. {
  2112.     P_FINISH;
  2113.  
  2114.     *(FLOAT*)Result = appFrand();
  2115. }  
  2116. IMPLEMENT_FUNCTION( UObject, 195, execFRand );
  2117.  
  2118. void UObject::execFMin( FFrame& Stack, RESULT_DECL )
  2119. {
  2120.     P_GET_FLOAT(A);
  2121.     P_GET_FLOAT(B);
  2122.     P_FINISH;
  2123.  
  2124.     *(FLOAT*)Result = Min(A,B);
  2125. }  
  2126. IMPLEMENT_FUNCTION( UObject, 244, execFMin );
  2127.  
  2128. void UObject::execFMax( FFrame& Stack, RESULT_DECL )
  2129. {
  2130.     P_GET_FLOAT(A);
  2131.     P_GET_FLOAT(B);
  2132.     P_FINISH;
  2133.  
  2134.     *(FLOAT*)Result = Max(A,B);
  2135. }  
  2136. IMPLEMENT_FUNCTION( UObject, 245, execFMax );
  2137.  
  2138. void UObject::execFClamp( FFrame& Stack, RESULT_DECL )
  2139. {
  2140.     P_GET_FLOAT(V);
  2141.     P_GET_FLOAT(A);
  2142.     P_GET_FLOAT(B);
  2143.     P_FINISH;
  2144.  
  2145.     *(FLOAT*)Result = Clamp(V,A,B);
  2146. }  
  2147. IMPLEMENT_FUNCTION( UObject, 246, execFClamp );
  2148.  
  2149. void UObject::execLerp( FFrame& Stack, RESULT_DECL )
  2150. {
  2151.     P_GET_FLOAT(V);
  2152.     P_GET_FLOAT(A);
  2153.     P_GET_FLOAT(B);
  2154.     P_FINISH;
  2155.  
  2156.     *(FLOAT*)Result = A + V*(B-A);
  2157. }  
  2158. IMPLEMENT_FUNCTION( UObject, 247, execLerp );
  2159.  
  2160. void UObject::execSmerp( FFrame& Stack, RESULT_DECL )
  2161. {
  2162.     P_GET_FLOAT(V);
  2163.     P_GET_FLOAT(A);
  2164.     P_GET_FLOAT(B);
  2165.     P_FINISH;
  2166.  
  2167.     *(FLOAT*)Result = A + V*V*(3.f - 2.f*V)*(B-A);
  2168. }
  2169. IMPLEMENT_FUNCTION( UObject, 248, execSmerp );
  2170.  
  2171. void UObject::execRotationConst( FFrame& Stack, RESULT_DECL )
  2172. {
  2173.     ((FRotator*)Result)->Pitch = Stack.ReadInt();
  2174.     ((FRotator*)Result)->Yaw   = Stack.ReadInt();
  2175.     ((FRotator*)Result)->Roll  = Stack.ReadInt();
  2176. }
  2177. IMPLEMENT_FUNCTION( UObject, EX_RotationConst, execRotationConst );
  2178.  
  2179. void UObject::execVectorConst( FFrame& Stack, RESULT_DECL )
  2180. {
  2181.     *(FVector*)Result = *(FVector*)Stack.Code;
  2182.     Stack.Code += sizeof(FVector);
  2183. }
  2184. IMPLEMENT_FUNCTION( UObject, EX_VectorConst, execVectorConst );
  2185.  
  2186. /////////////////
  2187. // Conversions //
  2188. /////////////////
  2189.  
  2190. void UObject::execStringToVector( FFrame& Stack, RESULT_DECL )
  2191. {
  2192.     P_GET_STR(Str);
  2193.  
  2194.     const TCHAR* Stream = *Str;
  2195.     FVector Value(0,0,0);
  2196.     Value.X = appAtof(Stream);
  2197.     Stream = appStrstr(Stream,TEXT(","));
  2198.     if( Stream )
  2199.     {
  2200.         Value.Y = appAtof(++Stream);
  2201.         Stream = appStrstr(Stream,TEXT(","));
  2202.         if( Stream )
  2203.             Value.Z = appAtof(++Stream);
  2204.     }
  2205.     *(FVector*)Result = Value;
  2206. }
  2207. IMPLEMENT_CAST_FUNCTION( UObject, CST_StringToVector, execStringToVector );
  2208.  
  2209. void UObject::execStringToRotator( FFrame& Stack, RESULT_DECL )
  2210. {
  2211.     P_GET_STR(Str);
  2212.  
  2213.     const TCHAR* Stream = *Str;
  2214.     FRotator Rotation(0,0,0);
  2215.     Rotation.Pitch = appAtoi(Stream);
  2216.     Stream = appStrstr(Stream,TEXT(","));
  2217.     if( Stream )
  2218.     {
  2219.         Rotation.Yaw = appAtoi(++Stream);
  2220.         Stream = appStrstr(Stream,TEXT(","));
  2221.         if( Stream )
  2222.             Rotation.Roll = appAtoi(++Stream);
  2223.     }
  2224.     *(FRotator*)Result = Rotation;
  2225. }
  2226. IMPLEMENT_CAST_FUNCTION( UObject, CST_StringToRotator, execStringToRotator );
  2227.  
  2228. void UObject::execVectorToBool( FFrame& Stack, RESULT_DECL )
  2229. {
  2230.     FVector V(0,0,0);
  2231.     Stack.Step( Stack.Object, &V );
  2232.     *(DWORD*)Result = V.IsZero() ? 0 : 1;
  2233. }
  2234. IMPLEMENT_CAST_FUNCTION( UObject, CST_VectorToBool, execVectorToBool );
  2235.  
  2236. void UObject::execVectorToString( FFrame& Stack, RESULT_DECL )
  2237. {
  2238.     P_GET_VECTOR(V);
  2239.     *(FString*)Result = FString::Printf( TEXT("%.2f,%.2f,%.2f"), V.X, V.Y, V.Z );
  2240. }
  2241. IMPLEMENT_CAST_FUNCTION( UObject, CST_VectorToString, execVectorToString );
  2242.  
  2243. void UObject::execVectorToRotator( FFrame& Stack, RESULT_DECL )
  2244. {
  2245.     FVector V(0,0,0);
  2246.     Stack.Step( Stack.Object, &V );
  2247.     *(FRotator*)Result = V.Rotation();
  2248. }
  2249. IMPLEMENT_CAST_FUNCTION( UObject, CST_VectorToRotator, execVectorToRotator );
  2250.  
  2251. void UObject::execRotatorToBool( FFrame& Stack, RESULT_DECL )
  2252. {
  2253.     FRotator R(0,0,0);
  2254.     Stack.Step( Stack.Object, &R );
  2255.     *(DWORD*)Result = R.IsZero() ? 0 : 1;
  2256. }
  2257. IMPLEMENT_CAST_FUNCTION( UObject, CST_RotatorToBool, execRotatorToBool );
  2258.  
  2259. void UObject::execRotatorToVector( FFrame& Stack, RESULT_DECL )
  2260. {
  2261.     FRotator R(0,0,0);
  2262.     Stack.Step( Stack.Object, &R );
  2263.     *(FVector*)Result = R.Vector();
  2264. }
  2265. IMPLEMENT_CAST_FUNCTION( UObject, CST_RotatorToVector, execRotatorToVector );
  2266.  
  2267. void UObject::execRotatorToString( FFrame& Stack, RESULT_DECL )
  2268. {
  2269.     P_GET_ROTATOR(R);
  2270.     *(FString*)Result = FString::Printf( TEXT("%i,%i,%i"), R.Pitch&65535, R.Yaw&65535, R.Roll&65535 );
  2271. }
  2272. IMPLEMENT_CAST_FUNCTION( UObject, CST_RotatorToString, execRotatorToString );
  2273.  
  2274. ////////////////////////////////////
  2275. // Vector operators and functions //
  2276. ////////////////////////////////////
  2277.  
  2278. void UObject::execSubtract_PreVector( FFrame& Stack, RESULT_DECL )
  2279. {
  2280.     P_GET_VECTOR(A);
  2281.     P_FINISH;
  2282.  
  2283.     *(FVector*)Result = -A;
  2284. }  
  2285. IMPLEMENT_FUNCTION( UObject, 0x80 + 83, execSubtract_PreVector );
  2286.  
  2287. void UObject::execMultiply_VectorFloat( FFrame& Stack, RESULT_DECL )
  2288. {
  2289.     P_GET_VECTOR(A);
  2290.     P_GET_FLOAT (B);
  2291.     P_FINISH;
  2292.  
  2293.     *(FVector*)Result = A*B;
  2294. }  
  2295. IMPLEMENT_FUNCTION( UObject, 0x80 + 84, execMultiply_VectorFloat );
  2296.  
  2297. void UObject::execMultiply_FloatVector( FFrame& Stack, RESULT_DECL )
  2298. {
  2299.     P_GET_FLOAT (A);
  2300.     P_GET_VECTOR(B);
  2301.     P_FINISH;
  2302.  
  2303.     *(FVector*)Result = A*B;
  2304. }  
  2305. IMPLEMENT_FUNCTION( UObject, 0x80 + 85, execMultiply_FloatVector );
  2306.  
  2307. void UObject::execMultiply_VectorVector( FFrame& Stack, RESULT_DECL )
  2308. {
  2309.     P_GET_VECTOR(A);
  2310.     P_GET_VECTOR(B);
  2311.     P_FINISH;
  2312.  
  2313.     *(FVector*)Result = A*B;
  2314. }  
  2315. IMPLEMENT_FUNCTION( UObject, 296, execMultiply_VectorVector );
  2316.  
  2317. void UObject::execDivide_VectorFloat( FFrame& Stack, RESULT_DECL )
  2318. {
  2319.     P_GET_VECTOR(A);
  2320.     P_GET_FLOAT (B);
  2321.     P_FINISH;
  2322.  
  2323.     if (B == 0.f)
  2324.     {
  2325.         Stack.Logf(NAME_ScriptWarning,TEXT("Divide by zero"));
  2326.     }
  2327.  
  2328.     *(FVector*)Result = A/B;
  2329. }  
  2330. IMPLEMENT_FUNCTION( UObject, 0x80 + 86, execDivide_VectorFloat );
  2331.  
  2332. void UObject::execAdd_VectorVector( FFrame& Stack, RESULT_DECL )
  2333. {
  2334.     P_GET_VECTOR(A);
  2335.     P_GET_VECTOR(B);
  2336.     P_FINISH;
  2337.  
  2338.     *(FVector*)Result = A+B;
  2339. }  
  2340. IMPLEMENT_FUNCTION( UObject, 0x80 + 87, execAdd_VectorVector );
  2341.  
  2342. void UObject::execSubtract_VectorVector( FFrame& Stack, RESULT_DECL )
  2343. {
  2344.     P_GET_VECTOR(A);
  2345.     P_GET_VECTOR(B);
  2346.     P_FINISH;
  2347.  
  2348.     *(FVector*)Result = A-B;
  2349. }  
  2350. IMPLEMENT_FUNCTION( UObject, 0x80 + 88, execSubtract_VectorVector );
  2351.  
  2352. void UObject::execLessLess_VectorRotator( FFrame& Stack, RESULT_DECL )
  2353. {
  2354.     P_GET_VECTOR(A);
  2355.     P_GET_ROTATOR(B);
  2356.     P_FINISH;
  2357.  
  2358.     *(FVector*)Result = FRotationMatrix(B).Transpose().TransformNormal( A );
  2359. }  
  2360. IMPLEMENT_FUNCTION( UObject, 275, execLessLess_VectorRotator );
  2361.  
  2362. void UObject::execGreaterGreater_VectorRotator( FFrame& Stack, RESULT_DECL )
  2363. {
  2364.     P_GET_VECTOR(A);
  2365.     P_GET_ROTATOR(B);
  2366.     P_FINISH;
  2367.  
  2368.     *(FVector*)Result = FRotationMatrix(B).TransformNormal( A );
  2369. }  
  2370. IMPLEMENT_FUNCTION( UObject, 276, execGreaterGreater_VectorRotator );
  2371.  
  2372. void UObject::execEqualEqual_VectorVector( FFrame& Stack, RESULT_DECL )
  2373. {
  2374.     P_GET_VECTOR(A);
  2375.     P_GET_VECTOR(B);
  2376.     P_FINISH;
  2377.  
  2378.     *(DWORD*)Result = A.X==B.X && A.Y==B.Y && A.Z==B.Z;
  2379. }  
  2380. IMPLEMENT_FUNCTION( UObject, 0x80 + 89, execEqualEqual_VectorVector );
  2381.  
  2382. void UObject::execNotEqual_VectorVector( FFrame& Stack, RESULT_DECL )
  2383. {
  2384.     P_GET_VECTOR(A);
  2385.     P_GET_VECTOR(B);
  2386.     P_FINISH;
  2387.  
  2388.     *(DWORD*)Result = A.X!=B.X || A.Y!=B.Y || A.Z!=B.Z;
  2389. }  
  2390. IMPLEMENT_FUNCTION( UObject, 0x80 + 90, execNotEqual_VectorVector );
  2391.  
  2392. void UObject::execDot_VectorVector( FFrame& Stack, RESULT_DECL )
  2393. {
  2394.     P_GET_VECTOR(A);
  2395.     P_GET_VECTOR(B);
  2396.     P_FINISH;
  2397.  
  2398.     *(FLOAT*)Result = A|B;
  2399. }  
  2400. IMPLEMENT_FUNCTION( UObject, 0x80 + 91, execDot_VectorVector );
  2401.  
  2402. void UObject::execCross_VectorVector( FFrame& Stack, RESULT_DECL )
  2403. {
  2404.     P_GET_VECTOR(A);
  2405.     P_GET_VECTOR(B);
  2406.     P_FINISH;
  2407.  
  2408.     *(FVector*)Result = A^B;
  2409. }  
  2410. IMPLEMENT_FUNCTION( UObject, 0x80 + 92, execCross_VectorVector );
  2411.  
  2412. void UObject::execMultiplyEqual_VectorFloat( FFrame& Stack, RESULT_DECL )
  2413. {
  2414.     P_GET_VECTOR_REF(A);
  2415.     P_GET_FLOAT(B);
  2416.     P_FINISH;
  2417.  
  2418.     *(FVector*)Result = (*A *= B);
  2419. }  
  2420. IMPLEMENT_FUNCTION( UObject, 0x80 + 93, execMultiplyEqual_VectorFloat );
  2421.  
  2422. void UObject::execMultiplyEqual_VectorVector( FFrame& Stack, RESULT_DECL )
  2423. {
  2424.     P_GET_VECTOR_REF(A);
  2425.     P_GET_VECTOR(B);
  2426.     P_FINISH;
  2427.  
  2428.     *(FVector*)Result = (*A *= B);
  2429. }  
  2430. IMPLEMENT_FUNCTION( UObject, 297, execMultiplyEqual_VectorVector );
  2431.  
  2432. void UObject::execDivideEqual_VectorFloat( FFrame& Stack, RESULT_DECL )
  2433. {
  2434.     P_GET_VECTOR_REF(A);
  2435.     P_GET_FLOAT(B);
  2436.     P_FINISH;
  2437.  
  2438.     if (B == 0.f)
  2439.     {
  2440.         Stack.Logf(NAME_ScriptWarning,TEXT("Divide by zero"));
  2441.     }
  2442.  
  2443.     *(FVector*)Result = (*A /= B);
  2444. }  
  2445. IMPLEMENT_FUNCTION( UObject, 0x80 + 94, execDivideEqual_VectorFloat );
  2446.  
  2447. void UObject::execAddEqual_VectorVector( FFrame& Stack, RESULT_DECL )
  2448. {
  2449.     P_GET_VECTOR_REF(A);
  2450.     P_GET_VECTOR(B);
  2451.     P_FINISH;
  2452.  
  2453.     *(FVector*)Result = (*A += B);
  2454. }  
  2455. IMPLEMENT_FUNCTION( UObject, 0x80 + 95, execAddEqual_VectorVector );
  2456.  
  2457. void UObject::execSubtractEqual_VectorVector( FFrame& Stack, RESULT_DECL )
  2458. {
  2459.     P_GET_VECTOR_REF(A);
  2460.     P_GET_VECTOR(B);
  2461.     P_FINISH;
  2462.  
  2463.     *(FVector*)Result = (*A -= B);
  2464. }  
  2465. IMPLEMENT_FUNCTION( UObject, 0x80 + 96, execSubtractEqual_VectorVector );
  2466.  
  2467. void UObject::execVSize( FFrame& Stack, RESULT_DECL )
  2468. {
  2469.     P_GET_VECTOR(A);
  2470.     P_FINISH;
  2471.  
  2472.     *(FLOAT*)Result = A.Size();
  2473. }  
  2474. IMPLEMENT_FUNCTION( UObject, 0x80 + 97, execVSize );
  2475.  
  2476. void UObject::execVSize2D( FFrame& Stack, RESULT_DECL )
  2477. {
  2478.     P_GET_VECTOR(A);
  2479.     P_FINISH;
  2480.  
  2481.     *(FLOAT*)Result = A.Size2D();
  2482. }
  2483. IMPLEMENT_FUNCTION( UObject, -1, execVSize2D );
  2484.  
  2485. void UObject::execVSizeSq( FFrame& Stack, RESULT_DECL )
  2486. {
  2487.     P_GET_VECTOR(A);
  2488.     P_FINISH;
  2489.  
  2490.     *(FLOAT*)Result = A.SizeSquared();
  2491. }
  2492. IMPLEMENT_FUNCTION( UObject, -1, execVSizeSq );
  2493.  
  2494. void UObject::execNormal( FFrame& Stack, RESULT_DECL )
  2495. {
  2496.     P_GET_VECTOR(A);
  2497.     P_FINISH;
  2498.  
  2499.     *(FVector*)Result = A.SafeNormal();
  2500. }
  2501. IMPLEMENT_FUNCTION( UObject, 0x80 + 98, execNormal );
  2502.  
  2503. void UObject::execVLerp( FFrame& Stack, RESULT_DECL )
  2504. {
  2505.     P_GET_FLOAT(V);
  2506.     P_GET_VECTOR(A);
  2507.     P_GET_VECTOR(B);
  2508.     P_FINISH;
  2509.  
  2510.     *(FVector*)Result = A + V*(B-A);
  2511. }  
  2512. IMPLEMENT_FUNCTION( UObject, -1, execVLerp );
  2513.  
  2514. void UObject::execVSmerp( FFrame& Stack, RESULT_DECL )
  2515. {
  2516.     P_GET_FLOAT(V);
  2517.     P_GET_VECTOR(A);
  2518.     P_GET_VECTOR(B);
  2519.     P_FINISH;
  2520.  
  2521.     *(FVector*)Result = A + V*V*(3.f - 2.f*V)*(B-A);
  2522. }
  2523. IMPLEMENT_FUNCTION( UObject, -1, execVSmerp );
  2524.  
  2525. void UObject::execVRand( FFrame& Stack, RESULT_DECL )
  2526. {
  2527.     P_FINISH;
  2528.     *((FVector*)Result) = VRand();
  2529. }
  2530. IMPLEMENT_FUNCTION( UObject, 0x80 + 124, execVRand );
  2531.  
  2532. void UObject::execRotRand( FFrame& Stack, RESULT_DECL )
  2533. {
  2534.     P_GET_UBOOL_OPTX(bRoll, 0);
  2535.     P_FINISH;
  2536.  
  2537.     FRotator RRot;
  2538.     RRot.Yaw = ((2 * appRand()) % 65535);
  2539.     RRot.Pitch = ((2 * appRand()) % 65535);
  2540.     if ( bRoll )
  2541.         RRot.Roll = ((2 * appRand()) % 65535);
  2542.     else
  2543.         RRot.Roll = 0;
  2544.     *((FRotator*)Result) = RRot;
  2545. }
  2546. IMPLEMENT_FUNCTION( UObject, 320, execRotRand );
  2547.  
  2548. void UObject::execMirrorVectorByNormal( FFrame& Stack, RESULT_DECL )
  2549. {
  2550.     P_GET_VECTOR(A);
  2551.     P_GET_VECTOR(B);
  2552.     P_FINISH;
  2553.  
  2554.     B = B.SafeNormal();
  2555.     *(FVector*)Result = A - 2.f * B * (B | A);
  2556. }
  2557. IMPLEMENT_FUNCTION( UObject, 300, execMirrorVectorByNormal );
  2558.  
  2559. //scion ===========================================================
  2560. //  SCION Function: execProjectOnTo
  2561. //  Author: superville
  2562. //
  2563. //  Description: Projects on vector (X) onto another (Y) and returns
  2564. //      the projected vector without modifying either of the arguments
  2565. //
  2566. //  Last Modified: 03/06/04 (superville)
  2567. // ================================================================
  2568. void UObject::execProjectOnTo(FFrame &Stack, RESULT_DECL)
  2569. {
  2570.     P_GET_VECTOR( X );
  2571.     P_GET_VECTOR( Y );
  2572.     P_FINISH;
  2573.  
  2574.     *(FVector*)Result = X.ProjectOnTo( Y );
  2575. }
  2576. IMPLEMENT_FUNCTION(UObject,1500,execProjectOnTo);
  2577.  
  2578. //scion ===========================================================
  2579. //  SCION Function: execIsZero
  2580. //  Author: superville
  2581. //
  2582. //  Description: Returns true if all components of the vector are zero
  2583. //
  2584. //  Last Modified: 03/06/04 (superville)
  2585. // ================================================================
  2586. void UObject::execIsZero(FFrame &Stack, RESULT_DECL)
  2587. {
  2588.     P_GET_VECTOR(A);
  2589.     P_FINISH;
  2590.  
  2591.     *(UBOOL*)Result = (A.X == 0 && A.Y == 0 && A.Z == 0);
  2592. }
  2593. IMPLEMENT_FUNCTION(UObject,1501,execIsZero);
  2594.  
  2595. //////////////////////////////////////
  2596. // Rotation operators and functions //
  2597. //////////////////////////////////////
  2598.  
  2599. void UObject::execEqualEqual_RotatorRotator( FFrame& Stack, RESULT_DECL )
  2600. {
  2601.     P_GET_ROTATOR(A);
  2602.     P_GET_ROTATOR(B);
  2603.     P_FINISH;
  2604.  
  2605.     *(DWORD*)Result = A.Pitch==B.Pitch && A.Yaw==B.Yaw && A.Roll==B.Roll;
  2606. }  
  2607. IMPLEMENT_FUNCTION( UObject, 0x80 + 14, execEqualEqual_RotatorRotator );
  2608.  
  2609. void UObject::execNotEqual_RotatorRotator( FFrame& Stack, RESULT_DECL )
  2610. {
  2611.     P_GET_ROTATOR(A);
  2612.     P_GET_ROTATOR(B);
  2613.     P_FINISH;
  2614.  
  2615.     *(DWORD*)Result = A.Pitch!=B.Pitch || A.Yaw!=B.Yaw || A.Roll!=B.Roll;
  2616. }  
  2617. IMPLEMENT_FUNCTION( UObject, 0x80 + 75, execNotEqual_RotatorRotator );
  2618.  
  2619. void UObject::execMultiply_RotatorFloat( FFrame& Stack, RESULT_DECL )
  2620. {
  2621.     P_GET_ROTATOR(A);
  2622.     P_GET_FLOAT(B);
  2623.     P_FINISH;
  2624.  
  2625.     *(FRotator*)Result = A * B;
  2626. }  
  2627. IMPLEMENT_FUNCTION( UObject, 287, execMultiply_RotatorFloat );
  2628.  
  2629. void UObject::execMultiply_FloatRotator( FFrame& Stack, RESULT_DECL )
  2630. {
  2631.     P_GET_FLOAT(A);
  2632.     P_GET_ROTATOR(B);
  2633.     P_FINISH;
  2634.  
  2635.     *(FRotator*)Result = B * A;
  2636. }  
  2637. IMPLEMENT_FUNCTION( UObject, 288, execMultiply_FloatRotator );
  2638.  
  2639. void UObject::execDivide_RotatorFloat( FFrame& Stack, RESULT_DECL )
  2640. {
  2641.     P_GET_ROTATOR(A);
  2642.     P_GET_FLOAT(B);
  2643.     P_FINISH;
  2644.  
  2645.     if (B == 0.f)
  2646.     {
  2647.         Stack.Logf(NAME_ScriptWarning,TEXT("Divide by zero"));
  2648.     }
  2649.  
  2650.     *(FRotator*)Result = A * (1.f/B);
  2651. }  
  2652. IMPLEMENT_FUNCTION( UObject, 289, execDivide_RotatorFloat );
  2653.  
  2654. void UObject::execMultiplyEqual_RotatorFloat( FFrame& Stack, RESULT_DECL )
  2655. {
  2656.     P_GET_ROTATOR_REF(A);
  2657.     P_GET_FLOAT(B);
  2658.     P_FINISH;
  2659.  
  2660.     *(FRotator*)Result = (*A *= B);
  2661. }  
  2662. IMPLEMENT_FUNCTION( UObject, 290, execMultiplyEqual_RotatorFloat );
  2663.  
  2664. void UObject::execDivideEqual_RotatorFloat( FFrame& Stack, RESULT_DECL )
  2665. {
  2666.     P_GET_ROTATOR_REF(A);
  2667.     P_GET_FLOAT(B);
  2668.     P_FINISH;
  2669.  
  2670.     if (B == 0.f)
  2671.     {
  2672.         Stack.Logf(NAME_ScriptWarning,TEXT("Divide by zero"));
  2673.     }
  2674.  
  2675.     *(FRotator*)Result = (*A *= (1.f/B));
  2676. }  
  2677. IMPLEMENT_FUNCTION( UObject, 291, execDivideEqual_RotatorFloat );
  2678.  
  2679. void UObject::execAdd_RotatorRotator( FFrame& Stack, RESULT_DECL )
  2680. {
  2681.     P_GET_ROTATOR(A);
  2682.     P_GET_ROTATOR(B);
  2683.     P_FINISH;
  2684.  
  2685.     *(FRotator*)Result = A + B;
  2686. }
  2687. IMPLEMENT_FUNCTION( UObject, 316, execAdd_RotatorRotator );
  2688.  
  2689. void UObject::execSubtract_RotatorRotator( FFrame& Stack, RESULT_DECL )
  2690. {
  2691.     P_GET_ROTATOR(A);
  2692.     P_GET_ROTATOR(B);
  2693.     P_FINISH;
  2694.  
  2695.     *(FRotator*)Result = A - B;
  2696. }
  2697. IMPLEMENT_FUNCTION( UObject, 317, execSubtract_RotatorRotator );
  2698.  
  2699. void UObject::execAddEqual_RotatorRotator( FFrame& Stack, RESULT_DECL )
  2700. {
  2701.     P_GET_ROTATOR_REF(A);
  2702.     P_GET_ROTATOR(B);
  2703.     P_FINISH;
  2704.  
  2705.     *(FRotator*)Result = (*A += B);
  2706. }
  2707. IMPLEMENT_FUNCTION( UObject, 318, execAddEqual_RotatorRotator );
  2708.  
  2709. void UObject::execSubtractEqual_RotatorRotator( FFrame& Stack, RESULT_DECL )
  2710. {
  2711.     P_GET_ROTATOR_REF(A);
  2712.     P_GET_ROTATOR(B);
  2713.     P_FINISH;
  2714.  
  2715.     *(FRotator*)Result = (*A -= B);
  2716. }
  2717. IMPLEMENT_FUNCTION( UObject, 319, execSubtractEqual_RotatorRotator );
  2718.  
  2719. void UObject::execGetAxes( FFrame& Stack, RESULT_DECL )
  2720. {
  2721.     P_GET_ROTATOR(A);
  2722.     P_GET_VECTOR_REF(X);
  2723.     P_GET_VECTOR_REF(Y);
  2724.     P_GET_VECTOR_REF(Z);
  2725.     P_FINISH;
  2726.  
  2727.     FRotationMatrix R(A);
  2728.     *X = R.GetAxis(0);
  2729.     *Y = R.GetAxis(1);
  2730.     *Z = R.GetAxis(2);
  2731. }
  2732. IMPLEMENT_FUNCTION( UObject, 0x80 + 101, execGetAxes );
  2733.  
  2734. void UObject::execGetUnAxes( FFrame& Stack, RESULT_DECL )
  2735. {
  2736.     P_GET_ROTATOR(A);
  2737.     P_GET_VECTOR_REF(X);
  2738.     P_GET_VECTOR_REF(Y);
  2739.     P_GET_VECTOR_REF(Z);
  2740.     P_FINISH;
  2741.  
  2742.     FMatrix R = FRotationMatrix(A).Transpose();
  2743.     *X = R.GetAxis(0);
  2744.     *Y = R.GetAxis(1);
  2745.     *Z = R.GetAxis(2);
  2746. }
  2747. IMPLEMENT_FUNCTION( UObject, 0x80 + 102, execGetUnAxes );
  2748.  
  2749. void UObject::execOrthoRotation( FFrame& Stack, RESULT_DECL )
  2750. {
  2751.     P_GET_VECTOR(X);
  2752.     P_GET_VECTOR(Y);
  2753.     P_GET_VECTOR(Z);
  2754.     P_FINISH;
  2755.  
  2756.     FMatrix M = FMatrix::Identity;
  2757.     M.SetAxis( 0, X );
  2758.     M.SetAxis( 1, Y );
  2759.     M.SetAxis( 2, Z );
  2760.  
  2761.     *(FRotator*)Result = M.Rotator();
  2762. }
  2763. IMPLEMENT_FUNCTION( UObject, INDEX_NONE, execOrthoRotation );
  2764.  
  2765. void UObject::execNormalize( FFrame& Stack, RESULT_DECL )
  2766. {
  2767.     P_GET_ROTATOR(Rot);
  2768.     P_FINISH;
  2769.  
  2770.     *(FRotator*)Result = Rot.Normalize();
  2771. }
  2772. IMPLEMENT_FUNCTION( UObject, INDEX_NONE, execNormalize );
  2773.  
  2774. void UObject::execRLerp( FFrame& Stack, RESULT_DECL )
  2775. {
  2776.     P_GET_FLOAT(V);
  2777.     P_GET_ROTATOR(A);
  2778.     P_GET_ROTATOR(B);
  2779.     P_FINISH;
  2780.  
  2781.     *(FRotator*)Result = A + V*(B-A);
  2782. }
  2783. IMPLEMENT_FUNCTION( UObject, INDEX_NONE, execRLerp );
  2784.  
  2785. void UObject::execRSmerp( FFrame& Stack, RESULT_DECL )
  2786. {
  2787.     P_GET_FLOAT(V);
  2788.     P_GET_ROTATOR(A);
  2789.     P_GET_ROTATOR(B);
  2790.     P_FINISH;
  2791.  
  2792.     *(FRotator*)Result = A + V*V*(3.f - 2.f*V)*(B-A);
  2793. }
  2794. IMPLEMENT_FUNCTION( UObject, INDEX_NONE, execRSmerp );
  2795.  
  2796. void UObject::execClockwiseFrom_IntInt( FFrame& Stack, RESULT_DECL )
  2797. {
  2798.     P_GET_INT(IntA);
  2799.     P_GET_INT(IntB);
  2800.     P_FINISH;
  2801.  
  2802.     IntA = IntA & 0xFFFF;
  2803.     IntB = IntB & 0xFFFF;
  2804.  
  2805.     *(DWORD*)Result = ( Abs(IntA - IntB) > 32768 ) ? ( IntA < IntB ) : ( IntA > IntB );
  2806. }
  2807. IMPLEMENT_FUNCTION( UObject, INDEX_NONE, execClockwiseFrom_IntInt );
  2808.  
  2809. ////////////////////////////////////
  2810. // Quaternion functions           //
  2811. ////////////////////////////////////
  2812.  
  2813. void UObject::execQuatProduct( FFrame& Stack, RESULT_DECL )
  2814. {
  2815.     P_GET_STRUCT(FQuat, A);
  2816.     P_GET_STRUCT(FQuat, B);
  2817.     P_FINISH;
  2818.  
  2819.     *(FQuat*)Result = A * B;
  2820. }
  2821. IMPLEMENT_FUNCTION( UObject, INDEX_NONE, execQuatProduct);
  2822.  
  2823. void UObject::execQuatInvert( FFrame& Stack, RESULT_DECL )
  2824. {
  2825.     P_GET_STRUCT(FQuat, A);
  2826.     P_FINISH;
  2827.  
  2828.     FQuat invA(-A.X, -A.Y, -A.Z, A.W);
  2829.     *(FQuat*)Result = invA;
  2830. }
  2831. IMPLEMENT_FUNCTION( UObject, INDEX_NONE, execQuatInvert);
  2832.  
  2833. void UObject::execQuatRotateVector( FFrame& Stack, RESULT_DECL )
  2834. {
  2835.     P_GET_STRUCT(FQuat, A);
  2836.     P_GET_VECTOR(B);
  2837.     P_FINISH;
  2838.  
  2839.     *(FVector*)Result = A.RotateVector(B);
  2840. }
  2841. IMPLEMENT_FUNCTION( UObject, INDEX_NONE, execQuatRotateVector);
  2842.  
  2843. // Generate the 'smallest' (geodesic) rotation between these two vectors.
  2844. void UObject::execQuatFindBetween( FFrame& Stack, RESULT_DECL )
  2845. {
  2846.     P_GET_VECTOR(A);
  2847.     P_GET_VECTOR(B);
  2848.     P_FINISH;
  2849.  
  2850.     FVector cross = A ^ B;
  2851.     FLOAT crossMag = cross.Size();
  2852.  
  2853.     // If these vectors are basically parallel - just return identity quaternion (ie no rotation).
  2854.     if(crossMag < KINDA_SMALL_NUMBER)
  2855.     {
  2856.         *(FQuat*)Result = FQuat::Identity;
  2857.         return;
  2858.     }
  2859.  
  2860.     FLOAT angle = appAsin(crossMag);
  2861.  
  2862.     FLOAT dot = A | B;
  2863.     if(dot < 0.f)
  2864.         angle = PI - angle;
  2865.  
  2866.     FLOAT sinHalfAng = appSin(0.5f * angle);
  2867.     FLOAT cosHalfAng = appCos(0.5f * angle);
  2868.     FVector axis = cross / crossMag;
  2869.  
  2870.     *(FQuat*)Result = FQuat(
  2871.         sinHalfAng * axis.X,
  2872.         sinHalfAng * axis.Y,
  2873.         sinHalfAng * axis.Z,
  2874.         cosHalfAng );
  2875. }
  2876. IMPLEMENT_FUNCTION( UObject, INDEX_NONE, execQuatFindBetween);
  2877.  
  2878. void UObject::execQuatFromAxisAndAngle( FFrame& Stack, RESULT_DECL )
  2879. {
  2880.     P_GET_VECTOR(Axis);
  2881.     P_GET_FLOAT(Angle);
  2882.     P_FINISH;
  2883.  
  2884.     FLOAT sinHalfAng = appSin(0.5f * Angle);
  2885.     FLOAT cosHalfAng = appCos(0.5f * Angle);
  2886.     FVector normAxis = Axis.SafeNormal();
  2887.  
  2888.     *(FQuat*)Result = FQuat(
  2889.         sinHalfAng * normAxis.X,
  2890.         sinHalfAng * normAxis.Y,
  2891.         sinHalfAng * normAxis.Z,
  2892.         cosHalfAng );
  2893. }
  2894. IMPLEMENT_FUNCTION( UObject, INDEX_NONE, execQuatFromAxisAndAngle);
  2895.  
  2896. void UObject::execQuatFromRotator( FFrame& Stack, RESULT_DECL )
  2897. {
  2898.     P_GET_ROTATOR(A);
  2899.     P_FINISH;
  2900.  
  2901.     *(FQuat*)Result = FQuat( FRotationMatrix(A) );
  2902. }
  2903. IMPLEMENT_FUNCTION( UObject, INDEX_NONE, execQuatFromRotator);
  2904.  
  2905. void UObject::execQuatToRotator( FFrame& Stack, RESULT_DECL )
  2906. {
  2907.     P_GET_STRUCT(FQuat, A);
  2908.     P_FINISH;
  2909.  
  2910.     *(FRotator*)Result = FMatrix( FVector(0.f), A).Rotator();
  2911. }
  2912. IMPLEMENT_FUNCTION( UObject, INDEX_NONE, execQuatToRotator);
  2913.  
  2914. ////////////////////////////////////
  2915. // Str operators and functions //
  2916. ////////////////////////////////////
  2917.  
  2918. void UObject::execEatString( FFrame& Stack, RESULT_DECL )
  2919. {
  2920.     // Call function returning a string, then discard the result.
  2921.     FString String;
  2922.     Stack.Step( this, &String );
  2923. }
  2924. IMPLEMENT_FUNCTION( UObject, EX_EatString, execEatString );
  2925.  
  2926. void UObject::execConcat_StringString( FFrame& Stack, RESULT_DECL )
  2927. {
  2928.     P_GET_STR(A);
  2929.     P_GET_STR(B);
  2930.     P_FINISH;
  2931.  
  2932.     *(FString*)Result = (A+B);
  2933. }
  2934. IMPLEMENT_FUNCTION( UObject, 112, execConcat_StringString );
  2935.  
  2936. void UObject::execAt_StringString( FFrame& Stack, RESULT_DECL )
  2937. {
  2938.     P_GET_STR(A);
  2939.     P_GET_STR(B);
  2940.     P_FINISH;
  2941.  
  2942.     *(FString*)Result = (A+TEXT(" ")+B);
  2943. }
  2944. IMPLEMENT_FUNCTION( UObject, 168, execAt_StringString );
  2945.  
  2946. void UObject::execLess_StringString( FFrame& Stack, RESULT_DECL )
  2947. {
  2948.     P_GET_STR(A);
  2949.     P_GET_STR(B);
  2950.     P_FINISH;
  2951.  
  2952.     *(DWORD*)Result = appStrcmp(*A,*B)<0;;
  2953. }
  2954. IMPLEMENT_FUNCTION( UObject, 115, execLess_StringString );
  2955.  
  2956. void UObject::execGreater_StringString( FFrame& Stack, RESULT_DECL )
  2957. {
  2958.     P_GET_STR(A);
  2959.     P_GET_STR(B);
  2960.     P_FINISH;
  2961.  
  2962.     *(DWORD*)Result = appStrcmp(*A,*B)>0;
  2963. }
  2964. IMPLEMENT_FUNCTION( UObject, 116, execGreater_StringString );
  2965.  
  2966. void UObject::execLessEqual_StringString( FFrame& Stack, RESULT_DECL )
  2967. {
  2968.     P_GET_STR(A);
  2969.     P_GET_STR(B);
  2970.     P_FINISH;
  2971.  
  2972.     *(DWORD*)Result = appStrcmp(*A,*B)<=0;
  2973. }
  2974. IMPLEMENT_FUNCTION( UObject, 120, execLessEqual_StringString );
  2975.  
  2976. void UObject::execGreaterEqual_StringString( FFrame& Stack, RESULT_DECL )
  2977. {
  2978.     P_GET_STR(A);
  2979.     P_GET_STR(B);
  2980.     P_FINISH;
  2981.  
  2982.     *(DWORD*)Result = appStrcmp(*A,*B)>=0;
  2983. }
  2984. IMPLEMENT_FUNCTION( UObject, 121, execGreaterEqual_StringString );
  2985.  
  2986. void UObject::execEqualEqual_StringString( FFrame& Stack, RESULT_DECL )
  2987. {
  2988.     P_GET_STR(A);
  2989.     P_GET_STR(B);
  2990.     P_FINISH;
  2991.  
  2992.     *(DWORD*)Result = appStrcmp(*A,*B)==0;
  2993. }
  2994. IMPLEMENT_FUNCTION( UObject, 122, execEqualEqual_StringString );
  2995.  
  2996. void UObject::execNotEqual_StringString( FFrame& Stack, RESULT_DECL )
  2997. {
  2998.     P_GET_STR(A);
  2999.     P_GET_STR(B);
  3000.     P_FINISH;
  3001.  
  3002.     *(DWORD*)Result = appStrcmp(*A,*B)!=0;
  3003. }
  3004. IMPLEMENT_FUNCTION( UObject, 123, execNotEqual_StringString );
  3005.  
  3006. void UObject::execComplementEqual_StringString( FFrame& Stack, RESULT_DECL )
  3007. {
  3008.     P_GET_STR(A);
  3009.     P_GET_STR(B);
  3010.     P_FINISH;
  3011.  
  3012.     *(DWORD*)Result = appStricmp(*A,*B)==0;
  3013. }
  3014. IMPLEMENT_FUNCTION( UObject, 124, execComplementEqual_StringString );
  3015.  
  3016. void UObject::execLen( FFrame& Stack, RESULT_DECL )
  3017. {
  3018.     P_GET_STR(S);
  3019.     P_FINISH;
  3020.  
  3021.     *(INT*)Result = S.Len();
  3022. }
  3023. IMPLEMENT_FUNCTION( UObject, 125, execLen );
  3024.  
  3025. void UObject::execInStr( FFrame& Stack, RESULT_DECL )
  3026. {
  3027.     P_GET_STR(S);
  3028.     P_GET_STR(A);
  3029.     P_FINISH;
  3030.     *(INT*)Result = S.InStr(A);
  3031. }
  3032. IMPLEMENT_FUNCTION( UObject, 126, execInStr );
  3033.  
  3034. void UObject::execMid( FFrame& Stack, RESULT_DECL )
  3035. {
  3036.     P_GET_STR(A);
  3037.     P_GET_INT(I);
  3038.     P_GET_INT_OPTX(C,65535);
  3039.     P_FINISH;
  3040.  
  3041.     *(FString*)Result = A.Mid(I,C);
  3042. }
  3043. IMPLEMENT_FUNCTION( UObject, 127, execMid );
  3044.  
  3045. void UObject::execLeft( FFrame& Stack, RESULT_DECL )
  3046. {
  3047.     P_GET_STR(A);
  3048.     P_GET_INT(N);
  3049.     P_FINISH;
  3050.  
  3051.     *(FString*)Result = A.Left(N);
  3052. }
  3053. IMPLEMENT_FUNCTION( UObject, 128, execLeft );
  3054.  
  3055. void UObject::execRight( FFrame& Stack, RESULT_DECL )
  3056. {
  3057.     P_GET_STR(A);
  3058.     P_GET_INT(N);
  3059.     P_FINISH;
  3060.  
  3061.     *(FString*)Result = A.Right(N);
  3062. }
  3063. IMPLEMENT_FUNCTION( UObject, 234, execRight );
  3064.  
  3065. void UObject::execCaps( FFrame& Stack, RESULT_DECL )
  3066. {
  3067.     P_GET_STR(A);
  3068.     P_FINISH;
  3069.  
  3070.     *(FString*)Result = A.Caps();
  3071. }
  3072. IMPLEMENT_FUNCTION( UObject, 235, execCaps );
  3073.  
  3074. void UObject::execChr( FFrame& Stack, RESULT_DECL )
  3075. {
  3076.     P_GET_INT(i);
  3077.     P_FINISH;
  3078.  
  3079.     TCHAR Temp[2];
  3080.     Temp[0] = i;
  3081.     Temp[1] = 0;
  3082.     *(FString*)Result = Temp;
  3083. }
  3084. IMPLEMENT_FUNCTION( UObject, 236, execChr );
  3085.  
  3086. void UObject::execAsc( FFrame& Stack, RESULT_DECL )
  3087. {
  3088.     P_GET_STR(S);
  3089.     P_FINISH;
  3090.  
  3091.     *(INT*)Result = **S;   
  3092. }
  3093. IMPLEMENT_FUNCTION( UObject, 237, execAsc );
  3094.  
  3095. /////////////////////////////////////////
  3096. // Native name operators and functions //
  3097. /////////////////////////////////////////
  3098.  
  3099. void UObject::execEqualEqual_NameName( FFrame& Stack, RESULT_DECL )
  3100. {
  3101.     P_GET_NAME(A);
  3102.     P_GET_NAME(B);
  3103.     P_FINISH;
  3104.  
  3105.     *(DWORD*)Result = A == B;
  3106. }
  3107. IMPLEMENT_FUNCTION( UObject, 254, execEqualEqual_NameName );
  3108.  
  3109. void UObject::execNotEqual_NameName( FFrame& Stack, RESULT_DECL )
  3110. {
  3111.     P_GET_NAME(A);
  3112.     P_GET_NAME(B);
  3113.     P_FINISH;
  3114.  
  3115.     *(DWORD*)Result = A != B;
  3116. }
  3117. IMPLEMENT_FUNCTION( UObject, 255, execNotEqual_NameName );
  3118.  
  3119. ////////////////////////////////////
  3120. // Object operators and functions //
  3121. ////////////////////////////////////
  3122.  
  3123. void UObject::execEqualEqual_ObjectObject( FFrame& Stack, RESULT_DECL )
  3124. {
  3125.     P_GET_OBJECT(UObject,A);
  3126.     P_GET_OBJECT(UObject,B);
  3127.     P_FINISH;
  3128.  
  3129.     *(DWORD*)Result = A == B;
  3130. }
  3131. IMPLEMENT_FUNCTION( UObject, 114, execEqualEqual_ObjectObject );
  3132.  
  3133. void UObject::execNotEqual_ObjectObject( FFrame& Stack, RESULT_DECL )
  3134. {
  3135.     P_GET_OBJECT(UObject,A);
  3136.     P_GET_OBJECT(UObject,B);
  3137.     P_FINISH;
  3138.  
  3139.     *(DWORD*)Result = A != B;
  3140. }
  3141. IMPLEMENT_FUNCTION( UObject, 119, execNotEqual_ObjectObject );
  3142.  
  3143. /////////////////////////////
  3144. // Log and error functions //
  3145. /////////////////////////////
  3146.  
  3147. void UObject::execLog( FFrame& Stack, RESULT_DECL )
  3148. {
  3149.     P_GET_STR(S);
  3150.     P_GET_NAME_OPTX(N,NAME_ScriptLog);
  3151.     P_FINISH;
  3152.  
  3153.     debugf( (EName)N.GetIndex(), TEXT("%s"), *S );
  3154. }
  3155. IMPLEMENT_FUNCTION( UObject, 231, execLog );
  3156.  
  3157. void UObject::execWarn( FFrame& Stack, RESULT_DECL )
  3158. {
  3159.     P_GET_STR(S);
  3160.     P_FINISH;
  3161.  
  3162.     Stack.Logf( TEXT("%s"), *S );
  3163. }
  3164. IMPLEMENT_FUNCTION( UObject, 232, execWarn );
  3165.  
  3166. void UObject::execLocalize( FFrame& Stack, RESULT_DECL )
  3167. {
  3168.     P_GET_STR(SectionName);
  3169.     P_GET_STR(KeyName);
  3170.     P_GET_STR(PackageName);
  3171.     P_FINISH;
  3172.  
  3173.     *(FString*)Result = Localize( *SectionName, *KeyName, *PackageName );
  3174. }
  3175. IMPLEMENT_FUNCTION( UObject, INDEX_NONE, execLocalize );
  3176.  
  3177. //////////////////
  3178. // High natives //
  3179. //////////////////
  3180.  
  3181. #define HIGH_NATIVE(n) \
  3182. void UObject::execHighNative##n( FFrame& Stack, RESULT_DECL ) \
  3183. { \
  3184.     BYTE B = *Stack.Code++; \
  3185.     (this->*GNatives[ n*0x100 + B ])( Stack, Result ); \
  3186. } \
  3187. IMPLEMENT_FUNCTION( UObject, 0x60 + n, execHighNative##n );
  3188.  
  3189. HIGH_NATIVE(0);
  3190. HIGH_NATIVE(1);
  3191. HIGH_NATIVE(2);
  3192. HIGH_NATIVE(3);
  3193. HIGH_NATIVE(4);
  3194. HIGH_NATIVE(5);
  3195. HIGH_NATIVE(6);
  3196. HIGH_NATIVE(7);
  3197. HIGH_NATIVE(8);
  3198. HIGH_NATIVE(9);
  3199. HIGH_NATIVE(10);
  3200. HIGH_NATIVE(11);
  3201. HIGH_NATIVE(12);
  3202. HIGH_NATIVE(13);
  3203. HIGH_NATIVE(14);
  3204. HIGH_NATIVE(15);
  3205. #undef HIGH_NATIVE
  3206.  
  3207. /////////////////////////
  3208. // Object construction //
  3209. /////////////////////////
  3210.  
  3211. void UObject::execNew( FFrame& Stack, RESULT_DECL )
  3212. {
  3213.     // Get parameters.
  3214.     P_GET_OBJECT_OPTX(UObject,Outer,NULL);
  3215.     P_GET_STR_OPTX(Name,TEXT(""));
  3216.     P_GET_INT_OPTX(Flags,0);
  3217.     P_GET_OBJECT_OPTX(UClass,Cls,NULL);
  3218.  
  3219.     // Validate parameters.
  3220.     if( Flags & ~RF_ScriptMask )
  3221.         Stack.Logf( TEXT("new: Flags %08X not allowed"), Flags & ~RF_ScriptMask );
  3222.  
  3223.     // Construct new object.
  3224.     if( !Outer )
  3225.         Outer = GetTransientPackage();
  3226.     *(UObject**)Result = StaticConstructObject( Cls, Outer, Name.Len()?FName(*Name):NAME_None, Flags&RF_ScriptMask, NULL, &Stack );
  3227. }
  3228. IMPLEMENT_FUNCTION( UObject, EX_New, execNew );
  3229.  
  3230. /////////////////////////////
  3231. // Class related functions //
  3232. /////////////////////////////
  3233.  
  3234. void UObject::execClassIsChildOf( FFrame& Stack, RESULT_DECL )
  3235. {
  3236.     P_GET_OBJECT(UClass,K);
  3237.     P_GET_OBJECT(UClass,C);
  3238.     P_FINISH;
  3239.  
  3240.     *(DWORD*)Result = (C && K) ? K->IsChildOf(C) : 0;
  3241. }
  3242. IMPLEMENT_FUNCTION( UObject, 258, execClassIsChildOf );
  3243.  
  3244. ///////////////////////////////
  3245. // State and label functions //
  3246. ///////////////////////////////
  3247.  
  3248. void UObject::execGotoState( FFrame& Stack, RESULT_DECL )
  3249. {
  3250.     FName CurrentStateName = (StateFrame && StateFrame->StateNode!=Class) ? StateFrame->StateNode->GetFName() : FName(NAME_None);
  3251.     P_GET_NAME_OPTX( S, CurrentStateName );
  3252.     P_GET_NAME_OPTX( L, NAME_None );
  3253.     P_GET_UBOOL_OPTX( bForceEvents, 0 );
  3254.     P_FINISH;
  3255.  
  3256.     // Go to the state.
  3257.     EGotoState ResultState = GOTOSTATE_Success;
  3258.     if( S!=CurrentStateName || bForceEvents)
  3259.     {
  3260.         ResultState = GotoState( S, bForceEvents );
  3261.     }
  3262.  
  3263.     // Handle success.
  3264.     if( ResultState==GOTOSTATE_Success )
  3265.     {
  3266.         // Now go to the label.
  3267.         if( !GotoLabel( L==NAME_None ? FName(NAME_Begin) : L ) && L!=NAME_None )
  3268.         {
  3269.             Stack.Logf( TEXT("GotoState (%s %s): Label not found"), *S, *L );
  3270.         }
  3271.     }
  3272.     else if( ResultState==GOTOSTATE_NotFound )
  3273.     {
  3274.         // Warning.
  3275.         if( S!=NAME_None && S!=NAME_Auto )
  3276.             Stack.Logf( TEXT("GotoState (%s %s): State not found"), *S, *L );
  3277.         else if ( S==NAME_None && GDebugger )
  3278.             GDebugger->DebugInfo(this, &Stack,DI_PrevStackState,0,0);
  3279.     }
  3280.     else
  3281.     {
  3282.         // Safely preempted by another GotoState.
  3283.     }
  3284. }
  3285. IMPLEMENT_FUNCTION( UObject, 113, execGotoState );
  3286.  
  3287. void UObject::execPushState(FFrame &Stack, RESULT_DECL)
  3288. {
  3289.     P_GET_NAME(newState);
  3290.     P_GET_NAME_OPTX(newLabel, NAME_None);
  3291.     P_FINISH;
  3292.     // if we support states
  3293.     if (StateFrame != NULL)
  3294.     {
  3295.         // find the new state
  3296.         UState *stateNode = FindState(newState);
  3297.         if (stateNode != NULL)
  3298.         {
  3299.             // notify the current state
  3300.             eventPausedState();
  3301.             // save the current state information
  3302.             INT idx = StateFrame->StateStack.AddZeroed();
  3303.             StateFrame->StateStack(idx).State = StateFrame->StateNode;
  3304.             StateFrame->StateStack(idx).Node = StateFrame->Node;
  3305.             StateFrame->StateStack(idx).Code = StateFrame->Code;
  3306.             // push the new state
  3307.             StateFrame->StateNode = stateNode;
  3308.             StateFrame->Node = stateNode;
  3309.             StateFrame->Code = NULL;
  3310.             StateFrame->ProbeMask = (stateNode->ProbeMask | GetClass()->ProbeMask) & stateNode->IgnoreMask;
  3311.             // and send pushed event
  3312.             eventPushedState();
  3313.             // and jump to label if specified
  3314.             GotoLabel(newLabel != NAME_None ? newLabel : NAME_Begin);
  3315.         }
  3316.         else
  3317.         {
  3318.             debugf(NAME_Warning,TEXT("Failed to find state %s"),*newState);
  3319.         }
  3320.     }
  3321. }
  3322. IMPLEMENT_FUNCTION(UObject, -1, execPushState);
  3323.  
  3324. void UObject::execPopState(FFrame &Stack, RESULT_DECL)
  3325. {
  3326.     P_GET_UBOOL_OPTX(bPopAll,0);
  3327.     P_FINISH;
  3328.     // if we support states, and we have a nested state
  3329.     if (StateFrame != NULL &&
  3330.         StateFrame->StateNode != NULL &&
  3331.         StateFrame->StateStack.Num())
  3332.     {
  3333.         // if popping all then find the lowest state, otherwise go one level up
  3334.         INT popCnt = 0;
  3335.         while (StateFrame->StateStack.Num() &&
  3336.                (bPopAll ||
  3337.                 popCnt == 0))
  3338.         {
  3339.             // send the popped event
  3340.             eventPoppedState();
  3341.             // grab the new desired state
  3342.             INT idx = StateFrame->StateStack.Num() - 1;
  3343.             UState *stateNode = StateFrame->StateStack(idx).State;
  3344.             UStruct *node = StateFrame->StateStack(idx).Node;
  3345.             BYTE *code = StateFrame->StateStack(idx).Code;
  3346.             // remove from the current stack
  3347.             StateFrame->StateStack.Pop();
  3348.             // and set the new state
  3349.             StateFrame->StateNode = stateNode;
  3350.             StateFrame->Node = node;
  3351.             StateFrame->Code = code;
  3352.             StateFrame->ProbeMask = (stateNode->ProbeMask | GetClass()->ProbeMask) & stateNode->IgnoreMask;
  3353.             popCnt++;
  3354.             // send continue event
  3355.             eventContinuedState();
  3356.         }
  3357.     }
  3358.     else
  3359.     {
  3360.         debugf(NAME_Warning,TEXT("%s called PopState() w/o a valid state stack!"),GetName());
  3361.     }
  3362. }
  3363. IMPLEMENT_FUNCTION(UObject, -1, execPopState);
  3364.  
  3365. void UObject::execEnable( FFrame& Stack, RESULT_DECL )
  3366. {
  3367.     P_GET_NAME(N);
  3368.     if( N.GetIndex()>=NAME_PROBEMIN && N.GetIndex()<NAME_PROBEMAX && StateFrame )
  3369.     {
  3370.         QWORD BaseProbeMask = (GetStateFrame()->StateNode->ProbeMask | GetClass()->ProbeMask) & GetStateFrame()->StateNode->IgnoreMask;
  3371.         GetStateFrame()->ProbeMask |= (BaseProbeMask & ((QWORD)1<<(N.GetIndex()-NAME_PROBEMIN)));
  3372.     }
  3373.     else Stack.Logf( TEXT("Enable: '%s' is not a probe function"), *N );
  3374.     P_FINISH;
  3375. }
  3376. IMPLEMENT_FUNCTION( UObject, 117, execEnable );
  3377.  
  3378. void UObject::execDisable( FFrame& Stack, RESULT_DECL )
  3379. {
  3380.     P_GET_NAME(N);
  3381.     P_FINISH;
  3382.  
  3383.     if( N.GetIndex()>=NAME_PROBEMIN && N.GetIndex()<NAME_PROBEMAX && StateFrame )
  3384.         GetStateFrame()->ProbeMask &= ~((QWORD)1<<(N.GetIndex()-NAME_PROBEMIN));
  3385.     else
  3386.         Stack.Logf( TEXT("Enable: '%s' is not a probe function"), *N );
  3387. }
  3388. IMPLEMENT_FUNCTION( UObject, 118, execDisable );
  3389.  
  3390. ///////////////////
  3391. // Property text //
  3392. ///////////////////
  3393.  
  3394. void UObject::execGetPropertyText( FFrame& Stack, RESULT_DECL )
  3395. {
  3396.     P_GET_STR(PropName);
  3397.     P_FINISH;
  3398.  
  3399.     UProperty* Property=FindField<UProperty>( Class, *PropName );
  3400.     if( Property && (Property->GetFlags() & RF_Public) )
  3401.     {
  3402.         FString Temp;
  3403.         Property->ExportText( 0, Temp, (BYTE*)this, (BYTE*)this, this, PPF_Localized );
  3404.         *(FString*)Result = Temp;
  3405.     }
  3406.     else *(FString*)Result = TEXT("");
  3407. }
  3408. IMPLEMENT_FUNCTION( UObject, INDEX_NONE, execGetPropertyText );
  3409.  
  3410. void UObject::execSetPropertyText( FFrame& Stack, RESULT_DECL )
  3411. {
  3412.     P_GET_STR(PropName);
  3413.     P_GET_STR(PropValue);
  3414.     P_FINISH;
  3415.  
  3416.     UProperty* Property=FindField<UProperty>( Class, *PropName );
  3417.     if
  3418.     (   (Property)
  3419.     &&  (Property->GetFlags() & RF_Public)
  3420.     &&  !(Property->PropertyFlags & CPF_Const) )
  3421.         Property->ImportText( *PropValue, (BYTE*)this + Property->Offset, PPF_Localized, this );
  3422. }
  3423. IMPLEMENT_FUNCTION( UObject, INDEX_NONE, execSetPropertyText );
  3424.  
  3425. void UObject::execSaveConfig( FFrame& Stack, RESULT_DECL )
  3426. {
  3427.     P_FINISH;
  3428.     SaveConfig();
  3429. }
  3430. IMPLEMENT_FUNCTION( UObject, 536, execSaveConfig);
  3431.  
  3432. void UObject::execStaticSaveConfig( FFrame& Stack, RESULT_DECL )
  3433. {
  3434.     P_FINISH;
  3435.     Class->GetDefaultObject()->SaveConfig();
  3436. }
  3437. IMPLEMENT_FUNCTION( UObject, INDEX_NONE, execStaticSaveConfig);
  3438.  
  3439. void UObject::execGetEnum( FFrame& Stack, RESULT_DECL )
  3440. {
  3441.     P_GET_OBJECT(UObject,E);
  3442.     P_GET_INT(i);
  3443.     P_FINISH;
  3444.  
  3445.     *(FName*)Result = NAME_None;
  3446.     if( Cast<UEnum>(E) && i>=0 && i<Cast<UEnum>(E)->Names.Num() )
  3447.         *(FName*)Result = Cast<UEnum>(E)->Names(i);
  3448. }
  3449. IMPLEMENT_FUNCTION( UObject, INDEX_NONE, execGetEnum);
  3450.  
  3451. void UObject::execDynamicLoadObject( FFrame& Stack, RESULT_DECL )
  3452. {
  3453.     P_GET_STR(Name);
  3454.     P_GET_OBJECT(UClass,Class);
  3455.     P_GET_UBOOL_OPTX(bMayFail,0);
  3456.     P_FINISH;
  3457.  
  3458.     *(UObject**)Result = StaticLoadObject( Class, NULL, *Name, NULL, LOAD_NoWarn | (bMayFail?LOAD_Quiet:0), NULL );
  3459. }
  3460. IMPLEMENT_FUNCTION( UObject, INDEX_NONE, execDynamicLoadObject );
  3461.  
  3462. void UObject::execFindObject( FFrame& Stack, RESULT_DECL )
  3463. {
  3464.     P_GET_STR(Name);
  3465.     P_GET_OBJECT(UClass,Class);
  3466.     P_FINISH;
  3467.  
  3468.     *(UObject**)Result = StaticFindObject( Class, NULL, *Name );
  3469. }
  3470. IMPLEMENT_FUNCTION( UObject, INDEX_NONE, execFindObject );
  3471.  
  3472. void UObject::execIsInState( FFrame& Stack, RESULT_DECL )
  3473. {
  3474.     P_GET_NAME(StateName);
  3475.     P_FINISH;
  3476.  
  3477.     if( StateFrame )
  3478.         for( UState* Test=StateFrame->StateNode; Test; Test=Test->GetSuperState() )
  3479.             if( Test->GetFName()==StateName )
  3480.                 {*(DWORD*)Result=1; return;}
  3481.     *(DWORD*)Result = 0;
  3482. }
  3483. IMPLEMENT_FUNCTION( UObject, 281, execIsInState );
  3484.  
  3485. void UObject::execGetStateName( FFrame& Stack, RESULT_DECL )
  3486. {
  3487.     P_FINISH;
  3488.     *(FName*)Result = (StateFrame && StateFrame->StateNode) ? StateFrame->StateNode->GetFName() : FName(NAME_None);
  3489. }
  3490. IMPLEMENT_FUNCTION( UObject, 284, execGetStateName );
  3491.  
  3492. void UObject::execGetFuncName(FFrame &Stack, RESULT_DECL)
  3493. {
  3494.     P_FINISH;
  3495.     *(FName*)Result = Stack.Node != NULL ? Stack.Node->GetFName() : NAME_None;
  3496. }
  3497. IMPLEMENT_FUNCTION(UObject,-1,execGetFuncName);
  3498.  
  3499. void UObject::execScriptTrace(FFrame &Stack, RESULT_DECL)
  3500. {
  3501.     P_FINISH;
  3502.     // grab the call stack
  3503.     TArray<FFrame*> frameStack;
  3504.     FFrame *frame = &Stack;
  3505.     while (frame != NULL)
  3506.     {
  3507.         frameStack.AddItem(frame);
  3508.         frame = frame->PreviousFrame;
  3509.     }
  3510.     // and log it
  3511.     debugf(TEXT("Script call stack:"));
  3512.     TCHAR spacer[256] = TEXT("\0");
  3513.     for (INT idx = frameStack.Num() - 1; idx >= 0; idx--)
  3514.     {
  3515.         debugf(TEXT("%s-> %s"),spacer,frameStack(idx)->Node->GetFullName());
  3516.         appStrcat(spacer,TEXT("  "));
  3517.     }
  3518. }
  3519. IMPLEMENT_FUNCTION(UObject,-1,execScriptTrace);
  3520.  
  3521. void UObject::execIsA( FFrame& Stack, RESULT_DECL )
  3522. {
  3523.     P_GET_NAME(ClassName);
  3524.     P_FINISH;
  3525.  
  3526.     UClass* TempClass;
  3527.     for( TempClass=GetClass(); TempClass; TempClass=TempClass->GetSuperClass() )
  3528.         if( TempClass->GetFName() == ClassName )
  3529.             break;
  3530.     *(DWORD*)Result = (TempClass!=NULL);
  3531. }
  3532. IMPLEMENT_FUNCTION(UObject,303,execIsA);
  3533.  
  3534. /*-----------------------------------------------------------------------------
  3535.     Native iterator functions.
  3536. -----------------------------------------------------------------------------*/
  3537.  
  3538. void UObject::execIterator( FFrame& Stack, RESULT_DECL )
  3539. {}
  3540. IMPLEMENT_FUNCTION( UObject, EX_Iterator, execIterator );
  3541.  
  3542. /*-----------------------------------------------------------------------------
  3543.     Native registry.
  3544. -----------------------------------------------------------------------------*/
  3545.  
  3546.  
  3547. // Optimizations break GRegisterNative with static linking on the PC, causing UObject::execUndefined to be called early on during script execution.
  3548. #if _MSC_VER > 1310 && !defined XBOX
  3549. #error re-evaluate need for workaround
  3550. #endif
  3551. #pragma DISABLE_OPTIMIZATION
  3552. //
  3553. // Register a native function.
  3554. // Warning: Called at startup time, before engine initialization.
  3555. //
  3556. BYTE GRegisterNative( INT iNative, const Native& Func )
  3557. {
  3558.     static int Initialized = 0;
  3559.     if( !Initialized )
  3560.     {
  3561.         Initialized = 1;
  3562.         for( int i=0; i<ARRAY_COUNT(GNatives); i++ )
  3563.             GNatives[i] = &UObject::execUndefined;
  3564.     }
  3565.     if( iNative != INDEX_NONE )
  3566.     {
  3567.         if( iNative<0 || iNative>ARRAY_COUNT(GNatives) || GNatives[iNative]!=&UObject::execUndefined)
  3568.             GNativeDuplicate = iNative;
  3569.         GNatives[iNative] = Func;
  3570.     }
  3571.     return 0;
  3572. }
  3573. #pragma ENABLE_OPTIMIZATION
  3574.  
  3575. BYTE GRegisterCast( INT CastCode, const Native& Func )
  3576. {
  3577.     static int Initialized = 0;
  3578.     if( !Initialized )
  3579.     {
  3580.         Initialized = 1;
  3581.         for( int i=0; i<ARRAY_COUNT(GCasts); i++ )
  3582.             GCasts[i] = &UObject::execUndefined;
  3583.     }
  3584.     if( CastCode != INDEX_NONE )
  3585.     {
  3586.         if( CastCode<0 || CastCode>ARRAY_COUNT(GCasts) || GCasts[CastCode]!=&UObject::execUndefined)
  3587.             GCastDuplicate = CastCode;
  3588.         GCasts[CastCode] = Func;
  3589.     }
  3590.     return 0;
  3591. }
  3592.  
  3593.  
  3594. /*-----------------------------------------------------------------------------
  3595.     Call graph profiling.
  3596. -----------------------------------------------------------------------------*/
  3597.  
  3598. /**
  3599.  * Constructor
  3600.  *
  3601.  * @param InSoftMemoryLimit     Max number of bytes used by call graph data (soft limit).
  3602.  */
  3603. FScriptCallGraph::FScriptCallGraph( DWORD InSoftMemoryLimit )
  3604. {
  3605.     check( InSoftMemoryLimit );
  3606.     Reset( InSoftMemoryLimit );
  3607. }
  3608.  
  3609. /**
  3610.  * Resets data collection and memory use.
  3611.  *
  3612.  * @param InSoftMemoryLimit     Max number of bytes used by call graph data (soft limit).
  3613.  */
  3614. void FScriptCallGraph::Reset( DWORD InSoftMemoryLimit )
  3615. {
  3616.     if( InSoftMemoryLimit )
  3617.     {
  3618.         SoftMemoryLimit = InSoftMemoryLimit;
  3619.     }
  3620.  
  3621.     Data.Empty( SoftMemoryLimit * 11 / 10 / sizeof(DWORD) );
  3622. }
  3623.  
  3624. /**
  3625.  * Serializes the profiling data to the passed in archive. 
  3626.  *
  3627.  * @param Ar    Archive to serialize data to.
  3628.  */
  3629. void FScriptCallGraph::Serialize( FArchive& Ar )
  3630. {
  3631.     if( Data.Num() )
  3632.     {
  3633.         INT StartIndex  = 0;
  3634.         INT EndIndex    = 0;
  3635.  
  3636.         // Skip the first frame as we most likely are in the middle of the call stack.
  3637.         while( StartIndex<Data.Num() && !IsFrameEndMarker(Data(StartIndex)) )
  3638.         {
  3639.             StartIndex++;
  3640.         }
  3641.         check(StartIndex<Data.Num());
  3642.  
  3643.         // Find the end of the call graph data.
  3644.         EndIndex = StartIndex;
  3645.         while( EndIndex<Data.Num() && !IsEndMarker(Data(EndIndex)) )
  3646.         {
  3647.             EndIndex++;
  3648.         }
  3649.  
  3650.         // Create a list of all functions currently loaded.
  3651.         TArray<UFunction*> Functions;
  3652.         for( TObjectIterator<UFunction> It; It; ++It )
  3653.         {
  3654.             Functions.AddItem( *It );
  3655.         }
  3656.  
  3657.         // First value to serialize is the number of usecs per cycle. (DOUBLE)
  3658.         DOUBLE usecsPerCycle = GSecondsPerCycle * 1000.0 * 1000.0;
  3659.         Ar << usecsPerCycle;
  3660.  
  3661.         // Second value is the number of functions that are being serialized (DWORD).
  3662.         DWORD FunctionCount = Functions.Num();
  3663.         Ar << FunctionCount;
  3664.  
  3665.         for( INT FunctionIndex=0; FunctionIndex<Functions.Num(); FunctionIndex++ )
  3666.         {
  3667.             FString         Name        = Functions(FunctionIndex)->GetPathName();
  3668.             DWORD           Length      = Name.Len();
  3669.             DWORD           Pointer     = (DWORD) Functions(FunctionIndex);
  3670.        
  3671.             // Serialize function pointer, length of name in characters and then serialize name without the
  3672.             // trailing '\0' as a chain of ANSI characters.
  3673.             Ar << Pointer;  // (DWORD)
  3674.             Ar << Length;   // (DWORD)
  3675.             for( DWORD i=0; i<Length; i++ )
  3676.             {
  3677.                 ANSICHAR ACh = ToAnsi( Name[i] );
  3678.                 Ar << ACh;  // (ANSICHAR)
  3679.             }
  3680.         }
  3681.  
  3682.         // Serialize raw collected data as tokens of DWORDs.
  3683.         Ar.Serialize( &Data(StartIndex), (EndIndex - StartIndex) * sizeof(DWORD) );
  3684.     }
  3685. }
  3686.  
  3687. /**
  3688.  * Emits the end of frame marker. Needs to be called when there are no script functions
  3689.  * on the stack. Also responsible for reseting call graph data if memory limit is reached.
  3690.  */
  3691. void FScriptCallGraph::Tick()
  3692. {
  3693.     EmitFrameEnd();
  3694.     if( (Data.Num()*sizeof(DWORD)) > SoftMemoryLimit )
  3695.     {
  3696.         Reset( SoftMemoryLimit );
  3697.     }
  3698. }
  3699.  
  3700. /** Global script call graph profiler */
  3701. FScriptCallGraph* GScriptCallGraph = NULL;
  3702.  
  3703. /**
  3704.  * Helper class for call graph profiling. Scoped to correctly deal with multiple return
  3705.  * paths.
  3706.  */
  3707. struct FScopedScriptStats
  3708. {
  3709.     /**
  3710.      * Constructor, emiting function pointer to stream.
  3711.      *
  3712.      * @param InFunction    Function about to be called.
  3713.      */
  3714.     FScopedScriptStats( UFunction* InFunction )
  3715.     {
  3716.         if( GScriptCallGraph )
  3717.         {
  3718.             StartCycles = appCycles();
  3719.             Function    = InFunction;
  3720.             GScriptCallGraph->EmitFunction( Function );
  3721.         }
  3722.     }
  3723.  
  3724.     /**
  3725.      * Destructor, emiting cycles spent in function call.  
  3726.      */
  3727.     ~FScopedScriptStats()
  3728.     {
  3729.         if( GScriptCallGraph )
  3730.         {
  3731.             DWORD Cycles = appCycles() - StartCycles;
  3732.             GScriptCallGraph->EmitCycles( Cycles );
  3733.         }
  3734.     }
  3735.  
  3736. private:
  3737.     /** Function associated with callss */
  3738.     UFunction*  Function;
  3739.     /** Cycle count before function was being called. */
  3740.     DWORD       StartCycles;
  3741. };
  3742.  
  3743. /*-----------------------------------------------------------------------------
  3744.     Script processing function.
  3745. -----------------------------------------------------------------------------*/
  3746.  
  3747. //
  3748. // Information remembered about an Out parameter.
  3749. //
  3750. struct FOutParmRec
  3751. {
  3752.     UProperty* Property;
  3753.     BYTE*      PropAddr;
  3754. };
  3755.  
  3756. //
  3757. // Call a function.
  3758. //
  3759. void UObject::CallFunction( FFrame& Stack, RESULT_DECL, UFunction* Function )
  3760. {
  3761.     FScopedScriptStats ScriptStats( Function );
  3762.  
  3763.     // Found it.
  3764.     UBOOL SkipIt = 0;
  3765.     if( Function->iNative )
  3766.     {
  3767.         // Call native final function.
  3768.         (this->*Function->Func)( Stack, Result );
  3769.     }
  3770.     else if( Function->FunctionFlags & FUNC_Native )
  3771.     {
  3772.         // Call native networkable function.
  3773.         BYTE Buffer[1024];
  3774.         if( !ProcessRemoteFunction( Function, Buffer, &Stack ) )
  3775.         {
  3776.             // Call regular native function.
  3777.             (this->*Function->Func)( Stack, Result );
  3778.         }
  3779.         else
  3780.         {
  3781.             // Eat up the remaining parameters in the stream.
  3782.             SkipIt = 1;
  3783.             goto Temporary;
  3784.         }
  3785.     }
  3786.     else
  3787.     {
  3788.         // Make new stack frame in the current context.
  3789.         Temporary:
  3790.         BYTE* Frame = (BYTE*)appAlloca(Function->PropertiesSize);
  3791.         appMemzero( Frame, Function->PropertiesSize );
  3792.         FFrame NewStack( this, Function, 0, Frame, &Stack );
  3793.         FOutParmRec Outs[MAX_FUNC_PARMS], *Out = Outs;
  3794.         for( UProperty* Property=(UProperty*)Function->Children; *Stack.Code!=EX_EndFunctionParms; Property=(UProperty*)Property->Next )
  3795.         {
  3796.             GPropAddr = NULL;
  3797.             GPropObject = NULL;
  3798.             BYTE* Param = NewStack.Locals + Property->Offset;
  3799.             Stack.Step( Stack.Object, Param );
  3800. #if !__INTEL_BYTE_ORDER__
  3801.             if( Property->GetID()==NAME_BoolProperty  )
  3802.             {
  3803.                 if( *(DWORD*)(Param) )
  3804.                     *(DWORD*)(Param) = FIRST_BITFIELD;
  3805.                 else
  3806.                     *(DWORD*)(Param) = 0;
  3807.             }
  3808. #endif
  3809.             if( (Property->PropertyFlags & CPF_OutParm) && GPropAddr )
  3810.             {
  3811.                 Out->PropAddr = GPropAddr;
  3812.                 Out->Property = Property;
  3813.                 Out++;
  3814.                 if ( GPropObject && GProperty && (GProperty->PropertyFlags & CPF_Net) )
  3815.                     GPropObject->NetDirty(GProperty);
  3816.             }
  3817.         }
  3818.         Stack.Code++;
  3819.  
  3820.         //DEBUGGER
  3821.         // This is necessary until I find a better solution, otherwise,
  3822.         // when the DebugInfo gets read out of the bytecode, it'll be called
  3823.         // AFTER the function returns, which is not useful. This is one of the
  3824.         // few places I check for debug information.
  3825.         if ( *Stack.Code == EX_DebugInfo )
  3826.             Stack.Step( Stack.Object, NULL );
  3827.  
  3828.         // Execute the code.
  3829.         if( !SkipIt )
  3830.             ProcessInternal( NewStack, Result );
  3831.  
  3832.         // Copy back outparms.
  3833.         while( --Out >= Outs )
  3834.             Out->Property->CopyCompleteValue( Out->PropAddr, NewStack.Locals + Out->Property->Offset );
  3835.  
  3836.         // Destruct properties on the stack.
  3837.         for( UProperty* Destruct=Function->ConstructorLink; Destruct; Destruct=Destruct->ConstructorLinkNext )
  3838.             Destruct->DestroyValue( NewStack.Locals + Destruct->Offset );
  3839.     }
  3840. }
  3841.  
  3842. //
  3843. // Internal function call processing.
  3844. // @warning: might not write anything to Result if singular or proper type isn't returned.
  3845. //
  3846. void UObject::ProcessInternal( FFrame& Stack, RESULT_DECL )
  3847. {
  3848.     DWORD SingularFlag = ((UFunction*)Stack.Node)->FunctionFlags & FUNC_Singular;
  3849.     if
  3850.     (   !ProcessRemoteFunction( (UFunction*)Stack.Node, Stack.Locals, NULL )
  3851.     &&  IsProbing( Stack.Node->GetFName() )
  3852.     &&  !(ObjectFlags & SingularFlag) )
  3853.     {
  3854.         ObjectFlags |= SingularFlag;
  3855.         BYTE Buffer[1024];//@hack hardcoded size
  3856.         appMemzero( Buffer, sizeof(FString) );//@hack
  3857. #if DO_GUARD
  3858.         if( ++Recurse > RECURSE_LIMIT )
  3859.         {
  3860.             if ( GDebugger && GDebugger->NotifyInfiniteLoop() )
  3861.             {
  3862.                 Recurse = 0;
  3863.             }
  3864.             else
  3865.             {
  3866.                 Stack.Logf( NAME_Critical, TEXT("Infinite script recursion (%i calls) detected"), RECURSE_LIMIT );
  3867.             }
  3868.         }
  3869. #endif
  3870.         while( *Stack.Code != EX_Return )
  3871.             Stack.Step( Stack.Object, Buffer );
  3872.         Stack.Code++;
  3873.         Stack.Step( Stack.Object, Result );
  3874.  
  3875.         //DEBUGGER: Necessary for the call stack. Grab an optional 'PREVSTACK' debug info.
  3876.         if ( *Stack.Code == EX_DebugInfo )
  3877.             Stack.Step( Stack.Object, Result );
  3878.        
  3879.         ObjectFlags &= ~SingularFlag;
  3880. #if DO_GUARD
  3881.         --Recurse;
  3882. #endif
  3883.     }
  3884. }
  3885.  
  3886. //
  3887. // Script processing functions.
  3888. //
  3889. void UObject::ProcessEvent( UFunction* Function, void* Parms, void* UnusedResult )
  3890. {
  3891.     static INT ScriptEntryTag = 0;
  3892.  
  3893.     // Reject.
  3894.     if
  3895.     (   !IsProbing( Function->GetFName() )
  3896.     ||  IsPendingKill()
  3897.     ||  Function->iNative
  3898.     ||  ((Function->FunctionFlags & FUNC_Native) && ProcessRemoteFunction( Function, Parms, NULL )) )
  3899.         return;
  3900.     checkSlow(Function->ParmsSize==0 || Parms!=NULL);
  3901.  
  3902.     if(++ScriptEntryTag == 1)
  3903.     {
  3904.         clock(GScriptCycles);
  3905.     }
  3906.  
  3907.     // Scope required for scoped script stats.
  3908.     {
  3909.         FScopedScriptStats ScriptStats( Function );
  3910.        
  3911.         // Create a new local execution stack.
  3912.         FFrame NewStack( this, Function, 0, appAlloca(Function->PropertiesSize) );
  3913.         appMemcpy( NewStack.Locals, Parms, Function->ParmsSize );
  3914.         appMemzero( NewStack.Locals+Function->ParmsSize, Function->PropertiesSize-Function->ParmsSize );
  3915.  
  3916.         // Call native function or UObject::ProcessInternal.
  3917.         (this->*Function->Func)( NewStack, NewStack.Locals+Function->ReturnValueOffset );
  3918.  
  3919.         // Copy everything back.
  3920.         appMemcpy( Parms, NewStack.Locals, Function->ParmsSize );
  3921.  
  3922.         // Destroy local variables except function parameters.!! see also UObject::ScriptConsoleExec
  3923.         for( UProperty* P=Function->ConstructorLink; P; P=P->ConstructorLinkNext )
  3924.             if( P->Offset >= Function->ParmsSize )
  3925.                 P->DestroyValue( NewStack.Locals + P->Offset );
  3926.     }
  3927.  
  3928.     if(--ScriptEntryTag == 0)
  3929.     {
  3930.         unclock(GScriptCycles);
  3931.     }
  3932. }
  3933.  
  3934. void UObject::ProcessDelegate( FName DelegateName, FScriptDelegate* Delegate, void* Parms, void* UnusedResult )
  3935. {
  3936.     if( Delegate->Object && Delegate->Object->IsPendingKill() )
  3937.     {
  3938.         Delegate->Object = NULL;
  3939.         Delegate->FunctionName = NAME_None;
  3940.     }
  3941.     if( Delegate->Object )
  3942.         Delegate->Object->ProcessEvent( Delegate->Object->FindFunctionChecked(Delegate->FunctionName), Parms, UnusedResult );
  3943.     else
  3944.         ProcessEvent( FindFunctionChecked(DelegateName), Parms, UnusedResult );
  3945. }
  3946.  
  3947. //
  3948. // Execute the state code of the object.
  3949. //
  3950. void UObject::ProcessState( FLOAT DeltaSeconds )
  3951. {}
  3952.  
  3953. //
  3954. // Process a remote function; returns 1 if remote, 0 if local.
  3955. //
  3956. UBOOL UObject::ProcessRemoteFunction( UFunction* Function, void* Parms, FFrame* Stack )
  3957. {
  3958.     return 0;
  3959. }
  3960.  
  3961. /*-----------------------------------------------------------------------------
  3962.     The End.
  3963. -----------------------------------------------------------------------------*/
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement